Water quality sensor Carlingford Park Lake
Jump to navigation
Jump to search
Objective
- Carlingford Park raingarden and lake are due for a major renewal.
- It is expected that the lake will be converted into a wetland.
- The outlet of the raingarden will be pumped into the lake so that the lake is constantly topped up during low flow events.
- Consultants have requested that a water level sensor be installed in the lake to check to see if the lake is leaking.
Freeboard.io Dashboard
Screen capture of Freeboard.io Dashboard creator.
{"version":1,"allow_edit":true,"plugins":["/plugins/all"],"panes":[{"width":1,"row":{"3":1},"col":{"3":2},"col_width":1,"widgets":[{"type":"plugin531a3b2b7df9e78c7300000f","settings":{"html":"<h1 style=\"font-weight:500; color:white; padding-left:10%;\">Carlingford Park Lake</h1>","height":"2"}},{"type":"text_widget","settings":{"title":"Time","size":"regular","value":"datasources[\"Time\"][\"time_string_value\"]","animate":true}},{"type":"text_widget","settings":{"title":"Last updated","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"time\"]","animate":true}},{"type":"text_widget","settings":{"title":"Battery voltage","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"bat\"]","animate":true,"units":"(Volts)"}},{"type":"text_widget","settings":{"title":"Pressure (water level)","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"P\"]","animate":true,"units":"(mV)"}},{"type":"text_widget","settings":{"title":"Salinity","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"EC\"]","animate":true,"units":"(mS/cm)"}},{"type":"text_widget","settings":{"title":"Internal Temperature","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"temp\"]","animate":true,"units":"(Celsius)"}},{"type":"text_widget","settings":{"title":"Internal humidity","size":"regular","value":"datasources[\"carlingford-park-lake\"][\"hum\"]","animate":true,"units":"(%)"}},{"type":"sparkline_widget","settings":{"title":"Battery voltage","value":["datasources[\"carlingford-park-lake\"][\"bat\"]"]}},{"type":"sparkline_widget","settings":{"title":"Water level","value":["datasources[\"carlingford-park-lake\"][\"P\"]"]}},{"type":"sparkline_widget","settings":{"title":"Salinity","value":["datasources[\"carlingford-park-lake\"][\"EC\"]"]}}]}],"datasources":[{"name":"Time","type":"plugin5319f8297df9e78c73000006","settings":{"refresh":1}},{"name":"carlingford-park-lake","type":"dweet_io","settings":{"thing_id":"carlingford-park-lake","show_full":false,"name":"carlingford-park-lake"}}],"columns":3,"pane_header_bg_color":null,"pane_bg_color":null}
Node-RED code
The Node_RED code has been collapsed by default. Click here to expand:
[
{
"id": "fd6d9916.675868",
"type": "tab",
"label": "Carlingford",
"disabled": false,
"info": ""
},
{
"id": "1d1b8359.569a6d",
"type": "cronplus",
"z": "fd6d9916.675868",
"name": "Three min past hour",
"outputField": "payload",
"timeZone": "",
"persistDynamic": false,
"commandResponseMsgOutput": "output1",
"outputs": 1,
"options": [
{
"name": "schedule1",
"topic": "topic1",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "0 3 * * * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
}
],
"x": 160,
"y": 60,
"wires": [
[
"dda0a462.4d83b8"
]
]
},
{
"id": "f7149fe9.18a6e",
"type": "http request",
"z": "fd6d9916.675868",
"name": "Get allData",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.particle.io/v1/devices/",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 210,
"y": 180,
"wires": [
[
"6e8c9cdb.316aa4"
]
]
},
{
"id": "198209ae.59b306",
"type": "debug",
"z": "fd6d9916.675868",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 650,
"y": 260,
"wires": []
},
{
"id": "dda0a462.4d83b8",
"type": "simpletime",
"z": "fd6d9916.675868",
"name": "",
"mydate": true,
"myymd": true,
"myyear": true,
"mymonth": true,
"mymonthn": true,
"mydom": true,
"mydoy": true,
"myday": true,
"myhourpm": true,
"myhour": true,
"mytime": true,
"mytimes": true,
"myminute": true,
"myminutes": true,
"mysecond": true,
"mymillis": true,
"myepoch": true,
"myrawdate": true,
"mypm": true,
"x": 370,
"y": 60,
"wires": [
[
"f7149fe9.18a6e"
]
]
},
{
"id": "6e8c9cdb.316aa4",
"type": "function",
"z": "fd6d9916.675868",
"name": "Dweet function",
"func": "var allData; // all data from Particle electron sensor\n\n\nallData = msg.payload.result;\n\n\nmsg.payload = allData + \"&\"\n + \"time=\" + String(msg.mytimes);\n\nmsg.url = \"https://dweet.io/dweet/for/carlingford-park-lake?\" + msg.payload;\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 430,
"y": 180,
"wires": [
[
"ff2978fd.52e288"
]
]
},
{
"id": "ff2978fd.52e288",
"type": "http request",
"z": "fd6d9916.675868",
"name": "Dweet POST",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 640,
"y": 180,
"wires": [
[
"198209ae.59b306"
]
]
},
{
"id": "a10c2283.5eede",
"type": "function",
"z": "fd6d9916.675868",
"name": "Save data function",
"func": "var battery; // battery voltage data (Volts)\nvar pressure; // pressure sensor reading (mV)\nvar salinity; // EC water sensor (mS/cm)\nvar iTemperature; // temperature in sensor housing\nvar iHumidity; // humidity in sensor housing\n\nbattery = msg.payload.with[0].content.bat;\npressure = msg.payload.with[0].content.P;\nsalinity = msg.payload.with[0].content.EC;\niTemperature = msg.payload.with[0].content.temp;\niHumidity = msg.payload.with[0].content.hum;\n\n\nmsg.payload = String(msg.myepoch) + \",\"\n + String(msg.mydate) + \",\"\n + String(msg.mytimes) + \",\"\n + String(battery) + \",\"\n + String(pressure) + \",\"\n + String(salinity) + \",\"\n + String(iTemperature) + \",\"\n + String(iHumidity);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 170,
"y": 500,
"wires": [
[
"30c94980.425bb6"
]
]
},
{
"id": "3843fbb5.742ad4",
"type": "http request",
"z": "fd6d9916.675868",
"name": "",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://dweet.io/get/latest/dweet/for/carlingford-park-lake",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 610,
"y": 380,
"wires": [
[
"a10c2283.5eede"
]
]
},
{
"id": "479c46fb.38d298",
"type": "debug",
"z": "fd6d9916.675868",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 630,
"y": 500,
"wires": []
},
{
"id": "ef569efd.fc42",
"type": "cronplus",
"z": "fd6d9916.675868",
"name": "5 min past hour",
"outputField": "payload",
"timeZone": "",
"persistDynamic": false,
"commandResponseMsgOutput": "output1",
"outputs": 1,
"options": [
{
"name": "schedule1",
"topic": "topic1",
"payloadType": "default",
"payload": "",
"expressionType": "cron",
"expression": "0 5 * * * * *",
"location": "",
"offset": "0",
"solarType": "all",
"solarEvents": "sunrise,sunset"
}
],
"x": 160,
"y": 380,
"wires": [
[
"7632eec6.5b42d"
]
]
},
{
"id": "7632eec6.5b42d",
"type": "simpletime",
"z": "fd6d9916.675868",
"name": "",
"mydate": true,
"myymd": true,
"myyear": true,
"mymonth": true,
"mymonthn": true,
"mydom": true,
"mydoy": true,
"myday": true,
"myhourpm": true,
"myhour": true,
"mytime": true,
"mytimes": true,
"myminute": true,
"myminutes": true,
"mysecond": true,
"mymillis": true,
"myepoch": true,
"myrawdate": true,
"mypm": true,
"x": 390,
"y": 380,
"wires": [
[
"3843fbb5.742ad4"
]
]
},
{
"id": "30c94980.425bb6",
"type": "file",
"z": "fd6d9916.675868",
"name": "carlingford-park-data",
"filename": "/home/pi/sensors/carlingford-park-data.txt",
"appendNewline": true,
"createDir": false,
"overwriteFile": "false",
"encoding": "none",
"x": 420,
"y": 500,
"wires": [
[
"479c46fb.38d298"
]
]
}
]
Particle electron code
The Particle electron code for Carlingford Park Lake has been collapsed by default. Click here to expand:
#include <Adafruit_DHT_Particle.h>
#include <RunningMedianST.h>
#include <JsonParserGeneratorRK.h>
// water-sensor-carlingford park - PS-4
// Example script for field deployed particle device - monitoring water quality using Atlas
// Scientific sensors mounted on a Whitebox Labs Tentacle
// Ensure all jumpers on the tentacle board are set to I2C and all ezo boards are also set to I2C
// Consult the tentacle and atlas documentation for further details
#include <Wire.h> //enable I2C.
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define DHTPIN D3 // what pin we're connected to
#define PRESSPIN A0 // A0 will be used for pressure sensor
#define TURBPIN A1 // Pin for reading turbidity (changed from A0 by Edmond 11 Jan 2022)
#define PWR5V D2 // Pin to turn on power to DHT, Atlas sensors, turbidity and pressure sensor
//#define PWR12V D7 // Pin to turn on power to turbidity sensor - in my case this is a 12V power supply - yours may be something different
SYSTEM_MODE(AUTOMATIC);
DHT dht(DHTPIN, DHTTYPE);
FuelGauge fuel;
double powerSource;
double batteryState;
double BatteryVoltage;
double BatterySOC;
byte code = 0; //usedanalogRead to hold the I2C response code.
byte in_char = 0; //used as a 1 byte buffer to store in bound bytes from the EZO Circuit.
byte i = 0; //counter used for IC2 data
int delay_time = 1800; //used to change the delay needed depending on the command sent to the EZO circuit.
int address;
char ezo_data[48]; //we make a 20 byte character array to hold incoming data from the EZO circuit.
String T_string;
String EC_string;
//String pH_string;
//String DO_string;
String T_status;
String EC_status;
//String pH_status;
//String DO_status;
String T_int_string;
String H_int_string;
String volt_string;
String Pvalue_string;
String allData;
double DateTime;
double Tvalue;
double ECvalue;
//double pHvalue;
//double DOvalue;
//double NTUV;
double Pvalue;
float internal_Tvalue;
float internal_Hvalue;
//Sampling time
int SampleTime = 30; //Sample time in seconds
int SleepTime = 15; //minutes to sleep before waking again / target is 15 minutes in the field / 60 minutes during testing
int ExtraSleep = 0;
String ExtraSleep_string;
int totalSleep;
String totalSleep_string;
int StartTime;
int elapsedTime;
RunningMedianFloat floatSamples = RunningMedianFloat(10); // number of samples to take for each composite sample - water quality
RunningMedianFloat floatSamples_int_T = RunningMedianFloat(4); // number of samples to take for each composite sample - internal temperature
RunningMedianFloat floatSamples_int_H = RunningMedianFloat(4); // number of samples to take for each composite sample - internal humidity
//RunningMedianFloat floatSamples_NTUV = RunningMedianFloat(10);
RunningMedianFloat floatSamples_int_P = RunningMedianFloat(10);
//SystemSleepConfiguration config;
////////////////////////////////////////////////////////////////////////////////////////////////
// Comment out when not using aquarium-tech
//PMIC pmic;
void setup() //hardware initialization.
{
//pmic.begin();
//pmic.setChargeCurrent(0,0,0,0,0,0);
Serial.begin(9600); //enable serial port.
//SerialLogHandler logHandler(LOG_LEVEL_ALL);
//ApplicationWatchdog wd(660000, System.reset); //This Watchdog code will reset the processor if the dog is not kicked every 11 mins which gives time for 2 modem reset's.
//set system power configuration
SystemPowerConfiguration conf;
conf.powerSourceMaxCurrent(550)
.powerSourceMinVoltage(4840)
.batteryChargeCurrent(1024)
.batteryChargeVoltage(4112); // charge battery to lower voltage - 4.112 volts (safer)
// comment out for aquarium-tech
System.setPowerConfiguration(conf);
//Log.info("setPowerConfiguration=%d", res);
Particle.variable("BatteryVoltage", BatteryVoltage);
Particle.variable("BatterySOC", BatterySOC);
//Particle.variable("powerSource", powerSource);
//Particle.variable("batteryState", batteryState);
//Particle.variable("temperature", Tvalue);
Particle.variable("conductivity", ECvalue);
//Particle.variable("disOxygen", DOvalue);
//Particle.variable("turbidity", NTUV);
Particle.variable("pressure", Pvalue);
Particle.variable("internalTemp", T_int_string);
Particle.variable("internalHumid", H_int_string);
Particle.variable("ExtraSleep", ExtraSleep);
Particle.variable("allData", allData);
Wire.begin(); //enable I2C port.
pinMode(PWR5V, OUTPUT);
}
//Main Loop
////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
Serial.println(("Turn on power to sensors")); //turn on power to sensors
digitalWrite(PWR5V, HIGH); // turn on power to sensors
//check at startup there is enough power
/////////////////////////////////////////////////////////////////////////
// Turning on power to sensors gives more realistic battery power estimation
Serial.println("Checking battery level");
BatteryVoltage = fuel.getVCell();
volt_string = String(BatteryVoltage, 2);
BatterySOC = fuel.getNormalizedSoC();
// More sophisticated battery control for field use - commented out for testing purposes
//3.85V - SoC 71.16
//3.84V - SoC 70.42
//3.77V - SoC 53.72
//3.75V - SoC 40.82
if (BatterySOC < double(20))
{
Serial.println("Battery below 20% : will sleep for 12 hours to charge battery");
ExtraSleep = (11*60);
digitalWrite(PWR5V, LOW); // turn off power to sensors
}
else if (BatterySOC < double(40))
{
Serial.println("Battery below 40% : will sleep for 6 hours to charge battery");
ExtraSleep = (5*60);
digitalWrite(PWR5V, LOW); // turn off power to sensors
}
else if (BatterySOC < double(60))
{
Serial.println("Battery below 60% : will sleep for 2 hours to charge battery");
//SleepTime = (2*60); // 2 hours
ExtraSleep = (1*60);
}
else
{
Serial.printlnf("Battery level OK - above 80% - will sleep for %i minutes", SleepTime);
ExtraSleep = 0;
delay(1000);
}
/////////////////////////////////////////////////////////////////////////
//Initialise DHT temperature adn humidity sensor
Serial.println("initialising temp and humidity sensor DHT22");
dht.begin();
delay(2000);
//Temp and Humidity
////////////////////////////////////////////////////////////////////////////////////////////////////////////
StartTime = Time.now();
Serial.print("Begin temperature and humidity sampling at: ");
Serial.println(StartTime);
floatSamples_int_T.clear();
floatSamples_int_H.clear();
while (Time.now() - StartTime < 6)
{
internal_Tvalue = dht.getTempCelcius();
internal_Hvalue = dht.getHumidity();
// Check if any reads failed and exit early (to try again).
if (isnan(internal_Hvalue) || isnan(internal_Tvalue) )
{
Serial.println("Failed to read from DHT sensor!");
//T_int_string = "no read";
}
else
{
Serial.printlnf("Spot temperature = %f, Spot humidity = %f", internal_Tvalue, internal_Hvalue);
floatSamples_int_T.add(internal_Tvalue);
floatSamples_int_H.add(internal_Hvalue);
//T_int_string = "yes read";
}
delay(2000);
}
Serial.print("Finished temperature and humidity sampling at: ");
Serial.println(Time.now());
internal_Tvalue = floatSamples_int_T.getMedian();
internal_Hvalue = floatSamples_int_H.getMedian();
T_int_string = String(internal_Tvalue, 0); // restrict to 0 decimal places
H_int_string = String(internal_Hvalue, 0);
Serial.printlnf("Median temperature = %f, Median humidity = %f", internal_Tvalue, internal_Hvalue);
//Water Quality - Temperature
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
ezoCommand("W", 102);
Serial.println(("checking T board status: "));
T_status = ezoCommand("Status", 102); //Check the status
Serial.print("T status: ");
Serial.println(T_status);
StartTime = Time.now();
Serial.print("Begin T sampling at: ");
Serial.println(StartTime);
floatSamples.clear();
while (Time.now() - StartTime < SampleTime/3)
{
T_string = ezoCommand("R",102);
Tvalue = atof(T_string);
Serial.print("Spot T = ");
Serial.println(Tvalue);
floatSamples.add(Tvalue);
delay(1000);
}
Serial.print("Finished T sampling at: ");
Serial.println(Time.now());
delay(200);
Tvalue = floatSamples.getMedian();
Serial.print("Median T = ");
Serial.println(Tvalue);
T_string = String(Tvalue);
*/
//Water Quality - Conductivity
////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println(("checking EC board status: "));
EC_status = ezoCommand("STATUS",100); //Check the status
Serial.print(("EC status: "));
Serial.println(EC_status);
delay(500);
ezoCommand("K,0.1",100); // Set conductivity probe to K0.1 - default is K1.0
delay(500);
Serial.print("Setting EC temperature compensation at: ");
Serial.println(Tvalue);
T_string = 16; // added when temperature sensor not installed
ezoCommand(String("T,"+T_string), 100);
delay(500);
StartTime = Time.now();
Serial.print("Begin EC sampling at: ");
Serial.println(StartTime);
floatSamples.clear();
while (Time.now() - StartTime < SampleTime)
{
EC_string = ezoCommand("R",100);
ECvalue = atof(EC_string);
Serial.print("Spot EC = ");
Serial.println(ECvalue);
floatSamples.add(ECvalue);
delay(1000);
}
Serial.print("Finished EC sampling at: ");
Serial.println(Time.now());
delay(200);
ECvalue = floatSamples.getMedian();
Serial.print("Median EC = ");
EC_string = String(ECvalue, 0);
Serial.println(ECvalue);
/*
//Water Quality - pH
////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println(("checking pH board status: "));
pH_status = ezoCommand("STATUS",99); //Check the status
Serial.print(("pH status: "));
Serial.println(pH_status);
Serial.print("Setting pH temperature compensation at: ");
Serial.println(Tvalue);
ezoCommand(String("T,"+T_string), 99);
delay(500);
StartTime = Time.now();
Serial.print("Begin pH sampling at: ");
Serial.println(StartTime);
floatSamples.clear();
while (Time.now() - StartTime < SampleTime)
{
pH_string = ezoCommand("R",99);
pHvalue = atof(pH_string);
Serial.print("Spot pH = ");
Serial.println(pHvalue);
floatSamples.add(pHvalue);
delay(1000);
}
Serial.print("Finished pH sampling at: ");
Serial.println(Time.now());
delay(200);
pHvalue = floatSamples.getMedian();
Serial.print("Median pH = ");
Serial.println(pHvalue);
*/
//Water Quality - Dissolved Oxygen
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
Serial.println(("checking DO board status: "));
DO_status = ezoCommand("STATUS",97); //Check the status
Serial.print(("DO status: "));
Serial.println(DO_status);
Serial.print("Setting DO temperature compensation at: ");
Serial.println(Tvalue);
ezoCommand(String("T,"+T_string), 97);
delay(500);
StartTime = Time.now();
Serial.print("Begin DO sampling at: ");
Serial.println(StartTime);
floatSamples.clear();
while (Time.now() - StartTime < SampleTime)
{
DO_string = ezoCommand("R",97);
DOvalue = atof(DO_string);
Serial.print("Spot DO = ");
Serial.println(DOvalue);
floatSamples.add(DOvalue);
delay(1000);
}
Serial.print("Finished DO sampling at: ");
Serial.println(Time.now());
delay(200);
DOvalue = floatSamples.getMedian();
Serial.print("Median DO = ");
Serial.println(DOvalue);
// Turbidity
////////////////////////////////////////////////////////////////////////////////////////////////////////////
StartTime = Time.now();
Serial.print("Begin turbidity sampling at: ");
Serial.println(StartTime);
floatSamples_NTUV.clear();
while (Time.now() - StartTime < SampleTime)
{
NTUV = analogRead(TURBPIN);
Serial.print("NTU: ");
Serial.println(NTUV);
floatSamples_NTUV.add(NTUV);
delay(500);
}
Serial.print("Finished turbidity sampling at: ");
Serial.println(Time.now());
delay(500);
NTUV = floatSamples_NTUV.getMedian();
Serial.print("Median turbidity: ");
Serial.println(NTUV);
delay(1000);
*/
// Pressure transducer - Water level sensor
////////////////////////////////////////////////////////////////////////////////////////////////////////////
StartTime = Time.now();
floatSamples_int_P.clear();
while (Time.now() - StartTime < SampleTime)
{
Pvalue = analogRead(PRESSPIN);
floatSamples_int_P.add(Pvalue);
delay(500);
}
delay(500);
Pvalue = floatSamples_int_P.getMedian();
Serial.print("Median pressure: ");
Serial.println(Pvalue);
Pvalue_string = String(Pvalue, 0);
delay(1000);
Serial.println("Turning off power to all sensors");
digitalWrite(PWR5V, LOW);
//Sens data to particle cloud
////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println("Preparing sensor data");
delay (1000);
// totalSleep indicative - will be out by approx 3 minutes
totalSleep = ((59-Time.minute()) + ExtraSleep);
totalSleep_string = String(totalSleep);
allData = "bat=" + volt_string + "&" + "P=" + Pvalue_string + "&" + "EC=" + EC_string + "&" + "temp=" + T_int_string + "&" + "hum=" + H_int_string + "&" + "S=" + totalSleep_string;
// COMMENTED OUT FOR CARLINGFORD
//Serial.printlnf("Sensor data - Temp: %f EC: %f DO: %f NTUV: %f Pressure: %f Internal Temp: %f Internal Hum: %f Battery Voltage: %f Battery Charge: %f", Tvalue, ECvalue, DOvalue, NTUV, Pvalue, internal_Tvalue, internal_Hvalue, BatteryVoltage, BatterySOC);
//Serial.printlnf("Sensor status - T Status: %s EC Status: %s", T_status.c_str(), EC_status.c_str());
//delay (1000);
//Serial.println("Uploading sensor data");
//createPayload(DateTime, Tvalue, ECvalue, DOvalue, NTUV, Pvalue, internal_Tvalue, internal_Hvalue, BatteryVoltage, BatterySOC);
//delay (3000);
//Serial.println("Turning off cellular modem");
//Cellular.off();
delay(1000*60*3); //3 minute delay before sleep
SleepTime = (59-Time.minute());
Serial.printlnf("Going to sleep for %i minutes" , (SleepTime + ExtraSleep));
//System.sleep(config);
//************
// Commented out sleep (following line)during testing (Edmond 11 Jan 2022)
// Comment out following line for aquarium-tech so that the battery can charge
// Note that deep sleep prevents charging of battery when powered using USB supply
// Note that deep sleep is in Seconds as units
System.sleep(SLEEP_MODE_DEEP, ((SleepTime + ExtraSleep) * 60));
// Comment out delay for normal operation (i.e. solar powered operation)
//delay(1000*60*15);
//***************
}
// Function Definitions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Read from sensors
////////////////////////////////////////////////////////////////////////////////////////
String ezoCommand(String command, int address)
{
Wire.beginTransmission(address); //call the circuit by its ID number.
Wire.write(command); //transmit the command that was sent through the serial port.
Wire.endTransmission(); //end the I2C data transmission.
delay(delay_time);
Wire.requestFrom(address,48,1); //call the circuit and request 20 bytes (this may be more than we need)
code=Wire.read();
while(Wire.available())
{ //are there bytes to receive.
in_char = Wire.read(); //receive a byte.
ezo_data[i]= in_char; //load this byte into our array.
i+=1; //incur the counter for the array element.
if(in_char==0)
{ //if we see that we have been sent a null command.
i=0; //reset the counter i to 0.
Wire.endTransmission(); //end the I2C data transmission.
break; //exit the while loop.
}
}
switch (code){ //switch case based on what the response code is.
case 1: //decimal 1.
Serial.print("Success - "); //means the command was successful.
break; //exits the switch case.
case 2: //decimal 2.
Serial.print("Failed"); //means the command has failed.
break; //exits the switch case.
case 254: //decimal 254.
Serial.print("Pending"); //means the command has not yet been finished calculating.
break; //exits the switch case.
case 255: //decimal 255.
Serial.print("No Data"); //means there is no further data to send.
break; //exits the switch case.
}
if (code == 1){
return ezo_data ;
}
else {
return "";
}
}
//JSON generator function for sensor data
///////////////////////////////////////////////////////
void createPayload(double DateTime, double Tvalue, double ECvalue, double DOvalue, double NTUV, double Pvalue, double internal_Tvalue, double internal_Hvalue, double BatteryVoltage, double BatterySOC)
{
JsonWriterStatic<256> jw;
{
JsonWriterAutoObject obj(&jw);
jw.insertKeyValue("DateTime", Time.now());
jw.insertKeyValue("T", Tvalue);
jw.insertKeyValue("EC", ECvalue);
jw.insertKeyValue("DO", DOvalue);
jw.insertKeyValue("NTUV", NTUV);
jw.insertKeyValue("pressure", Pvalue);
jw.insertKeyValue("internal_T", internal_Tvalue);
jw.insertKeyValue("internal_H", internal_Hvalue);
jw.insertKeyValue("BatteryVoltage", BatteryVoltage);
jw.insertKeyValue("BatterySOC", BatterySOC);
}
Particle.publish("PayloadJSON", jw.getBuffer(), PRIVATE);
}