From 32e1eda2e80b7115c18c7402c9b09f83112f53ed Mon Sep 17 00:00:00 2001 From: Atlas-Scientific <20248527+Atlas-Scientific@users.noreply.github.com> Date: Thu, 19 Sep 2019 17:13:01 -0400 Subject: [PATCH] Minor (breaking) method name changes in the API, more comments and more descriptive names in sample code --- .../I2c_read_mulitple_circuits.ino | 52 +++--- .../pH_EC_led_indicator.ino | 57 ++++--- Examples/pH_dosing_pump/pH_dosing_pump.ino | 56 +++--- .../temp_comp_example/temp_comp_example.ino | 144 +++++++++------- .../temp_comp_rt_example.ino | 145 +++++++++------- .../thingspeak_example/thingspeak_example.ino | 161 ++++++++++++++++++ Ezo_i2c.cpp | 6 +- Ezo_i2c.h | 6 +- README.md | 6 +- 9 files changed, 423 insertions(+), 210 deletions(-) create mode 100644 Examples/thingspeak_example/thingspeak_example.ino diff --git a/Examples/I2c_read_mulitple_circuits/I2c_read_mulitple_circuits.ino b/Examples/I2c_read_mulitple_circuits/I2c_read_mulitple_circuits.ino index 35212dc..4be4bd9 100644 --- a/Examples/I2c_read_mulitple_circuits/I2c_read_mulitple_circuits.ino +++ b/Examples/I2c_read_mulitple_circuits/I2c_read_mulitple_circuits.ino @@ -14,38 +14,15 @@ void setup() { Serial.begin(9600); //start the serial communication to the computer } -void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued - - Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading - - Sensor.receive_read(); //get the response data and put it into the [Sensor].reading variable if successful - - switch (Sensor.get_error()) { //switch case based on what the response code is. - case Ezo_board::SUCCESS: - Serial.print(Sensor.get_reading()); //the command was successful, print the reading - break; - - case Ezo_board::FAIL: - Serial.print("Failed "); //means the command has failed. - break; - case Ezo_board::NOT_READY: - Serial.print("Pending "); //the command has not yet been finished calculating. - break; - - case Ezo_board::NO_DATA: - Serial.print("No Data "); //the sensor has no data to send. - break; - } -} void loop() { if (reading_request_phase) { //if were in the phase where we ask for a reading //send a read command. we use this command instead of PH.send_cmd("R"); //to let the library know to parse the reading - PH.send_read(); - EC.send_read(); + PH.send_read_cmd(); + EC.send_read_cmd(); next_poll_time = millis() + response_delay; //set when the response will arrive reading_request_phase = false; //switch to the receiving phase @@ -62,3 +39,28 @@ void loop() { } } } + +void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued + + Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading + + Sensor.receive_read_cmd(); //get the response data and put it into the [Sensor].reading variable if successful + + switch (Sensor.get_error()) { //switch case based on what the response code is. + case Ezo_board::SUCCESS: + Serial.print(Sensor.get_last_received_reading()); //the command was successful, print the reading + break; + + case Ezo_board::FAIL: + Serial.print("Failed "); //means the command has failed. + break; + + case Ezo_board::NOT_READY: + Serial.print("Pending "); //the command has not yet been finished calculating. + break; + + case Ezo_board::NO_DATA: + Serial.print("No Data "); //the sensor has no data to send. + break; + } +} \ No newline at end of file diff --git a/Examples/pH_EC_led_indicator/pH_EC_led_indicator.ino b/Examples/pH_EC_led_indicator/pH_EC_led_indicator.ino index ed17a79..e5e47fb 100644 --- a/Examples/pH_EC_led_indicator/pH_EC_led_indicator.ino +++ b/Examples/pH_EC_led_indicator/pH_EC_led_indicator.ino @@ -28,38 +28,14 @@ void setup() { pinMode(EC_led, OUTPUT); //set pin for EC led as output } -void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued - - Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading - - Sensor.receive_read(); //get the response data and put it into the [Sensor].reading variable if successful - - switch (Sensor.get_error()) { //switch case based on what the response code is. - case Ezo_board::SUCCESS: - Serial.print(Sensor.get_reading()); //the command was successful, print the reading - break; - - case Ezo_board::FAIL: - Serial.print("Failed "); //means the command has failed. - break; - - case Ezo_board::NOT_READY: - Serial.print("Pending "); //the command has not yet been finished calculating. - break; - - case Ezo_board::NO_DATA: - Serial.print("No Data "); //the sensor has no data to send. - break; - } -} void loop() { if (reading_request_phase) { //if were in the phase where we ask for a reading //send a read command. we use this command instead of PH.send_cmd("R"); //to let the library know to parse the reading - PH.send_read(); - EC.send_read(); + PH.send_read_cmd(); + EC.send_read_cmd(); next_poll_time = millis() + response_delay; //set when the response will arrive reading_request_phase = false; //switch to the receiving phase @@ -68,7 +44,7 @@ void loop() { if (millis() >= next_poll_time) { //and its time to get the response receive_reading(PH); //get the reading from the PH circuit - if(PH.get_reading() > 10) { //test condition against pH reading + if(PH.get_last_received_reading() > 10) { //test condition against pH reading digitalWrite(PH_led,HIGH); //if condition true, led on } else{ @@ -77,7 +53,7 @@ void loop() { Serial.print(" "); receive_reading(EC); //get the reading from the EC circuit - if (EC.get_reading() > 500.00) { //test condition against EC reading + if (EC.get_last_received_reading() > 500.00) { //test condition against EC reading digitalWrite(EC_led,HIGH); //if condition true, led on } else{ @@ -90,3 +66,28 @@ void loop() { } } +void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued + + Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading + + Sensor.receive_read_cmd(); //get the response data and put it into the [Sensor].reading variable if successful + + switch (Sensor.get_error()) { //switch case based on what the response code is. + case Ezo_board::SUCCESS: + Serial.print(Sensor.get_last_received_reading()); //the command was successful, print the reading + break; + + case Ezo_board::FAIL: + Serial.print("Failed "); //means the command has failed. + break; + + case Ezo_board::NOT_READY: + Serial.print("Pending "); //the command has not yet been finished calculating. + break; + + case Ezo_board::NO_DATA: + Serial.print("No Data "); //the sensor has no data to send. + break; + } +} + diff --git a/Examples/pH_dosing_pump/pH_dosing_pump.ino b/Examples/pH_dosing_pump/pH_dosing_pump.ino index d4966c0..a0e2697 100644 --- a/Examples/pH_dosing_pump/pH_dosing_pump.ino +++ b/Examples/pH_dosing_pump/pH_dosing_pump.ino @@ -24,37 +24,12 @@ void setup() { Serial.begin(9600); //start the serial communication to the computer } -void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued - - Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading - - Sensor.receive_read(); //get the response data and put it into the [Sensor].reading variable if successful - - switch (Sensor.get_error()) { //switch case based on what the response code is. - case Ezo_board::SUCCESS: - Serial.print(Sensor.get_reading()); //the command was successful, print the reading - break; - - case Ezo_board::FAIL: - Serial.print("Failed "); //means the command has failed. - break; - - case Ezo_board::NOT_READY: - Serial.print("Pending "); //the command has not yet been finished calculating. - break; - - case Ezo_board::NO_DATA: - Serial.print("No Data "); //the sensor has no data to send. - break; - } -} - void loop() { if (reading_request_phase) { //if were in the phase where we ask for a reading //send a read command. we use this command instead of PH.send_cmd("R"); //to let the library know to parse the reading - PH.send_read(); + PH.send_read_cmd(); next_poll_time = millis() + response_delay; //set when the response will arrive reading_request_phase = false; //switch to the receiving phase @@ -66,7 +41,7 @@ void loop() { Serial.print(" "); - if (PH.get_reading() <= 8) { //test condition against pH reading + if (PH.get_last_received_reading() <= 8) { //test condition against pH reading Serial.println("PH LEVEL LOW,PMP_UP = ON"); PMP_UP.send_cmd_with_num("d,", 0.5); //if condition is true, send command to turn on pump (called PMP_UP) and dispense pH up solution, in amounts of 0.5ml. Pump turns clockwise. } @@ -74,7 +49,7 @@ void loop() { PMP_UP.send_cmd("x"); //if condition is false, send command to turn off pump (called PMP_UP) } - if (PH.get_reading() >= 8.5) { //test condition against pH reading + if (PH.get_last_received_reading() >= 8.5) { //test condition against pH reading Serial.println("PH LEVEL HIGH,PMP_DOWN = ON"); PMP_DOWN.send_cmd_with_num("d,", -0.5); //if condition is true, send command to turn on pump (called PMP_DOWN) and dispense pH down solution, in amounts of 0.5ml. Pump turns counter-clockwise. } @@ -87,3 +62,28 @@ void loop() { } } } + +void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued + + Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading + + Sensor.receive_read_cmd(); //get the response data and put it into the [Sensor].reading variable if successful + + switch (Sensor.get_error()) { //switch case based on what the response code is. + case Ezo_board::SUCCESS: + Serial.print(Sensor.get_last_received_reading()); //the command was successful, print the reading + break; + + case Ezo_board::FAIL: + Serial.print("Failed "); //means the command has failed. + break; + + case Ezo_board::NOT_READY: + Serial.print("Pending "); //the command has not yet been finished calculating. + break; + + case Ezo_board::NO_DATA: + Serial.print("No Data "); //the sensor has no data to send. + break; + } +} \ No newline at end of file diff --git a/Examples/temp_comp_example/temp_comp_example.ino b/Examples/temp_comp_example/temp_comp_example.ino index f28f6f4..2cf95b9 100644 --- a/Examples/temp_comp_example/temp_comp_example.ino +++ b/Examples/temp_comp_example/temp_comp_example.ino @@ -1,83 +1,107 @@ -#include //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib -#include //include arduinos i2c library +#include //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib +#include //include Arduinos i2c library +Ezo_board EC = Ezo_board(100, "EC"); //create a EC circuit object, who's I2C address is 100 and name is "EC" +Ezo_board RTD = Ezo_board(102, "RTD"); //create an RTD circuit object who's I2C address is 102 and name is "RTD" -Ezo_board EC = Ezo_board(100, "EC"); //create a EC circuit object, who's address is 100 and name is "EC" -Ezo_board RTD = Ezo_board(102, "RTD"); //create an RTD circuit object who's address is 102 and name is "RTD" +enum reading_step {REQUEST_TEMP, READ_TEMP_AND_COMPENSATE, REQUEST_EC, READ_RESPONSE }; //the readings are taken in 3 steps + //step 1 tell the temp sensor to take a reading + //step 2 consume the temp reading and send it to EC + //step 4 tell the EC to take a reading based on the temp reading we just received + //step 3 consume the EC readings -enum polling_phase {SEND_TEMP, REQUEST, RESPONSE }; -enum polling_phase reading_phase = SEND_TEMP; //selects our phase +enum reading_step current_step = REQUEST_TEMP; //the current step keeps track of where we are. lets set it to REQUEST_TEMP (step 1) on startup -uint32_t next_poll_time = 0; //holds the next time we receive a response, in milliseconds -const unsigned int response_delay = 1000; //how long we wait to receive a response, in milliseconds +unsigned long next_step_time = 0; //holds the time in milliseconds. this is used so we know when to move between the 3 steps +const unsigned long reading_delay = 815; //how long we wait to receive a response, in milliseconds const unsigned int temp_delay = 300; - -float ec; //used to hold floating point number that is ec -float temp; //used to hold floating point number that is temperature +const unsigned int loop_delay = 5000; void setup() { Wire.begin(); //start the I2C Serial.begin(9600); //start the serial communication to the computer } -void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued - - Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading - - Sensor.receive_read(); //get the response data and put it into the [Sensor].reading variable if successful - - switch (Sensor.get_error()) { //switch case based on what the response code is. - case Ezo_board::SUCCESS: - /* //uncomment this section for access to sensor readings - if (Sensor.get_name()=="EC"){ec = Sensor.get_reading();} //the EC readings are now stored in a float - if (Sensor.get_name()=="RTD"){temp = Sensor.get_reading();} //the temperature readings are now stored in a float - */ - Serial.print(Sensor.get_reading(), 3); //the command was successful, print the reading +void loop() { + switch(current_step) { //selects what to do based on what reading_step we are in +//------------------------------------------------------------------ + + case REQUEST_TEMP: //when we are in the first step + if (millis() >= next_step_time) { //check to see if enough time has past, if it has + RTD.send_read_cmd(); + next_step_time = millis() + reading_delay; //set when the response will arrive + current_step = READ_TEMP_AND_COMPENSATE; //switch to the receiving phase + } break; +//------------------------------------------------------------------ + case READ_TEMP_AND_COMPENSATE: + if (millis() >= next_step_time) { + + RTD.receive_read_cmd(); //get the temp reading + Serial.print(RTD.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if ((reading_succeeded(RTD) == true) && (RTD.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid + EC.send_cmd_with_num("T,", RTD.get_last_received_reading()); + } else { //if the temperature reading is invalid + EC.send_cmd_with_num("T,", 25.0); //send default temp = 25 deg C to EC sensor + } - case Ezo_board::FAIL: - Serial.print("Failed "); //means the command has failed. + if(RTD.get_error() == Ezo_board::SUCCESS){ //if the RTD reading was successful + Serial.print(RTD.get_last_received_reading(), 1); //print the reading (with 1 decimal places) + } + + Serial.print(" "); + next_step_time = millis() + temp_delay; //set when the response will arrive + current_step = REQUEST_EC; //switch to the receiving phase + } break; - - case Ezo_board::NOT_READY: - Serial.print("Pending "); //the command has not yet been finished calculating. + + case REQUEST_EC: + if (millis() >= next_step_time) { + EC.send_read_cmd(); + next_step_time = millis() + reading_delay; //advance the next step time by adding the delay we need for the sensor to take the reading + current_step = READ_RESPONSE; //switch to the next step + } break; +//------------------------------------------------------------------ + + case READ_RESPONSE: //if were in the receiving phase + if (millis() >= next_step_time) { //and its time to get the response + Serial.print(" "); + + EC.receive_read_cmd(); //get the EC reading + Serial.print(EC.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if(reading_succeeded(EC) == true){ //if the EC reading has been received and it is valid + Serial.print(EC.get_last_received_reading(), 0); //print the reading (with 0 decimal places) + } - case Ezo_board::NO_DATA: - Serial.print("No Data "); //the sensor has no data to send. + Serial.println(); + next_step_time = millis() + loop_delay; //update the time for the next reading loop + current_step = REQUEST_TEMP; //switch back to asking for readings + } break; } } -void loop() { - switch (reading_phase) { //if were in the phase where we ask for a reading - case SEND_TEMP: - if((RTD.get_error() == Ezo_board::SUCCESS) && (RTD.get_reading() > -1000.0)){ - EC.send_cmd_with_num("T,", RTD.get_reading()); - }else{ - EC.send_cmd_with_num("T,", 25.0); - } - next_poll_time = millis() + temp_delay; //set when the response will arrive - reading_phase = REQUEST; //switch to the receiving phase +bool reading_succeeded(Ezo_board &Sensor) { //this function makes sure that when we get a reading we know if it was valid or if we got an error + + switch (Sensor.get_error()) { //switch case based on what the response code was + case Ezo_board::SUCCESS: //if the reading was a success + return true; //return true, the reading succeeded - break; + case Ezo_board::FAIL: //if the reading faild + Serial.print("Failed "); //print "failed" + return false; //return false, the reading was not successful - case REQUEST: - if (millis() >= next_poll_time) { - EC.send_read(); - RTD.send_read(); - next_poll_time = millis() + response_delay; //set when the response will arrive - reading_phase = RESPONSE; //switch to the receiving phase - } - break; + case Ezo_board::NOT_READY: //if the reading was taken to early, the command has not yet finished calculating + Serial.print("Pending "); //print "Pending" + return false; //return false, the reading was not successful - case RESPONSE: //if were in the receiving phase - if (millis() >= next_poll_time) { //and its time to get the response - receive_reading(EC); //get the reading from the EC circuit - Serial.print(" "); - receive_reading(RTD); //get the reading from the RTD circuit - Serial.println(); - reading_phase = SEND_TEMP; //switch back to asking for readings - } - break; + case Ezo_board::NO_DATA: //the sensor has no data to send + Serial.print("No Data "); //print "no data" + return false; //return false, the reading was not successful + + default: //if none of the above happened + return false; //return false, the reading was not successful } -} +} \ No newline at end of file diff --git a/Examples/temp_comp_rt_example/temp_comp_rt_example.ino b/Examples/temp_comp_rt_example/temp_comp_rt_example.ino index 3ff60c4..a0fe9af 100644 --- a/Examples/temp_comp_rt_example/temp_comp_rt_example.ino +++ b/Examples/temp_comp_rt_example/temp_comp_rt_example.ino @@ -1,75 +1,100 @@ -#include //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib -#include //include arduinos i2c library +#include //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib +#include //include Arduinos i2c library +Ezo_board EC = Ezo_board(100, "EC"); //create a EC circuit object, who's I2C address is 100 and name is "EC" +Ezo_board RTD = Ezo_board(102, "RTD"); //create an RTD circuit object who's I2C address is 102 and name is "RTD" -Ezo_board EC = Ezo_board(100, "EC"); //create a EC circuit object, who's address is 100 and name is "EC" -Ezo_board RTD = Ezo_board(102, "RTD"); //create an RTD circuit object who's address is 102 and name is "RTD" +enum reading_step {REQUEST_TEMP, READ_TEMP_AND_REQUEST, READ_RESPONSE }; //the readings are taken in 3 steps + //step 1 tell the temp sensor to take a reading + //step 2 consume the temp reading and tell the EC to take a reading based on the temp reading we just received + //step 3 consume the EC readings -bool reading_request_phase = true; //selects our phase +enum reading_step current_step = REQUEST_TEMP; //the current step keeps track of where we are. lets set it to REQUEST_TEMP (step 1) on startup -uint32_t next_poll_time = 0; //holds the next time we receive a response, in milliseconds -const unsigned int response_delay = 1000; //how long we wait to receive a response, in milliseconds - -float ec; //used to hold floating point number that is ec -float temp; //used to hold floating point number that is temperature +unsigned long next_step_time = 0; //holds the time in milliseconds. this is used so we know when to move between the 3 steps +const unsigned long reading_delay = 815; //how long we wait to receive a response, in milliseconds +const unsigned int temp_delay = 300; +const unsigned int loop_delay = 5000; void setup() { Wire.begin(); //start the I2C - Serial.begin(9600); //start the serial communication to the computer + Serial.begin(9600); //start the serial communication to the computer } -void receive_reading(Ezo_board &Sensor) { // function to decode the reading after the read command was issued - - Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of the circuit getting the reading - - Sensor.receive_read(); //get the response data and put it into the [Sensor].reading variable if successful - - switch (Sensor.get_error()) { //switch case based on what the response code is. - case Ezo_board::SUCCESS: - /* //uncomment this section for access to sensor readings - if (Sensor.get_name()=="EC"){ec = Sensor.get_reading();} //the EC readings are now stored in a float - if (Sensor.get_name()=="RTD"){temp = Sensor.get_reading();} //the temperature readings are now stored in a float - */ - Serial.print(Sensor.get_reading(), 3); //the command was successful, print the reading - break; - - case Ezo_board::FAIL: - Serial.print("Failed "); //means the command has failed. +void loop() { + switch(current_step) { //selects what to do based on what reading_step we are in +//------------------------------------------------------------------ + + case REQUEST_TEMP: //when we are in the first step + if (millis() >= next_step_time) { //check to see if enough time has past, if it has + RTD.send_read_cmd(); + next_step_time = millis() + reading_delay; //set when the response will arrive + current_step = READ_TEMP_AND_REQUEST; //switch to the receiving phase + } break; - - case Ezo_board::NOT_READY: - Serial.print("Pending "); //the command has not yet been finished calculating. +//------------------------------------------------------------------ + + case READ_TEMP_AND_REQUEST: + if (millis() >= next_step_time) { + + RTD.receive_read_cmd(); //get the temp reading + Serial.print(RTD.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if ((reading_succeeded(RTD) == true) && (RTD.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid + EC.send_read_with_temp_comp(RTD.get_last_received_reading()); //send readings from temp sensor to EC sensor + } else { //if the temperature reading is invalid + EC.send_read_with_temp_comp(25.0); //send default temp = 25 deg C to EC sensor + } + + if(RTD.get_error() == Ezo_board::SUCCESS){ //if the RTD reading was successful + Serial.print(RTD.get_last_received_reading(), 1); //print the reading (with 1 decimal places) + } + + Serial.print(" "); //print a blank space so the output string on the serial monitor is easy to read + + next_step_time = millis() + reading_delay; //advance the next step time by adding the delay we need for the sensor to take the reading + current_step = READ_RESPONSE; //switch to the next step + } break; - - case Ezo_board::NO_DATA: - Serial.print("No Data "); //the sensor has no data to send. +//------------------------------------------------------------------ + + case READ_RESPONSE: //if were in the receiving phase + if (millis() >= next_step_time) { //and its time to get the response + Serial.print(" "); + + EC.receive_read_cmd(); //get the EC reading + Serial.print(EC.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if(reading_succeeded(EC) == true){ //if the EC reading has been received and it is valid + Serial.print(EC.get_last_received_reading(), 0); //print the reading (with 0 decimal places) + } + + Serial.println(); + next_step_time = millis() + loop_delay; //update the time for the next reading loop + current_step = REQUEST_TEMP; //switch back to asking for readings + } break; } } -void loop() { - if (reading_request_phase) { //if were in the phase where we ask for a reading - - //send a read command. we use this command instead of EC.send_cmd("R"); - //to let the library know to parse the reading - if((RTD.get_error() == Ezo_board::SUCCESS) && (RTD.get_reading() > -1000.0)){ - EC.send_read_with_temp_comp(RTD.get_reading()); - }else{ - EC.send_read_with_temp_comp(25.0); - } - RTD.send_read(); - - next_poll_time = millis() + response_delay; //set when the response will arrive - reading_request_phase = false; //switch to the receiving phase +bool reading_succeeded(Ezo_board &Sensor) { //this function makes sure that when we get a reading we know if it was valid or if we got an error + + switch (Sensor.get_error()) { //switch case based on what the response code was + case Ezo_board::SUCCESS: //if the reading was a success + return true; //return true, the reading succeeded + + case Ezo_board::FAIL: //if the reading faild + Serial.print("Failed "); //print "failed" + return false; //return false, the reading was not successful + + case Ezo_board::NOT_READY: //if the reading was taken to early, the command has not yet finished calculating + Serial.print("Pending "); //print "Pending" + return false; //return false, the reading was not successful + + case Ezo_board::NO_DATA: //the sensor has no data to send + Serial.print("No Data "); //print "no data" + return false; //return false, the reading was not successful + + default: //if none of the above happened + return false; //return false, the reading was not successful } - else { //if were in the receiving phase - if (millis() >= next_poll_time) { //and its time to get the response - - receive_reading(EC); //get the reading from the PH circuit - Serial.print(" "); - receive_reading(RTD); //get the reading from the RTD circuit - Serial.println(); - - reading_request_phase = true; //switch back to asking for readings - } - } -} +} \ No newline at end of file diff --git a/Examples/thingspeak_example/thingspeak_example.ino b/Examples/thingspeak_example/thingspeak_example.ino new file mode 100644 index 0000000..bbfb189 --- /dev/null +++ b/Examples/thingspeak_example/thingspeak_example.ino @@ -0,0 +1,161 @@ + +#include //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib +#include //include Arduinos i2c library +#include //include esp8266 wifi library +#include "ThingSpeak.h" //include thingspeak library +WiFiClient client; //declare that this device connects to a Wi-Fi network,create a connection to a specified internet IP address + + +//----------------Fill in your Wi-Fi / ThingSpeak Credentials------- +const String ssid = "Wifi Name"; //The name of the Wi-Fi network you are connecting to +const String pass = "Wifi Password"; //Your WiFi network password +const long myChannelNumber = NNNNNNN; //Your Thingspeak channel number +const char * myWriteAPIKey = "XXXXXXXXXXXXXXXX"; //Your ThingSpeak Write API Key +//------------------------------------------------------------------ + +Ezo_board PH = Ezo_board(99, "PH"); //create a pH circuit object, who's I2C address is 99 and name is "PH" +Ezo_board EC = Ezo_board(100, "EC"); //create a EC circuit object, who's I2C address is 100 and name is "EC" +Ezo_board RTD = Ezo_board(102, "RTD"); //create an RTD circuit object who's I2C address is 102 and name is "RTD" + + +enum reading_step {REQUEST_TEMP, READ_TEMP_AND_REQUEST_PH_EC, READ_PH_EC }; //the readings are taken in 3 steps + //step 1 tell the temp sensor to take a reading + //step 2 consume the temp reading and tell the ph and EC to take a reading based on the temp reading we just received + //step 3 consume the ph and EC readings + +enum reading_step current_step = REQUEST_TEMP; //the current step keeps track of where we are. lets set it to REQUEST_TEMP (step 1) on startup + +int return_code=0; //holds the return code sent back from thingSpeak after we upload the data +unsigned long next_step_time = 0; //holds the time in milliseconds. this is used so we know when to move between the 3 steps + +const unsigned long reading_delay = 815; //how long we wait to receive a response, in milliseconds +const unsigned long loop_delay = 15000; + + +void setup() { //set up the hardware + Wire.begin(); //enable I2C port + Serial.begin(9600); //enable serial port, set baud rate to 9600 + WiFi.mode(WIFI_STA); //set ESP8266 mode as a station to be connected to wifi network + ThingSpeak.begin(client); //enable ThingSpeak connection +} + + +void loop() { + //connect or reconnect to WiFi + if (WiFi.status() != WL_CONNECTED) { //if we are not connected (when WL_CONNECTED =1 we have a successful connection) + WiFi.begin(ssid, pass); //initialize wifi connection + + while (WiFi.status() != WL_CONNECTED) { //while we are not connected + Serial.print("."); //print "........connected" + delay(50); //a single dont is printed every 50 ms + } + Serial.println("connected"); //once connected print "connected" + } + + switch(current_step) { //selects what to do based on what reading_step we are in +//------------------------------------------------------------------ + + case REQUEST_TEMP: //when we are in the first step + if (millis() >= next_step_time) { //check to see if enough time has past, if it has + RTD.send_read_cmd(); //request a temp reading + next_step_time = millis() + reading_delay; //advance the next step time by adding the delay we need for the sensor to take the reading + current_step = READ_TEMP_AND_REQUEST_PH_EC; //switch to step 2 + } + break; //break out of this we are done +//------------------------------------------------------------------ + + case READ_TEMP_AND_REQUEST_PH_EC: //when we are in the second step + if (millis() >= next_step_time) { //check to see if enough time has past, if it has + + RTD.receive_read_cmd(); //get the temp reading + Serial.print(RTD.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if((reading_succeeded(RTD) == true) && (RTD.get_last_received_reading() > -1000.0)){ //if the temperature reading has been received and it is valid + PH.send_read_with_temp_comp(RTD.get_last_received_reading()); //send readings from temp sensor to pH sensor + EC.send_read_with_temp_comp(RTD.get_last_received_reading()); //send readings from temp sensor to EC sensor + } + else //if the temperature reading is invalid + { + PH.send_read_with_temp_comp(25.0); //send default temp = 25 deg C to pH sensor + EC.send_read_with_temp_comp(25.0); //send default temp = 25 deg C to EC sensor + } + + if(RTD.get_error() == Ezo_board::SUCCESS){ //if the RTD reading was successful + Serial.print(RTD.get_last_received_reading(), 1); //print the reading (with 1 decimal places) + } + + Serial.print(" "); //print a blank space so the output string on the serial monitor is easy to read + + next_step_time = millis() + reading_delay; //advance the next step time by adding the delay we need for the sensor to take the reading + current_step = READ_PH_EC; //switch to step 3 + } + break; //break out of this we are done +//------------------------------------------------------------------ + + case READ_PH_EC: //when we are in the third step + if (millis() >= next_step_time) { //check to see if enough time has past, if it has + + PH.receive_read_cmd(); //get the PH reading + Serial.print(PH.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if(reading_succeeded(PH) == true){ //if the pH reading has been received and it is valid + Serial.print(PH.get_last_received_reading(), 2); //print the reading (with 2 decimal places) + ThingSpeak.setField(1, String(PH.get_last_received_reading(), 2)); //assign pH readings to first column of thingspeak channel + } + + Serial.print(" "); //print a blank space so the output string on the serial monitor is easy to read + + EC.receive_read_cmd(); //get the EC reading + Serial.print(EC.get_name()); Serial.print(": "); //print the name of the circuit we just got a reading from + + if(reading_succeeded(EC) == true){ //if the EC reading has been received and it is valid + Serial.print(EC.get_last_received_reading(), 0); //print the reading (with 0 decimal places) + ThingSpeak.setField(2, String(EC.get_last_received_reading(),0)); //assign EC readings to the second column of thingspeak channel + } + + Serial.println(); //print a new line so the output string on the serial monitor is easy to read + + if(RTD.get_error() == Ezo_board::SUCCESS){ //if the RTD reading was successful (back in step 1) + ThingSpeak.setField(3, String(RTD.get_last_received_reading(),1)); //assign temperature readings to the third column of thingspeak channel + } + + return_code = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey); //upload the data to thingspeak, read the return code + + if (return_code == 200) { //check thingspeak return code if it is 200 then the upload was a success + Serial.println("success"); //print "success" + } + else { //if the thingspeak return code was not 200 + Serial.println("upload error, code: " + String(return_code)); //print "upload error, code:" and whatever number is in the return_code var + } + Serial.println(); //print a new line so the output string on the serial monitor is easy to read + next_step_time = millis() + loop_delay; //update the time for the next reading loop + current_step = REQUEST_TEMP; //switch back to step 1 + } + break; //break out of this we are done + } +//------------------------------------------------------------------ +} + + +bool reading_succeeded(Ezo_board &Sensor) { //this function makes sure that when we get a reading we know if it was valid or if we got an error + + switch (Sensor.get_error()) { //switch case based on what the response code was + case Ezo_board::SUCCESS: //if the reading was a success + return true; //return true, the reading succeeded + + case Ezo_board::FAIL: //if the reading faild + Serial.print("Failed "); //print "failed" + return false; //return false, the reading was not successful + + case Ezo_board::NOT_READY: //if the reading was taken to early, the command has not yet finished calculating + Serial.print("Pending "); //print "Pending" + return false; //return false, the reading was not successful + + case Ezo_board::NO_DATA: //the sensor has no data to send + Serial.print("No Data "); //print "no data" + return false; //return false, the reading was not successful + + default: //if none of the above happened + return false; //return false, the reading was not successful + } +} diff --git a/Ezo_i2c.cpp b/Ezo_i2c.cpp index e46050f..6288c4c 100644 --- a/Ezo_i2c.cpp +++ b/Ezo_i2c.cpp @@ -24,7 +24,7 @@ void Ezo_board::send_cmd(const char* command) { this->issued_read = false; } -void Ezo_board::send_read(){ +void Ezo_board::send_read_cmd(){ send_cmd("r"); this->issued_read = true; } @@ -41,7 +41,7 @@ void Ezo_board::send_read_with_temp_comp(float temperature){ } -enum Ezo_board::errors Ezo_board::receive_read(){ +enum Ezo_board::errors Ezo_board::receive_read_cmd(){ char _sensordata[this->bufferlen]; this->error = receive_cmd(_sensordata, bufferlen); @@ -61,7 +61,7 @@ bool Ezo_board::is_read_poll(){ return this->issued_read; } -float Ezo_board::get_reading(){ +float Ezo_board:: get_last_received_reading(){ return this->reading; } diff --git a/Ezo_i2c.h b/Ezo_i2c.h index f3fe061..6fdb022 100644 --- a/Ezo_i2c.h +++ b/Ezo_i2c.h @@ -45,7 +45,7 @@ class Ezo_board{ void send_cmd(const char* command); //send any command in a string, see the devices datasheet for available i2c commands - void send_read(); + void send_read_cmd(); //sends the "R" command to the device and sets issued_read() to true, //so we know to parse the data when we receive it with receive_read() @@ -63,7 +63,7 @@ class Ezo_board{ //Buffer should be long enough to hold the longest command //you'll receive. We recommand 32 bytes/chars as a default - enum errors receive_read(); + enum errors receive_read_cmd(); //gets the read response from the device, and parses it into the reading variable //if send_read() wasn't used to send the "R" command and issued_read() isnt set, the function will //return the "NOT_READ_CMD" error @@ -73,7 +73,7 @@ class Ezo_board{ //Useful for determining if we should call receive_read() (if is_read_poll() returns true) //or recieve_cmd() if is_read_poll() returns false) - float get_reading(); + float get_last_received_reading(); //returns the last reading the device received as a float const char* get_name(); diff --git a/README.md b/README.md index d35cd2c..b47534d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Ezo_board(uint8_t address, const char* name); void send_cmd(const char* command); //send any command in a string, see the devices datasheet for available i2c commands -void send_read(); +void send_read_cmd(); //sends the "R" command to the device and sets issued_read() to true, //so we know to parse the data when we receive it with receive_read() @@ -40,7 +40,7 @@ enum errors receive_cmd(char* sensordata_buffer, uint8_t buffer_len); //Buffer should be long enough to hold the longest command //you'll receive. We recommand 32 bytes/chars as a default -enum errors receive_read(); +enum errors receive_read_cmd(); //gets the read response from the device, and parses it into the reading variable //if send_read() wasn't used to send the "R" command and issued_read() isnt set, the function will //return the "NOT_READ_CMD" error @@ -50,7 +50,7 @@ bool is_read_poll(); //Useful for determining if we should call receive_read() (if is_read_poll() returns true) //or recieve_cmd() if is_read_poll() returns false) -float get_reading(); +float get_last_received_reading(); //returns the last reading the device received as a float const char* get_name();