Example for DRWI CitSci LTE sites.
Example for DRWI CitSci LTE sites.=========================================================================
This example shows proper settings for the following configuration:
Mayfly v1.0 board EnviroDIY SIM7080 LTE module (with Hologram SIM card) Hydros21 CTD sensor
See the walkthrough page for detailed instructions.
1/** =========================================================================
2 * @example{lineno} DRWI_Mayfly1.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 SIM7080 LTE module (with Hologram SIM card)
15 * See [the walkthrough page](@ref example_drwi_mayfly1) for detailed
18 * @m_examplenavigation{example_drwi_mayfly1,}
19 * ======================================================================= */
21// ==========================================================================
23// ==========================================================================
25#ifndef TINY_GSM_RX_BUFFER
26#define TINY_GSM_RX_BUFFER 64
28#ifndef TINY_GSM_YIELD_MS
29#define TINY_GSM_YIELD_MS 2
33// ==========================================================================
34// Include the libraries required for any data logger
35// ==========================================================================
36/** Start [includes] */
37// The Arduino library is needed for every Arduino program.
40// Include the main header for ModularSensors
41#include <ModularSensors.h>
45// ==========================================================================
46// Data Logging Options
47// ==========================================================================
48/** Start [logging_options] */
49// The name of this program file
50const char* sketchName = "DRWI_Mayfly1.ino";
51// Logger ID, also becomes the prefix for the name of the data file on SD card
52const char* LoggerID = "XXXXX";
53// How frequently (in minutes) to log data
54const uint8_t loggingInterval = 15;
55// Your logger's timezone.
56const int8_t timeZone = -5; // Eastern Standard Time
57// NOTE: Daylight savings time will not be applied! Please use standard time!
59// Set the input and output pins for the logger
60// NOTE: Use -1 for pins that do not apply
61const int32_t serialBaud = 57600; // Baud rate for debugging
62const int8_t greenLED = 8; // Pin for the green LED
63const int8_t redLED = 9; // Pin for the red LED
64const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
65const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep
66// Mayfly 0.x, 1.x D31 = A7
67const int8_t sdCardPwrPin = -1; // MCU SD card power pin
68const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
69const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
70/** End [logging_options] */
73// ==========================================================================
74// Wifi/Cellular Modem Options
75// ==========================================================================
76/** Start [sim_com_sim7080] */
77// For almost anything based on the SIMCom SIM7080G
78#include <modems/SIMComSIM7080.h>
80// Create a reference to the serial port for the modem
81HardwareSerial& modemSerial = Serial1; // Use hardware serial if possible
82const int32_t modemBaud = 9600; // SIM7080 does auto-bauding by default, but
83 // for simplicity we set to 9600
85// Modem Pins - Describe the physical pin connection of your modem to your board
86// NOTE: Use -1 for pins that do not apply
88const int8_t modemVccPin = 18;
89// MCU pin controlling modem power --- Pin 18 is the power enable pin for the
90// bee socket on Mayfly v1.0, use -1 if using Mayfly 0.5b or if the bee socket
91// is constantly powered (ie you changed SJ18 on Mayfly 1.x to 3.3v)
92const int8_t modemStatusPin = 19; // MCU pin used to read modem status
93const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
94const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
97// Network connection information
99 "hologram"; // APN connection name, typically Hologram unless you have a
100 // different provider's SIM card. Change as needed
102// Create the modem object
103SIMComSIM7080 modem7080(&modemSerial, modemVccPin, modemStatusPin,
104 modemSleepRqPin, apn);
105// Create an extra reference to the modem by a generic name
106SIMComSIM7080 modem = modem7080;
107/** End [sim_com_sim7080] */
110// ==========================================================================
111// Using the Processor as a Sensor
112// ==========================================================================
113/** Start [processor_sensor] */
114#include <sensors/ProcessorStats.h>
116// Create the main processor chip "sensor" - for general metadata
117const char* mcuBoardVersion = "v1.1";
118ProcessorStats mcuBoard(mcuBoardVersion);
119/** End [processor_sensor] */
122// ==========================================================================
123// Maxim DS3231 RTC (Real Time Clock)
124// Built in on all versions of the Mayfly
125// ==========================================================================
127#include <sensors/MaximDS3231.h>
129// Create a DS3231 sensor object
130MaximDS3231 ds3231(1);
134// ==========================================================================
135// Everlight ALS-PT19 Ambient Light Sensor
136// Built in on Mayfly 1.x
137// ==========================================================================
138/** Start [everlight_alspt19] */
139#include <sensors/EverlightALSPT19.h>
141// Create a Everlight ALS-PT19 sensor object
142// For an EnviroDIY Mayfly, you can use the abbreviated version
143const uint8_t alsNumberReadings = 10;
144EverlightALSPT19 alsPt19(alsNumberReadings);
145/** End [everlight_alspt19] */
148// ==========================================================================
149// Sensirion SHT4X Digital Humidity and Temperature Sensor
150// Built in on Mayfly 1.x
151// ==========================================================================
152/** Start [sensirion_sht4x] */
153#include <sensors/SensirionSHT4x.h>
155// NOTE: Use -1 for any pins that don't apply or aren't being used.
156const int8_t SHT4xPower = sensorPowerPin; // Power pin
157const bool SHT4xUseHeater = true;
159// Create an Sensirion SHT4X sensor object
160SensirionSHT4x sht4x(SHT4xPower, SHT4xUseHeater);
161/** End [sensirion_sht4x] */
164// ==========================================================================
165// Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
166// ==========================================================================
167/** Start [hydros21] */
168#include <sensors/MeterHydros21.h>
170const char* hydrosSDI12address = "1"; // The SDI-12 Address of the Hydros 21
171const uint8_t hydrosNumberReadings = 6; // The number of readings to average
172const int8_t SDI12Power = sensorPowerPin; // Power pin (-1 if unconnected)
173const int8_t SDI12Data = 7; // The SDI12 data pin
175// Create a Meter Hydros 21 sensor object
176MeterHydros21 hydros(*hydrosSDI12address, SDI12Power, SDI12Data,
177 hydrosNumberReadings);
181/* clang-format off */
182// ==========================================================================
183// Creating the Variable Array[s] and Filling with Variable Objects
184// ==========================================================================
185/** Start [variable_arrays] */
186Variable* variableList[] = {
187 new MeterHydros21_Cond(&hydros), // Specific conductance (Meter_Hydros21_Cond)
188 new MeterHydros21_Depth(&hydros), // Water depth (Meter_Hydros21_Depth)
189 new MeterHydros21_Temp(&hydros), // Temperature (Meter_Hydros21_Temp)
190 new SensirionSHT4x_Humidity(&sht4x), // Relative humidity (Sensirion_SHT40_Humidity)
191 new SensirionSHT4x_Temp(&sht4x), // Temperature (Sensirion_SHT40_Temperature)
192 new EverlightALSPT19_Illuminance(&alsPt19), // Illuminance (Everlight_AnalogALS_Illuminance)
193 new MaximDS3231_Temp(&ds3231), // Temperature (Maxim_DS3231_Temp)
194 new ProcessorStats_Battery(&mcuBoard), // Battery voltage (EnviroDIY_Mayfly_Batt)
195 new Modem_SignalPercent(&modem), // Percent full scale (EnviroDIY_LTEB_SignalPercent)
198// All UUID's, device registration, and sampling feature information can be
199// pasted directly from Monitor My Watershed.
200// To get the list, click the "View token UUID list" button on the upper right
203// *** CAUTION --- CAUTION --- CAUTION --- CAUTION --- CAUTION ***
204// Check the order of your variables in the variable list!!!
205// Be VERY certain that they match the order of your UUID's!
206// Rearrange the variables in the variable list ABOVE if necessary to match!
207// Do not change the order of the variables in the section below.
208// *** CAUTION --- CAUTION --- CAUTION --- CAUTION --- CAUTION ***
210// Replace all of the text in the following section with the UUID array from
212// --------------------- Beginning of Token UUID List ---------------------
215const char* UUIDs[] = // UUID array for device sensors
217 "12345678-abcd-1234-ef00-1234567890ab", // Specific conductance (Meter_Hydros21_Cond)
218 "12345678-abcd-1234-ef00-1234567890ab", // Water depth (Meter_Hydros21_Depth)
219 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Meter_Hydros21_Temp)
220 "12345678-abcd-1234-ef00-1234567890ab", // Relative humidity (Sensirion_SHT40_Humidity)
221 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Sensirion_SHT40_Temperature)
222 "12345678-abcd-1234-ef00-1234567890ab", // Illuminance (Everlight_AnalogALS_Illuminance)
223 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Maxim_DS3231_Temp)
224 "12345678-abcd-1234-ef00-1234567890ab", // Battery voltage (EnviroDIY_Mayfly_Batt)
225 "12345678-abcd-1234-ef00-1234567890ab", // Percent full scale (EnviroDIY_LTEB_SignalPercent)
227const char* registrationToken = "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token
228const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; // Sampling feature UUID
231// ----------------------- End of Token UUID List -----------------------
234// Count up the number of pointers in the array
235int variableCount = sizeof(variableList) / sizeof(variableList[0]);
237// Create the VariableArray object
238VariableArray varArray(variableCount, variableList, UUIDs);
239/** End [variable_arrays] */
242// ==========================================================================
243// The Logger Object[s]
244// ==========================================================================
245/** Start [loggers] */
246// Create a new logger instance
247Logger dataLogger(LoggerID, loggingInterval, &varArray);
251// ==========================================================================
252// Creating Data Publisher[s]
253// ==========================================================================
254/** Start [publishers] */
255// Create a data publisher for the Monitor My Watershed/EnviroDIY POST endpoint
256#include <publishers/EnviroDIYPublisher.h>
257EnviroDIYPublisher EnviroDIYPOST(dataLogger, &modem.gsmClient,
258 registrationToken, samplingFeature);
259/** End [publishers] */
262// ==========================================================================
264// ==========================================================================
265/** Start [working_functions] */
266// Flashes the LED's on the primary board
267void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) {
268 for (uint8_t i = 0; i < numFlash; i++) {
269 digitalWrite(greenLED, HIGH);
270 digitalWrite(redLED, LOW);
272 digitalWrite(greenLED, LOW);
273 digitalWrite(redLED, HIGH);
276 digitalWrite(redLED, LOW);
279// Reads the battery voltage
280// NOTE: This will actually return the battery level from the previous update!
281float getBatteryVoltage() {
282 if (mcuBoard.sensorValues[0] == -9999) mcuBoard.update();
283 return mcuBoard.sensorValues[0];
287// ==========================================================================
288// Arduino Setup Function
289// ==========================================================================
292 // Start the primary serial connection
293 Serial.begin(serialBaud);
295 // Print a start-up note to the first serial port
296 Serial.print(F("Now running "));
297 Serial.print(sketchName);
298 Serial.print(F(" on Logger "));
299 Serial.println(LoggerID);
302 Serial.print(F("Using ModularSensors Library version "));
303 Serial.println(MODULAR_SENSORS_VERSION);
304 Serial.print(F("TinyGSM Library version "));
305 Serial.println(TINYGSM_VERSION);
308 // Start the serial connection with the modem
309 modemSerial.begin(modemBaud);
311 // Set up pins for the LED's
312 pinMode(greenLED, OUTPUT);
313 digitalWrite(greenLED, LOW);
314 pinMode(redLED, OUTPUT);
315 digitalWrite(redLED, LOW);
316 // Blink the LEDs to show the board is on and starting up
319 pinMode(20, OUTPUT); // for proper operation of the onboard flash memory
320 // chip's ChipSelect (Mayfly v1.0 and later)
322 // Set the timezones for the logger/data and the RTC
323 // Logging in the given time zone
324 Logger::setLoggerTimeZone(timeZone);
325 // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
326 Logger::setRTCTimeZone(0);
328 // Attach the modem and information pins to the logger
329 dataLogger.attachModem(modem);
330 modem.setModemLED(modemLEDPin);
331 dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
337 // Note: Please change these battery voltages to match your battery
338 // Set up the sensors, except at lowest battery level
339 if (getBatteryVoltage() > 3.4) {
340 Serial.println(F("Setting up sensors..."));
341 varArray.setupSensors();
344 /** Start [setup_sim7080] */
345 modem.setModemWakeLevel(HIGH); // ModuleFun Bee inverts the signal
346 modem.setModemResetLevel(HIGH); // ModuleFun Bee inverts the signal
347 Serial.println(F("Waking modem and setting Cellular Carrier Options..."));
348 modem.modemWake(); // NOTE: This will also set up the modem
349 modem.gsmModem.setBaud(modemBaud); // Make sure we're *NOT* auto-bauding!
350 modem.gsmModem.setNetworkMode(38); // set to LTE only
354 // 51 GSM and LTE only
355 modem.gsmModem.setPreferredMode(1); // set to CAT-M
358 // 3 CAT-M and NB-IoT
359 /** End [setup_sim7080] */
362 // Sync the clock if it isn't valid or we have battery to spare
363 if (getBatteryVoltage() > 3.55 || !dataLogger.isRTCSane()) {
364 // Synchronize the RTC with NIST
365 // This will also set up the modem
366 dataLogger.syncRTC();
369 // Create the log file, adding the default header to it
370 // Do this last so we have the best chance of getting the time correct and
371 // all sensor names correct
372 // Writing to the SD card can be power intensive, so if we're skipping
373 // the sensor setup we'll skip this too.
374 if (getBatteryVoltage() > 3.4) {
375 Serial.println(F("Setting up file on SD card"));
376 dataLogger.turnOnSDcard(
377 true); // true = wait for card to settle after power up
378 dataLogger.createLogFile(true); // true = write a new header
379 dataLogger.turnOffSDcard(
380 true); // true = wait for internal housekeeping after write
383 // Call the processor sleep
384 Serial.println(F("Putting processor to sleep\n"));
385 dataLogger.systemSleep();
390// ==========================================================================
391// Arduino Loop Function
392// ==========================================================================
394// Use this short loop for simple data logging and sending
396 // Note: Please change these battery voltages to match your battery
397 // At very low battery, just go back to sleep
398 if (getBatteryVoltage() < 3.4) {
399 dataLogger.systemSleep();
401 // At moderate voltage, log data but don't send it over the modem
402 else if (getBatteryVoltage() < 3.55) {
403 dataLogger.logData();
405 // If the battery is good, send the data to the world
407 dataLogger.logDataAndPublish();