forked from DFRobot/DFRobot_EC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDFRobot_EC.cpp
353 lines (311 loc) · 11.6 KB
/
DFRobot_EC.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*
* file DFRobot_EC.cpp
* @ https://github.com/DFRobot/DFRobot_EC
*
* Arduino library for Gravity: Analog Electrical Conductivity Sensor / Meter Kit V2 (K=1), SKU: DFR0300
*
* Copyright [DFRobot](http://www.dfrobot.com), 2018
* Copyright GNU Lesser General Public License
*
* version V1.01
* date 2018-06
*
* version V1.1
* date 2020-04
* Changes the memory addressing to allow multiple EC sensors
*/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "DFRobot_EC.h"
#include <EEPROM.h>
#define EEPROM_write(address, value) {int i = 0; byte *pp = (byte*)&(value);for(; i < sizeof(value); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, value) {int i = 0; byte *pp = (byte*)&(value);for(; i < sizeof(value); i++) pp[i]=EEPROM.read(address+i);}
// The start address of the K value stored in the EEPROM. Start at 96 after the 12 values for the pH sensors
#define KVALUEADDR 96
#define RES2 820.0
#define ECREF 200.0
// Maps the pin (A0,A1..A11) to a number 0-11 so the address can be determined
uint8_t mapECPin(uint8_t ecPin)
{
int addressMap = 0;
if (ecPin == A0){
Serial.print(" pin A0 ");
addressMap = 0;
} else if (ecPin == A1){
Serial.print(" pin A1 ");
addressMap = 1;
} else if (ecPin == A2){
Serial.print(" pin A2 ");
addressMap = 2;
} else if (ecPin == A3){
Serial.print(" pin A3 ");
addressMap = 3;
} else if (ecPin == A4){
Serial.print(" pin A4 ");
addressMap = 4;
} else if (ecPin == A5){
Serial.print(" pin A5 ");
addressMap = 5;
} else if (ecPin == A6){
Serial.print(" pin A6 ");
addressMap = 6;
} else if (ecPin == A7){
Serial.print(" pin A7 ");
addressMap = 7;
} else if (ecPin == A8){
Serial.print(" pin A8 ");
addressMap = 8;
} else if (ecPin == A9){
Serial.print(" pin A9 ");
addressMap = 9;
} else if (ecPin == A10){
Serial.print(" pin A10 ");
addressMap = 10;
} else if (ecPin == A11){
Serial.print(" pin A11 ");
addressMap = 11;
}
return addressMap;
}
// Default construtor to ensure backwards compatibility
DFRobot_EC::DFRobot_EC()
{
// As no pin was provided we will use the data for pin A0
this->_pin = A0;
// Set the address
// For each EC sensor we need to store 2 floats (EC 1.413us/cm and EC 12.88ms/cm)
// This will be 8byte per sensor and the largest arduino has 12 analogue ports
// So let's start at address 0 and go up by 8b for each analogue port. This will use upto 96b
// For the EC library we will start after PH addresses
this->_address = KVALUEADDR + (sizeof(float) * 2 * mapECPin(this->_pin));
// Buffer solution EC 1.413us/cm at 25C
this->_kvalueLow = 1.0;
// Buffer solution EC 12.88ms/cm at 25C
this->_kvalueHigh = 1.0;
// Initialise the rest of the values with an initial starting value
this->_cmdReceivedBufferIndex = 0;
this->_voltage = 0.0;
this->_temperature = 25.0;
this->_ecvalue = 0.0;
this->_kvalue = 1.0;
}
// Updated construtor to allow multiple EC sensors
DFRobot_EC::DFRobot_EC(int ecPin)
{
// Set the pin to the supplied value
this->_pin = ecPin;
// Set the address
// For each EC sensor we need to store 2 floats (EC 1.413us/cm and EC 12.88ms/cm)
// This will be 8byte per sensor and the largest arduino has 12 analogue ports
// So let's start at address 0 and go up by 8b for each analogue port. This will use upto 96b
// For the EC library we will start after PH addresses
this->_address = KVALUEADDR + (sizeof(float) * 2 * mapECPin(this->_pin));
// Buffer solution EC 1.413us/cm at 25C
this->_kvalueLow = 1.0;
// Buffer solution EC 12.88ms/cm at 25C
this->_kvalueHigh = 1.0;
// Initialise the rest of the values with an initial starting value
this->_cmdReceivedBufferIndex = 0;
this->_voltage = 0.0;
this->_temperature = 25.0;
this->_ecvalue = 0.0;
this->_kvalue = 1.0;
}
// Default destructor
DFRobot_EC::~DFRobot_EC()
{
}
// Initialiser
void DFRobot_EC::begin()
{
Serial.print("_pin:");
Serial.println(this->_pin);
Serial.print("mapped:");
Serial.println(mapECPin(this->_pin));
Serial.print("_address:");
Serial.println(this->_address);
// Read the calibrated K value from EEPROM
EEPROM_read(this->_address, this->_kvalueLow);
Serial.print("_kvalueLow:");
Serial.println(this->_kvalueLow);
// If the values are all 255 then write a default value in
if(EEPROM.read(this->_address)==0xFF && EEPROM.read(this->_address+1)==0xFF && EEPROM.read(this->_address+2)==0xFF && EEPROM.read(this->_address+3)==0xFF){
// For new EEPROM, write default value( K = 1.0) to EEPROM
this->_kvalueLow = 1.0;
EEPROM_write(this->_address, this->_kvalueLow);
}
// Read the calibrated K value from EEPRM
EEPROM_read(this->_address+4, this->_kvalueHigh);
Serial.print("_kvalueHigh:");
Serial.println(this->_kvalueHigh);
// If the values are all 255 then write a default value in
if(EEPROM.read(this->_address+4)==0xFF && EEPROM.read(this->_address+5)==0xFF && EEPROM.read(this->_address+6)==0xFF && EEPROM.read(this->_address+7)==0xFF){
// For new EEPROM, write default value( K = 1.0) to EEPROM
this->_kvalueHigh = 1.0;
EEPROM_write(this->_address+4, this->_kvalueHigh);
}
// Set default K value: K = kvalueLow
this->_kvalue = this->_kvalueLow;
}
// Function to read the EC value
float DFRobot_EC::readEC(float voltage, float temperature)
{
float value = 0;
float valueTemp = 0;
this->_rawEC = 1000 * voltage / RES2 / ECREF;
valueTemp = this->_rawEC * this->_kvalue;
// Automatic shift process
// First Range:(0,2); Second Range:(2,20)
if(valueTemp > 2.5){
this->_kvalue = this->_kvalueHigh;
}else if(valueTemp < 2.0){
this->_kvalue = this->_kvalueLow;
}
// Calculate the EC value after automatic shift
value = this->_rawEC * this->_kvalue;
// Temperature compensation
value = value / (1.0+0.0185*(temperature-25.0));
// Store the EC value for Serial CMD calibration
this->_ecvalue = value;
return value;
}
void DFRobot_EC::calibration(float voltage, float temperature,char* cmd)
{
this->_voltage = voltage;
this->_temperature = temperature;
strupr(cmd);
// If received Serial CMD from the serial monitor, enter into the calibration mode
ecCalibration(cmdParse(cmd));
}
void DFRobot_EC::calibration(float voltage, float temperature)
{
this->_voltage = voltage;
this->_temperature = temperature;
// If received Serial CMD from the serial monitor, enter into the calibration mode
if(cmdSerialDataAvailable() > 0)
{
ecCalibration(cmdParse());
}
}
boolean DFRobot_EC::cmdSerialDataAvailable()
{
char cmdReceivedChar;
static unsigned long cmdReceivedTimeOut = millis();
while (Serial.available()>0)
{
if(millis() - cmdReceivedTimeOut > 500U){
this->_cmdReceivedBufferIndex = 0;
memset(this->_cmdReceivedBuffer,0,(ReceivedBufferLength));
}
cmdReceivedTimeOut = millis();
cmdReceivedChar = Serial.read();
if(cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex==ReceivedBufferLength-1){
this->_cmdReceivedBufferIndex = 0;
strupr(this->_cmdReceivedBuffer);
return true;
}else{
this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
this->_cmdReceivedBufferIndex++;
}
}
return false;
}
byte DFRobot_EC::cmdParse(const char* cmd)
{
byte modeIndex = 0;
if(strstr(cmd, "ENTEREC") != NULL){
modeIndex = 1;
}else if(strstr(cmd, "EXITEC") != NULL){
modeIndex = 3;
}else if(strstr(cmd, "CALEC") != NULL){
modeIndex = 2;
}
return modeIndex;
}
byte DFRobot_EC::cmdParse()
{
byte modeIndex = 0;
if(strstr(this->_cmdReceivedBuffer, "ENTEREC") != NULL)
modeIndex = 1;
else if(strstr(this->_cmdReceivedBuffer, "EXITEC") != NULL)
modeIndex = 3;
else if(strstr(this->_cmdReceivedBuffer, "CALEC") != NULL)
modeIndex = 2;
return modeIndex;
}
void DFRobot_EC::ecCalibration(byte mode)
{
char *receivedBufferPtr;
static boolean ecCalibrationFinish = 0;
static boolean enterCalibrationFlag = 0;
static float compECsolution;
float KValueTemp;
switch(mode){
case 0:
if(enterCalibrationFlag){
Serial.println(F(">>>Command Error<<<"));
}
break;
case 1:
enterCalibrationFlag = 1;
ecCalibrationFinish = 0;
Serial.println();
Serial.println(F(">>>Enter EC Calibration Mode<<<"));
Serial.println(F(">>>Please put the probe into the 1413us/cm or 12.88ms/cm buffer solution<<<"));
Serial.println();
break;
case 2:
if(enterCalibrationFlag){
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){ //recognize 1.413us/cm buffer solution
compECsolution = 1.413*(1.0+0.0185*(this->_temperature-25.0)); //temperature compensation
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){ //recognize 12.88ms/cm buffer solution
compECsolution = 12.88*(1.0+0.0185*(this->_temperature-25.0)); //temperature compensation
}else{
Serial.print(F(">>>Buffer Solution Error Try Again<<< "));
ecCalibrationFinish = 0;
}
KValueTemp = RES2*ECREF*compECsolution/1000.0/this->_voltage; //calibrate the k value
if((KValueTemp>0.5) && (KValueTemp<1.5)){
Serial.println();
Serial.print(F(">>>Successful,K:"));
Serial.print(KValueTemp);
Serial.println(F(", Send EXITEC to Save and Exit<<<"));
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){
this->_kvalueLow = KValueTemp;
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){
this->_kvalueHigh = KValueTemp;
}
ecCalibrationFinish = 1;
}
else{
Serial.println();
Serial.println(F(">>>Failed,Try Again<<<"));
Serial.println();
ecCalibrationFinish = 0;
}
}
break;
case 3:
if(enterCalibrationFlag){
Serial.println();
if(ecCalibrationFinish){
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){
EEPROM_write(this->_address, this->_kvalueLow);
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){
EEPROM_write(this->_address+4, this->_kvalueHigh);
}
Serial.print(F(">>>Calibration Successful"));
}else{
Serial.print(F(">>>Calibration Failed"));
}
Serial.println(F(",Exit EC Calibration Mode<<<"));
Serial.println();
ecCalibrationFinish = 0;
enterCalibrationFlag = 0;
}
break;
}
}