From e07b6a04679ff762371294fa777f1b6926e9d7a8 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 13:53:07 -0400 Subject: [PATCH 01/12] Removed overloads and renamed all "stream" functions to the less confusing "print" --- src/LoggerBase.cpp | 32 ++++--------------- src/LoggerBase.h | 10 ++---- src/LoggerDreamHost.cpp | 71 +++++------------------------------------ src/LoggerDreamHost.h | 20 +++--------- src/LoggerEnviroDIY.cpp | 67 ++++++-------------------------------- src/LoggerEnviroDIY.h | 26 ++++----------- 6 files changed, 39 insertions(+), 187 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 7c0375ebb..cff63a791 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -539,7 +539,7 @@ void Logger::generateAutoFileName(void) stream->println(); // This sends a file header out over an Arduino stream -void Logger::streamFileHeader(Stream *stream) +void Logger::printFileHeader(Stream *stream) { // Very first line of the header is the logger ID stream->print(F("Data Logger: ")); @@ -566,27 +566,9 @@ void Logger::streamFileHeader(Stream *stream) } -// This generates a comma separated list of volues of sensor data - including the time -String Logger::generateSensorDataCSV(void) -{ - String csvString = ""; - markedDateTime.addToString(csvString); - csvString += F(","); - - for (uint8_t i = 0; i < _internalArray->getVariableCount(); i++) - { - csvString += _internalArray->arrayOfVars[i]->getValueString(); - if (i + 1 != _internalArray->getVariableCount()) - { - csvString += F(","); - } - } - - return csvString; -} -// This sends a comma separated list of volues of sensor data - including the +// This prints a comma separated list of volues of sensor data - including the // time - out over an Arduino stream -void Logger::streamSensorDataCSV(Stream *stream) +void Logger::printSensorDataCSV(Stream *stream) { String csvString = ""; markedDateTime.addToString(csvString); @@ -670,11 +652,11 @@ bool Logger::openFile(String& filename, bool createFile, bool writeDefaultHeader if (writeDefaultHeader) { // Add header information - streamFileHeader(&logFile); + printFileHeader(&logFile); // Print out the header for debugging #if defined(DEBUGGING_SERIAL_OUTPUT) MS_DBG(F("\n \\/---- File Header ----\\/ ")); - streamFileHeader(&DEBUGGING_SERIAL_OUTPUT); + printFileHeader(&DEBUGGING_SERIAL_OUTPUT); MS_DBG('\n'); #endif // Set write/modification date time @@ -783,11 +765,11 @@ bool Logger::logToSD(void) } // Write the data - streamSensorDataCSV(&logFile); + printSensorDataCSV(&logFile); // Echo the line to the serial port #if defined(STANDARD_SERIAL_OUTPUT) PRINTOUT(F("\n \\/---- Line Saved to SD Card ----\\/ ")); - streamSensorDataCSV(&STANDARD_SERIAL_OUTPUT); + printSensorDataCSV(&STANDARD_SERIAL_OUTPUT); PRINTOUT('\n'); #endif diff --git a/src/LoggerBase.h b/src/LoggerBase.h index 007427d74..5494c6625 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -39,8 +39,6 @@ #include // To communicate with the SD card -static String LOGGER_EMPTY = ""; - // Defines the "Logger" Class class Logger { @@ -140,13 +138,11 @@ class Logger // This prints a header onto a stream - this removes need to pass around // very long string objects which can crash the logger - virtual void streamFileHeader(Stream *stream); + virtual void printFileHeader(Stream *stream); - // This generates a comma separated list of volues of sensor data - including the time - String generateSensorDataCSV(void); - // This sends a comma separated list of volues of sensor data - including the + // This prints a comma separated list of volues of sensor data - including the // time - out over an Arduino stream - void streamSensorDataCSV(Stream *stream); + void printSensorDataCSV(Stream *stream); // These functions create a file on an SD card and set the created/modified/ // accessed timestamps in that file. diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 30063a530..3ab6b288e 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -31,25 +31,8 @@ void LoggerDreamHost::setDreamHostPortalRX(const char *URL) } -// This creates all of the URL parameters -String LoggerDreamHost::generateSensorDataDreamHost(void) -{ - String dhString = String(_DreamHostPortalRX); - dhString += F("?LoggerID="); - dhString += String(Logger::_loggerID); - dhString += F("&Loggertime="); - dhString += String(Logger::markedEpochTime - 946684800); // Coorect time from epoch to y2k - - for (int i = 0; i < _internalArray->getVariableCount(); i++) - { - dhString += F("&"); - dhString += _internalArray->arrayOfVars[i]->getVarCode(); - dhString += F("="); - dhString += _internalArray->arrayOfVars[i]->getValueString(); - } - return dhString; -} -void LoggerDreamHost::streamSensorDataDreamHost(Stream *stream) +// This prints the URL out to an Arduino stream +void LoggerDreamHost::printSensorDataDreamHost(Stream *stream) { stream->print(String(_DreamHostPortalRX)); stream->print(String(F("?LoggerID=")) + String(Logger::_loggerID)); @@ -61,63 +44,27 @@ void LoggerDreamHost::streamSensorDataDreamHost(Stream *stream) + String(F("=")) + String(_internalArray->arrayOfVars[i]->getValueString())); } } -void LoggerDreamHost::streamSensorDataDreamHost(Stream& stream) -{ - streamSensorDataDreamHost(&stream); -} - - -// // This generates a fully structured GET request for DreamHost -// String LoggerDreamHost::generateDreamHostGetRequest(String fullURL) -// { -// String GETstring = String(F("GET ")); -// GETstring += String(fullURL); -// GETstring += String(F(" HTTP/1.1")); -// GETstring += String(F("\r\nHost: swrcsensors.dreamhosters.com")); -// GETstring += String(F("\r\n\r\n")); -// return GETstring; -// } -// String LoggerDreamHost::generateDreamHostGetRequest(void) -// { -// return generateDreamHostGetRequest(generateSensorDataDreamHost()); -// } // This prints a fully structured GET request for DreamHost to the -// specified stream using the specified url. -void LoggerDreamHost::streamDreamHostRequest(Stream *stream, String& fullURL) -{ - stream->print(String(F("GET "))); - stream->print(fullURL); - stream->print(String(F(" HTTP/1.1"))); - stream->print(String(F("\r\nHost: swrcsensors.dreamhosters.com"))); - stream->print(String(F("\r\n\r\n"))); -} -void LoggerDreamHost::streamDreamHostRequest(Stream& stream, String& fullURL) -{ - streamDreamHostRequest(&stream, fullURL); -} -void LoggerDreamHost::streamDreamHostRequest(Stream *stream) +// specified stream +void LoggerDreamHost::printDreamHostRequest(Stream *stream) { // Start the request stream->print(String(F("GET "))); // Stream the full URL with parameters - streamSensorDataDreamHost(stream); + printSensorDataDreamHost(stream); // Send the rest of the HTTP header stream->print(String(F(" HTTP/1.1"))); stream->print(String(F("\r\nHost: swrcsensors.dreamhosters.com"))); stream->print(String(F("\r\n\r\n"))); } -void LoggerDreamHost::streamDreamHostRequest(Stream& stream) -{ - streamDreamHostRequest(&stream); -} // Post the data to dream host. -int LoggerDreamHost::postDataDreamHost(String& fullURL) +int LoggerDreamHost::postDataDreamHost(void) { // do not continue if no modem! if (_logModem == NULL) @@ -136,14 +83,12 @@ int LoggerDreamHost::postDataDreamHost(String& fullURL) // Send the request to the serial for debugging #if defined(STANDARD_SERIAL_OUTPUT) PRINTOUT(F("\n \\/------ Data to DreamHost ------\\/ ")); - if (fullURL.length() > 1) streamDreamHostRequest(&STANDARD_SERIAL_OUTPUT, fullURL); - else streamDreamHostRequest(&STANDARD_SERIAL_OUTPUT); + printDreamHostRequest(&STANDARD_SERIAL_OUTPUT); STANDARD_SERIAL_OUTPUT.flush(); #endif // Send the request to the modem stream - if (fullURL.length() > 1) streamDreamHostRequest(_logModem->_tinyClient, fullURL); - else streamDreamHostRequest(_logModem->_tinyClient); + printDreamHostRequest(_logModem->_tinyClient); _logModem->_tinyClient->flush(); // wait for sending to finish uint32_t start_timer = millis(); diff --git a/src/LoggerDreamHost.h b/src/LoggerDreamHost.h index 936a107c8..3ea8aeff1 100644 --- a/src/LoggerDreamHost.h +++ b/src/LoggerDreamHost.h @@ -37,29 +37,17 @@ class LoggerDreamHost : public LoggerEnviroDIY void setDreamHostPortalRX(const char *URL); // This creates all of the URL parameters - String generateSensorDataDreamHost(void); - void streamSensorDataDreamHost(Stream *stream); - void streamSensorDataDreamHost(Stream& stream); + void printSensorDataDreamHost(Stream *stream); - // // This generates a fully structured GET request for DreamHost - // String generateDreamHostGetRequest(String fullURL); - // String generateDreamHostGetRequest(void); - - // This prints a fully structured GET request for DreamHost to the - // specified stream using the specified url. - // This may be necessary to work around very long strings for the post request. - void streamDreamHostRequest(Stream *stream, String& fullURL); - void streamDreamHostRequest(Stream& stream, String& fullURL); // This prints a fully structured GET request for DreamHost to the - // specified stream with the default url. - void streamDreamHostRequest(Stream *stream); - void streamDreamHostRequest(Stream& stream); + // specified stream. + void printDreamHostRequest(Stream *stream); // This utilizes an attached modem to make a TCP connection to the // DreamHost URL and then streams out a get request // over that connection. // The return is the http status code of the response. - int postDataDreamHost(String& fullURL = LOGGER_EMPTY); + int postDataDreamHost(void); // This prevents the logging function from dual-posting to EnviroDIY void disableDualPost(void); diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 821bcb964..9e4141231 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -75,7 +75,7 @@ void LoggerEnviroDIY::setSamplingFeatureUUID(const char *samplingFeature) stream->println(); // This adds extra data to the datafile header -void LoggerEnviroDIY::streamFileHeader(Stream *stream) +void LoggerEnviroDIY::printFileHeader(Stream *stream) { // Very first line of the header is the logger ID stream->print(F("Data Logger: ")); @@ -86,7 +86,7 @@ void LoggerEnviroDIY::streamFileHeader(Stream *stream) stream->println(_fileName); // Next we're going to print the sampling feature UUID - // NOTE: This is the only line different from in Logger::streamFileHeader + // NOTE: This is the only line different from in Logger::printFileHeader stream->print(F("Sampling Feature UUID: ")); stream->println(_samplingFeature); @@ -107,30 +107,8 @@ void LoggerEnviroDIY::streamFileHeader(Stream *stream) } -// This generates a properly formatted JSON for EnviroDIY -String LoggerEnviroDIY::generateSensorDataJSON(void) -{ - String jsonString = F("{"); - jsonString += F("\"sampling_feature\": \""); - jsonString += String(_samplingFeature) + F("\", "); - jsonString += F("\"timestamp\": \""); - jsonString += String(Logger::markedISO8601Time) + F("\", "); - - for (int i = 0; i < _internalArray->getVariableCount(); i++) - { - jsonString += F("\""); - jsonString += _internalArray->arrayOfVars[i]->getVarUUID() + F("\": "); - jsonString += _internalArray->arrayOfVars[i]->getValueString(); - if (i + 1 != _internalArray->getVariableCount()) - { - jsonString += F(", "); - } - } - - jsonString += F("}"); - return jsonString; -} -void LoggerEnviroDIY::streamSensorDataJSON(Stream *stream) +// This prints a properly formatted JSON for EnviroDIY to an Arduino stream +void LoggerEnviroDIY::printSensorDataJSON(Stream *stream) { stream->print(String(F("{"))); stream->print(String(F("\"sampling_feature\": \""))); @@ -149,30 +127,11 @@ void LoggerEnviroDIY::streamSensorDataJSON(Stream *stream) stream->print(F("}")); } -void LoggerEnviroDIY::streamSensorDataJSON(Stream& stream) -{ - streamSensorDataJSON(&stream); -} // This prints a fully structured post request for EnviroDIY to the -// specified stream using the specified json. -void LoggerEnviroDIY::streamEnviroDIYRequest(Stream *stream, String& enviroDIYjson) -{ - stream->print(String(F("POST /api/data-stream/ HTTP/1.1"))); - stream->print(String(F("\r\nHost: data.envirodiy.org"))); - stream->print(String(F("\r\nTOKEN: ")) + String(_registrationToken)); - // stream->print(String(F("\r\nCache-Control: no-cache"))); - // stream->print(String(F("\r\nConnection: close"))); - stream->print(String(F("\r\nContent-Length: ")) + String(enviroDIYjson.length())); - stream->print(String(F("\r\nContent-Type: application/json\r\n\r\n"))); - stream->print(String(enviroDIYjson)); -} -void LoggerEnviroDIY::streamEnviroDIYRequest(Stream& stream, String& enviroDIYjson) -{ - streamEnviroDIYRequest(&stream, enviroDIYjson); -} -void LoggerEnviroDIY::streamEnviroDIYRequest(Stream *stream) +// specified stream. +void LoggerEnviroDIY::printEnviroDIYRequest(Stream *stream) { // First we need to calculate how long the json string is going to be // This is needed for the "Content-Length" header @@ -204,11 +163,7 @@ void LoggerEnviroDIY::streamEnviroDIYRequest(Stream *stream) stream->print(String(F("\r\nContent-Type: application/json\r\n\r\n"))); // Stream the JSON itself - streamSensorDataJSON(stream); -} -void LoggerEnviroDIY::streamEnviroDIYRequest(Stream& stream) -{ - streamEnviroDIYRequest(&stream); + printSensorDataJSON(stream); } @@ -216,7 +171,7 @@ void LoggerEnviroDIY::streamEnviroDIYRequest(Stream& stream) // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. // The return is the http status code of the response. -int LoggerEnviroDIY::postDataEnviroDIY(String& enviroDIYjson) +int LoggerEnviroDIY::postDataEnviroDIY(void) { // do not continue if no modem! if (_logModem == NULL) @@ -235,15 +190,13 @@ int LoggerEnviroDIY::postDataEnviroDIY(String& enviroDIYjson) // Send the request to the serial for debugging #if defined(STANDARD_SERIAL_OUTPUT) PRINTOUT(F("\n \\/---- Post Request to EnviroDIY ----\\/ ")); - if (enviroDIYjson.length() > 1) streamEnviroDIYRequest(&STANDARD_SERIAL_OUTPUT, enviroDIYjson); - else streamEnviroDIYRequest(&STANDARD_SERIAL_OUTPUT); + printEnviroDIYRequest(&STANDARD_SERIAL_OUTPUT); PRINTOUT('\n'); STANDARD_SERIAL_OUTPUT.flush(); #endif // Send the request to the modem stream - if (enviroDIYjson.length() > 1) streamEnviroDIYRequest(_logModem->_tinyClient, enviroDIYjson); - else streamEnviroDIYRequest(_logModem->_tinyClient); + printEnviroDIYRequest(_logModem->_tinyClient); _logModem->_tinyClient->flush(); // wait for sending to finish uint32_t start_timer = millis(); diff --git a/src/LoggerEnviroDIY.h b/src/LoggerEnviroDIY.h index fecc0e4dd..55b8f7e0e 100644 --- a/src/LoggerEnviroDIY.h +++ b/src/LoggerEnviroDIY.h @@ -43,32 +43,20 @@ class LoggerEnviroDIY : public Logger void setSamplingFeatureUUID(const char *samplingFeature); // This adds extra data to the datafile header - void streamFileHeader(Stream *stream) override; + void printFileHeader(Stream *stream) override; // This generates a properly formatted JSON for EnviroDIY - String generateSensorDataJSON(void); - void streamSensorDataJSON(Stream *stream); - void streamSensorDataJSON(Stream& stream); - - // // This generates a fully structured POST request for EnviroDIY - // String generateEnviroDIYPostRequest(String enviroDIYjson); - // String generateEnviroDIYPostRequest(void); - - // This prints a fully structured post request for EnviroDIY to the - // specified stream using the specified json. - // This may be necessary to work around very long strings for the post request. - void streamEnviroDIYRequest(Stream *stream, String& enviroDIYjson); - void streamEnviroDIYRequest(Stream& stream, String& enviroDIYjson); - // This prints a fully structured post request for EnviroDIY to the - // specified stream with the default json. - void streamEnviroDIYRequest(Stream *stream); - void streamEnviroDIYRequest(Stream& stream); + void printSensorDataJSON(Stream *stream); + + // This prints a fully structured post request for WikiWatershed/EnviroDIY + // to the specified stream. + void printEnviroDIYRequest(Stream *stream); // This utilizes an attached modem to make a TCP connection to the // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. // The return is the http status code of the response. - int postDataEnviroDIY(String& enviroDIYjson = LOGGER_EMPTY); + int postDataEnviroDIY(void); // ===================================================================== // // Convience functions to call several of the above functions From 8680984dd0d9206be53e70ba810f50993004fe12 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 14:31:18 -0400 Subject: [PATCH 02/12] starting queueing fxn --- src/LoggerEnviroDIY.cpp | 35 +++++++++++++++++++++++++++++++++++ src/LoggerEnviroDIY.h | 3 +++ 2 files changed, 38 insertions(+) diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 9e4141231..ac262adf1 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -167,6 +167,41 @@ void LoggerEnviroDIY::printEnviroDIYRequest(Stream *stream) } +// This writes the post request to a "queue" file for later +bool LoggerEnviroDIY::queueDataEnviroDIY(void) +{ + String queueFile = "EnviroDIYQueue.txt"; + // First attempt to open the file without creating a new one + if (!openFile(queueFile, true, false)) + { + // Next try to create the file, bail if we couldn't create it + // This will not attempt to generate a new file name or add a header! + if (!openFile(queueFile, true, false)) + { + PRINTOUT(F("Unable to write to SD card!")); + return false; + } + } + + // If we could successfully open or create the file, write the request to it + printEnviroDIYRequest(&logFile); + // Echo the line to the serial port + #if defined(STANDARD_SERIAL_OUTPUT) + PRINTOUT(F("\n \\/---- Queued POST request ----\\/ ")); + printEnviroDIYRequest(&STANDARD_SERIAL_OUTPUT); + PRINTOUT('\n'); + #endif + + // Set write/modification date time + setFileTimestamp(logFile, T_WRITE); + // Set access date time + setFileTimestamp(logFile, T_ACCESS); + // Close the file to save it + logFile.close(); + return true; +} + + // This utilizes an attached modem to make a TCP connection to the // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. diff --git a/src/LoggerEnviroDIY.h b/src/LoggerEnviroDIY.h index 55b8f7e0e..53a9d7d94 100644 --- a/src/LoggerEnviroDIY.h +++ b/src/LoggerEnviroDIY.h @@ -52,6 +52,9 @@ class LoggerEnviroDIY : public Logger // to the specified stream. void printEnviroDIYRequest(Stream *stream); + // This writes the post request to a "queue" file for later + bool queueDataEnviroDIY(void); + // This utilizes an attached modem to make a TCP connection to the // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. From bfdada710c33f4cd43448820d2d4e136bf36c95a Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 14:43:58 -0400 Subject: [PATCH 03/12] Made continueSleep fxn --- src/LoggerBase.cpp | 10 ++++++++++ src/LoggerBase.h | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index cff63a791..a54356f15 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -972,3 +972,13 @@ void Logger::log(void) // Sleep if(_mcuWakePin >= 0){systemSleep();} } + + +// This function immediately puts the logger back to sleep +// This would be used to allow a logger to continue to gain charge and not +// begin logging until reaching a power threshold +void Logger::continueSleep(void) +{ + // Sleep + if(_mcuWakePin >= 0){systemSleep();} +} diff --git a/src/LoggerBase.h b/src/LoggerBase.h index 5494c6625..e40b68db8 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -193,6 +193,12 @@ class Logger // This is a one-and-done to log data virtual void log(void); + // This function immediately puts the logger back to sleep + // This would be used to allow a logger to continue to gain charge and not + // begin logging until reaching a power threshold + virtual void continueSleep(void); + + // Public variables // Time stamps - want to set them at a single time and carry them forward static uint32_t markedEpochTime; @@ -231,11 +237,15 @@ class Logger uint16_t _loggingIntervalMinutes; int8_t _SDCardPin; int8_t _mcuWakePin; - VariableArray *_internalArray; - - uint8_t _numTimepointsLogged; int8_t _ledPin; int8_t _buttonPin; + VariableArray *_internalArray; + + // The number of time points that have been logged. + // NOTE: This is not intended to be a perfect count, and it will zero + // after every time the logger restarts (such as running out of battery). + // A value of -1 indicates that set-up hasn't been run. + int8_t _numTimepointsLogged; // This checks if the SD card is available and ready // We run this check before every communication with the SD card to prevent From 6ffbf1cea789ac86e2e6d96a9dd61befb7e098ef Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 15:41:34 -0400 Subject: [PATCH 04/12] Can begin w/o setting up sensors and have them set-up later --- src/LoggerBase.cpp | 67 ++++++++++++++++++++++++++++++----------- src/LoggerBase.h | 12 +++++--- src/LoggerDreamHost.cpp | 24 +++++++++++++-- src/LoggerEnviroDIY.cpp | 29 +++++++++++++++++- 4 files changed, 106 insertions(+), 26 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index a54356f15..d40ac668a 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -48,8 +48,8 @@ Logger::Logger(const char *loggerID, uint16_t loggingIntervalMinutes, _mcuWakePin = mcuWakePin; _internalArray = inputArray; - // Initialize with no points recorded - _numTimepointsLogged = 0; + // Initialize with a negative number of intervals - that is, set-up not run + _numIntervals = -1; // Set the testing/logging flags to false isLoggingNow = false; @@ -258,11 +258,11 @@ bool Logger::checkInterval(void) MS_DBG(F("Current Unix Timestamp: "), checkTime); MS_DBG(F("Logging interval in seconds: "), (_loggingIntervalMinutes*60)); MS_DBG(F("Mod of Logging Interval: "), checkTime % (_loggingIntervalMinutes*60)); - MS_DBG(F("Number of Readings so far: "), _numTimepointsLogged); + MS_DBG(F("Number of Intervals so far: "), _numIntervals); MS_DBG(F("Mod of 120: "), checkTime % 120); if ((checkTime % (_loggingIntervalMinutes*60) == 0 ) or - (_numTimepointsLogged < 10 and checkTime % 120 == 0)) + (_numIntervals < 10 and checkTime % 120 == 0)) { // Update the time variables with the current time markTime(); @@ -274,8 +274,8 @@ bool Logger::checkInterval(void) MS_DBG(F(" minute: "), markedDateTime.minute()); MS_DBG(F(" second: "), markedDateTime.second()); MS_DBG(F("Time marked at [char]: "), markedISO8601Time); - // Update the number of readings taken - _numTimepointsLogged ++; + // Tick up the number of intervals + _numIntervals++; MS_DBG(F("Time to log!")); retval = true; } @@ -296,15 +296,15 @@ bool Logger::checkMarkedInterval(void) MS_DBG(F("Marked Time: "), markedEpochTime); MS_DBG(F("Logging interval in seconds: "), (_loggingIntervalMinutes*60)); MS_DBG(F("Mod of Logging Interval: "), markedEpochTime % (_loggingIntervalMinutes*60)); - MS_DBG(F("Number of Readings so far: "), _numTimepointsLogged); + MS_DBG(F("Number of Intervals so far: "), _numIntervals); MS_DBG(F("Mod of 120: "), markedEpochTime % 120); if (markedEpochTime != 0 && ((markedEpochTime % (_loggingIntervalMinutes*60) == 0 ) or - (_numTimepointsLogged < 10 and markedEpochTime % 120 == 0))) + (_numIntervals < 10 and markedEpochTime % 120 == 0))) { - // Update the number of readings taken - _numTimepointsLogged ++; + // Tick up the number of intervals + _numIntervals++; MS_DBG(F("Time to log!")); retval = true; } @@ -882,8 +882,10 @@ void Logger::testingMode() // Convience functions to call several of the above functions // ===================================================================== // -// This calls all of the setup functions - must be run AFTER init - void Logger::begin(void) +// This does all of the setup that can't happen in the constructors +// That is, things that require the actual processor/MCU to do something +// rather than the compiler to do something. + void Logger::begin(bool skipSensorSetup) { // Set up pins for the LED and button if (_ledPin >= 0) pinMode(_ledPin, OUTPUT); @@ -908,17 +910,29 @@ void Logger::testingMode() F(" come from "),_internalArray->getSensorCount(), F(" sensors and "), _internalArray->getCalculatedVariableCount(), F(" are calculated.")); - // Set up the sensors - _internalArray->setupSensors(); + if (!skipSensorSetup) + { + // Set up the sensors + PRINTOUT(F("Setting up sensors.")); + _internalArray->setupSensors(); + + // Create the log file, adding the default header to it + if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); + else PRINTOUT(F("Unable to create a file to save data to!")); - // Create the log file, adding the default header to it - if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); - else PRINTOUT(F("Unable to create a file to save data to!")); + // Set the number of intervals to 0 + // When the logger instance is created, it will have _numIntervals set to -1. + // We use the negative value to indicate that the sensors and log file have + // not been set up + _numIntervals = 0; + } // Setup sleep mode if(_mcuWakePin >= 0){setupSleep();} // Set up the interrupt to be able to enter sensor testing mode + // NOTE: Entering testing mode before the sensors have been set-up may + // give unexpected results. if (_buttonPin >= 0) { enableInterrupt(_buttonPin, Logger::testingISR, CHANGE); @@ -938,8 +952,27 @@ void Logger::testingMode() // This is a one-and-done to log data void Logger::log(void) { + // If the number of intervals is negative, then the sensors and file on + // the SD card haven't been setup and we want to set them up. + // NOTE: Unless it completed in less than one second, the sensor set-up + // will take the place of logging for this interval! + if (_numIntervals < 0) + { + // Set up the sensors + _internalArray->setupSensors(); + + // Create the log file, adding the default header to it + if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); + else PRINTOUT(F("Unable to create a file to save data to!")); + + // Now, set the number of intervals to 0 + _numIntervals = 0; + } + // Assuming we were woken up by the clock, check if the current time is an // even interval of the logging interval + // NOTE: When checkInterval() returns true, it also ticks up the value of + // _numIntervals. if (checkInterval()) { // Flag to notify that we're in already awake and logging a point diff --git a/src/LoggerBase.h b/src/LoggerBase.h index e40b68db8..7fb350be7 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -187,8 +187,10 @@ class Logger // ===================================================================== // // Convience functions to call several of the above functions // ===================================================================== // - // This calls all of the setup functions - must be run AFTER init - virtual void begin(void); + // This does all of the setup that can't happen in the constructors + // That is, things that require the actual processor/MCU to do something + // rather than the compiler to do something. + virtual void begin(bool skipSensorSetup = false); // This is a one-and-done to log data virtual void log(void); @@ -241,11 +243,11 @@ class Logger int8_t _buttonPin; VariableArray *_internalArray; - // The number of time points that have been logged. + // The number of logging intervals that have passed. // NOTE: This is not intended to be a perfect count, and it will zero // after every time the logger restarts (such as running out of battery). - // A value of -1 indicates that set-up hasn't been run. - int8_t _numTimepointsLogged; + // A value of -1 indicates that sensor set-up hasn't been run! + int8_t _numIntervals; // This checks if the SD card is available and ready // We run this check before every communication with the SD card to prevent diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 3ab6b288e..15b0f8997 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -97,8 +97,7 @@ int LoggerDreamHost::postDataDreamHost(void) // Read only the first 12 characters of the response // We're only reading as far as the http code, anything beyond that - // we don't care about so we're not reading to save on total - // data used for transmission. + // we don't care about. did_respond = _logModem->_tinyClient->readBytes(response_buffer, 12); // Close the TCP/IP connection as soon as the first 12 characters are read @@ -141,8 +140,27 @@ void LoggerDreamHost::disableDualPost(void) // This is a one-and-done to log data void LoggerDreamHost::logAndSend(void) { + // If the number of intervals is negative, then the sensors and file on + // the SD card haven't been setup and we want to set them up. + // NOTE: Unless it completed in less than one second, the sensor set-up + // will take the place of logging for this interval! + if (_numIntervals < 0) + { + // Set up the sensors + _internalArray->setupSensors(); + + // Create the log file, adding the default header to it + if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); + else PRINTOUT(F("Unable to create a file to save data to!")); + + // Now, set the number of intervals to 0 + _numIntervals = 0; + } + // Assuming we were woken up by the clock, check if the current time is an // even interval of the logging interval + // NOTE: When checkInterval() returns true, it also ticks up the value of + // _numIntervals. if (checkInterval()) { // Flag to notify that we're in already awake and logging a point @@ -180,7 +198,7 @@ void LoggerDreamHost::logAndSend(void) // Sync the clock every 288 readings (1/day at 5 min intervals) MS_DBG(F(" Running a daily clock sync...")); - if (_numTimepointsLogged % 288 == 0) + if (_numIntervals % 288 == 0) { syncRTClock(_logModem->getNISTTime()); } diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index ac262adf1..3534889b7 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -302,6 +302,8 @@ void LoggerEnviroDIY::testingMode() { PRINTOUT(F("------------------------------------------")); // Update the values from all attached sensors + // NOTE: NOT using complete update because we want everything left + // on between iterations in testing mode. _internalArray->updateAllSensors(); // Print out the current logger time PRINTOUT(F("Current logger time is ")); @@ -386,6 +388,12 @@ void LoggerEnviroDIY::beginAndSync(void) if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); else PRINTOUT(F("Unable to create a file to save data to!")); + // Set the number of intervals to 0 + // When the logger instance is created, it will have _numIntervals set to -1. + // We use the negative value to indicate that the sensors and log file have + // not been set up + _numIntervals = 0; + if (_logModem != NULL) { // Print out the modem info @@ -429,8 +437,27 @@ void LoggerEnviroDIY::beginAndSync(void) // This is a one-and-done to log data void LoggerEnviroDIY::logAndSend(void) { + // If the number of intervals is negative, then the sensors and file on + // the SD card haven't been setup and we want to set them up. + // NOTE: Unless it completed in less than one second, the sensor set-up + // will take the place of logging for this interval! + if (_numIntervals < 0) + { + // Set up the sensors + _internalArray->setupSensors(); + + // Create the log file, adding the default header to it + if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); + else PRINTOUT(F("Unable to create a file to save data to!")); + + // Now, set the number of intervals to 0 + _numIntervals = 0; + } + // Assuming we were woken up by the clock, check if the current time is an // even interval of the logging interval + // NOTE: When checkInterval() returns true, it also ticks up the value of + // _numIntervals. if (checkInterval()) { // Flag to notify that we're in already awake and logging a point @@ -462,7 +489,7 @@ void LoggerEnviroDIY::logAndSend(void) // Sync the clock every 288 readings (1/day at 5 min intervals) MS_DBG(F(" Running a daily clock sync...")); - if (_numTimepointsLogged % 288 == 0) + if (_numIntervals % 288 == 0) { syncRTClock(_logModem->getNISTTime()); } From c7d9f4ad6fc0960f780b693b7485c3f5d1e8db76 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 17:49:03 -0400 Subject: [PATCH 05/12] Don't need continueSleep, use systemSleep --- src/LoggerBase.cpp | 11 +---------- src/LoggerBase.h | 5 ----- src/LoggerDreamHost.cpp | 1 + src/LoggerEnviroDIY.cpp | 1 + 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index d40ac668a..9e0ff708e 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -959,6 +959,7 @@ void Logger::log(void) if (_numIntervals < 0) { // Set up the sensors + PRINTOUT(F("Setting up sensors.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it @@ -1005,13 +1006,3 @@ void Logger::log(void) // Sleep if(_mcuWakePin >= 0){systemSleep();} } - - -// This function immediately puts the logger back to sleep -// This would be used to allow a logger to continue to gain charge and not -// begin logging until reaching a power threshold -void Logger::continueSleep(void) -{ - // Sleep - if(_mcuWakePin >= 0){systemSleep();} -} diff --git a/src/LoggerBase.h b/src/LoggerBase.h index 7fb350be7..3c4f009f9 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -195,11 +195,6 @@ class Logger // This is a one-and-done to log data virtual void log(void); - // This function immediately puts the logger back to sleep - // This would be used to allow a logger to continue to gain charge and not - // begin logging until reaching a power threshold - virtual void continueSleep(void); - // Public variables // Time stamps - want to set them at a single time and carry them forward diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 15b0f8997..5444fb638 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -147,6 +147,7 @@ void LoggerDreamHost::logAndSend(void) if (_numIntervals < 0) { // Set up the sensors + PRINTOUT(F("Setting up sensors.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 3534889b7..7fd5422a0 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -444,6 +444,7 @@ void LoggerEnviroDIY::logAndSend(void) if (_numIntervals < 0) { // Set up the sensors + PRINTOUT(F("Setting up sensors.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it From 9b6f63be9fd1679a1b9f38f958f27fc3be5961cb Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 17 Oct 2018 18:46:39 -0400 Subject: [PATCH 06/12] Added extra power down to setup just in case --- examples/data_saving/data_saving.ino | 20 ++++++++++++++++++-- src/LoggerBase.cpp | 18 ++++++++++-------- src/LoggerDreamHost.cpp | 4 ++-- src/LoggerEnviroDIY.cpp | 22 +++++++++++----------- src/SensorBase.cpp | 3 +-- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/examples/data_saving/data_saving.ino b/examples/data_saving/data_saving.ino index 52d057bb5..9d89fa886 100644 --- a/examples/data_saving/data_saving.ino +++ b/examples/data_saving/data_saving.ino @@ -530,11 +530,18 @@ void setup() loggerToGo.setToken(registrationToken); loggerToGo.setSamplingFeatureUUID(samplingFeature); + // Update the Mayfly "sensor" to get us updated battery voltages + // We'll use the battery voltage to decide which version of the begin() to use + // NOTE: This update happens very fast + mayfly.update(); + // Because we've given it a modem and it knows all of the tokens, we can // just "begin" the complete logger to set up the datafile, clock, sleep, // and all of the sensors. We don't need to bother with the "begin" for the // other logger because it has the same processor and clock. - loggerComplete.begin(); + if (mayflyBatt->getValue() < 3.4) loggerComplete.begin(true); // skip sensor set-up + else if (mayflyBatt->getValue() < 3.7) loggerComplete.begin(); // set up sensors + else loggerComplete.beginAndSync(); // set up sensors and synchronize clock with NIST } @@ -546,9 +553,16 @@ void setup() // and start the loop every minute exactly on the minute. void loop() { + // Update the Mayfly "sensor" to get us updated battery voltages + // NOTE: This update happens fast enough that it won't throw off the check + // interval timing. If the update took more than 1 second to run, + // it would throw off the checkInterval() function. + mayfly.update(); + // Assuming we were woken up by the clock, check if the current time is an // even interval of the logging interval - if (loggerComplete.checkInterval()) + // We're only doing anything at all if the battery is above 3.4V + if (loggerComplete.checkInterval() && mayflyBatt->getValue() > 3.4) { // Print a line to show new reading Serial.print(F("------------------------------------------\n")); @@ -571,6 +585,8 @@ void loop() // Do a complete update on the "full" array. // This will do all the power management + // NOTE: The wake function for each sensor should force sensor setup + // to run if the sensor was not previously set up. Serial.print(F("Updating all sensors...\n")); arrayComplete.completeUpdate(); diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 9e0ff708e..3771fcc8c 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -855,8 +855,7 @@ void Logger::testingMode() // on between iterations in testing mode. _internalArray->updateAllSensors(); // Print out the current logger time - PRINTOUT(F("Current logger time is ")); - PRINTOUT(formatDateTime_ISO8601(getNowEpoch())); + PRINTOUT(F("Current logger time is "), formatDateTime_ISO8601(getNowEpoch())); PRINTOUT(F(" -----------------------")); // Print out the sensor data #if defined(STANDARD_SERIAL_OUTPUT) @@ -889,7 +888,7 @@ void Logger::testingMode() { // Set up pins for the LED and button if (_ledPin >= 0) pinMode(_ledPin, OUTPUT); - if (_buttonPin >= 0) pinMode(_buttonPin, INPUT); + if (_buttonPin >= 0) pinMode(_buttonPin, INPUT_PULLUP); #if defined ARDUINO_ARCH_SAMD zero_sleep_rtc.begin(); @@ -913,7 +912,7 @@ void Logger::testingMode() if (!skipSensorSetup) { // Set up the sensors - PRINTOUT(F("Setting up sensors.")); + PRINTOUT(F("Setting up sensors...")); _internalArray->setupSensors(); // Create the log file, adding the default header to it @@ -936,11 +935,14 @@ void Logger::testingMode() if (_buttonPin >= 0) { enableInterrupt(_buttonPin, Logger::testingISR, CHANGE); - PRINTOUT(F("Push button on pin ")); - PRINTOUT(_buttonPin); - PRINTOUT(F(" at any time to enter sensor testing mode.")); + PRINTOUT(F("Push button on pin "), _buttonPin, + F(" at any time to enter sensor testing mode.")); } + // Make sure all sensors are powered down at the end + // The should be, but just in case + _internalArray->sensorsPowerDown(); + PRINTOUT(F("Logger setup finished!")); PRINTOUT(F("------------------------------------------\n")); @@ -959,7 +961,7 @@ void Logger::log(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Setting up sensors.")); + PRINTOUT(F("Sensors had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 5444fb638..0b319d710 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -147,7 +147,7 @@ void LoggerDreamHost::logAndSend(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Setting up sensors.")); + PRINTOUT(F("Sensors had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it @@ -198,9 +198,9 @@ void LoggerDreamHost::logAndSend(void) postDataDreamHost(); // Sync the clock every 288 readings (1/day at 5 min intervals) - MS_DBG(F(" Running a daily clock sync...")); if (_numIntervals % 288 == 0) { + MS_DBG(F(" Running a daily clock sync...")); syncRTClock(_logModem->getNISTTime()); } diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 7fd5422a0..181c0a825 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -306,8 +306,7 @@ void LoggerEnviroDIY::testingMode() // on between iterations in testing mode. _internalArray->updateAllSensors(); // Print out the current logger time - PRINTOUT(F("Current logger time is ")); - PRINTOUT(formatDateTime_ISO8601(getNowEpoch())); + PRINTOUT(F("Current logger time is "), formatDateTime_ISO8601(getNowEpoch())); PRINTOUT(F(" -----------------------")); // Print out the sensor data #if defined(STANDARD_SERIAL_OUTPUT) @@ -319,9 +318,7 @@ void LoggerEnviroDIY::testingMode() { // Specially highlight the modem signal quality in the debug mode _logModem->update(); - PRINTOUT(F("Current modem signal is ")); - PRINTOUT(_logModem->getSignalPercent()); - PRINTOUT(F("%")); + PRINTOUT(F("Current modem signal is "), _logModem->getSignalPercent(), "%"); } delay(5000); @@ -381,7 +378,7 @@ void LoggerEnviroDIY::beginAndSync(void) if (_logModem != NULL) _logModem->modemPowerUp(); // Set up the sensors, this includes the modem - PRINTOUT(F("Setting up sensors.")); + PRINTOUT(F("Setting up sensors...")); _internalArray->setupSensors(); // Create the log file, adding the default header to it @@ -421,11 +418,14 @@ void LoggerEnviroDIY::beginAndSync(void) if (_buttonPin >= 0) { enableInterrupt(_buttonPin, Logger::testingISR, CHANGE); - PRINTOUT(F("Push button on pin ")); - PRINTOUT(_buttonPin); - PRINTOUT(F(" at any time to enter sensor testing mode.")); + PRINTOUT(F("Push button on pin "), _buttonPin, + F(" at any time to enter sensor testing mode.")); } + // Make sure all sensors are powered down at the end + // The should be, but just in case + _internalArray->sensorsPowerDown(); + PRINTOUT(F("Logger setup finished!")); PRINTOUT(F("------------------------------------------\n")); @@ -444,7 +444,7 @@ void LoggerEnviroDIY::logAndSend(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Setting up sensors.")); + PRINTOUT(F("Sensors had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it @@ -489,9 +489,9 @@ void LoggerEnviroDIY::logAndSend(void) postDataEnviroDIY(); // Sync the clock every 288 readings (1/day at 5 min intervals) - MS_DBG(F(" Running a daily clock sync...")); if (_numIntervals % 288 == 0) { + MS_DBG(F(" Running a daily clock sync...")); syncRTClock(_logModem->getNISTTime()); } diff --git a/src/SensorBase.cpp b/src/SensorBase.cpp index 2520cede5..2503d9a1f 100644 --- a/src/SensorBase.cpp +++ b/src/SensorBase.cpp @@ -171,8 +171,7 @@ bool Sensor::setup(void) _stabilizationTime_ms, F("ms, and takes a single measurement in "), _measurementTime_ms, F("ms.")); - MS_DBG(_measurementsToAverage); - MS_DBG(F(" individual measurements will be averaged for each reading.")); + MS_DBG(_measurementsToAverage, F(" individual measurements will be averaged for each reading.")); if (_powerPin >= 0) pinMode(_powerPin, OUTPUT); if (_dataPin >= 0) pinMode(_dataPin, INPUT); From 737d650fe4f6e9895b54979c36b31e8946ce8fc8 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 12:08:45 -0400 Subject: [PATCH 07/12] Fixed all wasOn/off --- src/LoggerModem.cpp | 9 +++++++-- src/SensorBase.cpp | 6 +++--- src/sensors/BoschBME280.cpp | 2 +- src/sensors/FreescaleMPL115A2.cpp | 2 +- src/sensors/MaximDS18.cpp | 2 +- src/sensors/MeaSpecMS5803.cpp | 2 +- src/sensors/SDI12Sensors.cpp | 8 ++------ 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/LoggerModem.cpp b/src/LoggerModem.cpp index 460342965..7a8462aa8 100644 --- a/src/LoggerModem.cpp +++ b/src/LoggerModem.cpp @@ -70,7 +70,7 @@ bool loggerModem::setup(void) // NOTE: We ar NOT powering up the modem! Set up will NOT be successful // unless the modem is already powered external to this function. bool wasAwake = ( (_dataPin >= 0 && digitalRead(_dataPin) == _statusLevel) - && !bitRead(_sensorStatus, 4) ); + || bitRead(_sensorStatus, 4) ); if (!wasAwake) { MS_MOD_DBG(F("Running modem's wake function ...")); @@ -273,8 +273,13 @@ bool loggerModem::setup(void) else _sensorStatus |= 0b10000000; // Put the modem to sleep after finishing setup - if(wasAwake || (_dataPin >= 0 && digitalRead(_dataPin) == _statusLevel)) + // Only go to sleep if it had been asleep and is now awake + bool isAwake = ( (_dataPin >= 0 && digitalRead(_dataPin) == _statusLevel) + || bitRead(_sensorStatus, 4) ); + if (!wasAwake && isAwake) success &= _sleepFxn(); + // Do NOT power down at the end, because this fxn cannot have powered the + // modem up. return success; } diff --git a/src/SensorBase.cpp b/src/SensorBase.cpp index 2503d9a1f..909993a05 100644 --- a/src/SensorBase.cpp +++ b/src/SensorBase.cpp @@ -173,8 +173,8 @@ bool Sensor::setup(void) MS_DBG(_measurementsToAverage, F(" individual measurements will be averaged for each reading.")); - if (_powerPin >= 0) pinMode(_powerPin, OUTPUT); - if (_dataPin >= 0) pinMode(_dataPin, INPUT); + if (_powerPin >= 0) pinMode(_powerPin, OUTPUT); // NOTE: Not setting value + if (_dataPin >= 0) pinMode(_dataPin, INPUT); // NOTE: Not turning on pull-up! // Set the status bit marking that the sensor has been set up (bit 0) _sensorStatus |= 0b00000001; @@ -410,7 +410,7 @@ bool Sensor::update(void) if(wasActive){sleep();} // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} // Update the registered variables with the new values notifyVariables(); diff --git a/src/sensors/BoschBME280.cpp b/src/sensors/BoschBME280.cpp index 913d0aecb..baf236f20 100644 --- a/src/sensors/BoschBME280.cpp +++ b/src/sensors/BoschBME280.cpp @@ -80,7 +80,7 @@ bool BoschBME280::setup(void) retVal &= success; // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} return retVal; } diff --git a/src/sensors/FreescaleMPL115A2.cpp b/src/sensors/FreescaleMPL115A2.cpp index cb72d15e2..b173026cb 100644 --- a/src/sensors/FreescaleMPL115A2.cpp +++ b/src/sensors/FreescaleMPL115A2.cpp @@ -53,7 +53,7 @@ bool MPL115A2::setup(void) mpl115a2_internal.begin(); // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} return retVal; } diff --git a/src/sensors/MaximDS18.cpp b/src/sensors/MaximDS18.cpp index 0c83db8c6..48a16abd7 100644 --- a/src/sensors/MaximDS18.cpp +++ b/src/sensors/MaximDS18.cpp @@ -159,7 +159,7 @@ bool MaximDS18::setup(void) _internalDallasTemp.setWaitForConversion(false); // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} if (!retVal) // if set-up failed { diff --git a/src/sensors/MeaSpecMS5803.cpp b/src/sensors/MeaSpecMS5803.cpp index 43122d4e8..de90da618 100644 --- a/src/sensors/MeaSpecMS5803.cpp +++ b/src/sensors/MeaSpecMS5803.cpp @@ -72,7 +72,7 @@ bool MeaSpecMS5803::setup(void) MS5803_internal.reset(); // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} return retVal; } diff --git a/src/sensors/SDI12Sensors.cpp b/src/sensors/SDI12Sensors.cpp index 95a43483b..df66922bf 100644 --- a/src/sensors/SDI12Sensors.cpp +++ b/src/sensors/SDI12Sensors.cpp @@ -82,7 +82,7 @@ bool SDI12Sensors::setup(void) _SDI12Internal.end(); // Turn the power back off it it had been turned on - if(wasOn){powerDown();} + if(!wasOn){powerDown();} if (!retVal) // if set-up failed { @@ -162,11 +162,7 @@ bool SDI12Sensors::getSensorInfo(void) _SDI12Internal.clearBuffer(); // Check that the sensor is there and responding - if (!requestSensorAcknowledgement()) - { - // if(!wasOn){powerDown();} - return false; - } + if (!requestSensorAcknowledgement()) return false; MS_DBG(F(" Getting sensor info")); String myCommand = ""; From c992fd7fc81c9a9335388f4c7f3ecb78cc2927d1 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 12:44:58 -0400 Subject: [PATCH 08/12] Removed some unnecessary static variables. Also making sure file name is always generated. --- src/LoggerBase.cpp | 50 +++++++++++++++++++++++++---------------- src/LoggerBase.h | 6 ++--- src/LoggerEnviroDIY.cpp | 6 +++-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 3771fcc8c..cad2910b8 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -23,8 +23,8 @@ int8_t Logger::_timeZone = 0; int8_t Logger::_offset = 0; // Initialize the static timestamps uint32_t Logger::markedEpochTime = 0; -DateTime Logger::markedDateTime = 0; -char Logger::markedISO8601Time[26]; +// DateTime Logger::markedDateTime = 0; +// char Logger::markedISO8601Time[26]; // Initialize the testing/logging flags volatile bool Logger::isLoggingNow = false; volatile bool Logger::isTestingNow = false; @@ -244,8 +244,8 @@ bool Logger::syncRTClock(uint32_t nist) void Logger::markTime(void) { Logger::markedEpochTime = getNowEpoch(); - Logger::markedDateTime = dtFromEpoch(markedEpochTime); - formatDateTime_ISO8601(markedDateTime).toCharArray(markedISO8601Time, 26); + // Logger::markedDateTime = dtFromEpoch(markedEpochTime); + // formatDateTime_ISO8601(markedDateTime).toCharArray(markedISO8601Time, 26); } @@ -267,13 +267,6 @@ bool Logger::checkInterval(void) // Update the time variables with the current time markTime(); MS_DBG(F("Time marked at (unix): "), markedEpochTime); - MS_DBG(F(" year: "), markedDateTime.year()); - MS_DBG(F(" month: "), markedDateTime.month()); - MS_DBG(F(" date: "), markedDateTime.date()); - MS_DBG(F(" hour: "), markedDateTime.hour()); - MS_DBG(F(" minute: "), markedDateTime.minute()); - MS_DBG(F(" second: "), markedDateTime.second()); - MS_DBG(F("Time marked at [char]: "), markedISO8601Time); // Tick up the number of intervals _numIntervals++; MS_DBG(F("Time to log!")); @@ -310,7 +303,7 @@ bool Logger::checkMarkedInterval(void) } else { - MS_DBG(F("Not time yet, back to sleep")); + MS_DBG(F("Not time yet.")); retval = false; } return retval; @@ -324,7 +317,10 @@ bool Logger::checkMarkedInterval(void) // Set up the Interrupt Service Request for waking // In this case, we're doing nothing, we just want the processor to wake // This must be a static function (which means it can only call other static funcions.) -void Logger::wakeISR(void){MS_DBG(F("Clock interrupt!"));} +void Logger::wakeISR(void) +{ + // MS_DBG(F("Clock interrupt!")); +} #if defined ARDUINO_ARCH_SAMD @@ -369,6 +365,9 @@ void Logger::wakeISR(void){MS_DBG(F("Clock interrupt!"));} // Put the processor into sleep mode. zero_sleep_rtc.standbyMode(); + // --------------------------------------------------------------------- + // -- The portion below this happens on wake up, after any wake ISR's -- + // Reattach the USB after waking USBDevice.attach(); @@ -459,6 +458,7 @@ void Logger::wakeISR(void){MS_DBG(F("Clock interrupt!"));} // Set the sleep enable bit. sleep_enable(); + // Re-enables interrupts so we can wake up again interrupts(); @@ -466,7 +466,8 @@ void Logger::wakeISR(void){MS_DBG(F("Clock interrupt!"));} // This must happen after the SE bit is set. sleep_cpu(); - // ----------------- This portion happens on wake up ----------------- + // --------------------------------------------------------------------- + // -- The portion below this happens on wake up, after any wake ISR's -- // Re-enable all power modules (ie, the processor module clocks) // NOTE: This only re-enables the various clocks on the processor! @@ -571,7 +572,7 @@ void Logger::printFileHeader(Stream *stream) void Logger::printSensorDataCSV(Stream *stream) { String csvString = ""; - markedDateTime.addToString(csvString); + dtFromEpoch(markedEpochTime).addToString(csvString); csvString += F(","); stream->print(csvString); for (uint8_t i = 0; i < _internalArray->getVariableCount(); i++) @@ -743,12 +744,17 @@ bool Logger::logToSD(String& filename, String& rec) } bool Logger::logToSD(String& rec) { + // Get a new file name if the name is blank + if (_fileName == "") generateAutoFileName(); return logToSD(_fileName, rec); } // NOTE: This is structured differently than the version with a string input // record. This is to avoid the creation/passing of very long strings. bool Logger::logToSD(void) { + // Get a new file name if the name is blank + if (_fileName == "") generateAutoFileName(); + // First attempt to open the file without creating a new one if (!openFile(_fileName, false, false)) { @@ -793,7 +799,7 @@ bool Logger::logToSD(void) void Logger::checkForTestingMode(int8_t buttonPin) { // Set the pin attached to some button to enter debug mode - if (buttonPin >= 0) pinMode(buttonPin, INPUT); + if (buttonPin >= 0) pinMode(buttonPin, INPUT_PULLUP); // Flash the LED to let user know it is now possible to enter debug mode for (uint8_t i = 0; i < 15; i++) @@ -819,11 +825,11 @@ void Logger::checkForTestingMode(int8_t buttonPin) // A static function if you'd prefer to enter testing based on an interrupt void Logger::testingISR() { - MS_DBG(F("Testing interrupt!")); + // MS_DBG(F("Testing interrupt!")); if (!Logger::isTestingNow && !Logger::isLoggingNow) { Logger::startTesting = true; - MS_DBG(F("Testing flag has been set.")); + // MS_DBG(F("Testing flag has been set.")); } } @@ -887,7 +893,11 @@ void Logger::testingMode() void Logger::begin(bool skipSensorSetup) { // Set up pins for the LED and button - if (_ledPin >= 0) pinMode(_ledPin, OUTPUT); + if (_ledPin >= 0) + { + pinMode(_ledPin, OUTPUT); + digitalWrite(_ledPin, LOW); + } if (_buttonPin >= 0) pinMode(_buttonPin, INPUT_PULLUP); #if defined ARDUINO_ARCH_SAMD @@ -916,6 +926,7 @@ void Logger::testingMode() _internalArray->setupSensors(); // Create the log file, adding the default header to it + if (_autoFileName) generateAutoFileName(); if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); else PRINTOUT(F("Unable to create a file to save data to!")); @@ -965,6 +976,7 @@ void Logger::log(void) _internalArray->setupSensors(); // Create the log file, adding the default header to it + if (_autoFileName) generateAutoFileName(); if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); else PRINTOUT(F("Unable to create a file to save data to!")); diff --git a/src/LoggerBase.h b/src/LoggerBase.h index 3c4f009f9..b43533d73 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -28,7 +28,7 @@ #include #endif -// Bring in the library to commuinicate with an external high-precision real time clock +// Bring in the library to communicate with an external high-precision real time clock // This also implements a needed date/time class #include #define EPOCH_TIME_OFF 946684800 @@ -226,8 +226,8 @@ class Logger static int8_t _offset; // Time stamps - want to set them at a single time and carry them forward - static DateTime markedDateTime; - static char markedISO8601Time[26]; + // static DateTime markedDateTime; + // static char markedISO8601Time[26]; // Initialization variables const char *_loggerID; diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 181c0a825..295db038e 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -114,7 +114,7 @@ void LoggerEnviroDIY::printSensorDataJSON(Stream *stream) stream->print(String(F("\"sampling_feature\": \""))); stream->print(String(_samplingFeature)); + F(""); stream->print(String(F("\", \"timestamp\": \""))); - stream->print(String(Logger::markedISO8601Time) + F("\", ")); + stream->print(String(formatDateTime_ISO8601(markedEpochTime)) + F("\", ")); for (int i = 0; i < _internalArray->getVariableCount(); i++) { @@ -353,7 +353,7 @@ void LoggerEnviroDIY::beginAndSync(void) { // Set up pins for the LED and button if (_ledPin >= 0) pinMode(_ledPin, OUTPUT); - if (_buttonPin >= 0) pinMode(_buttonPin, INPUT); + if (_buttonPin >= 0) pinMode(_buttonPin, INPUT_PULLUP); #if defined ARDUINO_ARCH_SAMD zero_sleep_rtc.begin(); @@ -382,6 +382,7 @@ void LoggerEnviroDIY::beginAndSync(void) _internalArray->setupSensors(); // Create the log file, adding the default header to it + if (_autoFileName) generateAutoFileName(); if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); else PRINTOUT(F("Unable to create a file to save data to!")); @@ -448,6 +449,7 @@ void LoggerEnviroDIY::logAndSend(void) _internalArray->setupSensors(); // Create the log file, adding the default header to it + if (_autoFileName) generateAutoFileName(); if (createLogFile(true)) PRINTOUT(F("Data will be saved as "), _fileName); else PRINTOUT(F("Unable to create a file to save data to!")); From 8d15276130f82881761367f31d622767601a8625 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 13:32:40 -0400 Subject: [PATCH 09/12] How did I never notice I'd over written a basic mathematical function?! --- examples/DRWI_CitSci/DRWI_CitSci.ino | 4 +- examples/DRWI_NoCellular/DRWI_NoCellular.ino | 2 +- examples/ReadMe.md | 2 +- .../baro_rho_correction.ino | 4 +- examples/double_logger/ReadMe.md | 2 +- .../logging_to_EnviroDIY.ino | 166 ++++++++++-------- .../logging_to_EnviroDIY_Zero.ino | 2 +- examples/simple_logging/simple_logging.ino | 2 +- sensor_tests/AnthonyTest2/AnthonyTest2.ino | 4 +- src/LoggerBase.cpp | 4 +- src/LoggerBase.h | 2 +- src/LoggerDreamHost.cpp | 2 +- src/LoggerDreamHost.h | 2 +- src/LoggerEnviroDIY.cpp | 2 +- src/LoggerEnviroDIY.h | 2 +- 15 files changed, 111 insertions(+), 91 deletions(-) diff --git a/examples/DRWI_CitSci/DRWI_CitSci.ino b/examples/DRWI_CitSci/DRWI_CitSci.ino index 2ca28a92c..d75fe9f55 100644 --- a/examples/DRWI_CitSci/DRWI_CitSci.ino +++ b/examples/DRWI_CitSci/DRWI_CitSci.ino @@ -282,6 +282,6 @@ void loop() // Log the data if (mayflyBatt->getValue() > 3.7) // This will check against the battery level at the previous logging interval! - EnviroDIYLogger.logAndSend(); - else EnviroDIYLogger.log(); + EnviroDIYLogger.logDataAndSend(); + else EnviroDIYLogger.logData(); } diff --git a/examples/DRWI_NoCellular/DRWI_NoCellular.ino b/examples/DRWI_NoCellular/DRWI_NoCellular.ino index 851777867..e565a39d3 100644 --- a/examples/DRWI_NoCellular/DRWI_NoCellular.ino +++ b/examples/DRWI_NoCellular/DRWI_NoCellular.ino @@ -186,5 +186,5 @@ void setup() void loop() { // Log the data - logger.log(); + logger.logData(); } diff --git a/examples/ReadMe.md b/examples/ReadMe.md index aacb278a1..29554da62 100644 --- a/examples/ReadMe.md +++ b/examples/ReadMe.md @@ -43,7 +43,7 @@ This is uses just the sensors and equipment standard to the DWRI Citizen Science This example demonstrates how to work with calculated variables. ### double_logger.ino -This is a more complicated example using two different logger instances to log data at two different intervals, in this case, an AM3215 logging every minute, while checking the battery voltage only every 5 minutes. This showcases both how to use two different logging instances and how to use some of the functions to set up your own logging loop rather than using the log() function. +This is a more complicated example using two different logger instances to log data at two different intervals, in this case, an AM3215 logging every minute, while checking the battery voltage only every 5 minutes. This showcases both how to use two different logging instances and how to use some of the functions to set up your own logging loop rather than using the logData() function. ### data_saving.ino This is another double logger example, but in this case, both loggers are going at the same interval and the only difference between the loggers is the list of variables. There are two sets of variables, all coming from Yosemitech sensors. Because each sensor outputs temperature and we don't want to waste cellular data sending out multiple nearly identical temperature values, we have one logger that logs every possible variable result to the SD card and another logger that sends only unique results to the EnviroDIY data portal. diff --git a/examples/baro_rho_correction/baro_rho_correction.ino b/examples/baro_rho_correction/baro_rho_correction.ino index 826465058..bdfca4aaf 100644 --- a/examples/baro_rho_correction/baro_rho_correction.ino +++ b/examples/baro_rho_correction/baro_rho_correction.ino @@ -581,6 +581,6 @@ void loop() // Log the data if (mayflyBatt->getValue() > 3.7) // This will check against the battery level at the previous logging interval! - EnviroDIYLogger.logAndSend(); - else EnviroDIYLogger.log(); + EnviroDIYLogger.logDataAndSend(); + else EnviroDIYLogger.logData(); } diff --git a/examples/double_logger/ReadMe.md b/examples/double_logger/ReadMe.md index f5c3205ae..af9770b39 100644 --- a/examples/double_logger/ReadMe.md +++ b/examples/double_logger/ReadMe.md @@ -1,3 +1,3 @@ # Example using the Modular Sensors Library to Record data from Two Different Groups of Sensors at Two Different Time Intervals -This is a more complicated example using two different logger instances to log data at two different intervals, in this case, an AM3215 logging every minute, while checking the battery voltage only every 5 minutes. This showcases both how to use two different logging instances and how to use some of the functions to set up your own logging loop rather than using the log() function. +This is a more complicated example using two different logger instances to log data at two different intervals, in this case, an AM3215 logging every minute, while checking the battery voltage only every 5 minutes. This showcases both how to use two different logging instances and how to use some of the functions to set up your own logging loop rather than using the logData() function. diff --git a/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino b/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino index c3d23b54d..6473ff89e 100644 --- a/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino +++ b/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino @@ -72,17 +72,6 @@ ProcessorStats mayfly(MFVersion); // Set the serial port for the modem - software serial can also be used. HardwareSerial &ModemSerial = Serial1; -// Create a variable for the modem baud rate - this will be used in the begin function for the port -#if defined(TINY_GSM_MODEM_XBEE) -const long ModemBaud = 9600; // Default for XBee is 9600 -#elif defined(TINY_GSM_MODEM_ESP8266) -const long ModemBaud = 57600; // Default for ESP8266 is 115200, but the Mayfly itself stutters above 57600 -#elif defined(TINY_GSM_MODEM_UBLOX) -const long ModemBaud = 9600; // SARA-U201 default seems to be 9600 -#else -const long ModemBaud = 9600; -#endif - // Create a new TinyGSM modem to run on that serial port and return a pointer to it TinyGsm *tinyModem = new TinyGsm(ModemSerial); @@ -94,88 +83,62 @@ TinyGsm *tinyModem = new TinyGsm(ModemSerial); // Create a new TCP client on that modem and return a pointer to it TinyGsmClient *tinyClient = new TinyGsmClient(*tinyModem); -// Describe the physical pin connection of your modem to your board #if defined(TINY_GSM_MODEM_XBEE) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) const bool modemStatusLevel = LOW; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_ESP8266) -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) -const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) -const int8_t modemSleepRqPin = 19; // MCU pin used for wake from light sleep (-1 if not applicable) -const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) -const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_UBLOX) -const int8_t modemVccPin = 23; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 20; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#else -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#endif - // And create the wake and sleep methods for the modem // These can be functions of any type and must return a boolean -#if defined(TINY_GSM_MODEM_XBEE) // After setting up pin sleep, the sleep request pin is held LOW to keep the XBee on -bool wakeFxn(void) +// Use XCTU to set up pin sleep! +bool sleepFxn(void) { - if (modemVccPin >= 0) // Turns on when power is applied - return true; - else + if (modemSleepRqPin >= 0) // Don't go to sleep if there's not a wake pin! { - digitalWrite(modemSleepRqPin, LOW); - digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights + digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, LOW); return true; } + else return true; } -bool sleepFxn(void) -{ - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, LOW); - return true; -} -#elif defined(TINY_GSM_MODEM_ESP8266) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied - { - digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights - return true; - } - else if (modemResetPin >= 0) - { - digitalWrite(modemResetPin, LOW); - delay(1); - digitalWrite(modemResetPin, HIGH); - digitalWrite(redLED, HIGH); return true; - } else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); - delay(1); - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, HIGH); + digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights return true; } else return true; } + +#elif defined(TINY_GSM_MODEM_ESP8266) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 57600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) +const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) +const int8_t modemSleepRqPin = 19; // MCU pin used for wake from light sleep (-1 if not applicable) +const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) +const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool sleepFxn(void) { - // Use this if you have an external pin connected to the reset pin to wake from deep sleep + // Use this if you have an MCU pin connected to the ESP's reset pin to wake from deep sleep if (modemResetPin >= 0) { digitalWrite(redLED, LOW); return tinyModem->poweroff(); } // Use this if you have GPIO16 connected to the reset pin to wake from deep sleep + // but no other MCU pin connected to the reset pin. // NOTE: This will NOT work nicely with things like "testingMode" and the // initial 2-minute logging interval at boot up. // if (loggingInterval > 1) @@ -188,8 +151,9 @@ bool sleepFxn(void) // return tinyModem->waitResponse() == 1; // } // Use this if you don't have access to the ESP8266's reset pin for deep sleep but you - // do have access to another GPIO pin for light sleep - if (modemSleepRqPin >= 0 && modemStatusPin >= 0) + // do have access to another GPIO pin for light sleep. This also sets up another + // pin to view the sleep status. + else if (modemSleepRqPin >= 0 && modemStatusPin >= 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0,"), String(espStatusPin), GF(","), modemStatusLevel); @@ -199,6 +163,7 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } + // Light sleep without the status pin else if (modemSleepRqPin >= 0 && modemStatusPin < 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0")); @@ -208,46 +173,94 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } - else return true; + else return true; // DON'T go to sleep if we can't wake up! } -#elif defined(TINY_GSM_MODEM_UBLOX) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied + { + digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights return true; - else if(modemSleepRqPin >= 0) + } + else if (modemResetPin >= 0) + { + digitalWrite(modemResetPin, LOW); + delay(1); + digitalWrite(modemResetPin, HIGH); + digitalWrite(redLED, HIGH); + return true; + } + else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); + delay(1); + digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, HIGH); - delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 - // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 + return true; + } + else return true; +} + +#elif defined(TINY_GSM_MODEM_UBLOX) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = 23; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 20; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean +bool sleepFxn(void) +{ + if (modemVccPin >= 0 && modemSleepRqPin < 0) + return tinyModem->poweroff(); + else if (modemSleepRqPin >= 0) + { + digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, HIGH); // A light to watch to verify pulse timing + delay(1100); // >1s pulse for power down digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; // DON'T go to sleep if we can't wake up! } -bool sleepFxn(void) +bool wakeFxn(void) { - if (modemSleepRqPin < 0) return tinyModem->poweroff(); - else + if (modemVccPin >= 0) // Turns on when power is applied + return true; + else if(modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); digitalWrite(redLED, HIGH); - delay(1100); // >1s pulse for power down + delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 + // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; } + #else +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool wakeFxn(void) { digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, HIGH); // A light just for show return true; } bool sleepFxn(void) { digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, LOW); return true; } #endif @@ -700,6 +713,7 @@ Variable *variableList[] = { int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); + // Create a new logger instance #include LoggerEnviroDIY EnviroDIYLogger(LoggerID, loggingInterval, sdCardPin, wakePin, &varArray); @@ -740,6 +754,12 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); + // Print a start-up note to the first serial port + Serial.print(F("Now running ")); + Serial.print(sketchName); + Serial.print(F(" on Logger ")); + Serial.println(LoggerID); + // Start the serial connection with the modem ModemSerial.begin(ModemBaud); @@ -831,5 +851,5 @@ void setup() void loop() { // Log the data - EnviroDIYLogger.logAndSend(); + EnviroDIYLogger.logDataAndSend(); } diff --git a/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino b/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino index 2506ab81a..caf921e78 100644 --- a/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino +++ b/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino @@ -833,5 +833,5 @@ void setup() void loop() { // Log the data - EnviroDIYLogger.logAndSend(); + EnviroDIYLogger.logDataAndSend(); } diff --git a/examples/simple_logging/simple_logging.ino b/examples/simple_logging/simple_logging.ino index 63e788c2f..c14eec596 100644 --- a/examples/simple_logging/simple_logging.ino +++ b/examples/simple_logging/simple_logging.ino @@ -552,5 +552,5 @@ void setup() void loop() { // Log the data - logger.log(); + logger.logData(); } diff --git a/sensor_tests/AnthonyTest2/AnthonyTest2.ino b/sensor_tests/AnthonyTest2/AnthonyTest2.ino index 9b0a72209..3489483cf 100644 --- a/sensor_tests/AnthonyTest2/AnthonyTest2.ino +++ b/sensor_tests/AnthonyTest2/AnthonyTest2.ino @@ -970,6 +970,6 @@ void loop() // Log the data if (mayflyBatt->getValue() > 3.7) // This will check against the battery level at the previous logging interval! - EnviroDIYLogger.logAndSend(); - else EnviroDIYLogger.log(); + EnviroDIYLogger.logDataAndSend(); + else EnviroDIYLogger.logData(); } diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index cad2910b8..90ff9dff7 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -389,7 +389,7 @@ void Logger::wakeISR(void) // cannot interrupt on any frequencies other than every second, minute, // hour, day, or date. We could set it to alarm hourly every 5 minutes past // the hour, but not every 5 minutes. This is why we set the alarm for - // every minute and still need the timer function. This is a hardware + // every minute and use the checkInterval function. This is a hardware // limitation of the DS3231; it is not due to the libraries or software. rtc.enableInterrupts(EveryMinute); @@ -963,7 +963,7 @@ void Logger::testingMode() // This is a one-and-done to log data -void Logger::log(void) +void Logger::logData(void) { // If the number of intervals is negative, then the sensors and file on // the SD card haven't been setup and we want to set them up. diff --git a/src/LoggerBase.h b/src/LoggerBase.h index b43533d73..d8da13f0c 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -193,7 +193,7 @@ class Logger virtual void begin(bool skipSensorSetup = false); // This is a one-and-done to log data - virtual void log(void); + virtual void logData(void); // Public variables diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 0b319d710..3f2cf187f 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -138,7 +138,7 @@ void LoggerDreamHost::disableDualPost(void) // ===================================================================== // // This is a one-and-done to log data -void LoggerDreamHost::logAndSend(void) +void LoggerDreamHost::logDataAndSend(void) { // If the number of intervals is negative, then the sensors and file on // the SD card haven't been setup and we want to set them up. diff --git a/src/LoggerDreamHost.h b/src/LoggerDreamHost.h index 3ea8aeff1..45b3dda98 100644 --- a/src/LoggerDreamHost.h +++ b/src/LoggerDreamHost.h @@ -57,7 +57,7 @@ class LoggerDreamHost : public LoggerEnviroDIY // ===================================================================== // // This is a one-and-done to log data - virtual void logAndSend(void) override; + virtual void logDataAndSend(void) override; private: const char *_DreamHostPortalRX; diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 295db038e..74371db0c 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -436,7 +436,7 @@ void LoggerEnviroDIY::beginAndSync(void) // This is a one-and-done to log data -void LoggerEnviroDIY::logAndSend(void) +void LoggerEnviroDIY::logDataAndSend(void) { // If the number of intervals is negative, then the sensors and file on // the SD card haven't been setup and we want to set them up. diff --git a/src/LoggerEnviroDIY.h b/src/LoggerEnviroDIY.h index 53a9d7d94..9cfd33f71 100644 --- a/src/LoggerEnviroDIY.h +++ b/src/LoggerEnviroDIY.h @@ -74,7 +74,7 @@ class LoggerEnviroDIY : public Logger virtual void beginAndSync(void); // This is a one-and-done to log data - virtual void logAndSend(void); + virtual void logDataAndSend(void); // The internal modem instance loggerModem *_logModem; From 9e5b848c5126ac44d102f94303bed6234e389403 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 15:10:01 -0400 Subject: [PATCH 10/12] More thorough checking that we'll wake up before sleeping --- src/LoggerBase.cpp | 54 ++++++++++++++++++++++++++++--------- src/LoggerDreamHost.cpp | 2 +- src/LoggerEnviroDIY.cpp | 2 +- src/sensors/MaximDS3231.cpp | 2 +- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 90ff9dff7..6eaa9adc0 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -417,10 +417,30 @@ void Logger::wakeISR(void) DEBUGGING_SERIAL_OUTPUT.flush(); // for debugging #endif - // This clears the interrrupt flag in status register of the clock + // Make sure the RTC is still sending out interrupts + rtc.enableInterrupts(EveryMinute); + + // Clear the last interrupt flag in the RTC status register // The next timed interrupt will not be sent until this is cleared rtc.clearINTStatus(); + // Make sure we're still set up to handle the clock interrupt + pinMode(_mcuWakePin, INPUT_PULLUP); + enableInterrupt(_mcuWakePin, wakeISR, CHANGE); + + // Stop any I2C connections + // This function actually disables the two-wire pin functionality and + // turns off the internal pull-up resistors. + // It does NOT set the pin mode! + Wire.end(); + // Now force the I2C pins to LOW + // I2C devices have a nasty habit of stealing power from the SCL and SDA pins... + // This will only work for the "main" I2C/TWI interface + pinMode(SDA, OUTPUT); // set output mode + pinMode(SCL, OUTPUT); + digitalWrite(SDA, LOW); // Set the pins low + digitalWrite(SCL, LOW); + // Temporarily disables interrupts, so no mistakes are made when writing // to the processor registers noInterrupts(); @@ -437,17 +457,6 @@ void Logger::wakeISR(void) sleep_bod_disable(); #endif - // turn off I2C - Wire.end(); - - // Force the I2C pins to LOW - // I2C devices have a nasty habit of stealing power from the SCL and SDA pins... - // This will only work for the "main" I2C/TWI interface - pinMode(SDA, OUTPUT); // set output mode - pinMode(SCL, OUTPUT); - digitalWrite(SDA, LOW); // Set the pins low - digitalWrite(SCL, LOW); - // disable all power-reduction modules (ie, the processor module clocks) // NOTE: This only shuts down the various clocks on the processor via // the power reduction register! It does NOT actually disable the @@ -469,6 +478,10 @@ void Logger::wakeISR(void) // --------------------------------------------------------------------- // -- The portion below this happens on wake up, after any wake ISR's -- + // Temporarily disables interrupts, so no mistakes are made when writing + // to the processor registers + noInterrupts(); + // Re-enable all power modules (ie, the processor module clocks) // NOTE: This only re-enables the various clocks on the processor! // The modules may need to be re-initialized after the clocks re-start. @@ -480,8 +493,16 @@ void Logger::wakeISR(void) // Re-enable the processor ADC ADCSRA |= _BV(ADEN); + // Re-enables interrupts + interrupts(); + // Re-start the I2C interface + pinMode(SDA, INPUT_PULLUP); // set as input with the pull-up on + pinMode(SCL, INPUT_PULLUP); Wire.begin(); + + // The logger will now start the next function after the systemSleep + // function in either the loop or setup } #endif @@ -875,6 +896,9 @@ void Logger::testingMode() _internalArray->sensorsSleep(); _internalArray->sensorsPowerDown(); + PRINTOUT(F("Exiting testing mode")); + PRINTOUT(F("------------------------------------------")); + // Unset testing mode flag Logger::isTestingNow = false; @@ -903,6 +927,10 @@ void Logger::testingMode() #if defined ARDUINO_ARCH_SAMD zero_sleep_rtc.begin(); #else + // Set the pins for I2C + pinMode(SDA, INPUT_PULLUP); + pinMode(SCL, INPUT_PULLUP); + Wire.begin(); rtc.begin(); delay(100); #endif @@ -972,7 +1000,7 @@ void Logger::logData(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Sensors had not been set up! Setting them up now.")); + PRINTOUT(F("Sensors and data file had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it diff --git a/src/LoggerDreamHost.cpp b/src/LoggerDreamHost.cpp index 3f2cf187f..6d615dbd1 100644 --- a/src/LoggerDreamHost.cpp +++ b/src/LoggerDreamHost.cpp @@ -147,7 +147,7 @@ void LoggerDreamHost::logDataAndSend(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Sensors had not been set up! Setting them up now.")); + PRINTOUT(F("Sensors and data file had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it diff --git a/src/LoggerEnviroDIY.cpp b/src/LoggerEnviroDIY.cpp index 74371db0c..e6d989a28 100644 --- a/src/LoggerEnviroDIY.cpp +++ b/src/LoggerEnviroDIY.cpp @@ -445,7 +445,7 @@ void LoggerEnviroDIY::logDataAndSend(void) if (_numIntervals < 0) { // Set up the sensors - PRINTOUT(F("Sensors had not been set up! Setting them up now.")); + PRINTOUT(F("Sensors and data file had not been set up! Setting them up now.")); _internalArray->setupSensors(); // Create the log file, adding the default header to it diff --git a/src/sensors/MaximDS3231.cpp b/src/sensors/MaximDS3231.cpp index f77cf0436..8f5092f27 100644 --- a/src/sensors/MaximDS3231.cpp +++ b/src/sensors/MaximDS3231.cpp @@ -33,7 +33,7 @@ String MaximDS3231::getSensorLocation(void) {return F("I2C_0x68");} bool MaximDS3231::setup(void) { - rtc.begin(); + rtc.begin(); // NOTE: This also turns of interrupts on the RTC! return Sensor::setup(); // this will set pin modes and the setup status bit // The clock should be continuously powered, so we never need to worry about power up } From 92df7608a486cb7423b2c631fe86a514d597a131 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 17:04:54 -0400 Subject: [PATCH 11/12] Update examples --- examples/DRWI_CitSci/DRWI_CitSci.ino | 78 ++++--- examples/DRWI_NoCellular/DRWI_NoCellular.ino | 65 ++++-- .../baro_rho_correction.ino | 210 +++++++++--------- examples/data_saving/data_saving.ino | 24 +- .../logging_to_EnviroDIY.ino | 22 +- .../logging_to_EnviroDIY_Zero.ino | 186 ++++++++-------- 6 files changed, 301 insertions(+), 284 deletions(-) diff --git a/examples/DRWI_CitSci/DRWI_CitSci.ino b/examples/DRWI_CitSci/DRWI_CitSci.ino index d75fe9f55..fae309dd1 100644 --- a/examples/DRWI_CitSci/DRWI_CitSci.ino +++ b/examples/DRWI_CitSci/DRWI_CitSci.ino @@ -58,12 +58,6 @@ const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power (-1 i // Create and return the processor "sensor" const char *MFVersion = "v0.5b"; ProcessorStats mayfly(MFVersion); -// Create the battery voltage and free RAM variable objects for the processor and return variable-type pointers to them -// We're going to use the battery variable in the set-up and loop to decide if the battery level is high enough to -// send data over the modem or if the data should only be logged. -Variable *mayflyBatt = new ProcessorStats_Batt(&mayfly, "12345678-abcd-1234-efgh-1234567890ab"); -// Variable *mayflyRAM = new ProcessorStats_FreeRam(&mayfly, "12345678-abcd-1234-efgh-1234567890ab"); - // ========================================================================== // Modem/Internet connection options @@ -78,9 +72,6 @@ Variable *mayflyBatt = new ProcessorStats_Batt(&mayfly, "12345678-abcd-1234-efgh // Set the serial port for the modem - software serial can also be used. HardwareSerial &ModemSerial = Serial1; -// Create a variable for the modem baud rate - this will be used in the begin function for the port -const long ModemBaud = 9600; - // Create a new TinyGSM modem to run on that serial port and return a pointer to it TinyGsm *tinyModem = new TinyGsm(ModemSerial); @@ -88,21 +79,22 @@ TinyGsm *tinyModem = new TinyGsm(ModemSerial); TinyGsmClient *tinyClient = new TinyGsmClient(*tinyModem); // Describe the physical pin connection of your modem to your board -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) // And create the wake and sleep methods for the modem // These can be functions of any type and must return a boolean -bool wakeFxn(void) +bool sleepFxn(void) { - digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(modemSleepRqPin, LOW); return true; } -bool sleepFxn(void) +bool wakeFxn(void) { - digitalWrite(modemSleepRqPin, LOW); + digitalWrite(modemSleepRqPin, HIGH); return true; } @@ -170,7 +162,7 @@ Variable *variableList[] = { new DecagonCTD_Depth(&ctd, "12345678-abcd-1234-efgh-1234567890ab"), new CampbellOBS3_Turbidity(&osb3low, "12345678-abcd-1234-efgh-1234567890ab", "TurbLow"), new CampbellOBS3_Turbidity(&osb3high, "12345678-abcd-1234-efgh-1234567890ab", "TurbHigh"), - mayflyBatt, + new ProcessorStats_Batt(&mayfly, "12345678-abcd-1234-efgh-1234567890ab"), new MaximDS3231_Temp(&ds3231, "12345678-abcd-1234-efgh-1234567890ab"), new Modem_RSSI(&modem, "12345678-abcd-1234-efgh-1234567890ab"), new Modem_SignalPercent(&modem, "12345678-abcd-1234-efgh-1234567890ab"), @@ -212,6 +204,26 @@ void greenredflash(int numFlash = 4, int rate = 75) } +// Read's the battery voltage +float getBatteryVoltage(const char *version = MFVersion) +{ + float batteryVoltage; + if (strcmp(version, "v0.3") == 0 or strcmp(version, "v0.4") == 0) + { + // Get the battery voltage + float rawBattery = analogRead(A6); + batteryVoltage = (3.3 / 1023.) * 1.47 * rawBattery; + } + if (strcmp(version, "v0.5") == 0 or strcmp(version, "v0.5b") == 0) + { + // Get the battery voltage + float rawBattery = analogRead(A6); + batteryVoltage = (3.3 / 1023.) * 4.7 * rawBattery; + } + return batteryVoltage; +} + + // ========================================================================== // Main setup function // ========================================================================== @@ -220,6 +232,12 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); + // Print a start-up note to the first serial port + Serial.print(F("Now running ")); + Serial.print(sketchName); + Serial.print(F(" on Logger ")); + Serial.println(LoggerID); + // Start the serial connection with the modem ModemSerial.begin(ModemBaud); @@ -231,22 +249,10 @@ void setup() // Blink the LEDs to show the board is on and starting up greenredflash(); - // Set up some of the power pins so the board boots up with them off - pinMode(modemVccPin, OUTPUT); - digitalWrite(modemVccPin, LOW); - pinMode(sensorPowerPin, OUTPUT); - digitalWrite(sensorPowerPin, LOW); - // Set up the sleep/wake pin for the modem and put it's inital value as "off" pinMode(modemSleepRqPin, OUTPUT); digitalWrite(modemSleepRqPin, LOW); - // Print a start-up note to the first serial port - Serial.print(F("Now running ")); - Serial.print(sketchName); - Serial.print(F(" on Logger ")); - Serial.println(LoggerID); - // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); @@ -266,11 +272,11 @@ void setup() EnviroDIYLogger.setDreamHostPortalRX(DreamHostPortalRX); // Begin the logger - mayfly.update(); Serial.print("Battery: "); - Serial.println(mayflyBatt->getValue()); - if (mayflyBatt->getValue() > 3.7) EnviroDIYLogger.beginAndSync(); - else EnviroDIYLogger.begin(); + Serial.println(getBatteryVoltage()); + if (getBatteryVoltage() < 3.4) EnviroDIYLogger.begin(true); // skip sensor set-up + else if (getBatteryVoltage() < 3.7) EnviroDIYLogger.begin(); // set up sensors + else EnviroDIYLogger.beginAndSync(); // set up sensors and synchronize clock with NIST } @@ -280,8 +286,8 @@ void setup() void loop() { // Log the data - if (mayflyBatt->getValue() > 3.7) // This will check against the battery level at the previous logging interval! - EnviroDIYLogger.logDataAndSend(); - else EnviroDIYLogger.logData(); + if (getBatteryVoltage() < 3.4) EnviroDIYLogger.systemSleep(); // just keep sleeping + else if (getBatteryVoltage() < 3.7) EnviroDIYLogger.logData(); // log data + else EnviroDIYLogger.logDataAndSend(); // log data and send it out } diff --git a/examples/DRWI_NoCellular/DRWI_NoCellular.ino b/examples/DRWI_NoCellular/DRWI_NoCellular.ino index e565a39d3..d87b4853e 100644 --- a/examples/DRWI_NoCellular/DRWI_NoCellular.ino +++ b/examples/DRWI_NoCellular/DRWI_NoCellular.ino @@ -19,7 +19,6 @@ THIS CODE IS PROVIDED "AS IS" - NO WARRANTY IS GIVEN. // ========================================================================== #include // The base Arduino library #include // for external and pin change interrupts -#include // ========================================================================== @@ -32,7 +31,8 @@ const char *LoggerID = "XXXXX"; // How frequently (in minutes) to log data const uint8_t loggingInterval = 5; // Your logger's timezone. -const int8_t timeZone = -5; +const int8_t timeZone = -5; // Eastern Standard Time +// NOTE: Daylight savings time will not be applied! Please use standard time! // ========================================================================== @@ -40,20 +40,20 @@ const int8_t timeZone = -5; // ========================================================================== #include -const long serialBaud = 115200; // Baud rate for the primary serial port for debugging -const int8_t greenLED = 8; // Pin for the green LED (-1 if unconnected) -const int8_t redLED = 9; // Pin for the red LED (-1 if unconnected) -const int8_t buttonPin = 21; // Pin for a button to use to enter debugging mode (-1 if unconnected) -const int8_t wakePin = A7; // Interrupt/Alarm pin to wake from sleep +const long serialBaud = 115200; // Baud rate for the primary serial port for debugging +const int8_t greenLED = 8; // MCU pin for the green LED (-1 if not applicable) +const int8_t redLED = 9; // MCU pin for the red LED (-1 if not applicable) +const int8_t buttonPin = 21; // MCU pin for a button to use to enter debugging mode (-1 if not applicable) +const int8_t wakePin = A7; // MCU interrupt/alarm pin to wake from sleep // Set the wake pin to -1 if you do not want the main processor to sleep. // In a SAMD system where you are using the built-in rtc, set wakePin to 1 -const int8_t sdCardPin = 12; // SD Card Chip Select/Slave Select Pin (must be defined!) +const int8_t sdCardPin = 12; // MCU SD card chip select/slave select pin (must be given!) +const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power (-1 if not applicable) // Create and return the processor "sensor" const char *MFVersion = "v0.5b"; ProcessorStats mayfly(MFVersion); - // ========================================================================== // Maxim DS3231 RTC (Real Time Clock) // ========================================================================== @@ -100,6 +100,7 @@ DecagonCTD ctd(*CTDSDI12address, SDI12Power, SDI12Data, CTDnumberReadings); // ========================================================================== // The array that contains all variables to be logged // ========================================================================== +#include // Create pointers for all of the variables from the sensors // at the same time putting them into an array Variable *variableList[] = { @@ -115,7 +116,9 @@ Variable *variableList[] = { int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); + // Create a new logger instance +#include Logger logger(LoggerID, loggingInterval, sdCardPin, wakePin, &varArray); // ========================================================================== @@ -145,6 +148,26 @@ void greenredflash(int numFlash = 4, int rate = 75) } +// Read's the battery voltage +float getBatteryVoltage(const char *version = MFVersion) +{ + float batteryVoltage; + if (strcmp(version, "v0.3") == 0 or strcmp(version, "v0.4") == 0) + { + // Get the battery voltage + float rawBattery = analogRead(A6); + batteryVoltage = (3.3 / 1023.) * 1.47 * rawBattery; + } + if (strcmp(version, "v0.5") == 0 or strcmp(version, "v0.5b") == 0) + { + // Get the battery voltage + float rawBattery = analogRead(A6); + batteryVoltage = (3.3 / 1023.) * 4.7 * rawBattery; + } + return batteryVoltage; +} + + // ========================================================================== // Main setup function // ========================================================================== @@ -153,18 +176,20 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); - // Set up pins for the LED's - pinMode(greenLED, OUTPUT); - pinMode(redLED, OUTPUT); - // Blink the LEDs to show the board is on and starting up - greenredflash(); - // Print a start-up note to the first serial port Serial.print(F("Now running ")); Serial.print(sketchName); Serial.print(F(" on Logger ")); Serial.println(LoggerID); + // Set up pins for the LED's + pinMode(greenLED, OUTPUT); + digitalWrite(greenLED, LOW); + pinMode(redLED, OUTPUT); + digitalWrite(redLED, LOW); + // Blink the LEDs to show the board is on and starting up + greenredflash(); + // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); @@ -176,7 +201,10 @@ void setup() logger.setTestingModePin(buttonPin); // Begin the logger - logger.begin(); + Serial.print("Battery: "); + Serial.println(getBatteryVoltage()); + if (getBatteryVoltage() < 3.4) logger.begin(true); // skip sensor set-up + else logger.begin(); // set up sensors } @@ -186,5 +214,8 @@ void setup() void loop() { // Log the data - logger.logData(); + Serial.print("Battery: "); + Serial.println(getBatteryVoltage()); + if (getBatteryVoltage() < 3.4) logger.systemSleep(); // just go back to sleep + else logger.logData(); // log data } diff --git a/examples/baro_rho_correction/baro_rho_correction.ino b/examples/baro_rho_correction/baro_rho_correction.ino index bdfca4aaf..143f1402b 100644 --- a/examples/baro_rho_correction/baro_rho_correction.ino +++ b/examples/baro_rho_correction/baro_rho_correction.ino @@ -53,7 +53,7 @@ const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power (-1 i // Create and return the processor "sensor" const char *MFVersion = "v0.5b"; ProcessorStats mayfly(MFVersion); -// Create the battery voltage and free RAM variable objects for the Y504 and return variable-type pointers to them +// Create the battery voltage and free RAM variable objects for the processor and return variable-type pointers to them Variable *mayflyBatt = new ProcessorStats_Batt(&mayfly, "12345678-abcd-1234-efgh-1234567890ab"); Variable *mayflyRAM = new ProcessorStats_FreeRam(&mayfly, "12345678-abcd-1234-efgh-1234567890ab"); @@ -75,21 +75,12 @@ Variable *mayflyRAM = new ProcessorStats_FreeRam(&mayfly, "12345678-abcd-1234-ef // Set the serial port for the modem - software serial can also be used. HardwareSerial &ModemSerial = Serial1; -// Create a variable for the modem baud rate - this will be used in the begin function for the port -#if defined(TINY_GSM_MODEM_XBEE) -const long ModemBaud = 9600; // Default for XBee is 9600 -#elif defined(TINY_GSM_MODEM_ESP8266) -const long ModemBaud = 57600; // Default for ESP8266 is 115200, but the Mayfly itself stutters above 57600 -#elif defined(TINY_GSM_MODEM_UBLOX) -const long ModemBaud = 9600; // SARA-U201 default seems to be 9600 -#else -const long ModemBaud = 9600; -#endif - // Create a new TinyGSM modem to run on that serial port and return a pointer to it TinyGsm *tinyModem = new TinyGsm(ModemSerial); -// Use this if you want to spy on modem communication +// Use this to create a modem if you want to spy on modem communication through +// a secondary Arduino stream. Make sure you install the StreamDebugger library! +// https://github.com/vshymanskyy/StreamDebugger // #include // StreamDebugger modemDebugger(Serial1, Serial); // TinyGsm *tinyModem = new TinyGsm(modemDebugger); @@ -97,88 +88,62 @@ TinyGsm *tinyModem = new TinyGsm(ModemSerial); // Create a new TCP client on that modem and return a pointer to it TinyGsmClient *tinyClient = new TinyGsmClient(*tinyModem); -// Describe the physical pin connection of your modem to your board #if defined(TINY_GSM_MODEM_XBEE) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) const bool modemStatusLevel = LOW; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_ESP8266) -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) -const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) -const int8_t modemSleepRqPin = 19; // MCU pin used for wake from light sleep (-1 if not applicable) -const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) -const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_UBLOX) -const int8_t modemVccPin = 23; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 20; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#else -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#endif - // And create the wake and sleep methods for the modem // These can be functions of any type and must return a boolean -#if defined(TINY_GSM_MODEM_XBEE) // After setting up pin sleep, the sleep request pin is held LOW to keep the XBee on -bool wakeFxn(void) +// Use XCTU to set up pin sleep! +bool sleepFxn(void) { - if (modemVccPin >= 0) // Turns on when power is applied - return true; - else + if (modemSleepRqPin >= 0) // Don't go to sleep if there's not a wake pin! { - digitalWrite(modemSleepRqPin, LOW); - digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights + digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, LOW); return true; } + else return true; } -bool sleepFxn(void) -{ - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, LOW); - return true; -} -#elif defined(TINY_GSM_MODEM_ESP8266) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied - { - digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights return true; - } - else if (modemResetPin >= 0) - { - digitalWrite(modemResetPin, LOW); - delay(1); - digitalWrite(modemResetPin, HIGH); - digitalWrite(redLED, HIGH); - return true; - } else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); - delay(1); - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, HIGH); + digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights return true; } else return true; } + +#elif defined(TINY_GSM_MODEM_ESP8266) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 57600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) +const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) +const int8_t modemSleepRqPin = 19; // MCU pin used for wake from light sleep (-1 if not applicable) +const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) +const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool sleepFxn(void) { - // Use this if you have an external pin connected to the reset pin to wake from deep sleep + // Use this if you have an MCU pin connected to the ESP's reset pin to wake from deep sleep if (modemResetPin >= 0) { digitalWrite(redLED, LOW); return tinyModem->poweroff(); } // Use this if you have GPIO16 connected to the reset pin to wake from deep sleep + // but no other MCU pin connected to the reset pin. // NOTE: This will NOT work nicely with things like "testingMode" and the // initial 2-minute logging interval at boot up. // if (loggingInterval > 1) @@ -191,8 +156,9 @@ bool sleepFxn(void) // return tinyModem->waitResponse() == 1; // } // Use this if you don't have access to the ESP8266's reset pin for deep sleep but you - // do have access to another GPIO pin for light sleep - if (modemSleepRqPin >= 0 && modemStatusPin >= 0) + // do have access to another GPIO pin for light sleep. This also sets up another + // pin to view the sleep status. + else if (modemSleepRqPin >= 0 && modemStatusPin >= 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0,"), String(espStatusPin), GF(","), modemStatusLevel); @@ -202,6 +168,7 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } + // Light sleep without the status pin else if (modemSleepRqPin >= 0 && modemStatusPin < 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0")); @@ -211,56 +178,102 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } - else return true; + else return true; // DON'T go to sleep if we can't wake up! } -#elif defined(TINY_GSM_MODEM_UBLOX) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied + { + digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights return true; - else if(modemSleepRqPin >= 0) + } + else if (modemResetPin >= 0) + { + digitalWrite(modemResetPin, LOW); + delay(1); + digitalWrite(modemResetPin, HIGH); + digitalWrite(redLED, HIGH); + return true; + } + else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); + delay(1); + digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, HIGH); - delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 - // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 + return true; + } + else return true; +} + +#elif defined(TINY_GSM_MODEM_UBLOX) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = 23; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 20; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean +bool sleepFxn(void) +{ + if (modemVccPin >= 0 && modemSleepRqPin < 0) + return tinyModem->poweroff(); + else if (modemSleepRqPin >= 0) + { + digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, HIGH); // A light to watch to verify pulse timing + delay(1100); // >1s pulse for power down digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; // DON'T go to sleep if we can't wake up! } -bool sleepFxn(void) +bool wakeFxn(void) { - if (modemSleepRqPin < 0) return tinyModem->poweroff(); - else + if (modemVccPin >= 0) // Turns on when power is applied + return true; + else if(modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); digitalWrite(redLED, HIGH); - delay(1100); // >1s pulse for power down + delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 + // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; } + #else +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 19; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool wakeFxn(void) { digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, HIGH); // A light just for show return true; } bool sleepFxn(void) { digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, LOW); return true; } #endif // And we still need the connection information for the network -const char *apn = "hologram"; // The APN for the gprs connection, unnecessary for WiFi -const char *wifiId = "Stroud-Mobile"; // The WiFi access point, unnecessary for gprs -const char *wifiPwd = "phone970"; // The password for connecting to WiFi, unnecessary for gprs -// const char *wifiId = "4DsAndCounting"; // The WiFi access point, unnecessary for gprs -// const char *wifiPwd = "W4171n843"; // The password for connecting to WiFi, unnecessary for gprs +const char *apn = "xxxxx"; // The APN for the gprs connection, unnecessary for WiFi +const char *wifiId = "xxxxx"; // The WiFi access point, unnecessary for gprs +const char *wifiPwd = "xxxxx"; // The password for connecting to WiFi, unnecessary for gprs // Create the loggerModem instance #include @@ -457,6 +470,7 @@ Variable *variableList[] = { int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); + // Create a new logger instance #include LoggerEnviroDIY EnviroDIYLogger(LoggerID, loggingInterval, sdCardPin, wakePin, &varArray); @@ -497,6 +511,12 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); + // Print a start-up note to the first serial port + Serial.print(F("Now running ")); + Serial.print(sketchName); + Serial.print(F(" on Logger ")); + Serial.println(LoggerID); + // Start the serial connection with the modem ModemSerial.begin(ModemBaud); @@ -508,18 +528,6 @@ void setup() // Blink the LEDs to show the board is on and starting up greenredflash(); - // Set up some of the power pins so the board boots up with them off - if (modemVccPin >= 0) - { - pinMode(modemVccPin, OUTPUT); - digitalWrite(modemVccPin, LOW); - } - if (sensorPowerPin >= 0) - { - pinMode(sensorPowerPin, OUTPUT); - digitalWrite(sensorPowerPin, LOW); - } - // Set up the sleep/wake pin for the modem and put it's inital value as "off" #if defined(TINY_GSM_MODEM_XBEE) pinMode(modemSleepRqPin, OUTPUT); @@ -543,12 +551,6 @@ void setup() digitalWrite(modemSleepRqPin, LOW); #endif - // Print a start-up note to the first serial port - Serial.print(F("Now running ")); - Serial.print(sketchName); - Serial.print(F(" on Logger ")); - Serial.println(LoggerID); - // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); @@ -568,8 +570,9 @@ void setup() mayfly.update(); Serial.print("Battery: "); Serial.println(mayflyBatt->getValue()); - if (mayflyBatt->getValue() > 3.7) EnviroDIYLogger.beginAndSync(); - else EnviroDIYLogger.begin(); + // if (mayflyBatt->getValue() < 3.4) EnviroDIYLogger.begin(true); // skip sensor set-up + // else if (mayflyBatt->getValue() < 3.7) EnviroDIYLogger.begin(); // set up sensors + // else EnviroDIYLogger.beginAndSync(); // set up sensors and synchronize clock with NIST } @@ -579,8 +582,9 @@ void setup() void loop() { // Log the data - if (mayflyBatt->getValue() > 3.7) - // This will check against the battery level at the previous logging interval! - EnviroDIYLogger.logDataAndSend(); - else EnviroDIYLogger.logData(); + Serial.print("Battery: "); + Serial.println(mayflyBatt->getValue()); + if (mayflyBatt->getValue() < 3.4) EnviroDIYLogger.systemSleep(); // just go back to sleep + else if (mayflyBatt->getValue() < 3.7) EnviroDIYLogger.logData(); // log data, but don't send + else EnviroDIYLogger.logDataAndSend(); // send data } diff --git a/examples/data_saving/data_saving.ino b/examples/data_saving/data_saving.ino index 9d89fa886..4a2aac780 100644 --- a/examples/data_saving/data_saving.ino +++ b/examples/data_saving/data_saving.ino @@ -453,6 +453,12 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); + // Print a start-up note to the first serial port + Serial.print(F("Now running ")); + Serial.print(sketchName); + Serial.print(F(" on Logger ")); + Serial.println(LoggerID); + // Start the serial connection with the modem ModemSerial.begin(ModemBaud); @@ -467,18 +473,6 @@ void setup() // Blink the LEDs to show the board is on and starting up greenredflash(); - // Set up some of the power pins so the board boots up with them off - if (modemVccPin >= 0) - { - pinMode(modemVccPin, OUTPUT); - digitalWrite(modemVccPin, LOW); - } - if (sensorPowerPin >= 0) - { - pinMode(sensorPowerPin, OUTPUT); - digitalWrite(sensorPowerPin, LOW); - } - // Set up the sleep/wake pin for the modem and put it's inital value as "off" #if defined(TINY_GSM_MODEM_XBEE) pinMode(modemSleepRqPin, OUTPUT); @@ -502,12 +496,6 @@ void setup() digitalWrite(modemSleepRqPin, LOW); #endif - // Print a start-up note to the first serial port - Serial.print(F("Now running ")); - Serial.print(sketchName); - Serial.print(F(" on Logger ")); - Serial.println(LoggerID); - // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); diff --git a/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino b/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino index 6473ff89e..11b744e99 100644 --- a/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino +++ b/examples/logging_to_EnviroDIY/logging_to_EnviroDIY.ino @@ -75,7 +75,9 @@ HardwareSerial &ModemSerial = Serial1; // Create a new TinyGSM modem to run on that serial port and return a pointer to it TinyGsm *tinyModem = new TinyGsm(ModemSerial); -// Use this if you want to spy on modem communication +// Use this to create a modem if you want to spy on modem communication through +// a secondary Arduino stream. Make sure you install the StreamDebugger library! +// https://github.com/vshymanskyy/StreamDebugger // #include // StreamDebugger modemDebugger(Serial1, Serial); // TinyGsm *tinyModem = new TinyGsm(modemDebugger); @@ -784,18 +786,6 @@ void setup() // Blink the LEDs to show the board is on and starting up greenredflash(); - // Set up some of the power pins so the board boots up with them off - if (modemVccPin >= 0) - { - pinMode(modemVccPin, OUTPUT); - digitalWrite(modemVccPin, LOW); - } - if (sensorPowerPin >= 0) - { - pinMode(sensorPowerPin, OUTPUT); - digitalWrite(sensorPowerPin, LOW); - } - // Set up the sleep/wake pin for the modem and put it's inital value as "off" #if defined(TINY_GSM_MODEM_XBEE) pinMode(modemSleepRqPin, OUTPUT); @@ -819,12 +809,6 @@ void setup() digitalWrite(modemSleepRqPin, LOW); #endif - // Print a start-up note to the first serial port - Serial.print(F("Now running ")); - Serial.print(sketchName); - Serial.print(F(" on Logger ")); - Serial.println(LoggerID); - // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); diff --git a/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino b/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino index caf921e78..43d7e64fc 100644 --- a/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino +++ b/examples/logging_to_EnviroDIY_Zero/logging_to_EnviroDIY_Zero.ino @@ -73,21 +73,12 @@ ProcessorStats feather(featherVersion) ; // Set the serial port for the modem - software serial can also be used. HardwareSerial &ModemSerial = Serial1; -// Create a variable for the modem baud rate - this will be used in the begin function for the port -#if defined(TINY_GSM_MODEM_XBEE) -const long ModemBaud = 9600; // Default for XBee is 9600 -#elif defined(TINY_GSM_MODEM_ESP8266) -const long ModemBaud = 57600; // Default for ESP8266 is 115200, but the Mayfly itself stutters above 57600 -#elif defined(TINY_GSM_MODEM_UBLOX) -const long ModemBaud = 9600; // SARA-U201 default seems to be 9600 -#else -const long ModemBaud = 9600; -#endif - // Create a new TinyGSM modem to run on that serial port and return a pointer to it TinyGsm *tinyModem = new TinyGsm(ModemSerial); -// Use this if you want to spy on modem communication +// Use this to create a modem if you want to spy on modem communication through +// a secondary Arduino stream. Make sure you install the StreamDebugger library! +// https://github.com/vshymanskyy/StreamDebugger // #include // StreamDebugger modemDebugger(Serial1, Serial); // TinyGsm *tinyModem = new TinyGsm(modemDebugger); @@ -95,88 +86,62 @@ TinyGsm *tinyModem = new TinyGsm(ModemSerial); // Create a new TCP client on that modem and return a pointer to it TinyGsmClient *tinyClient = new TinyGsmClient(*tinyModem); -// Describe the physical pin connection of your modem to your board #if defined(TINY_GSM_MODEM_XBEE) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) const int8_t modemSleepRqPin = 14; // MCU pin used for modem sleep/wake request (-1 if not applicable) const int8_t modemStatusPin = 15; // MCU pin used to read modem status (-1 if not applicable) const bool modemStatusLevel = LOW; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_ESP8266) -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) -const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) -const int8_t modemSleepRqPin = 15; // MCU pin used for wake from light sleep (-1 if not applicable) -const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) -const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#elif defined(TINY_GSM_MODEM_UBLOX) -const int8_t modemVccPin = 9; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 14; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 15; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#else -const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) -const int8_t modemSleepRqPin = 14; // MCU pin used for modem sleep/wake request (-1 if not applicable) -const int8_t modemStatusPin = 15; // MCU pin used to read modem status (-1 if not applicable) -const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) -#endif - // And create the wake and sleep methods for the modem // These can be functions of any type and must return a boolean -#if defined(TINY_GSM_MODEM_XBEE) // After setting up pin sleep, the sleep request pin is held LOW to keep the XBee on -bool wakeFxn(void) +// Use XCTU to set up pin sleep! +bool sleepFxn(void) { - if (modemVccPin >= 0) // Turns on when power is applied - return true; - else + if (modemSleepRqPin >= 0) // Don't go to sleep if there's not a wake pin! { - digitalWrite(modemSleepRqPin, LOW); - digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights + digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, LOW); return true; } + else return true; } -bool sleepFxn(void) -{ - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, LOW); - return true; -} -#elif defined(TINY_GSM_MODEM_ESP8266) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied - { - digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights return true; - } - else if (modemResetPin >= 0) - { - digitalWrite(modemResetPin, LOW); - delay(1); - digitalWrite(modemResetPin, HIGH); - digitalWrite(redLED, HIGH); - return true; - } else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); - delay(1); - digitalWrite(modemSleepRqPin, HIGH); - digitalWrite(redLED, HIGH); + digitalWrite(redLED, HIGH); // Because the XBee doesn't have any lights return true; } else return true; } + +#elif defined(TINY_GSM_MODEM_ESP8266) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 57600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemResetPin = -1; // MCU Pin connected to ESP8266's RSTB pin (-1 if unconnected) +const int8_t espSleepRqPin = 13; // ESP8266 GPIO pin used for wake from light sleep (-1 if not applicable) +const int8_t modemSleepRqPin = 15; // MCU pin used for wake from light sleep (-1 if not applicable) +const int8_t espStatusPin = -1; // ESP8266 GPIO pin used to give modem status (-1 if not applicable) +const int8_t modemStatusPin = -1; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool sleepFxn(void) { - // Use this if you have an external pin connected to the reset pin to wake from deep sleep + // Use this if you have an MCU pin connected to the ESP's reset pin to wake from deep sleep if (modemResetPin >= 0) { digitalWrite(redLED, LOW); return tinyModem->poweroff(); } // Use this if you have GPIO16 connected to the reset pin to wake from deep sleep + // but no other MCU pin connected to the reset pin. // NOTE: This will NOT work nicely with things like "testingMode" and the // initial 2-minute logging interval at boot up. // if (loggingInterval > 1) @@ -189,8 +154,9 @@ bool sleepFxn(void) // return tinyModem->waitResponse() == 1; // } // Use this if you don't have access to the ESP8266's reset pin for deep sleep but you - // do have access to another GPIO pin for light sleep - if (modemSleepRqPin >= 0 && modemStatusPin >= 0) + // do have access to another GPIO pin for light sleep. This also sets up another + // pin to view the sleep status. + else if (modemSleepRqPin >= 0 && modemStatusPin >= 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0,"), String(espStatusPin), GF(","), modemStatusLevel); @@ -200,6 +166,7 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } + // Light sleep without the status pin else if (modemSleepRqPin >= 0 && modemStatusPin < 0) { tinyModem->sendAT(GF("+WAKEUPGPIO=1,"), String(espSleepRqPin), GF(",0")); @@ -209,46 +176,94 @@ bool sleepFxn(void) digitalWrite(redLED, LOW); return success; } - else return true; + else return true; // DON'T go to sleep if we can't wake up! } -#elif defined(TINY_GSM_MODEM_UBLOX) bool wakeFxn(void) { if (modemVccPin >= 0) // Turns on when power is applied + { + digitalWrite(redLED, HIGH); // Because the ESP8266 doesn't have any lights return true; - else if(modemSleepRqPin >= 0) + } + else if (modemResetPin >= 0) + { + digitalWrite(modemResetPin, LOW); + delay(1); + digitalWrite(modemResetPin, HIGH); + digitalWrite(redLED, HIGH); + return true; + } + else if (modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); + delay(1); + digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, HIGH); - delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 - // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 + return true; + } + else return true; +} + +#elif defined(TINY_GSM_MODEM_UBLOX) +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = 9; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 14; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 15; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean +bool sleepFxn(void) +{ + if (modemVccPin >= 0 && modemSleepRqPin < 0) + return tinyModem->poweroff(); + else if (modemSleepRqPin >= 0) + { + digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, HIGH); // A light to watch to verify pulse timing + delay(1100); // >1s pulse for power down digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; // DON'T go to sleep if we can't wake up! } -bool sleepFxn(void) +bool wakeFxn(void) { - if (modemSleepRqPin < 0) return tinyModem->poweroff(); - else + if (modemVccPin >= 0) // Turns on when power is applied + return true; + else if(modemSleepRqPin >= 0) { digitalWrite(modemSleepRqPin, LOW); digitalWrite(redLED, HIGH); - delay(1100); // >1s pulse for power down + delay(200); // 0.15-3.2s pulse for wake on SARA R4/N4 + // delayMicroseconds(65); // 50-80µs pulse for wake on SARA/LISA U2/G2 digitalWrite(modemSleepRqPin, HIGH); digitalWrite(redLED, LOW); return true; } + else return true; } + #else +// Describe the physical pin connection of your modem to your board +const long ModemBaud = 9600; // Communication speed of the modem +const int8_t modemVccPin = -2; // MCU pin controlling modem power (-1 if not applicable) +const int8_t modemSleepRqPin = 14; // MCU pin used for modem sleep/wake request (-1 if not applicable) +const int8_t modemStatusPin = 15; // MCU pin used to read modem status (-1 if not applicable) +const bool modemStatusLevel = HIGH; // The level of the status pin when the module is active (HIGH or LOW) +// And create the wake and sleep methods for the modem +// These can be functions of any type and must return a boolean bool wakeFxn(void) { digitalWrite(modemSleepRqPin, HIGH); + digitalWrite(redLED, HIGH); // A light just for show return true; } bool sleepFxn(void) { digitalWrite(modemSleepRqPin, LOW); + digitalWrite(redLED, LOW); return true; } #endif @@ -703,6 +718,7 @@ Variable *variableList[] = { int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); + // Create a new logger instance #include LoggerEnviroDIY EnviroDIYLogger(LoggerID, loggingInterval, sdCardPin, wakePin, &varArray); @@ -743,6 +759,12 @@ void setup() // Start the primary serial connection Serial.begin(serialBaud); + // Print a start-up note to the first serial port + Serial.print(F("Now running ")); + Serial.print(sketchName); + Serial.print(F(" on Logger ")); + Serial.println(LoggerID); + // Start the serial connection with the modem ModemSerial.begin(ModemBaud); @@ -766,18 +788,6 @@ void setup() // Blink the LEDs to show the board is on and starting up greenredflash(); - // Set up some of the power pins so the board boots up with them off - if (modemVccPin >= 0) - { - pinMode(modemVccPin, OUTPUT); - digitalWrite(modemVccPin, LOW); - } - if (sensorPowerPin >= 0) - { - pinMode(sensorPowerPin, OUTPUT); - digitalWrite(sensorPowerPin, LOW); - } - // Set up the sleep/wake pin for the modem and put it's inital value as "off" #if defined(TINY_GSM_MODEM_XBEE) pinMode(modemSleepRqPin, OUTPUT); @@ -801,12 +811,6 @@ void setup() digitalWrite(modemSleepRqPin, LOW); #endif - // Print a start-up note to the first serial port - Serial.print(F("Now running ")); - Serial.print(sketchName); - Serial.print(F(" on Logger ")); - Serial.println(LoggerID); - // Set the timezone and offsets // Logging in the given time zone Logger::setTimeZone(timeZone); From 9cf2bcb07efc12709b499e6014328e82d1415881 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 18 Oct 2018 17:18:19 -0400 Subject: [PATCH 12/12] Version bump --- examples/DRWI_CitSci/platformio.ini | 2 +- examples/DRWI_NoCellular/platformio.ini | 2 +- examples/baro_rho_correction/platformio.ini | 2 +- examples/data_saving/platformio.ini | 2 +- examples/double_logger/platformio.ini | 2 +- examples/logging_to_EnviroDIY/platformio.ini | 2 +- examples/logging_to_EnviroDIY_Zero/platformio.ini | 2 +- examples/multisensor_print/platformio.ini | 2 +- examples/simple_logging/platformio.ini | 2 +- examples/single_sensor/platformio.ini | 2 +- library.json | 2 +- library.properties | 2 +- src/LoggerBase.cpp | 4 ---- src/LoggerBase.h | 4 ---- 14 files changed, 12 insertions(+), 20 deletions(-) diff --git a/examples/DRWI_CitSci/platformio.ini b/examples/DRWI_CitSci/platformio.ini index aa1a6c8f1..176664121 100644 --- a/examples/DRWI_CitSci/platformio.ini +++ b/examples/DRWI_CitSci/platformio.ini @@ -18,4 +18,4 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 diff --git a/examples/DRWI_NoCellular/platformio.ini b/examples/DRWI_NoCellular/platformio.ini index 93bdb3bec..8193f3cb5 100644 --- a/examples/DRWI_NoCellular/platformio.ini +++ b/examples/DRWI_NoCellular/platformio.ini @@ -18,4 +18,4 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 diff --git a/examples/baro_rho_correction/platformio.ini b/examples/baro_rho_correction/platformio.ini index 57f4b8580..f5cc9514b 100644 --- a/examples/baro_rho_correction/platformio.ini +++ b/examples/baro_rho_correction/platformio.ini @@ -19,4 +19,4 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 diff --git a/examples/data_saving/platformio.ini b/examples/data_saving/platformio.ini index 3a3ad85fb..342ebe73f 100644 --- a/examples/data_saving/platformio.ini +++ b/examples/data_saving/platformio.ini @@ -18,5 +18,5 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 https://github.com/PaulStoffregen/AltSoftSerial.git diff --git a/examples/double_logger/platformio.ini b/examples/double_logger/platformio.ini index c15b96d1a..0d99bb97f 100644 --- a/examples/double_logger/platformio.ini +++ b/examples/double_logger/platformio.ini @@ -18,4 +18,4 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 diff --git a/examples/logging_to_EnviroDIY/platformio.ini b/examples/logging_to_EnviroDIY/platformio.ini index c5b0283a5..68f1ad15d 100644 --- a/examples/logging_to_EnviroDIY/platformio.ini +++ b/examples/logging_to_EnviroDIY/platformio.ini @@ -18,6 +18,6 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 https://github.com/PaulStoffregen/AltSoftSerial.git https://github.com/EnviroDIY/SoftwaterSerial_ExternalInts.git diff --git a/examples/logging_to_EnviroDIY_Zero/platformio.ini b/examples/logging_to_EnviroDIY_Zero/platformio.ini index d4947aad2..5fea4b9ef 100644 --- a/examples/logging_to_EnviroDIY_Zero/platformio.ini +++ b/examples/logging_to_EnviroDIY_Zero/platformio.ini @@ -18,5 +18,5 @@ framework = arduino lib_ldf_mode = deep lib_ignore = SoftwareSerial_ExtInts, AltSoftSerial lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 RTCZero diff --git a/examples/multisensor_print/platformio.ini b/examples/multisensor_print/platformio.ini index 82f334994..dea344f4b 100644 --- a/examples/multisensor_print/platformio.ini +++ b/examples/multisensor_print/platformio.ini @@ -18,6 +18,6 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 https://github.com/PaulStoffregen/AltSoftSerial.git https://github.com/EnviroDIY/SoftwaterSerial_ExternalInts.git diff --git a/examples/simple_logging/platformio.ini b/examples/simple_logging/platformio.ini index 11ac18c54..9be3674b9 100644 --- a/examples/simple_logging/platformio.ini +++ b/examples/simple_logging/platformio.ini @@ -18,6 +18,6 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 https://github.com/PaulStoffregen/AltSoftSerial.git https://github.com/EnviroDIY/SoftwaterSerial_ExternalInts.git diff --git a/examples/single_sensor/platformio.ini b/examples/single_sensor/platformio.ini index f38ae1f51..ec1a3ae5e 100644 --- a/examples/single_sensor/platformio.ini +++ b/examples/single_sensor/platformio.ini @@ -18,5 +18,5 @@ framework = arduino lib_ldf_mode = deep lib_ignore = RTCZero lib_deps = - EnviroDIY_ModularSensors@=0.15.3 + EnviroDIY_ModularSensors@=0.16.0 https://github.com/EnviroDIY/SoftwaterSerial_ExternalInts.git diff --git a/library.json b/library.json index e5a858ab8..4fac602b9 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "EnviroDIY_ModularSensors", - "version": "0.15.4", + "version": "0.16.0", "description": "A library that allows access to multiple sensors through a unified interface. This allows the user to simply access many sensors to log the data or send the data to data repositories like the EnviroDIY data portal.", "keywords": "modular, sensor, sensors, datalogger, logger, low power, sleeping, EnviroDIY, ModularSensors, Mayfly, WikiWatershed", "platforms": "atmelavr, atmelsam", diff --git a/library.properties b/library.properties index 2262313b1..099a95585 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=EnviroDIY_ModularSensors -version=0.15.4 +version=0.16.0 author=Sara Damiano , Shannon Hicks maintainer=Sara Damiano sentence=A library that allows access to multiple sensors through a unified interface. diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 6eaa9adc0..f5746efb0 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -23,8 +23,6 @@ int8_t Logger::_timeZone = 0; int8_t Logger::_offset = 0; // Initialize the static timestamps uint32_t Logger::markedEpochTime = 0; -// DateTime Logger::markedDateTime = 0; -// char Logger::markedISO8601Time[26]; // Initialize the testing/logging flags volatile bool Logger::isLoggingNow = false; volatile bool Logger::isTestingNow = false; @@ -244,8 +242,6 @@ bool Logger::syncRTClock(uint32_t nist) void Logger::markTime(void) { Logger::markedEpochTime = getNowEpoch(); - // Logger::markedDateTime = dtFromEpoch(markedEpochTime); - // formatDateTime_ISO8601(markedDateTime).toCharArray(markedISO8601Time, 26); } diff --git a/src/LoggerBase.h b/src/LoggerBase.h index d8da13f0c..b37fadcb2 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -225,10 +225,6 @@ class Logger static int8_t _timeZone; static int8_t _offset; - // Time stamps - want to set them at a single time and carry them forward - // static DateTime markedDateTime; - // static char markedISO8601Time[26]; - // Initialization variables const char *_loggerID; uint16_t _loggingIntervalMinutes;