DRWI_Mayfly1.ino example

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>
6 *
7 * @brief Example for DRWI CitSci LTE sites.
8 *
9 * This example shows proper settings for the following configuration:
10 *
11 * Mayfly v1.0 board
12 * EnviroDIY SIM7080 LTE module (with Hologram SIM card)
13 * Hydros21 CTD sensor
14 *
15 * See [the walkthrough page](@ref example_drwi_mayfly1) for detailed
16 * instructions.
17 *
18 * @m_examplenavigation{example_drwi_mayfly1,}
19 * ======================================================================= */
20
21// ==========================================================================
22// Defines for TinyGSM
23// ==========================================================================
24/** Start [defines] */
25#ifndef TINY_GSM_RX_BUFFER
26#define TINY_GSM_RX_BUFFER 64
27#endif
28#ifndef TINY_GSM_YIELD_MS
29#define TINY_GSM_YIELD_MS 2
30#endif
31/** End [defines] */
32
33// ==========================================================================
34// Include the libraries required for any data logger
35// ==========================================================================
36/** Start [includes] */
37// The Arduino library is needed for every Arduino program.
38#include <Arduino.h>
39
40// Include the main header for ModularSensors
41#include <ModularSensors.h>
42/** End [includes] */
43
44
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!
58
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] */
71
72
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>
79
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
84
85// Modem Pins - Describe the physical pin connection of your modem to your board
86// NOTE: Use -1 for pins that do not apply
87
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
95 // status
96
97// Network connection information
98const char* apn =
99 "hologram"; // APN connection name, typically Hologram unless you have a
100 // different provider's SIM card. Change as needed
101
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] */
108
109
110// ==========================================================================
111// Using the Processor as a Sensor
112// ==========================================================================
113/** Start [processor_sensor] */
114#include <sensors/ProcessorStats.h>
115
116// Create the main processor chip "sensor" - for general metadata
117const char* mcuBoardVersion = "v1.1";
118ProcessorStats mcuBoard(mcuBoardVersion);
119/** End [processor_sensor] */
120
121
122// ==========================================================================
123// Maxim DS3231 RTC (Real Time Clock)
124// Built in on all versions of the Mayfly
125// ==========================================================================
126/** Start [ds3231] */
127#include <sensors/MaximDS3231.h>
128
129// Create a DS3231 sensor object
130MaximDS3231 ds3231(1);
131/** End [ds3231] */
132
133
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>
140
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] */
146
147
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>
154
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;
158
159// Create an Sensirion SHT4X sensor object
160SensirionSHT4x sht4x(SHT4xPower, SHT4xUseHeater);
161/** End [sensirion_sht4x] */
162
163
164// ==========================================================================
165// Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
166// ==========================================================================
167/** Start [hydros21] */
168#include <sensors/MeterHydros21.h>
169
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
174
175// Create a Meter Hydros 21 sensor object
176MeterHydros21 hydros(*hydrosSDI12address, SDI12Power, SDI12Data,
177 hydrosNumberReadings);
178/** End [hydros21] */
179
180
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)
196};
197
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
201// of the site page.
202
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 ***
209
210// Replace all of the text in the following section with the UUID array from
211// MonitorMyWatershed
212// --------------------- Beginning of Token UUID List ---------------------
213
214
215const char* UUIDs[] = // UUID array for device sensors
216 {
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)
226};
227const char* registrationToken = "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token
228const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; // Sampling feature UUID
229
230
231// ----------------------- End of Token UUID List -----------------------
232/* clang-format on */
233
234// Count up the number of pointers in the array
235int variableCount = sizeof(variableList) / sizeof(variableList[0]);
236
237// Create the VariableArray object
238VariableArray varArray(variableCount, variableList, UUIDs);
239/** End [variable_arrays] */
240
241
242// ==========================================================================
243// The Logger Object[s]
244// ==========================================================================
245/** Start [loggers] */
246// Create a new logger instance
247Logger dataLogger(LoggerID, loggingInterval, &varArray);
248/** End [loggers] */
249
250
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] */
260
261
262// ==========================================================================
263// Working Functions
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);
271 delay(rate);
272 digitalWrite(greenLED, LOW);
273 digitalWrite(redLED, HIGH);
274 delay(rate);
275 }
276 digitalWrite(redLED, LOW);
277}
278
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];
284}
285
286
287// ==========================================================================
288// Arduino Setup Function
289// ==========================================================================
290/** Start [setup] */
291void setup() {
292 // Start the primary serial connection
293 Serial.begin(serialBaud);
294
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);
300 Serial.println();
301
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);
306 Serial.println();
307
308 // Start the serial connection with the modem
309 modemSerial.begin(modemBaud);
310
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
317 greenredflash();
318
319 pinMode(20, OUTPUT); // for proper operation of the onboard flash memory
320 // chip's ChipSelect (Mayfly v1.0 and later)
321
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);
327
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,
332 greenLED);
333
334 // Begin the logger
335 dataLogger.begin();
336
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();
342 }
343
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
351 // 2 Automatic
352 // 13 GSM only
353 // 38 LTE only
354 // 51 GSM and LTE only
355 modem.gsmModem.setPreferredMode(1); // set to CAT-M
356 // 1 CAT-M
357 // 2 NB-IoT
358 // 3 CAT-M and NB-IoT
359 /** End [setup_sim7080] */
360
361
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();
367 }
368
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
381 }
382
383 // Call the processor sleep
384 Serial.println(F("Putting processor to sleep\n"));
385 dataLogger.systemSleep();
386}
387/** End [setup] */
388
389
390// ==========================================================================
391// Arduino Loop Function
392// ==========================================================================
393/** Start [loop] */
394// Use this short loop for simple data logging and sending
395void loop() {
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();
400 }
401 // At moderate voltage, log data but don't send it over the modem
402 else if (getBatteryVoltage() < 3.55) {
403 dataLogger.logData();
404 }
405 // If the battery is good, send the data to the world
406 else {
407 dataLogger.logDataAndPublish();
408 }
409}
410/** End [loop] */