Home › Forums › Mayfly Data Logger › Atlas Scientific Logger – Sleep between readings
- This topic has 10 replies, 4 voices, and was last updated 2020-11-16 at 10:29 AM by ggraves.
-
AuthorPosts
-
-
2020-10-26 at 11:22 AM #14714
Hi,
I am having an issue attempting to setup a datalogger to record readings and put the Mayfly to sleep. My setup is an Atlas Scientific EC and temperature probe as I2C protocol connected to an I2C hub. I would like to simultaneously take readings from both of these sensors and save them to the SD card. Meanwhile, have the sensors go to sleep between readings. Would anyone be able to tell me what I’m missing? Please see code below
Thanks!
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300#include <Sodaq_PcInt.h>#include <Ezo_i2c.h> //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib#include <Wire.h> //include arduinos i2c library#include <SPI.h>#include <SD.h>#include <Sodaq_DS3231.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <RTCTimer.h>//RTC Interrupt pin#define RTC_PIN A7#define RTC_INT_PERIOD EveryMinute//Digital pin 12 is the MicroSD slave select pin on the Mayfly#define SD_SS_PIN 12//The data log file#define FILE_NAME "DataLog.txt"//Data header (these lines get written to the beginning of a file when it's created)#define LOGGERNAME "Mayfly Writing EC and temp data to microSD card"#define DATA_HEADER "SampleNumber, Millis, DateTime, Temp(C), EC(uS/cm), Battery_V"int samplenum = 1; // declare the variable "samplenum" and start with 1int batteryPin = A6; //read battery voltageint batterysenseValue = 0;float batteryvoltage;String dataRec = "";int currentminute;long currentepochtime = 0;int sleepMinutes = 1;int State8 = LOW;int State9 = LOW;int delayTime = 1000; //millisecondsEzo_board RTD = Ezo_board(102, "TEMP"); //create a Temp circuit object, who's address is 102 and name is "RTD"Ezo_board EC = Ezo_board(100, "EC"); //create an EC circuit object who's address is 100 and name is "EC"bool reading_request_phase = true; //selects our phaseuint32_t next_poll_time = 0; //holds the next time we receive a response, in millisecondsconst unsigned int response_delay = 0; //how long we wait to receive a response, in millisecondschar weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };RTCTimer timer;void setup() {pinMode(22, OUTPUT);pinMode(8, OUTPUT);rtc.begin();Serial.begin(9600); //start the serial communication to the computersetupLogFile();setupTimer();setupSleep();Wire.begin();}void loop() {//Update the timertimer.update();if(currentminute % sleepMinutes == 0) // change "2" to "5" to wake up logger every 5 minutes instead{ Serial.println("Multiple of 1! Initiating sensor reading and logging data to SDcard....");digitalWrite(22, HIGH); // turn the Green ledPin on//Echo the data to the serial connectiondelay(5000);digitalWrite(22, LOW);digitalWrite(8, LOW);String dataRec = createDataRecord();logData(dataRec);Serial.println(dataRec);getdata();//Save the data record to the log file}delay(1000);systemSleep();}void getdata(){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 readingRTD.send_read_cmd();EC.send_read_cmd();next_poll_time = millis() + response_delay; //set when the response will arrivereading_request_phase = false; //switch to the receiving phase}else { //if were in the receiving phaseif (millis() >= next_poll_time) { //and its time to get the responsereceive_reading(RTD); //get the reading from the PH circuit//Serial.print(" ");receive_reading(EC); //get the reading from the EC circuit//Serial.println();reading_request_phase = true; //switch back to asking for readings}}}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 setup//void sensorsWake()//{//// digitalWrite(22, HIGH); //Turn on power to EZO ckt// Serial.println("..I'm awake!");// delay(100);////}//void sensorsSleep(){Serial.println("..going to sleep!");// digitalWrite(22, LOW); //Turn off power to EZO ckt// delay(100); //adding delay fixed the never-sleep problem}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 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 readingSensor.receive_read_cmd(); //get the response data and put it into the [Sensor].reading variable if successful}void setupLogFile(){//Initialise the SD cardSD.begin(SD_SS_PIN);//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();}String createDataRecord(){DateTime now = rtc.now(); //get the current date-timeuint32_t ts = now.getEpoch();//Create a String type data record in csv formatString data = "";data += samplenum; //creates a string called "data", put in the sample numberdata += ","; //adds a comma between valuesdata += millis();data += ",";data += (now.year());data +=('/');data += (now.month());data += ('/');data += (now.date());data += (' ');data += (now.hour());data += (':');data += (now.minute());data += (':');data += (now.second());data += ",";//Write pressure, temp to recorddata += RTD.get_last_received_reading(), 1;data += ",";data += EC.get_last_received_reading(), 0;data += ",";batterysenseValue = analogRead(batteryPin);batteryvoltage = (3.3 / 1023.) * 4.7 * batterysenseValue;data += batteryvoltage;// data += pressure_relative;samplenum++; //increment the sample numberdelay(delayTime);return data;} -
2020-10-26 at 2:13 PM #14715
It looks like this code was based on one of our old sleeping Mayfly logger example sketches, but there’s some stuff in the main Loop that is out of order. I’m assuming you’ve got the Atlas sensors connected to the I2C Grove port on the Mayfly. If you want to be able to switch their power on and off, then you need to move the small jumper on the headers pins next to those Grove ports to the 3.3v-SWITCHED position. Then you need to turn on the sensor power pin (D22) on and off in your code. Pin D8 is the green LED and your code sets it low once but never does anything else with it. I typically turn the green LED on when the board is awake and taking a reading, to let the use know that something is happening. You’ll also see the red LED by the Grove sockets turn on when the switched power is turned on, too. You’ve also got to run the sensor sampling function while the sensor power is on, and in your code you’ve got that happening after everything, including writing the data. I didn’t go through the entire sketch to look for all problems, but I think fixing a few things in the main Loop will get you most of the way to solving your issue. Here’s how I would write that section, but you might want to change it based on your goals.
123456789101112131415161718192021222324252627void loop() {//Update the timertimer.update();if(currentminute % sleepMinutes == 0) // change "2" to "5" to wake up logger every 5 minutes instead{ Serial.println("Multiple of 1! Initiating sensor reading and logging data to SDcard....");digitalWrite(8, HIGH); // turn the Green led pin ondigitalWrite(22, HIGH); // turn the switched power ondelay(5000); //wait 5 seconds for the sensors to stabilize?getdata(); //take readings from the Atlas sensorsdigitalWrite(22, LOW); //turn the switched power offdigitalWrite(8, LOW); //turn the green LED offString dataRec = createDataRecord(); //puts timestamp and sensor data into a stringlogData(dataRec); //Save the data record to the log fileSerial.println(dataRec); //Echo the data to the serial connection}delay(1000);systemSleep();} -
2020-10-26 at 2:42 PM #14716
Thanks! I worked through a couple of things, including your suggestions, and I still can’t get the logger to wake up… I know the switch works because if I set it to HIGH in the setup the board does come on and the sensors read/turn on without the sleep functions (and the RTC is functioning/correct). Do I need to have a wakeup function or something in the getdata() function for the sensors as well?
-
2020-10-26 at 2:53 PM #14717
Is the board sleeping all the time and not waking? Or is it awake all the time and not sleeping? Is data being saved to the card or printed to the serial terminal?
-
2020-10-26 at 2:55 PM #14718
It is sleeping all the time and not waking. No data is being saved or printed to the serial terminal.
-
2020-10-26 at 3:39 PM #14719
I just compiled and ran your code on my own Mayfly board (replacing the Loop function with the one I edited above), and commenting out anything relate to the Atlas sensors since I don’t have any here for testing, and the Mayfly board slept properly, woke up every minute and took a “sample”, wrote data to the card, and went back to sleep.
If you board isn’t waking up and you don’t even have the two header lines on your memory card, then that means your board isn’t even getting to the main loop. I would guess there’s problem with either your memory card, memory card socket, RTC chip or battery (you have the positive side of the coin cell facing up, right?), or something wrong in your sensor wiring that is either shorting something out or causing the sketch to lock up before it can run.
-
2020-10-26 at 10:50 PM #14721
Thanks for troubleshooting the code. Looking at it more…It works with one sensor but not with both on the same I2C hub. It seems that there is a problem when both grounds are connected to the hub with the sleep/RTC pin. I have tried multiple hubs/cables to no avail. Starting to think it is a conflict with one of the sleep functions/libraries because I can run 2 sensors on this hub just fine if I don’t have the sleep code.
-
2020-10-29 at 10:50 AM #14738
I am using the same hardware with my Low Cost EC stations which is set up for UART mode but I have since upgraded to I2C mode when I added the 2G modems. I am using the sensorex probe for the EZO EC which has an integral RTD which I read thru the analog input. I think its only about a $30 premium for the the RTD option. Maybe there are some ideas in my blog that will help.
-
2020-10-29 at 9:02 PM #14755
I’m sorry I’m late to the game on this one.
Shannon said more clearly what I would have said. But re-reading, I remember that the Atlas sensors are special. You can’t cut the power to the Atlas circuits while they’re connected to the I2C bus of the Mayfly or your program will crash. The Atlas circuits have the I2C lines pulled up to the voltage in line. If you set the voltage in to ground (ie, turn it off) the I2C lines get pulled down as well. The Arduino I2C (Wire) library hangs forever when that happens. So if you want to power down your Atlas sensors you need to get an isolator.
-
2020-10-29 at 9:11 PM #14756
All of the Atlas sensors do have a built in sleep command that you can use for low power without needing the isolator. You should be able to add ‘RTD.send_cmd(“SLEEP”);’ and ‘EC.send_cmd(“SLEEP”);’ to your system sleep function.
-
2020-11-16 at 10:29 AM #14823
Thanks, @srgdamiano and @shicks! After working through the code, what seemed to work was actually placing the sensor sleep commands in my getdata() function. For whatever reason it didn’t work too well in the systemSleep function as it seemed to stall my sensors and not allow enough time to wakeup the sensors for reading. Still working on cleaning up the code, but will share for those that are interested once I get everything up and running!
-
-
-
AuthorPosts
- You must be logged in to reply to this topic.