Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 156 additions & 24 deletions DFRobot_EC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
*
* version V1.01
* date 2018-06
*
* version V1.1
* date 2020-04
* Changes the memory addressing to allow multiple EC sensors
*/


Expand All @@ -21,60 +25,185 @@
#include "DFRobot_EC.h"
#include <EEPROM.h>

#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}
#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 KVALUEADDR 0x0A //the start address of the K value stored in the EEPROM
#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()
{
EEPROM_read(KVALUEADDR, this->_kvalueLow); //read the calibrated K value from EEPROM
if(EEPROM.read(KVALUEADDR)==0xFF && EEPROM.read(KVALUEADDR+1)==0xFF && EEPROM.read(KVALUEADDR+2)==0xFF && EEPROM.read(KVALUEADDR+3)==0xFF){
this->_kvalueLow = 1.0; // For new EEPROM, write default value( K = 1.0) to EEPROM
EEPROM_write(KVALUEADDR, this->_kvalueLow);
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);
}
EEPROM_read(KVALUEADDR+4, this->_kvalueHigh); //read the calibrated K value from EEPRM
if(EEPROM.read(KVALUEADDR+4)==0xFF && EEPROM.read(KVALUEADDR+5)==0xFF && EEPROM.read(KVALUEADDR+6)==0xFF && EEPROM.read(KVALUEADDR+7)==0xFF){
this->_kvalueHigh = 1.0; // For new EEPROM, write default value( K = 1.0) to EEPROM
EEPROM_write(KVALUEADDR+4, this->_kvalueHigh);

// 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);
}
this->_kvalue = this->_kvalueLow; // set default K value: K = kvalueLow

// 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,valueTemp = 0;
this->_rawEC = 1000*voltage/RES2/ECREF;
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)

// 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;
}

value = this->_rawEC * this->_kvalue; //calculate the EC value after automatic shift
value = value / (1.0+0.0185*(temperature-25.0)); //temperature compensation
this->_ecvalue = value; //store the EC value for Serial CMD calibration
// 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;
}

Expand All @@ -83,17 +212,20 @@ void DFRobot_EC::calibration(float voltage, float temperature,char* cmd)
this->_voltage = voltage;
this->_temperature = temperature;
strupr(cmd);
ecCalibration(cmdParse(cmd)); //if received Serial CMD from the serial monitor, enter into the calibration mode

// 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()); // if received Serial CMD from the serial monitor, enter into the calibration mode
ecCalibration(cmdParse());
}
}

Expand Down Expand Up @@ -203,9 +335,9 @@ void DFRobot_EC::ecCalibration(byte mode)
Serial.println();
if(ecCalibrationFinish){
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){
EEPROM_write(KVALUEADDR, this->_kvalueLow);
EEPROM_write(this->_address, this->_kvalueLow);
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){
EEPROM_write(KVALUEADDR+4, this->_kvalueHigh);
EEPROM_write(this->_address+4, this->_kvalueHigh);
}
Serial.print(F(">>>Calibration Successful"));
}else{
Expand Down
42 changes: 35 additions & 7 deletions DFRobot_EC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
*
* version V1.01
* date 2018-06
*
* version V1.1
* date 2020-04
* Changes the memory addressing to allow multiple EC sensors
*/

#ifndef _DFROBOT_EC_H_
Expand All @@ -19,19 +23,39 @@
#include "WProgram.h"
#endif

#define ReceivedBufferLength 10 //length of the Serial CMD buffer
// Length of the Serial CMD buffer
#define ReceivedBufferLength 10

/**
* Maps the pin (A0,A1..A11) to a number 0-11 so the address can be determined
* @param ecPin the pin the EC sensor is attached to
* @return the address multiplier
*/
uint8_t mapECPin(uint8_t ecPin);

class DFRobot_EC
{
public:
// Construtors
DFRobot_EC();
DFRobot_EC(int ecPin);

// Destructors
~DFRobot_EC();
void calibration(float voltage, float temperature,char* cmd); //calibration by Serial CMD
void calibration(float voltage, float temperature); //calibration by Serial CMD
float readEC(float voltage, float temperature); // voltage to EC value, with temperature compensation
void begin(); //initialization

// Initialization
void begin();

// Calibration by Serial CMD
void calibration(float voltage, float temperature, char* cmd);
void calibration(float voltage, float temperature);

// Voltage to EC value with temperature compensation
float readEC(float voltage, float temperature);

private:
int _pin;
int _address;
float _ecvalue;
float _kvalue;
float _kvalueLow;
Expand All @@ -40,12 +64,16 @@ class DFRobot_EC
float _temperature;
float _rawEC;

char _cmdReceivedBuffer[ReceivedBufferLength]; //store the Serial CMD
// Store the Serial CMD
char _cmdReceivedBuffer[ReceivedBufferLength];
byte _cmdReceivedBufferIndex;

private:
// Calibration process, wirte key parameters to EEPROM
void ecCalibration(byte mode);

boolean cmdSerialDataAvailable();
void ecCalibration(byte mode); // calibration process, wirte key parameters to EEPROM

byte cmdParse(const char* cmd);
byte cmdParse();
};
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ This is the sample code for Gravity: Analog Electrical Conductivity Sensor / Met
## Methods

```C++
/*
* @brief The new optional constructor to allow multiple EC sensors
*
* @param ecPin: The pin of the EC sensor i.e. A0
*/
DFRobot_EC(int ecPin);

/*
* @brief Init The Analog Electrical Conductivity Sensor
Expand Down Expand Up @@ -54,6 +60,9 @@ Meag2560 | √ | | |

- date 2018-11-6
- version V1.0
- date 2020-04-18
- version V1.1
- Update to allow multiple EC sensors each with their own calibration

## Credits

Expand Down