Example for DRWI CitSci LTE sites.
Example for DRWI CitSci LTE sites.=========================================================================
This example shows proper settings for the following configuration:
Mayfly v1.x board EnviroDIY ESP32 Wifi Bee module Hydros21 CTD sensor
1/** =========================================================================
2 * @example{lineno} DRWI_Mayfly1_WiFi.ino
3 * @copyright Stroud Water Research Center
4 * @license This example is published under the BSD-3 license.
5 * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org>
7 * @brief Example for DRWI CitSci LTE sites.
9 * This example shows proper settings for the following configuration:
12 * EnviroDIY ESP32 Wifi Bee module
15 * @m_examplenavigation{example_drwi_mayfly1_wifi,}
16 * ======================================================================= */
18// ==========================================================================
20// ==========================================================================
22#ifndef TINY_GSM_RX_BUFFER
23#define TINY_GSM_RX_BUFFER 256
25#ifndef TINY_GSM_YIELD_MS
26#define TINY_GSM_YIELD_MS 2
30// ==========================================================================
31// Include the libraries required for any data logger
32// ==========================================================================
33/** Start [includes] */
34// The Arduino library is needed for every Arduino program.
37// Include the main header for ModularSensors
38#include <ModularSensors.h>
42// ==========================================================================
43// Data Logging Options
44// ==========================================================================
45/** Start [logging_options] */
46// The name of this program file
47const char* sketchName = "DRWI_Mayfly1_WiFi.ino";
48// Logger ID, also becomes the prefix for the name of the data file on SD card
49const char* LoggerID = "XXXXX";
50// How frequently (in minutes) to log data
51const uint8_t loggingInterval = 15;
52// Your logger's timezone.
53const int8_t timeZone = -5; // Eastern Standard Time
54// NOTE: Daylight savings time will not be applied! Please use standard time!
56// Set the input and output pins for the logger
57// NOTE: Use -1 for pins that do not apply
58const int32_t serialBaud = 57600; // Baud rate for debugging
59const int8_t greenLED = 8; // Pin for the green LED
60const int8_t redLED = 9; // Pin for the red LED
61const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
62const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep
63// Mayfly 0.x, 1.x D31 = A7
64const int8_t sdCardPwrPin = -1; // MCU SD card power pin
65const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
66const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
67/** End [logging_options] */
70// ==========================================================================
71// Wifi/Cellular Modem Options
72// ==========================================================================
73/** Start [espressif_esp32] */
74#include <modems/EspressifESP32.h>
76// Create a reference to the serial port for the modem
77HardwareSerial& modemSerial = Serial1; // Use hardware serial if possible
78const int32_t modemBaud = 115200; // Communication speed of the modem
79// NOTE: This baud rate too fast for the Mayfly. We'll slow it down in the
82// Modem Pins - Describe the physical pin connection of your modem to your board
83// NOTE: Use -1 for pins that do not apply
84// Example pins here are for a EnviroDIY ESP32 Bluetooth/Wifi Bee with
86const int8_t modemVccPin = 18; // MCU pin controlling modem power
87const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
88const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
91// Network connection information
92const char* wifiId = "xxxxx"; // WiFi access point name
93const char* wifiPwd = "xxxxx"; // WiFi password (WPA2)
95// Create the modem object
96EspressifESP32 modemESP(&modemSerial, modemVccPin, modemResetPin, wifiId,
98// Create an extra reference to the modem by a generic name
99EspressifESP32 modem = modemESP;
100/** End [espressif_esp32] */
103// ==========================================================================
104// Using the Processor as a Sensor
105// ==========================================================================
106/** Start [processor_sensor] */
107#include <sensors/ProcessorStats.h>
109// Create the main processor chip "sensor" - for general metadata
110const char* mcuBoardVersion = "v1.1";
111ProcessorStats mcuBoard(mcuBoardVersion);
112/** End [processor_sensor] */
115// ==========================================================================
116// Maxim DS3231 RTC (Real Time Clock)
117// Built in on all versions of the Mayfly
118// ==========================================================================
120#include <sensors/MaximDS3231.h>
122// Create a DS3231 sensor object
123MaximDS3231 ds3231(1);
127// ==========================================================================
128// Sensirion SHT4X Digital Humidity and Temperature Sensor
129// Built in on Mayfly 1.x
130// ==========================================================================
131/** Start [sensirion_sht4x] */
132#include <sensors/SensirionSHT4x.h>
134// NOTE: Use -1 for any pins that don't apply or aren't being used.
135const int8_t SHT4xPower = sensorPowerPin; // Power pin
136const bool SHT4xUseHeater = true;
138// Create an Sensirion SHT4X sensor object
139SensirionSHT4x sht4x(SHT4xPower, SHT4xUseHeater);
140/** End [sensirion_sht4x] */
143// ==========================================================================
144// Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
145// ==========================================================================
146/** Start [hydros21] */
147#include <sensors/MeterHydros21.h>
149const char* hydrosSDI12address = "1"; // The SDI-12 Address of the Hydros 21
150const uint8_t hydrosNumberReadings = 6; // The number of readings to average
151const int8_t SDI12Power = sensorPowerPin; // Power pin (-1 if unconnected)
152const int8_t SDI12Data = 7; // The SDI12 data pin
154// Create a Meter Hydros 21 sensor object
155MeterHydros21 hydros(*hydrosSDI12address, SDI12Power, SDI12Data,
156 hydrosNumberReadings);
160/* clang-format off */
161// ==========================================================================
162// Creating the Variable Array[s] and Filling with Variable Objects
163// ==========================================================================
164/** Start [variable_arrays] */
165Variable* variableList[] = {
166 new MeterHydros21_Cond(&hydros), // Specific conductance (Meter_Hydros21_Cond)
167 new MeterHydros21_Depth(&hydros), // Water depth (Meter_Hydros21_Depth)
168 new MeterHydros21_Temp(&hydros), // Temperature (Meter_Hydros21_Temp)
169 new SensirionSHT4x_Humidity(&sht4x), // Relative humidity (Sensirion_SHT40_Humidity)
170 new SensirionSHT4x_Temp(&sht4x), // Temperature (Sensirion_SHT40_Temperature)
171 new ProcessorStats_Battery(&mcuBoard), // Battery voltage (EnviroDIY_Mayfly_Batt)
172 new Modem_SignalPercent(&modem), // Percent full scale (EnviroDIY_LTEB_SignalPercent)
175// All UUID's, device registration, and sampling feature information can be
176// pasted directly from Monitor My Watershed.
177// To get the list, click the "View token UUID list" button on the upper right
180// *** CAUTION --- CAUTION --- CAUTION --- CAUTION --- CAUTION ***
181// Check the order of your variables in the variable list!!!
182// Be VERY certain that they match the order of your UUID's!
183// Rearrange the variables in the variable list ABOVE if necessary to match!
184// Do not change the order of the variables in the section below.
185// *** CAUTION --- CAUTION --- CAUTION --- CAUTION --- CAUTION ***
187// Replace all of the text in the following section with the UUID array from
189// --------------------- Beginning of Token UUID List ---------------------
192const char* UUIDs[] = // UUID array for device sensors
194 "12345678-abcd-1234-ef00-1234567890ab", // Specific conductance (Meter_Hydros21_Cond)
195 "12345678-abcd-1234-ef00-1234567890ab", // Water depth (Meter_Hydros21_Depth)
196 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Meter_Hydros21_Temp)
197 "12345678-abcd-1234-ef00-1234567890ab", // Relative humidity (Sensirion_SHT40_Humidity)
198 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Sensirion_SHT40_Temperature)
199 "12345678-abcd-1234-ef00-1234567890ab", // Battery voltage (EnviroDIY_Mayfly_Batt)
200 "12345678-abcd-1234-ef00-1234567890ab", // Percent full scale (EnviroDIY_LTEB_SignalPercent)
202const char* registrationToken = "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token
203const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; // Sampling feature UUID
206// ----------------------- End of Token UUID List -----------------------
209// Count up the number of pointers in the array
210int variableCount = sizeof(variableList) / sizeof(variableList[0]);
212// Create the VariableArray object
213VariableArray varArray(variableCount, variableList, UUIDs);
214/** End [variable_arrays] */
217// ==========================================================================
218// The Logger Object[s]
219// ==========================================================================
220/** Start [loggers] */
221// Create a new logger instance
222Logger dataLogger(LoggerID, loggingInterval, &varArray);
226// ==========================================================================
227// Creating Data Publisher[s]
228// ==========================================================================
229/** Start [publishers] */
230// Create a data publisher for the Monitor My Watershed/EnviroDIY POST endpoint
231#include <publishers/EnviroDIYPublisher.h>
232EnviroDIYPublisher EnviroDIYPOST(dataLogger, &modem.gsmClient,
233 registrationToken, samplingFeature);
234/** End [publishers] */
237// ==========================================================================
239// ==========================================================================
240/** Start [working_functions] */
241// Flashes the LED's on the primary board
242void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) {
243 for (uint8_t i = 0; i < numFlash; i++) {
244 digitalWrite(greenLED, HIGH);
245 digitalWrite(redLED, LOW);
247 digitalWrite(greenLED, LOW);
248 digitalWrite(redLED, HIGH);
251 digitalWrite(redLED, LOW);
254// Reads the battery voltage
255// NOTE: This will actually return the battery level from the previous update!
256float getBatteryVoltage() {
257 if (mcuBoard.sensorValues[0] == -9999) mcuBoard.update();
258 return mcuBoard.sensorValues[0];
262// ==========================================================================
263// Arduino Setup Function
264// ==========================================================================
267 // Start the primary serial connection
268 Serial.begin(serialBaud);
270 // Print a start-up note to the first serial port
271 Serial.print(F("Now running "));
272 Serial.print(sketchName);
273 Serial.print(F(" on Logger "));
274 Serial.println(LoggerID);
277 Serial.print(F("Using ModularSensors Library version "));
278 Serial.println(MODULAR_SENSORS_VERSION);
279 Serial.print(F("TinyGSM Library version "));
280 Serial.println(TINYGSM_VERSION);
283 // Start the serial connection with the modem
284 modemSerial.begin(modemBaud);
286 // Set up pins for the LED's
287 pinMode(greenLED, OUTPUT);
288 digitalWrite(greenLED, LOW);
289 pinMode(redLED, OUTPUT);
290 digitalWrite(redLED, LOW);
291 // Blink the LEDs to show the board is on and starting up
294 pinMode(20, OUTPUT); // for proper operation of the onboard flash memory
295 // chip's ChipSelect (Mayfly v1.0 and later)
297 // Set the timezones for the logger/data and the RTC
298 // Logging in the given time zone
299 Logger::setLoggerTimeZone(timeZone);
300 // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
301 Logger::setRTCTimeZone(0);
303 // Attach the modem and information pins to the logger
304 dataLogger.attachModem(modem);
305 modem.setModemLED(modemLEDPin);
306 dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
311 EnviroDIYPOST.begin(dataLogger, &modem.gsmClient, registrationToken,
314 // Note: Please change these battery voltages to match your battery
315 // Set up the sensors, except at lowest battery level
316 if (getBatteryVoltage() > 3.4) {
317 Serial.println(F("Setting up sensors..."));
318 varArray.setupSensors();
321 /** Start [setup_esp] */
322 for (int8_t ntries = 5; ntries; ntries--) {
323 // This will also verify communication and set up the modem
324 if (modem.modemWake()) break;
325 // if that didn't work, try changing baud rate
326 modemSerial.begin(115200);
327 modem.gsmModem.sendAT(GF("+UART_DEF=9600,8,1,0,0"));
328 modem.gsmModem.waitResponse();
330 modemSerial.begin(9600);
332 /** End [setup_esp] */
335 // Sync the clock if it isn't valid or we have battery to spare
336 if (getBatteryVoltage() > 3.55 || !dataLogger.isRTCSane()) {
337 // Synchronize the RTC with NIST
338 // This will also set up the modem
339 dataLogger.syncRTC();
342 // Create the log file, adding the default header to it
343 // Do this last so we have the best chance of getting the time correct
344 // and all sensor names correct Writing to the SD card can be power
345 // intensive, so if we're skipping the sensor setup we'll skip this too.
346 if (getBatteryVoltage() > 3.4) {
347 Serial.println(F("Setting up file on SD card"));
348 dataLogger.turnOnSDcard(
349 true); // true = wait for card to settle after power up
350 dataLogger.createLogFile(true); // true = write a new header
351 dataLogger.turnOffSDcard(
352 true); // true = wait for internal housekeeping after write
355 // Call the processor sleep
356 Serial.println(F("Putting processor to sleep\n"));
357 dataLogger.systemSleep();
362// ==========================================================================
363// Arduino Loop Function
364// ==========================================================================
366// Use this short loop for simple data logging and sending
368 // Note: Please change these battery voltages to match your battery
369 // At very low battery, just go back to sleep
370 if (getBatteryVoltage() < 3.4) {
371 dataLogger.systemSleep();
373 // At moderate voltage, log data but don't send it over the modem
374 else if (getBatteryVoltage() < 3.55) {
375 dataLogger.logData();
377 // If the battery is good, send the data to the world
379 dataLogger.logDataAndPublish();