Home › Forums › Mayfly Data Logger › Atlas Scientific EZO logging program
Tagged: Atlas Scientific, EZO sensors, sleep
- This topic has 11 replies, 2 voices, and was last updated 2017-03-19 at 9:57 AM by Jim Moore.
-
AuthorPosts
-
-
2017-02-11 at 11:51 PM #2016
I am working on code to log data from the Atlas Scientific EZO sensors. I have a working program that will calibrate and configure the subject sensors and log data to an SD card using the Mayfly board.
After attending the excellent 2 day seminar at Stroud I was inspired to add the sleep functionality and got the sample program (Mayfly-sleep) functioning but limited to simply turning on my sensor via the grove connector for 10 seconds.I have added additional code to send r\r to the sensor to initiate data collection and log this data. The attached code is where I’m at and it now won’t compile and I get a “collect2.exe: error: ld returned 1 exit status” error. I’m stuck and any help would be appreciated.
Also is the code for the Decagon sensors that we set up at the seminar available?
-
2017-02-12 at 10:58 AM #2019
By process of elimination the the compile error seems to be related to
-
#include <SoftwareSerial.h</ul
…and I assume this is where the code goes.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318/*This example sketch puts the Mayfly board into sleep mode. It wakes up at specific times,records the temperature and battery voltage onto the microSD card, prints the data stringto the serial port, and goes back to sleep.JOM 2/9/17 added power on/off to EZO board*/#include <Wire.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <SPI.h>#include <SD.h>#include <SoftwareSerial.h> //we have to include the SoftwareSerial library, or else we can't use it.#include <RTCTimer.h>#include <Sodaq_DS3231.h>#include <Sodaq_PcInt.h>RTCTimer timer;#define rx 7 //D7 to Tx on EZO (white on Grove conn)#define tx 6 //D6 to Rx on EZO (yellow on Grove conn)SoftwareSerial myserial(rx, tx); //define how the soft serial port is going to work.String dataRec = "";String sensorstring = "EZO data"; //a string to hold the data from the EZO productint currentminute;long currentepochtime = 0;float boardtemp;int batteryPin = A6; // select the input pin for the potentiometerint batterysenseValue = 0; // variable to store the value coming from the sensorfloat batteryvoltage;boolean sensor_stringcomplete = false; //have we received all the data from the EZO productunsigned long previousMillis = 0; // will store last time EZO was readconst long interval = 5000;//RTC Interrupt pin#define RTC_PIN A7#define RTC_INT_PERIOD EveryMinute#define SD_SS_PIN 12 //orig had pin 11//The data log file#define FILE_NAME "datafile.txt"//Data header#define LOGGERNAME "SampleLogger"#define DATA_HEADER "DateTime_EST,Loggertime,BoardTemp_C,Battery_V"void setup(){//Initialise the serial connectionSerial.begin(9600);myserial.begin(9600); //set baud rate for software serial port_3 to 9600rtc.begin();delay(100);pinMode(8, OUTPUT);pinMode(9, OUTPUT);pinMode(22, OUTPUT); //Power to Grove connectorssensorstring.reserve(30); //set aside some bytes for receiving data from EZO productgreenred4flash(); //blink the LEDs to show the board is onsetupLogFile();setupTimer(); //Setup timer eventssetupSleep(); //Setup sleep modeSerial.println("Power On, running: mayfly_sleep_sample1.ino");showTime(getNow());}void loop(){//Update the timertimer.update();if (currentminute % 1 == 0) // change "2" to "5" to wake up logger every 5 minutes instead{ Serial.println("Multiple of 2! Initiating sensor reading and logging data to SDcard....");recieveSensorData(); //recieve data from EZO sensor to log on sd card and display on monitor//add loop here to run n timesunsigned long currentMillis = millis();if (currentMillis - previousMillis >= interval){previousMillis = currentMillis; // save the last time you blinked the LEDmyserial.print("r\r"); // if its time then send "r \r" to the EZO product// digitalWrite(greenPin, LEDstate);// LEDstate = !LEDstate;// digitalWrite(redPin, LEDstate);}/*dataRec = createDataRecord();//Save the data record to the log filelogData(dataRec);//Echo the data to the serial connection//Serial.println();Serial.print("Data Record: ");Serial.println(dataRec);String dataRec = "";*/}delay(1000);//SleepsystemSleep();}void showTime(uint32_t ts){//Retrieve and display the current date/timeString dateTime = getDateTime();//Serial.println(dateTime);}void setupTimer(){//Schedule the wakeup every minutetimer.every(1, showTime);//Instruct the RTCTimer how to get the current time readingtimer.setNowCallback(getNow);}void wakeISR(){//Leave this blank}void setupSleep(){pinMode(RTC_PIN, INPUT_PULLUP);PcInt::attachInterrupt(RTC_PIN, wakeISR);//Setup the RTC in interrupt modertc.enableInterrupts(RTC_INT_PERIOD);//Set the sleep modeset_sleep_mode(SLEEP_MODE_PWR_DOWN);}void systemSleep(){//This method handles any sensor specific sleep setupsensorsSleep();//Wait until the serial ports have finished transmittingSerial.flush();// Serial1.flush();//The next timed interrupt will not be sent until this is clearedrtc.clearINTStatus();//Disable ADCADCSRA &= ~_BV(ADEN);//Sleep timenoInterrupts();sleep_enable();interrupts();sleep_cpu();sleep_disable();//Enbale ADCADCSRA |= _BV(ADEN);//This method handles any sensor specific wake setupsensorsWake();}void sensorsSleep(){digitalWrite(22, false); //Turn off power to EZO ckt}void sensorsWake(){digitalWrite(22, true); //Turn on power to EZO cktdelay(10000); //replace with EZO code for auto r\r n times}String getDateTime(){String dateTimeStr;//Create a DateTime object from the current timeDateTime dt(rtc.makeDateTime(rtc.now().getEpoch()));currentepochtime = (dt.get()); //Unix time in secondscurrentminute = (dt.minute());//Convert it to a Stringdt.addToString(dateTimeStr);return dateTimeStr;}uint32_t getNow(){currentepochtime = rtc.now().getEpoch();return currentepochtime;}void greenred4flash(){for (int i = 1; i <= 4; i++) {digitalWrite(8, HIGH);digitalWrite(9, LOW);delay(50);digitalWrite(8, LOW);digitalWrite(9, HIGH);delay(50);}digitalWrite(9, LOW);}void setupLogFile(){//Initialise the SD cardif (!SD.begin(SD_SS_PIN)){Serial.println("Error: SD card failed to initialise or is missing.");//Hang// while (true);}//Check if the file already existsbool oldFile = SD.exists(FILE_NAME);//Open the file in write modeFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Add header information if the file did not already existif (!oldFile){logFile.println(LOGGERNAME);logFile.println(DATA_HEADER);}//Close the file to save itlogFile.close();}void logData(String rec){//Re-open the fileFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Write the CSV datalogFile.println(rec);//Close the file to save itlogFile.close();}void recieveSensorData(){if (myserial.available() > 0) { //if we see that the EZO product has sent a character.char inchar = (char)myserial.read(); //get the char we just receivedsensorstring += inchar;if (inchar == '\r') {sensor_stringcomplete = true; //if the incoming character is a <CR>, set the flag}}if (sensor_stringcomplete) { //if a string from the EZO product has been received//in its entiretydataRec = createDataRecord();logData(dataRec); //Save the data record to the log fileSerial.print(" ");Serial.println(dataRec);sensorstring = ""; //clear the string:sensor_stringcomplete = false; //reset the flag used to tell if we have received a}}String createDataRecord(){//Create a String type data record in csv format//TimeDate, Loggertime,Temp_DS, Diff1, Diff2, boardtempString data = getDateTime();data += ",";rtc.convertTemperature(); //convert current temperature into registersboardtemp = rtc.getTemperature(); //Read temperature sensor valuebatterysenseValue = analogRead(batteryPin);batteryvoltage = (3.3 / 1023.) * 1.47 * batterysenseValue;data += currentepochtime;data += ",";addFloatToString(data, boardtemp, 3, 1); //floatdata += ",";addFloatToString(data, batteryvoltage, 4, 2);data += " , "; //adds a comma between valuesdata += sensorstring; //adds pH to the data stringreturn data;}static void addFloatToString(String & str, float val, char width, unsigned char precision){char buffer[10];dtostrf(val, width, precision, buffer);str += buffer;} -
2017-02-12 at 11:01 AM #2020
Maybe I should put all of my code in the sensorWake() function…
-
2017-02-12 at 11:41 AM #2021
I tried the NewSoftSerial.h library, which I understand uses interupts instead of polling, and still no joy.
I think I have run out of options so any suggestions would be appreciated!
-
2017-02-12 at 1:32 PM #2022
The error you’re getting is because the SoftwareSerial library uses an interrupt method that conflicts with the SODAQ_PcInt library. In order to use those 2 libraries together, you have to use the modified versions of the libraries we posted in our Github repo, along with modifying the library names in your sketch in 3 places. Plus you’ll need to change the pins for your Atlas sensors to use 10 and 11 instead of 6 and 7. This is because the SoftwareSerialMod library ignores interrupts on the port that includes all of the analog pins (where the DS3231 interrupt is on A7) and it ignores pins D0-D7. This allows people to use the SDI12_Mod library to look at SDI12 sensors on pin D6 or D7.
So download all of the libraries from our repo: https://github.com/EnviroDIY/Libraries/tree/master and be sure to follow the instructions on that page about how to download the .zip file from the tree and not use the green “clone or download” button.
Once you have the libraries installed, restart you IDE and then modify the top section of your code to point to the new library filenames and update the pin numbers. It’ll look like this:
Arduino123456789101112131415161718#include <Wire.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <SPI.h>#include <SD.h>#include <SoftwareSerialMod.h>#include <RTCTimer.h>#include <Sodaq_DS3231.h>#include <Sodaq_PcInt_Mod.h>RTCTimer timer;#define rx 11 //D11 to Tx on EZO (white on Grove conn)#define tx 10 //D10 to Rx on EZO (yellow on Grove conn)SoftwareSerialMod myserial(rx, tx); //define how the soft serial port is going to work.String dataRec = "";String sensorstring = "EZO data"; //a string to hold the data from the EZO productI compiled your code with the above changes and get no errors.
Or if all of this is too complicated, and you have Mayfly board v0.4, you can simply cut the trace on the back of the board on JP1 to change the clock interrupt from A7 to D10, so you can use the board’s third hardware interrupt pin to wake it up instead of using the PcInt pin change library. Then you can remove all reference to the PCInt library from your sketch, change the wakeup pin from A7 to 10, and then use the regular SoftwareSerial library, and putting your sensors back on D6-7. Another user brought this issue up recently: http://envirodiy.org/topic/low-power-project/
-
2017-02-12 at 10:13 PM #2023
I have version 0.3 and it looks like I would cut the trace at JP1 but would then have to wire the int pin to D10 since there is only two pads at JP1. I think I can add the wire with out making too much of a mess. Will this work? I’ll also give the software fix a try.
Any updates on Amazon stock and protoshield availability?
Thanks for all your help!
-
2017-02-13 at 7:16 AM #2024
Just do the software fix as suggested above and leave the clock interrupt on A7, then you won’t have to worry about doing any wiring changes. I added the D10 interrupt option on version 0.4 and higher because I thought it might come in handy for people who had interrupt library complications. But it works just fine if you simply use the modified libraries instead.
I’m still waiting for the shipment of boards from the manufacturer, but hope to have them and the protoshields on Amazon by the end of the month.
-
2017-02-13 at 5:36 PM #2025
Thanks, that’s what I did and my program now compiles but doesn’t work but its progress and I’m learning.
Btw, the libraries.zip gave me a corrupt file error but loading the two _Mod libraries separately worked.
Is the Decagon code that was used in the seminar available? That might help me understand the deep sleep mode better.
-
2017-03-14 at 8:45 PM #2082
I would appreciate help on a problem with my code derived from the Mayfly-sleep.ino example. I am using the SoftwareSerialMod.h library as recommended to resolve a pin conflict. However, when I activate myserial.begin(9600) the program does
-
not
go into sleep mode.
attached is my code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326/*This example sketch puts the Mayfly board into sleep mode. It wakes up at specific times,records the temperature and battery voltage onto the microSD card, prints the data stringto the serial port, and goes back to sleep.JOM 2/9/17 added power on/off to EZO boardJOM 2/12/17 downloaded ...Mod.h libraries to fix RTC interupt conflicts. Need to turn off rx and txwhen putting to sleep otherwise rx/tx powers the sensor after Vcc is turned offJOM 2/13/17 Problem sensor on most of time. may need to serial.flushJOM 3/12/17 problem was not plugged into grove 10/11 socket!!JOM 3/13/17 does not go to sleep even with minimal EZO codeJOM 3/14/17 activating myserial.begin(9600) causes sleep mode not to work.*/#include <Wire.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <SPI.h>#include <SD.h>#include <SoftwareSerialMod.h>#include <RTCTimer.h>#include <Sodaq_DS3231.h>#include <Sodaq_PcInt_Mod.h>RTCTimer timer;#define rx 11 //D11 to Tx on EZO (white on Grove conn)#define tx 10 //D10 to Rx on EZO (yellow on Grove conn)SoftwareSerialMod myserial(rx, tx); //define how the soft serial port is going to work.String dataRec = "";String sensorstring = "EZO data"; //a string to hold the data from the EZO productint currentminute;int n = 0;long currentepochtime = 0;float boardtemp;int batteryPin = A6; // select the input pin for the potentiometerint batterysenseValue = 0; // variable to store the value coming from the sensorfloat batteryvoltage;boolean sensor_stringcomplete = false; //have we received all the data from the EZO product//RTC Interrupt pin#define RTC_PIN A7#define RTC_INT_PERIOD EveryMinute#define SD_SS_PIN 12 //orig had pin 11//The data log file#define FILE_NAME "datafile.txt"//Data header#define LOGGERNAME "SampleLogger"#define DATA_HEADER "DateTime_EST,Loggertime,BoardTemp_C,Battery_V"void setup(){//Initialise the serial connectionSerial.begin(9600);//myserial.begin(9600); //set baud rate for software serial port_3 to 9600//if myserial active sleep doesn't workrtc.begin();delay(100);pinMode(8, OUTPUT);pinMode(9, OUTPUT);pinMode(22, OUTPUT); //Power to Grove connectorssensorstring.reserve(30); //set aside some bytes for receiving data from EZO productgreenred4flash(); //blink the LEDs to show the board is onsetupLogFile();setupTimer(); //Setup timer eventssetupSleep(); //Setup sleep modeSerial.println("Power On, running: mayfly_sleep_sample1.ino");showTime(getNow());}void loop(){//Update the timertimer.update();if (currentminute % 1 == 0) // change "2" to "5" to wake up logger every 5 minutes instead{ //Serial.println(" Initiating sensor reading and logging data to SDcard....");dataRec = createDataRecord();//Save the data record to the log filelogData(dataRec);//Echo the data to the serial connection//Serial.println();Serial.print("Data Record: ");Serial.println(dataRec);String dataRec = "";while (!sensor_stringcomplete && (n <= 10) ){recieveSensorData();Serial.print("n= ");Serial.println(n);delay(1000);n++;}n = 0;}delay(1000);//SleepsystemSleep();} //end loopvoid sensorsSleep(){digitalWrite(22, false); //Turn off power to EZO cktdigitalWrite(10, false); //Turn off tx to EZO ckt//digitalWrite(11, false); //Turn off rx to EZO ckt}void sensorsWake(){digitalWrite(22, true); //Turn on power to EZO cktSerial.println("..I'm awake!");delay(5000);}void recieveSensorData(){if (myserial.available() > 0) { //if we see that the EZO product has sent a character.char inchar = (char)myserial.read(); //get the char we just receivedsensorstring += inchar;if (inchar == '\r') {sensor_stringcomplete = true; //if the incoming character is a <CR>, set the flag}}if (sensor_stringcomplete) { //if a string from the EZO product has been received//in its entiretydataRec = createDataRecord();logData(dataRec); //Save the data record to the log fileSerial.print(" ");Serial.println(dataRec);sensorstring = ""; //clear the string:sensor_stringcomplete = false; //reset the flag used to tell if we have received a}}String createDataRecord(){//Create a String type data record in csv format//TimeDate, Loggertime,Temp_DS, Diff1, Diff2, boardtempString data = getDateTime();data += ",";rtc.convertTemperature(); //convert current temperature into registersboardtemp = rtc.getTemperature(); //Read temperature sensor valuebatterysenseValue = analogRead(batteryPin);batteryvoltage = (3.3 / 1023.) * 1.47 * batterysenseValue;data += currentepochtime;data += ",";addFloatToString(data, boardtemp, 3, 1); //floatdata += ",";addFloatToString(data, batteryvoltage, 4, 2);data += " , "; //adds a comma between valuesdata += sensorstring; //adds pH to the data stringreturn data;}void showTime(uint32_t ts){//Retrieve and display the current date/timeString dateTime = getDateTime();//Serial.println(dateTime);}void setupTimer(){//Schedule the wakeup every minutetimer.every(1, showTime);//Instruct the RTCTimer how to get the current time readingtimer.setNowCallback(getNow);}void wakeISR(){//Leave this blank}void setupSleep(){pinMode(RTC_PIN, INPUT_PULLUP);PcInt::attachInterrupt(RTC_PIN, wakeISR);//Setup the RTC in interrupt modertc.enableInterrupts(RTC_INT_PERIOD);//Set the sleep modeset_sleep_mode(SLEEP_MODE_PWR_DOWN);}void systemSleep(){//This method handles any sensor specific sleep setupsensorsSleep();//Wait until the serial ports have finished transmittingSerial.flush();// Serial1.flush();//The next timed interrupt will not be sent until this is clearedrtc.clearINTStatus();//Disable ADCADCSRA &= ~_BV(ADEN);//Sleep timenoInterrupts();sleep_enable();interrupts();sleep_cpu();sleep_disable();//Enbale ADCADCSRA |= _BV(ADEN);//This method handles any sensor specific wake setupsensorsWake();}String getDateTime(){String dateTimeStr;//Create a DateTime object from the current timeDateTime dt(rtc.makeDateTime(rtc.now().getEpoch()));currentepochtime = (dt.get()); //Unix time in secondscurrentminute = (dt.minute());//Convert it to a Stringdt.addToString(dateTimeStr);return dateTimeStr;}uint32_t getNow(){currentepochtime = rtc.now().getEpoch();return currentepochtime;}void greenred4flash(){for (int i = 1; i <= 4; i++) {digitalWrite(8, HIGH);digitalWrite(9, LOW);delay(50);digitalWrite(8, LOW);digitalWrite(9, HIGH);delay(50);}digitalWrite(9, LOW);}void setupLogFile(){//Initialise the SD cardif (!SD.begin(SD_SS_PIN)){Serial.println("Error: SD card failed to initialise or is missing.");//Hang// while (true);}//Check if the file already existsbool oldFile = SD.exists(FILE_NAME);//Open the file in write modeFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Add header information if the file did not already existif (!oldFile){logFile.println(LOGGERNAME);logFile.println(DATA_HEADER);}//Close the file to save itlogFile.close();}void logData(String rec){//Re-open the fileFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Write the CSV datalogFile.println(rec);//Close the file to save itlogFile.close();}static void addFloatToString(String & str, float val, char width, unsigned char precision){char buffer[10];dtostrf(val, width, precision, buffer);str += buffer;}-
2017-03-17 at 4:47 PM #2088
How did you verify that the board isn’t going into sleep mode? Can I assume that you didn’t modify the pads on JP1 and that the clock interrupt is still connected to A7 and you didn’t do anything with D10 other than use the D10-D11 grove port for connecting your sensor?
-
-
2017-03-17 at 9:53 PM #2090
You assume correctly. When operating correctly the red power LED3 is off during sleep mode. I just retested with my sensor disconnected and works properly with myserial.begin(9600) active. Therefor my problem seems to be when the sensor is connected and returning data.
I need to do a bit more trouble shooting. The objective is to wake the mayfly, turn on the sensor and let it collect n samples of data (1 per second) then go to sleep. A possible related problem is that the tx pin (10) needs to be set low when in sleep mode otherwise it feeds Vcc to the sensor.
I’ll report back after some further testing.
Thanks, Shannon
-
2017-03-19 at 9:57 AM #2101
I finally solved the never-sleep problem. The problem seems to be related to the slow decay of the power to the Grove connector. With the sensor connected the decay is approximately 50ms. In the senosrSleep() function the power and rx/tx are turned off but the Vcc voltage doesn’t get a chance to decay before this function is exited which seems to cause an immediate wakeup. I added a 100ms delay to that function and now seems to work as planned.
I am not sure what causes the immediate wake up but must be related to the residual voltage on the pwr pin. With the sensor disconnected the code works with out the delay probably because there is no capacitance to hold up the voltage.
I cleaned up the code a bit and here is rev 1.0
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318/*This example sketch puts the Mayfly board into sleep mode. It wakes up at specific timesto turn on the Atlas Scientific EZO sensors. The EZO sensor is configured to output sensordata once per second (c,1 command)which is logged to the SD card along with time stamp,board temp, and battery voltage. Note: if sleep time is greater than 1 minute the board willstill wake for 100ms which is less than the turn on time of the sensor.JOM 2/9/17 added power on/off to EZO boardJOM 2/12/17 downloaded ...Mod.h libraries to fix RTC interupt conflicts. Need to turn offrx and tx when putting to sleep otherwise rx/tx powers the sensor after Vcc is turned offJOM 2/13/17 Problem sensor on most of time.JOM 3/18/17 The never-sleep problem was fixed by adding a 100ms delay to the sensorsSleep()function. This allows Vcc to the sensor to decay to zero which is ~50 ms. The pwr on takes only ~5us.*/#include <Wire.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <SPI.h>#include <SD.h>#include <SoftwareSerialMod.h>#include <RTCTimer.h>#include <Sodaq_DS3231.h>#include <Sodaq_PcInt_Mod.h>RTCTimer timer;#define rx 11 //D11 to Tx on EZO (white on Grove conn)#define tx 10 //D10 to Rx on EZO (yellow on Grove conn)SoftwareSerialMod myserial(rx, tx); //define how the soft serial port is going to work.String dataRec = "";String sensorstring = "EZO data"; //a string to hold the data from the EZO productint currentminute;int n = 0;int nMax = 20;int sleepMinutes = 5; //total minutes the Mayfly is in sleep modelong currentepochtime = 0;float boardtemp;int batteryPin = A6; // to read battery voltageint batterysenseValue = 0; // variable to store the value coming from the sensorfloat batteryvoltage;boolean sensor_stringcomplete = false; //have we received all the data from the EZO product//RTC Interrupt pin#define RTC_PIN A7#define RTC_INT_PERIOD EveryMinute#define SD_SS_PIN 12 //orig had pin 11//The data log file#define FILE_NAME "datafile.txt"//Data header#define LOGGERNAME "SampleLogger"#define DATA_HEADER "DateTime_EST,Loggertime,BoardTemp_C,Battery_V"void setup(){//Initialise the serial connectionSerial.begin(9600);myserial.begin(9600); //set baud rate for software serial port_3 to 9600//if myserial active sleep doesn't workrtc.begin();pinMode(8, OUTPUT);pinMode(9, OUTPUT);pinMode(22, OUTPUT); //Power to Grove connectorssensorstring.reserve(30); //set aside some bytes for receiving data from EZO productgreenred4flash(); //blink the LEDs to show the board is onsetupLogFile();setupTimer(); //Setup timer eventssetupSleep(); //Setup sleep modedigitalWrite(10, false); //Turn off tx to EZO cktdigitalWrite(11, false); //Turn off rx to EZO cktdigitalWrite(22, true); //Turn on power to EZO cktSerial.println("Power On, running: mayfly_sleep_sample1.ino");showTime(getNow());}void loop(){//Update the timertimer.update();if (currentminute % sleepMinutes == 0) //will wake every minute for set delay untill condition//is satisfied{while (!sensor_stringcomplete && (n < nMax)){recieveSensorData();}n = 0;}delay(100); //should be less than sensor turnon time which is ~1sec//SleepsystemSleep();} //end loopvoid sensorsSleep(){Serial.println("..going to sleep!");digitalWrite(22, false); //Turn off power to EZO cktdigitalWrite(10, false); //Turn off tx to EZO cktdigitalWrite(11, false); //Turn off rx to EZO cktdelay(100); //adding delay fixed the never-sleep problem}void sensorsWake(){digitalWrite(22, true); //Turn on power to EZO cktSerial.println("..I'm awake!");}void recieveSensorData(){if (myserial.available() > 0) { //if we see that the EZO product has sent a character.char inchar = (char)myserial.read(); //get the char we just receivedsensorstring += inchar;if (inchar == '\r') {sensor_stringcomplete = true; //if the incoming character is a <CR>, set the flagn++;}}if (sensor_stringcomplete) { //if a string from the EZO product has been received//in its entiretydataRec = createDataRecord();if (n >= 3) //don't log sensor startup response{logData(dataRec); //Save the data record to the log file}Serial.print(" ");Serial.println(dataRec);Serial.print("n= ");Serial.println(n);sensorstring = ""; //clear the string:sensor_stringcomplete = false; //reset the flag used to tell if we have received a}}String createDataRecord(){//Create a String type data record in csv format//TimeDate, Loggertime,Temp_DS, Diff1, Diff2, boardtempString data = getDateTime();data += ",";rtc.convertTemperature(); //convert current temperature into registersboardtemp = rtc.getTemperature(); //Read temperature sensor valuebatterysenseValue = analogRead(batteryPin);batteryvoltage = (3.3 / 1023.) * 1.47 * batterysenseValue;data += currentepochtime;data += ",";addFloatToString(data, boardtemp, 3, 1); //floatdata += ",";addFloatToString(data, batteryvoltage, 4, 2);data += " , "; //adds a comma between valuesdata += sensorstring; //adds pH to the data stringreturn data;}void showTime(uint32_t ts){//Retrieve and display the current date/timeString dateTime = getDateTime();//Serial.println(dateTime);}void setupTimer(){//Schedule the wakeup every minutetimer.every(1, showTime);//Instruct the RTCTimer how to get the current time readingtimer.setNowCallback(getNow);}void wakeISR(){//Leave this blank}void setupSleep(){pinMode(RTC_PIN, INPUT_PULLUP);PcInt::attachInterrupt(RTC_PIN, wakeISR);//Setup the RTC in interrupt modertc.enableInterrupts(RTC_INT_PERIOD);//Set the sleep modeset_sleep_mode(SLEEP_MODE_PWR_DOWN);}void systemSleep(){//This method handles any sensor specific sleep setupsensorsSleep();//Wait until the serial ports have finished transmittingSerial.flush();// Serial1.flush();//The next timed interrupt will not be sent until this is clearedrtc.clearINTStatus();//Disable ADCADCSRA &= ~_BV(ADEN);//Sleep timenoInterrupts();sleep_enable();interrupts();sleep_cpu();sleep_disable();//Enbale ADCADCSRA |= _BV(ADEN);//This method handles any sensor specific wake setupsensorsWake();}String getDateTime(){String dateTimeStr;//Create a DateTime object from the current timeDateTime dt(rtc.makeDateTime(rtc.now().getEpoch()));currentepochtime = (dt.get()); //Unix time in secondscurrentminute = (dt.minute());//Convert it to a Stringdt.addToString(dateTimeStr);return dateTimeStr;}uint32_t getNow(){currentepochtime = rtc.now().getEpoch();return currentepochtime;}void greenred4flash(){for (int i = 1; i <= 4; i++) {digitalWrite(8, HIGH);digitalWrite(9, LOW);delay(50);digitalWrite(8, LOW);digitalWrite(9, HIGH);delay(50);}digitalWrite(9, LOW);}void setupLogFile(){//Initialise the SD cardif (!SD.begin(SD_SS_PIN)){Serial.println("Error: SD card failed to initialise or is missing.");//Hang// while (true);}//Check if the file already existsbool oldFile = SD.exists(FILE_NAME);//Open the file in write modeFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Add header information if the file did not already existif (!oldFile){logFile.println(LOGGERNAME);logFile.println(DATA_HEADER);}//Close the file to save itlogFile.close();}void logData(String rec){//Re-open the fileFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Write the CSV datalogFile.println(rec);//Close the file to save itlogFile.close();}static void addFloatToString(String & str, float val, char width, unsigned char precision){char buffer[10];dtostrf(val, width, precision, buffer);str += buffer;}
-
-
AuthorPosts
- You must be logged in to reply to this topic.