DRWI_SIM7080LTE.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 Campbell Scientific OBS3+ Turbidity sensor

See the walkthrough page for detailed instructions.


1/** =========================================================================
2 * @example{lineno} DRWI_SIM7080LTE.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 * Campbell Scientific OBS3+ Turbidity sensor
15 *
16 * See [the walkthrough page](@ref example_drwi_ediylte) for detailed
17 * instructions.
18 *
19 * @m_examplenavigation{example_drwi_ediylte,}
20 * ======================================================================= */
21
22// ==========================================================================
23// Defines for TinyGSM
24// ==========================================================================
25/** Start [defines] */
26#ifndef TINY_GSM_RX_BUFFER
27#define TINY_GSM_RX_BUFFER 64
28#endif
29#ifndef TINY_GSM_YIELD_MS
30#define TINY_GSM_YIELD_MS 2
31#endif
32/** End [defines] */
33
34// ==========================================================================
35// Include the libraries required for any data logger
36// ==========================================================================
37/** Start [includes] */
38// The Arduino library is needed for every Arduino program.
39#include <Arduino.h>
40
41// Include the main header for ModularSensors
42#include <ModularSensors.h>
43/** End [includes] */
44
45
46// ==========================================================================
47// Data Logging Options
48// ==========================================================================
49/** Start [logging_options] */
50// The name of this program file
51const char* sketchName = "DRWI_SIM7080LTE.ino";
52// Logger ID, also becomes the prefix for the name of the data file on SD card
53const char* LoggerID = "XXXXX";
54// How frequently (in minutes) to log data
55const uint8_t loggingInterval = 15;
56// Your logger's timezone.
57const int8_t timeZone = -5; // Eastern Standard Time
58// NOTE: Daylight savings time will not be applied! Please use standard time!
59
60// Set the input and output pins for the logger
61// NOTE: Use -1 for pins that do not apply
62const int32_t serialBaud = 57600; // Baud rate for debugging
63const int8_t greenLED = 8; // Pin for the green LED
64const int8_t redLED = 9; // Pin for the red LED
65const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
66const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep
67// Mayfly 0.x D31 = A7
68const int8_t sdCardPwrPin = -1; // MCU SD card power pin
69const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
70const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
71/** End [logging_options] */
72
73
74// ==========================================================================
75// Wifi/Cellular Modem Options
76// ==========================================================================
77/** Start [sim_com_sim7080] */
78// For almost anything based on the SIMCom SIM7080G
79#include <modems/SIMComSIM7080.h>
80
81// Create a reference to the serial port for the modem
82HardwareSerial& modemSerial = Serial1; // Use hardware serial if possible
83const int32_t modemBaud = 9600; // SIM7080 does auto-bauding by default, but
84 // for simplicity we set to 9600
85
86// Modem Pins - Describe the physical pin connection of your modem to your board
87// NOTE: Use -1 for pins that do not apply
88
89const int8_t modemVccPin = 18;
90// MCU pin controlling modem power --- Pin 18 is the power enable pin for the
91// bee socket on Mayfly v1.0, use -1 if using Mayfly 0.5b or if the bee socket
92// is constantly powered (ie you changed SJ18 on Mayfly 1.x to 3.3v)
93const int8_t modemStatusPin = 19; // MCU pin used to read modem status
94const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
95const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
96 // status
97
98// Network connection information
99const char* apn =
100 "hologram"; // APN connection name, typically Hologram unless you have a
101 // different provider's SIM card. Change as needed
102
103// Create the modem object
104SIMComSIM7080 modem7080(&modemSerial, modemVccPin, modemStatusPin,
105 modemSleepRqPin, apn);
106// Create an extra reference to the modem by a generic name
107SIMComSIM7080 modem = modem7080;
108/** End [sim_com_sim7080] */
109
110
111// ==========================================================================
112// Using the Processor as a Sensor
113// ==========================================================================
114/** Start [processor_sensor] */
115#include <sensors/ProcessorStats.h>
116
117// Create the main processor chip "sensor" - for general metadata
118const char* mcuBoardVersion = "v1.1";
119ProcessorStats mcuBoard(mcuBoardVersion);
120/** End [processor_sensor] */
121
122
123// ==========================================================================
124// Maxim DS3231 RTC (Real Time Clock)
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// Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
136// ==========================================================================
137/** Start [hydros21] */
138#include <sensors/MeterHydros21.h>
139
140const char* hydrosSDI12address = "1"; // The SDI-12 Address of the Hydros 21
141const uint8_t hydrosNumberReadings = 6; // The number of readings to average
142const int8_t SDI12Power = sensorPowerPin; // Power pin (-1 if unconnected)
143const int8_t SDI12Data = 7; // The SDI12 data pin
144
145// Create a Meter Hydros 21 sensor object
146MeterHydros21 hydros(*hydrosSDI12address, SDI12Power, SDI12Data,
147 hydrosNumberReadings);
148/** End [hydros21] */
149
150
151// ==========================================================================
152// Campbell OBS 3 / OBS 3+ Analog Turbidity Sensor
153// ==========================================================================
154/** Start [obs3] */
155#include <sensors/CampbellOBS3.h>
156
157const int8_t OBS3Power = sensorPowerPin; // Power pin (-1 if unconnected)
158const uint8_t OBS3NumberReadings = 10;
159const uint8_t ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
160// Campbell OBS 3+ *Low* Range Calibration in Volts
161const int8_t OBSLowADSChannel = 0; // ADS channel for *low* range output
162const float OBSLow_A = 0.000E+00; // "A" value (X^2) [*low* range]
163const float OBSLow_B = 1.000E+00; // "B" value (X) [*low* range]
164const float OBSLow_C = 0.000E+00; // "C" value [*low* range]
165
166// Create a Campbell OBS3+ *low* range sensor object
167CampbellOBS3 osb3low(OBS3Power, OBSLowADSChannel, OBSLow_A, OBSLow_B, OBSLow_C,
168 ADSi2c_addr, OBS3NumberReadings);
169
170
171// Campbell OBS 3+ *High* Range Calibration in Volts
172const int8_t OBSHighADSChannel = 1; // ADS channel for *high* range output
173const float OBSHigh_A = 0.000E+00; // "A" value (X^2) [*high* range]
174const float OBSHigh_B = 1.000E+00; // "B" value (X) [*high* range]
175const float OBSHigh_C = 0.000E+00; // "C" value [*high* range]
176
177// Create a Campbell OBS3+ *high* range sensor object
178CampbellOBS3 osb3high(OBS3Power, OBSHighADSChannel, OBSHigh_A, OBSHigh_B,
179 OBSHigh_C, ADSi2c_addr, OBS3NumberReadings);
180/** End [obs3] */
181
182
183// ==========================================================================
184// Creating the Variable Array[s] and Filling with Variable Objects
185// ==========================================================================
186/** Start [variable_arrays] */
187Variable* variableList[] = {
188 new MeterHydros21_Cond(&hydros),
189 new MeterHydros21_Depth(&hydros),
190 new MeterHydros21_Temp(&hydros),
191 new CampbellOBS3_Turbidity(&osb3low, "", "TurbLow"),
192 new CampbellOBS3_Turbidity(&osb3high, "", "TurbHigh"),
193 new ProcessorStats_Battery(&mcuBoard),
194 new MaximDS3231_Temp(&ds3231),
195 new Modem_SignalPercent(&modem),
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
213/* clang-format off */
214// --------------------- Beginning of Token UUID List ---------------------
215
216
217const char* UUIDs[] = // UUID array for device sensors
218 {
219 "12345678-abcd-1234-ef00-1234567890ab", // Specific conductance (Meter_Hydros21_Cond)
220 "12345678-abcd-1234-ef00-1234567890ab", // Water depth (Meter_Hydros21_Depth)
221 "12345678-abcd-1234-ef00-1234567890ab", // Temperature (Meter_Hydros21_Temp)
222 "12345678-abcd-1234-ef00-1234567890ab", // Turbidity (Campbell_OBS3_Turb) (Low)
223 "12345678-abcd-1234-ef00-1234567890ab", // Turbidity (Campbell_OBS3_Turb) (High)
224 "12345678-abcd-1234-ef00-1234567890ab", // Battery voltage (EnviroDIY_Mayfly_Batt)
225 "12345678-abcd-1234-ef00-1234567890ab", // Battery voltage (EnviroDIY_Mayfly_Batt)
226 "12345678-abcd-1234-ef00-1234567890ab", // Percent full scale (EnviroDIY_LTEB_SignalPercent)
227};
228const char* registrationToken = "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token
229const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; // Sampling feature UUID
230
231
232// ----------------------- End of Token UUID List -----------------------
233/* clang-format on */
234
235// Count up the number of pointers in the array
236int variableCount = sizeof(variableList) / sizeof(variableList[0]);
237
238// Create the VariableArray object
239VariableArray varArray(variableCount, variableList, UUIDs);
240/** End [variable_arrays] */
241
242
243// ==========================================================================
244// The Logger Object[s]
245// ==========================================================================
246/** Start [loggers] */
247// Create a new logger instance
248Logger dataLogger(LoggerID, loggingInterval, &varArray);
249/** End [loggers] */
250
251
252// ==========================================================================
253// Creating Data Publisher[s]
254// ==========================================================================
255/** Start [publishers] */
256// Create a data publisher for the Monitor My Watershed/EnviroDIY POST endpoint
257#include <publishers/EnviroDIYPublisher.h>
258EnviroDIYPublisher EnviroDIYPOST(dataLogger, &modem.gsmClient,
259 registrationToken, samplingFeature);
260/** End [publishers] */
261
262
263// ==========================================================================
264// Working Functions
265// ==========================================================================
266/** Start [working_functions] */
267// Flashes the LED's on the primary board
268void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) {
269 for (uint8_t i = 0; i < numFlash; i++) {
270 digitalWrite(greenLED, HIGH);
271 digitalWrite(redLED, LOW);
272 delay(rate);
273 digitalWrite(greenLED, LOW);
274 digitalWrite(redLED, HIGH);
275 delay(rate);
276 }
277 digitalWrite(redLED, LOW);
278}
279
280// Reads the battery voltage
281// NOTE: This will actually return the battery level from the previous update!
282float getBatteryVoltage() {
283 if (mcuBoard.sensorValues[0] == -9999) mcuBoard.update();
284 return mcuBoard.sensorValues[0];
285}
286
287
288// ==========================================================================
289// Arduino Setup Function
290// ==========================================================================
291/** Start [setup] */
292void setup() {
293 // Start the primary serial connection
294 Serial.begin(serialBaud);
295
296 // Print a start-up note to the first serial port
297 Serial.print(F("Now running "));
298 Serial.print(sketchName);
299 Serial.print(F(" on Logger "));
300 Serial.println(LoggerID);
301 Serial.println();
302
303 Serial.print(F("Using ModularSensors Library version "));
304 Serial.println(MODULAR_SENSORS_VERSION);
305 Serial.print(F("TinyGSM Library version "));
306 Serial.println(TINYGSM_VERSION);
307 Serial.println();
308
309 // Start the serial connection with the modem
310 modemSerial.begin(modemBaud);
311
312 // Set up pins for the LED's
313 pinMode(greenLED, OUTPUT);
314 digitalWrite(greenLED, LOW);
315 pinMode(redLED, OUTPUT);
316 digitalWrite(redLED, LOW);
317 // Blink the LEDs to show the board is on and starting up
318 greenredflash();
319
320 pinMode(20, OUTPUT); // for proper operation of the onboard flash memory
321 // chip's ChipSelect (Mayfly v1.0 and later)
322
323 // Set the timezones for the logger/data and the RTC
324 // Logging in the given time zone
325 Logger::setLoggerTimeZone(timeZone);
326 // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
327 Logger::setRTCTimeZone(0);
328
329 // Attach the modem and information pins to the logger
330 dataLogger.attachModem(modem);
331 modem.setModemLED(modemLEDPin);
332 dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
333 greenLED);
334
335 // Begin the logger
336 dataLogger.begin();
337
338 // Note: Please change these battery voltages to match your battery
339 // Set up the sensors, except at lowest battery level
340 if (getBatteryVoltage() > 3.4) {
341 Serial.println(F("Setting up sensors..."));
342 varArray.setupSensors();
343 }
344
345 /** Start [setup_sim7080] */
346 modem.setModemWakeLevel(HIGH); // ModuleFun Bee inverts the signal
347 modem.setModemResetLevel(HIGH); // ModuleFun Bee inverts the signal
348 Serial.println(F("Waking modem and setting Cellular Carrier Options..."));
349 modem.modemWake(); // NOTE: This will also set up the modem
350 modem.gsmModem.setBaud(modemBaud); // Make sure we're *NOT* auto-bauding!
351 modem.gsmModem.setNetworkMode(38); // set to LTE only
352 // 2 Automatic
353 // 13 GSM only
354 // 38 LTE only
355 // 51 GSM and LTE only
356 modem.gsmModem.setPreferredMode(1); // set to CAT-M
357 // 1 CAT-M
358 // 2 NB-IoT
359 // 3 CAT-M and NB-IoT
360 /** End [setup_sim7080] */
361
362
363 // Sync the clock if it isn't valid or we have battery to spare
364 if (getBatteryVoltage() > 3.55 || !dataLogger.isRTCSane()) {
365 // Synchronize the RTC with NIST
366 // This will also set up the modem
367 dataLogger.syncRTC();
368 }
369
370 // Create the log file, adding the default header to it
371 // Do this last so we have the best chance of getting the time correct and
372 // all sensor names correct
373 // Writing to the SD card can be power intensive, so if we're skipping
374 // the sensor setup we'll skip this too.
375 if (getBatteryVoltage() > 3.4) {
376 Serial.println(F("Setting up file on SD card"));
377 dataLogger.turnOnSDcard(
378 true); // true = wait for card to settle after power up
379 dataLogger.createLogFile(true); // true = write a new header
380 dataLogger.turnOffSDcard(
381 true); // true = wait for internal housekeeping after write
382 }
383
384 // Call the processor sleep
385 Serial.println(F("Putting processor to sleep\n"));
386 dataLogger.systemSleep();
387}
388/** End [setup] */
389
390
391// ==========================================================================
392// Arduino Loop Function
393// ==========================================================================
394/** Start [loop] */
395// Use this short loop for simple data logging and sending
396void loop() {
397 // Note: Please change these battery voltages to match your battery
398 // At very low battery, just go back to sleep
399 if (getBatteryVoltage() < 3.4) {
400 dataLogger.systemSleep();
401 }
402 // At moderate voltage, log data but don't send it over the modem
403 else if (getBatteryVoltage() < 3.55) {
404 dataLogger.logData();
405 }
406 // If the battery is good, send the data to the world
407 else {
408 dataLogger.logDataAndPublish();
409 }
410}
411/** End [loop] */