Example showing all possible functionality

This shows most of the functionality of the library at once. It has code in it for every possible sensor and modem and for both AVR and SAMD boards. This example should never be used directly; it is intended to document all possibilities and to verify compilation.

To create your own code, I recommend starting from a much simpler targeted example, like the Logging to MMW example, and then adding to it based on only the parts of this menu example that apply to you.


Walking Through the Code

PlatformIO Configuration

1; PlatformIO Project Configuration File
2;
3; Build options: build flags, source filter
4; Upload options: custom upload port, speed and extra flags
5; Library options: dependencies, extra library storages
6; Advanced options: extra scripting
7;
8; Please visit documentation for the other options and examples
9; http://docs.platformio.org/page/projectconf.html
10
11[platformio]
12description = ModularSensors example menu_a_la_carte
13
14[env:mayfly]
15monitor_speed = 115200
16board = mayfly
17platform = atmelavr
18framework = arduino
19lib_ldf_mode = deep+
20lib_ignore =
21 RTCZero
22 Adafruit NeoPixel
23 Adafruit GFX Library
24 Adafruit SSD1306
25 Adafruit ADXL343
26 Adafruit STMPE610
27 Adafruit TouchScreen
28 Adafruit ILI9341
29build_flags =
30 -DSDI12_EXTERNAL_PCINT
31 -DNEOSWSERIAL_EXTERNAL_PCINT
32 -DMQTT_MAX_PACKET_SIZE=240
33 -DTINY_GSM_RX_BUFFER=64
34 -DTINY_GSM_YIELD_MS=2
35 -DENABLE_SERIAL2
36 -DENABLE_SERIAL3
37 ; -D BUILD_MODEM_DIGI_XBEE_CELLULAR_TRANSPARENT ; Turn on first time w/ a Digi LTE-M module
38 ; -D MS_LOGGERBASE_DEBUG
39 ; -D MS_DATAPUBLISHERBASE_DEBUG
40 ; -D MS_ENVIRODIYPUBLISHER_DEBUG
41lib_deps =
42 envirodiy/EnviroDIY_ModularSensors
43; ^^ Use this when working from a tagged release of the library
44; See tags at https://platformio.org/lib/show/1648/EnviroDIY_ModularSensors
45
46; https://github.com/EnviroDIY/ModularSensors.git#develop
47; ^^ Use this when if you want to pull from the develop branch
48
49 https://github.com/PaulStoffregen/AltSoftSerial.git
50 https://github.com/SRGDamia1/NeoSWSerial.git
51 https://github.com/EnviroDIY/SoftwareSerial_ExternalInts.git
52; ^^ These are software serial port emulator libraries, you may not need them

The Complete Code

1/** =========================================================================
2 * @example{lineno} menu_a_la_carte.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 with all possible functionality.
8 *
9 * See [the walkthrough page](@ref example_menu) for detailed instructions.
10 *
11 * @m_examplenavigation{example_menu,}
12 * ======================================================================= */
13
14// Defines to help me print strings
15// this converts to string
16#define STR_(X) #X
17// this makes sure the argument is expanded before converting to string
18#define STR(X) STR_(X)
19
20// ==========================================================================
21// Defines for TinyGSM
22// ==========================================================================
23/** Start [defines] */
24#ifndef TINY_GSM_RX_BUFFER
25#define TINY_GSM_RX_BUFFER 64
26#endif
27#ifndef TINY_GSM_YIELD_MS
28#define TINY_GSM_YIELD_MS 2
29#endif
30/** End [defines] */
31
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// Creating Additional Serial Ports
47// ==========================================================================
48// The modem and a number of sensors communicate over UART/TTL - often called
49// "serial". "Hardware" serial ports (automatically controlled by the MCU) are
50// generally the most accurate and should be configured and used for as many
51// peripherals as possible. In some cases (ie, modbus communication) many
52// sensors can share the same serial port.
53
54// For AVR boards
55#if defined(__AVR__) || defined(ARDUINO_ARCH_AVR)
56// Unfortunately, most AVR boards have only one or two hardware serial ports,
57// so we'll set up three types of extra software serial ports to use
58
59#if defined(BUILD_TEST_ALTSOFTSERIAL)
60// AltSoftSerial by Paul Stoffregen
61// (https://github.com/PaulStoffregen/AltSoftSerial) is the most accurate
62// software serial port for AVR boards. AltSoftSerial can only be used on one
63// set of pins on each board so only one AltSoftSerial port can be used. Not all
64// AVR boards are supported by AltSoftSerial.
65/** Start [altsoftserial] */
66#include <AltSoftSerial.h>
67AltSoftSerial altSoftSerial;
68/** End [altsoftserial] */
69#endif // #if defined (BUILD_TEST_ALTSOFTSERIAL)
70
71#if defined(BUILD_TEST_NEOSWSERIAL)
72// NeoSWSerial (https://github.com/SRGDamia1/NeoSWSerial) is the best software
73// serial that can be used on any pin supporting interrupts.
74// You can use as many instances of NeoSWSerial as you need.
75// Not all AVR boards are supported by NeoSWSerial.
76/** Start [neoswserial] */
77#include <NeoSWSerial.h> // for the stream communication
78const int8_t neoSSerial1Rx = 11; // data in pin
79const int8_t neoSSerial1Tx = -1; // data out pin
80NeoSWSerial neoSSerial1(neoSSerial1Rx, neoSSerial1Tx);
81// To use NeoSWSerial in this library, we define a function to receive data
82// This is just a short-cut for later
83void neoSSerial1ISR() {
84 NeoSWSerial::rxISR(*portInputRegister(digitalPinToPort(neoSSerial1Rx)));
85}
86/** End [neoswserial] */
87#endif // #if defined (BUILD_TEST_NEOSWSERIAL)
88
89#if defined(BUILD_TEST_SOFTSERIAL)
90// The "standard" software serial library uses interrupts that conflict
91// with several other libraries used within this program. I've created a
92// [version of software serial that has been stripped of
93// interrupts](https://github.com/EnviroDIY/SoftwareSerial_ExtInts) but it is
94// still far from ideal.
95// NOTE: Only use if necessary. This is not a very accurate serial port!
96// You can use as many instances of SoftwareSerial as you need.
97/** Start [softwareserial] */
98const int8_t softSerialRx = A3; // data in pin
99const int8_t softSerialTx = A4; // data out pin
100
101#include <SoftwareSerial_ExtInts.h> // for the stream communication
102SoftwareSerial_ExtInts softSerial1(softSerialRx, softSerialTx);
103/** End [softwareserial] */
104#endif // #if defined (BUILD_TEST_SOFTSERIAL)
105
106
107#if defined(MS_PALEOTERRA_SOFTWAREWIRE) || defined(MS_RAIN_SOFTWAREWIRE)
108/** Start [softwarewire] */
109// A software I2C (Wire) instance using Testato's SoftwareWire
110// To use SoftwareWire, you must also set a define for the sensor you want to
111// use Software I2C for, ie:
112// `#define MS_RAIN_SOFTWAREWIRE`
113// `#define MS_PALEOTERRA_SOFTWAREWIRE`
114// or set the build flag(s):
115// `-D MS_RAIN_SOFTWAREWIRE`
116// `-D MS_PALEOTERRA_SOFTWAREWIRE`
117#include <SoftwareWire.h> // Testato's Software I2C
118const int8_t softwareSDA = 5;
119const int8_t softwareSCL = 4;
120SoftwareWire softI2C(softwareSDA, softwareSCL);
121/** End [softwarewire] */
122#endif // #if defined(MS_PALEOTERRA_SOFTWAREWIRE) ...
123
124#endif // End software serial for avr boards
125
126#if defined(ARDUINO_SAMD_FEATHER_M0)
127/** Start [serial_ports_feather_m0] */
128// The SAMD21 has 6 "SERCOM" ports, any of which can be used for UART
129// communication. The "core" code for most boards defines one or more UART
130// (Serial) ports with the SERCOMs and uses others for I2C and SPI. We can
131// create new UART ports on any available SERCOM. The table below shows
132// definitions for select boards.
133
134// Board => Arduino Zero Adafruit Feather M0
135// ------- --------------- ----------------
136// SERCOM0 Serial1 (D0/D1) Serial1 (D0/D1)
137// SERCOM1 Available Available
138// SERCOM2 Available Available
139// SERCOM3 I2C (D20/D21) I2C (D20/D21)
140// SERCOM4 SPI (D21/22/23) SPI (D21/22/23)
141// SERCOM5 EDBG/Serial Available
142
143#include <wiring_private.h> // Needed for SAMD pinPeripheral() function
144
145// Set up a 'new' UART using SERCOM1
146// The Rx will be on digital pin 11, which is SERCOM1's Pad #0
147// The Tx will be on digital pin 10, which is SERCOM1's Pad #2
148// NOTE: SERCOM1 is undefined on a "standard" Arduino Zero and many clones,
149// but not all! Please check the variant.cpp file for you individual
150// board!
151Uart Serial2(&sercom1, 11, 10, SERCOM_RX_PAD_0, UART_TX_PAD_2);
152// Hand over the interrupts to the sercom port
153void SERCOM1_Handler() {
154 Serial2.IrqHandler();
155}
156#define ENABLE_SERIAL2
157
158// Set up a 'new' UART using SERCOM2
159// The Rx will be on digital pin 5, which is SERCOM2's Pad #3
160// The Tx will be on digital pin 2, which is SERCOM2's Pad #2
161// NOTE: SERCOM2 is undefined on a "standard" Arduino Zero and many clones,
162// but not all! Please check the variant.cpp file for you individual
163// board! Sodaq Autonomo's and Sodaq One's do NOT follow the 'standard'
164// SERCOM definitions!
165Uart Serial3(&sercom2, 5, 2, SERCOM_RX_PAD_3, UART_TX_PAD_2);
166// Hand over the interrupts to the sercom port
167void SERCOM2_Handler() {
168 Serial3.IrqHandler();
169}
170#define ENABLE_SERIAL3
171
172/** End [serial_ports_feather_m0] */
173#endif // End hardware serial on SAMD21 boards
174
175#if defined(ADAFRUIT_GRAND_CENTRAL_M4)
176/** Start [serial_ports_grand_central] */
177// The Grand Central nominally sets up four serial ports in Variant.h, but
178// doesn't initialize them in Variant.cpp. Doing that here.
179
180Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX,
181 PAD_SERIAL2_TX);
182
183void SERCOM4_0_Handler() {
184 Serial2.IrqHandler();
185}
186void SERCOM4_1_Handler() {
187 Serial2.IrqHandler();
188}
189void SERCOM4_2_Handler() {
190 Serial2.IrqHandler();
191}
192void SERCOM4_3_Handler() {
193 Serial2.IrqHandler();
194}
195#define ENABLE_SERIAL2
196
197Uart Serial3(&sercom1, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX,
198 PAD_SERIAL3_TX);
199
200void SERCOM1_0_Handler() {
201 Serial3.IrqHandler();
202}
203void SERCOM1_1_Handler() {
204 Serial3.IrqHandler();
205}
206void SERCOM1_2_Handler() {
207 Serial3.IrqHandler();
208}
209void SERCOM1_3_Handler() {
210 Serial3.IrqHandler();
211}
212#define ENABLE_SERIAL3
213
214/** End [serial_ports_grand_central] */
215#endif // End hardware serial on Grand Central
216
217
218// ==========================================================================
219// Assigning Serial Port Functionality
220// ==========================================================================
221#if (defined(ENABLE_SERIAL2) && defined(ENABLE_SERIAL3)) || \
222 defined(ENVIRODIY_STONEFLY_M4) || defined(ADAFRUIT_GRAND_CENTRAL_M4) || \
223 defined(ATMEGA2560) || defined(ARDUINO_AVR_MEGA2560)
224/** Start [assign_ports_hw] */
225// If there are additional hardware Serial ports possible - use them!
226
227// We give the modem first priority and assign it to hardware serial
228// All of the supported processors have a hardware port available named Serial1
229#if defined(ENVIRODIY_STONEFLY_M4)
230#define modemSerial SerialBee
231// Helper for alternate print out
232// useful for SAMD boards which are a PITA to debug over USB when sleeping
233#elif defined(ARDUINO_ARCH_SAMD) && defined(MS_2ND_OUTPUT)
234#define modemSerial Serial2
235#else
236#define modemSerial Serial1
237#endif
238
239// Define the serial port for modbus
240// Modbus (at 9600 8N1) is used by the Keller level loggers and Yosemitech
241// sensors
242#define modbusSerial Serial2
243
244#if defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
245#define sonarSerial Serial3
246#endif
247
248#if defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
249#define cameraSerial Serial1
250#endif
251
252/** End [assign_ports_hw] */
253#else
254/** Start [assign_ports_sw] */
255
256// We give the modem first priority and assign it to hardware serial
257// All of the supported processors have a hardware port available named Serial1
258#define modemSerial Serial1
259
260// Define the serial port for modbus
261// Modbus (at 9600 8N1) is used by the Keller level loggers and Yosemitech
262// sensors
263// Since AltSoftSerial is the best software option, we use it for modbus
264// If AltSoftSerial (or its pins) aren't available, use NeoSWSerial
265// SoftwareSerial **WILL NOT** work for modbus!
266#if defined(BUILD_TEST_ALTSOFTSERIAL) && \
267 (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
268// For AltSoftSerial
269#define modbusSerial altSoftSerial
270#elif defined(BUILD_TEST_NEOSWSERIAL) && \
271 (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
272// For Neo software serial
273#define modbusSerial neoSSerial1
274#elif defined(BUILD_TEST_SOFTSERIAL) && \
275 (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
276// For software serial
277#define modbusSerial softSerial1
278#else
279// Hardware serial
280#define modbusSerial Serial1
281#endif
282
283// Since the Maxbotix only needs one-way communication and sends a simple text
284// string repeatedly, almost any software serial port will do for it.
285#if defined(BUILD_TEST_ALTSOFTSERIAL) && defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
286// For AltSoftSerial
287#define sonarSerial altSoftSerial
288#elif defined(BUILD_TEST_NEOSWSERIAL) && defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
289// For Neo software serial
290#define sonarSerial neoSSerial1
291#elif defined(BUILD_TEST_SOFTSERIAL) && defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
292// For software serial
293#define sonarSerial softSerial1
294#elif defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
295// Hardware serial
296#define sonarSerial Serial1
297#endif
298
299// I **REALLY** don't recommend using a software serial for the camera, but oh
300// well
301#if defined(BUILD_TEST_ALTSOFTSERIAL) && defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
302// For AltSoftSerial
303#define cameraSerial altSoftSerial
304#elif defined(BUILD_TEST_NEOSWSERIAL) && defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
305// For Neo software serial
306#define cameraSerial neoSSerial1
307#elif defined(BUILD_TEST_SOFTSERIAL) && defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
308// For software serial
309#define cameraSerial softSerial1
310#elif defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
311// Hardware serial
312#define cameraSerial Serial1
313#endif
314
315/** End [assign_ports_sw] */
316#endif
317
318
319// ==========================================================================
320// Data Logging Options
321// ==========================================================================
322/** Start [logging_options] */
323// The name of this program file - this is used only for console printouts at
324// start-up
325const char* sketchName = "menu_a_la_carte.ino";
326// Logger ID, also becomes the prefix for the name of the data file on SD card
327// This is also used as the Thing Name, MQTT Client ID, and topic for AWS IOT
328// Core
329const char* LoggerID = "your_logger_id";
330// Sampling feature UUID
331// This is used as the UUID for the sampling feature on Monitor My Watershed and
332// the sub-topic for AWS IOT Core
333const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab";
334// How frequently (in minutes) to log data
335const int8_t loggingInterval = 15;
336// Your logger's timezone.
337const int8_t timeZone = -5; // Eastern Standard Time
338// NOTE: Daylight savings time will not be applied! Please use standard time!
339
340// Set the input and output pins for the logger
341// NOTE: Use -1 for pins that do not apply
342#if defined(ARDUINO_AVR_ENVIRODIY_MAYFLY)
343const int32_t serialBaud = 115200; // Baud rate for debugging
344const int8_t greenLED = 8; // Pin for the green LED
345const int8_t redLED = 9; // Pin for the red LED
346const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
347uint8_t buttonPinMode = INPUT; // mode for debugging pin
348// NOTE: On the Mayfly (and Stonefly), pin 21 is tied to a button that pulls the
349// pin HIGH when pressed and an external pull-down that keeps the pin LOW when
350// the button is not pressed. We want the pin mode to be INPUT - ie, floating
351// internally and pulled down externally until the button is pressed. AVR
352// processors like the 1284P on the Mayfly do not have internal pull-down
353// resistors - they do not have an INPUT_PULLDOWN mode like SAMD processors.
354const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep
355uint8_t wakePinMode = INPUT_PULLUP; // mode for wake pin
356// Mayfly 0.x, 1.x D31 = A7
357// NOTE: On the Mayfly, pin D31=A7 is tied directly to the RTC INT/SQW pin
358// on the onboard DS3231 RTC. The interrupt from the DS3231 will pull the pin
359// DOWN, so we want the pin mode to be INPUT_PULLUP - ie, pulled up until the
360// RTC pulls it down.
361// Set the wake pin to -1 if you do not want the main processor to sleep.
362// In a SAMD system where you are using the built-in RTC, set the wakePin to 1.
363const int8_t sdCardPwrPin = -1; // MCU SD card power pin
364const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin
365const int8_t flashSSPin = 20; // onboard flash chip select/slave select pin
366const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
367const int8_t sdi12DataPin = 7;
368const int8_t relayPowerPin = A3; // MCU pin controlling an optional power relay
369#elif defined(ENVIRODIY_STONEFLY_M4)
370const int32_t serialBaud = 921600; // Baud rate for debugging
371const int8_t greenLED = 8; // Pin for the green LED
372const int8_t redLED = 9; // Pin for the red LED
373const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin)
374uint8_t buttonPinMode = INPUT_PULLDOWN; // mode for debugging pin
375// NOTE: On the Stonefly (and Mayfly), 21 is tied to a button that pulls the pin
376// HIGH when pressed and an external pull-down that keeps the pin LOW when the
377// button is not pressed. We want the pin mode to be INPUT_PULLDOWN - ie, pulled
378// down both internally and externally until the button is pressed.
379const int8_t wakePin = 38; // MCU interrupt/alarm pin to wake from sleep
380uint8_t wakePinMode = INPUT_PULLUP; // mode for wake pin
381// NOTE: On the Stonefly, pin D38 is tied directly to the RTC INT/SQW pin
382// on the onboard RV-8803 RTC. The interrupt from the RV-8803 will pull the pin
383// DOWN, so we want the pin mode to be INPUT_PULLUP - ie, pulled up until the
384// RTC pulls it down.
385const int8_t sdCardPwrPin = -1; // MCU SD card power pin
386// const int8_t sdCardPwrPin = 32; // MCU SD card power pin
387const int8_t sdCardSSPin = 29; // SD card chip select/slave select pin
388const int8_t flashSSPin = 20; // onboard flash chip select/slave select pin
389const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power
390const int8_t relayPowerPin = 41; // MCU pin controlling an optional power relay
391const int8_t sdi12DataPin = 3;
392#else
393const int32_t serialBaud = 115200; // Baud rate for debugging
394#if defined(PIN_LED2)
395const int8_t greenLED = PIN_LED2; // Pin for the green LED
396#else
397const int8_t greenLED = -1; // Pin for the green LED
398#endif
399const int8_t redLED = LED_BUILTIN; // Pin for the red LED
400const int8_t buttonPin = -1; // Pin for debugging mode (ie, button pin)
401uint8_t buttonPinMode = INPUT_PULLUP; // mode for debugging pin
402const int8_t wakePin = -1; // MCU interrupt/alarm pin to wake from sleep
403uint8_t wakePinMode = INPUT_PULLUP; // mode for wake pin
404const int8_t sdCardPwrPin = -1; // MCU SD card power pin
405#if defined(SDCARD_SS_PIN)
406const int8_t sdCardSSPin =
407 SDCARD_SS_PIN; // SD card chip select/slave select pin
408#elif defined(PIN_SPI_SS)
409const int8_t sdCardSSPin = PIN_SPI_SS; // SD card chip select/slave select pin
410#else
411const int8_t sdCardSSPin = -1; // SD card chip select/slave select pin
412#endif
413const int8_t flashSSPin = -1; // onboard flash chip select/slave select pin
414const int8_t sensorPowerPin = -1; // MCU pin controlling main sensor power
415const int8_t relayPowerPin = -1; // MCU pin controlling an optional power relay
416const int8_t sdi12DataPin = 3;
417#endif
418/** End [logging_options] */
419
420
421// ==========================================================================
422// The Logger Object[s]
423// ==========================================================================
424/** Start [loggers] */
425// Create a new logger instance
426// NOTE: We haven't set the pins or variable array here! We will need to call
427// setVariableArray and the various pin assignment functions in the setup!
428Logger dataLogger(LoggerID, samplingFeature, loggingInterval);
429/** End [loggers] */
430
431
432// ==========================================================================
433// Wifi/Cellular Modem Options
434// NOTE: DON'T USE MORE THAN ONE MODEM OBJECT!
435// Delete the sections you are not using!
436// ==========================================================================
437
438// Network connection information
439// APN for cellular connection
440#define CELLULAR_APN "add_your_cellular_apn"
441// WiFi access point name
442#define WIFI_ID "your_wifi_ssid"
443// WiFi password (WPA2)
444#define WIFI_PASSWD "your_wifi_password"
445
446#if defined(BUILD_MODEM_DIGI_XBEE_CELLULAR_TRANSPARENT)
447#define BUILD_HAS_MODEM
448/** Start [digi_xbee_cellular_transparent] */
449// For any Digi Cellular XBee's
450// NOTE: The u-blox based Digi XBee's (3G global and LTE-M global) can be used
451// in either bypass or transparent mode, each with pros and cons
452// The Telit based Digi XBees (LTE Cat1) can only use this mode.
453#include <modems/DigiXBeeCellularTransparent.h>
454
455// NOTE: Extra hardware and software serial ports are created in the "Settings
456// for Additional Serial Ports" section
457const int32_t modemBaud = 9600; // All XBee's use 9600 by default
458
459// Modem Pins - Describe the physical pin connection of your modem to your board
460// NOTE: Use -1 for pins that do not apply
461// The pin numbers here are for a Digi XBee with a Mayfly 0.x and LTE adapter
462// For options https://github.com/EnviroDIY/LTEbee-Adapter/edit/master/README.md
463const int8_t modemVccPin = -1; // MCU pin controlling modem power
464 // Option: modemVccPin = A5, if Mayfly SJ7 is
465 // connected to the ASSOC pin
466const int8_t modemStatusPin = 19; // MCU pin used to read modem status
467// NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but
468// the CTS pin can also be used if necessary
469const bool useCTSforStatus = false; // Flag to use the CTS pin for status
470const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin
471const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
472const int8_t modemLEDPin =
473 redLED; // MCU pin connected an LED to show modem status
474
475// Network connection information
476const char* apn = CELLULAR_APN; // APN for GPRS connection
477
478// Create the modem object
479DigiXBeeCellularTransparent modemXBCT(&modemSerial, modemVccPin, modemStatusPin,
480 useCTSforStatus, modemResetPin,
481 modemSleepRqPin, apn);
482// Create an extra reference to the modem by a generic name
483DigiXBeeCellularTransparent modem = modemXBCT;
484/** End [digi_xbee_cellular_transparent] */
485// ==========================================================================
486
487
488#elif defined(BUILD_MODEM_DIGI_XBEE_LTE_BYPASS)
489#define BUILD_HAS_MODEM
490/** Start [digi_xbee_lte_bypass] */
491// For the u-blox SARA R410M based Digi LTE-M XBee3
492// NOTE: According to the manual, this should be less stable than transparent
493// mode, but my experience is the complete reverse.
494#include <modems/DigiXBeeLTEBypass.h>
495
496// NOTE: Extra hardware and software serial ports are created in the "Settings
497// for Additional Serial Ports" section
498const int32_t modemBaud = 9600; // All XBee's use 9600 by default
499
500// Modem Pins - Describe the physical pin connection of your modem to your board
501// NOTE: Use -1 for pins that do not apply
502// The pin numbers here are for a Digi XBee with a Mayfly 0.x and LTE adapter
503const int8_t modemVccPin = A5; // MCU pin controlling modem power
504const int8_t modemStatusPin = 19; // MCU pin used to read modem status
505// NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but
506// the CTS pin can also be used if necessary
507const bool useCTSforStatus = false; // Flag to use the CTS pin for status
508const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin
509const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
510const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
511 // status
512
513// Network connection information
514const char* apn = CELLULAR_APN; // APN for GPRS connection
515
516// Create the modem object
517DigiXBeeLTEBypass modemXBLTEB(&modemSerial, modemVccPin, modemStatusPin,
518 useCTSforStatus, modemResetPin, modemSleepRqPin,
519 apn);
520// Create an extra reference to the modem by a generic name
521DigiXBeeLTEBypass modem = modemXBLTEB;
522/** End [digi_xbee_lte_bypass] */
523// ==========================================================================
524
525
526#elif defined(BUILD_MODEM_DIGI_XBEE_3G_BYPASS)
527#define BUILD_HAS_MODEM
528/** Start [digi_xbee_3g_bypass] */
529// For the u-blox SARA U201 based Digi 3G XBee with 2G fallback
530// NOTE: According to the manual, this should be less stable than transparent
531// mode, but my experience is the complete reverse.
532#include <modems/DigiXBee3GBypass.h>
533
534// NOTE: Extra hardware and software serial ports are created in the "Settings
535// for Additional Serial Ports" section
536const int32_t modemBaud = 9600; // All XBee's use 9600 by default
537
538// Modem Pins - Describe the physical pin connection of your modem to your board
539// NOTE: Use -1 for pins that do not apply
540// The pin numbers here are for a Digi XBee with a Mayfly and LTE adapter
541const int8_t modemVccPin = A5; // MCU pin controlling modem power
542const int8_t modemStatusPin = 19; // MCU pin used to read modem status
543// NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but
544// the CTS pin can also be used if necessary
545const bool useCTSforStatus = false; // Flag to use the CTS pin for status
546const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin
547const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
548const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
549 // status
550
551// Network connection information
552const char* apn = CELLULAR_APN; // APN for GPRS connection
553
554// Create the modem object
555DigiXBee3GBypass modemXB3GB(&modemSerial, modemVccPin, modemStatusPin,
556 useCTSforStatus, modemResetPin, modemSleepRqPin,
557 apn);
558// Create an extra reference to the modem by a generic name
559DigiXBee3GBypass modem = modemXB3GB;
560/** End [digi_xbee_3g_bypass] */
561// ==========================================================================
562
563
564#elif defined(BUILD_MODEM_DIGI_XBEE_WIFI)
565#define BUILD_HAS_MODEM
566/** Start [digi_xbee_wifi] */
567// For the Digi Wifi XBee (S6B)
568#include <modems/DigiXBeeWifi.h>
569
570// NOTE: Extra hardware and software serial ports are created in the "Settings
571// for Additional Serial Ports" section
572const int32_t modemBaud = 9600; // All XBee's use 9600 by default
573
574// Modem Pins - Describe the physical pin connection of your modem to your board
575// NOTE: Use -1 for pins that do not apply
576// The pin numbers here are for a Digi XBee directly connected to a Mayfly 1.x
577const int8_t modemVccPin = 18; // MCU pin controlling modem power
578const int8_t modemStatusPin = 19; // MCU pin used to read modem status
579// NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but
580// the CTS pin can also be used if necessary
581const bool useCTSforStatus = true; // Flag to use the CTS pin for status
582const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin
583const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
584const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
585 // status
586
587// Network connection information
588const char* wifiId = WIFI_ID; // WiFi access point name
589const char* wifiPwd = WIFI_PASSWD; // WiFi password (WPA2)
590
591// Create the modem object
592DigiXBeeWifi modemXBWF(&modemSerial, modemVccPin, modemStatusPin,
593 useCTSforStatus, modemResetPin, modemSleepRqPin, wifiId,
594 wifiPwd);
595// Create an extra reference to the modem by a generic name
596DigiXBeeWifi modem = modemXBWF;
597/** End [digi_xbee_wifi] */
598// ==========================================================================
599
600
601#elif defined(BUILD_MODEM_ESPRESSIF_ESP8266)
602#define BUILD_HAS_MODEM
603/** Start [espressif_esp8266] */
604// For almost anything based on the Espressif ESP8266 using the
605// AT command firmware
606#include <modems/EspressifESP8266.h>
607
608// NOTE: Extra hardware and software serial ports are created in the "Settings
609// for Additional Serial Ports" section
610const int32_t modemBaud = 115200; // Communication speed of the modem
611// NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The
612// module should be programmed to a slower baud rate or set to auto-baud using
613// the AT+UART_CUR or AT+UART_DEF command.
614
615// Modem Pins - Describe the physical pin connection of your modem to your board
616// NOTE: Use -1 for pins that do not apply
617const int8_t modemVccPin = -1; // MCU pin controlling modem power
618const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
619const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
620 // status
621
622// Network connection information
623const char* wifiId = WIFI_ID; // WiFi access point name
624const char* wifiPwd = WIFI_PASSWD; // WiFi password (WPA2)
625
626// Create the modem object
627EspressifESP8266 modemESP(&modemSerial, modemVccPin, modemResetPin, wifiId,
628 wifiPwd);
629// Create an extra reference to the modem by a generic name
630EspressifESP8266 modem = modemESP;
631/** End [espressif_esp8266] */
632// ==========================================================================
633
634
635#elif defined(BUILD_MODEM_ESPRESSIF_ESP32)
636#define BUILD_HAS_MODEM
637/** Start [espressif_esp32] */
638// For almost anything based on the Espressif ESP8266 using the
639// AT command firmware
640#include <modems/EspressifESP32.h>
641
642// NOTE: Extra hardware and software serial ports are created in the "Settings
643// for Additional Serial Ports" section
644const int32_t modemBaud = 57600; // Communication speed of the modem
645// NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The
646// module should be programmed to a slower baud rate or set to auto-baud using
647// the AT+UART_CUR or AT+UART_DEF command.
648
649// Modem Pins - Describe the physical pin connection of your modem to your board
650// NOTE: Use -1 for pins that do not apply
651// Example pins here are for a EnviroDIY ESP32 Bluetooth/Wifi Bee with
652// Mayfly 1.1
653const int8_t modemVccPin = 18; // MCU pin controlling modem power
654const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin
655const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
656 // status
657
658// Network connection information
659const char* wifiId = WIFI_ID; // WiFi access point name
660const char* wifiPwd = WIFI_PASSWD; // WiFi password (WPA2)
661
662// Create the modem object
663EspressifESP32 modemESP(&modemSerial, modemVccPin, modemResetPin, wifiId,
664 wifiPwd);
665// Create an extra reference to the modem by a generic name
666EspressifESP32 modem = modemESP;
667/** End [espressif_esp32] */
668// ==========================================================================
669
670
671#elif defined(BUILD_MODEM_QUECTEL_BG96)
672#define BUILD_HAS_MODEM
673/** Start [quectel_bg96] */
674// For the Dragino, Nimbelink or other boards based on the Quectel BG96
675#include <modems/QuectelBG96.h>
676
677// NOTE: Extra hardware and software serial ports are created in the "Settings
678// for Additional Serial Ports" section
679const int32_t modemBaud = 115200; // Communication speed of the modem
680// NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The
681// module should be programmed to a slower baud rate or set to auto-baud using
682// the AT+IPR=9600 command.
683
684// Modem Pins - Describe the physical pin connection of your modem to your board
685// NOTE: Use -1 for pins that do not apply
686// Example pins here are for a Mayfly 1.x and a Dragino IoT Bee
687const int8_t modemVccPin = 18; // MCU pin controlling modem power
688const int8_t modemStatusPin = -1; // MCU pin used to read modem status
689const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin
690const int8_t modemSleepRqPin = -1; // MCU pin for modem sleep/wake request
691const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
692 // status
693
694// Network connection information
695const char* apn = CELLULAR_APN; // APN for GPRS connection
696
697// Create the modem object
698QuectelBG96 modemBG96(&modemSerial, modemVccPin, modemStatusPin, modemResetPin,
699 modemSleepRqPin, apn);
700// Create an extra reference to the modem by a generic name
701QuectelBG96 modem = modemBG96;
702/** End [quectel_bg96] */
703// ==========================================================================
704
705
706#elif defined(BUILD_MODEM_SEQUANS_MONARCH)
707#define BUILD_HAS_MODEM
708/** Start [sequans_monarch] */
709// For the Nimbelink LTE-M Verizon/Sequans or other boards based on the Sequans
710// Monarch series
711#include <modems/SequansMonarch.h>
712
713// NOTE: Extra hardware and software serial ports are created in the "Settings
714// for Additional Serial Ports" section
715const int32_t modemBaud = 921600; // Default baud rate of SVZM20 is 921600
716// NOTE: This baud rate is much too fast for many Arduinos! The module should
717// be programmed to a slower baud rate or set to auto-baud using the AT+IPR
718// command.
719
720// Modem Pins - Describe the physical pin connection of your modem to your board
721// NOTE: Use -1 for pins that do not apply
722// Nimbelink Skywire (NOT directly connectable to a Mayfly!)
723const int8_t modemVccPin = 18; // MCU pin controlling modem power
724const int8_t modemStatusPin = 19; // MCU pin used to read modem status
725const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin
726const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
727const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
728 // status
729
730// Network connection information
731const char* apn = CELLULAR_APN; // APN for GPRS connection
732
733// Create the modem object
734SequansMonarch modemSVZM(&modemSerial, modemVccPin, modemStatusPin,
735 modemResetPin, modemSleepRqPin, apn);
736// Create an extra reference to the modem by a generic name
737SequansMonarch modem = modemSVZM;
738/** End [sequans_monarch] */
739// ==========================================================================
740
741
742#elif defined(BUILD_MODEM_SIM_COM_SIM800)
743#define BUILD_HAS_MODEM
744/** Start [sim_com_sim800] */
745// For almost anything based on the SIMCom SIM800 EXCEPT the Sodaq 2GBee R6 and
746// higher
747#include <modems/SIMComSIM800.h>
748
749// NOTE: Extra hardware and software serial ports are created in the "Settings
750// for Additional Serial Ports" section
751const int32_t modemBaud = 9600; // SIM800 does auto-bauding by default
752
753// Modem Pins - Describe the physical pin connection of your modem to your board
754// NOTE: Use -1 for pins that do not apply
755// Example pins are for a Sodaq GPRSBee R4 with a Mayfly 0.x
756const int8_t modemVccPin = -1; // MCU pin controlling modem power
757const int8_t modemStatusPin = 19; // MCU pin used to read modem status
758const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
759const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
760const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
761 // status
762
763// Network connection information
764const char* apn = CELLULAR_APN; // APN for GPRS connection
765
766// Create the modem object
767SIMComSIM800 modemS800(&modemSerial, modemVccPin, modemStatusPin, modemResetPin,
768 modemSleepRqPin, apn);
769// Create an extra reference to the modem by a generic name
770SIMComSIM800 modem = modemS800;
771/** End [sim_com_sim800] */
772// ==========================================================================
773
774
775#elif defined(BUILD_MODEM_SIM_COM_SIM7000)
776#define BUILD_HAS_MODEM
777/** Start [sim_com_sim7000] */
778// For almost anything based on the SIMCom SIM7000
779#include <modems/SIMComSIM7000.h>
780
781// NOTE: Extra hardware and software serial ports are created in the "Settings
782// for Additional Serial Ports" section
783const int32_t modemBaud = 9600; // SIM7000 does auto-bauding by default
784
785// Modem Pins - Describe the physical pin connection of your modem to your board
786// NOTE: Use -1 for pins that do not apply
787const int8_t modemVccPin = 18; // MCU pin controlling modem power
788const int8_t modemStatusPin = 19; // MCU pin used to read modem status
789const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin
790const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
791const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
792 // status
793
794// Network connection information
795const char* apn = CELLULAR_APN; // APN for GPRS connection
796
797// Create the modem object
798SIMComSIM7000 modem7000(&modemSerial, modemVccPin, modemStatusPin,
799 modemResetPin, modemSleepRqPin, apn);
800// Create an extra reference to the modem by a generic name
801SIMComSIM7000 modem = modem7000;
802/** End [sim_com_sim7000] */
803// ==========================================================================
804
805
806#elif defined(BUILD_MODEM_SIM_COM_SIM7080)
807#define BUILD_HAS_MODEM
808/** Start [sim_com_sim7080] */
809// For almost anything based on the SIMCom SIM7080G
810#include <modems/SIMComSIM7080.h>
811
812// NOTE: Extra hardware and software serial ports are created in the "Settings
813// for Additional Serial Ports" section
814const int32_t modemBaud =
815 9600; // SIM7080 does auto-bauding by default, but I set mine to 9600
816
817// Modem Pins - Describe the physical pin connection of your modem to your board
818// NOTE: Use -1 for pins that do not apply
819const int8_t modemVccPin = 18; // MCU pin controlling modem power
820const int8_t modemStatusPin = 19; // MCU pin used to read modem status
821const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request
822const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
823 // status
824
825// Network connection information
826const char* apn = CELLULAR_APN; // APN for GPRS connection
827
828// Create the modem object
829SIMComSIM7080 modem7080(&modemSerial, modemVccPin, modemStatusPin,
830 modemSleepRqPin, apn);
831// Create an extra reference to the modem by a generic name
832SIMComSIM7080 modem = modem7080;
833/** End [sim_com_sim7080] */
834// ==========================================================================
835
836
837#elif defined(BUILD_MODEM_SODAQ_2G_BEE_R6)
838#define BUILD_HAS_MODEM
839/** Start [sodaq_2g_bee_r6] */
840// For the Sodaq 2GBee R6 and R7 based on the SIMCom SIM800
841// NOTE: The Sodaq GPRSBee doesn't expose the SIM800's reset pin
842#include <modems/Sodaq2GBeeR6.h>
843
844// NOTE: Extra hardware and software serial ports are created in the "Settings
845// for Additional Serial Ports" section
846const int32_t modemBaud = 9600; // SIM800 does auto-bauding by default
847
848// Modem Pins - Describe the physical pin connection of your modem to your board
849// NOTE: Use -1 for pins that do not apply
850// Example pins are for a Sodaq GPRSBee R6 or R7 with a Mayfly 0.x
851const int8_t modemVccPin = 23; // MCU pin controlling modem power
852const int8_t modemStatusPin = 19; // MCU pin used to read modem status
853const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
854const int8_t modemSleepRqPin = -1; // MCU pin for modem sleep/wake request
855const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
856 // status
857
858// Network connection information
859const char* apn = CELLULAR_APN; // APN for GPRS connection
860
861// Create the modem object
862Sodaq2GBeeR6 modem2GB(&modemSerial, modemVccPin, modemStatusPin, apn);
863// Create an extra reference to the modem by a generic name
864Sodaq2GBeeR6 modem = modem2GB;
865/** End [sodaq_2g_bee_r6] */
866// ==========================================================================
867
868
869#elif defined(BUILD_MODEM_SODAQ_UBEE_R410M)
870#define BUILD_HAS_MODEM
871/** Start [sodaq_ubee_r410m] */
872// For the Sodaq UBee based on the 4G LTE-M u-blox SARA R410M
873#include <modems/SodaqUBeeR410M.h>
874
875// NOTE: Extra hardware and software serial ports are created in the "Settings
876// for Additional Serial Ports" section
877const int32_t modemBaud =
878 115200; // Default baud rate of the SARA R410M is 115200
879// NOTE: The SARA R410N DOES NOT save baud rate to non-volatile memory. After
880// every power loss, the module will return to the default baud rate of 115200.
881// NOTE: 115200 is TOO FAST for an 8MHz Arduino. This library attempts to
882// compensate by sending a baud rate change command in the wake function when
883// compiled for a 8MHz board. Because of this, 8MHz boards, LIKE THE MAYFLY,
884// *MUST* use a HardwareSerial instance as modemSerial.
885
886// Modem Pins - Describe the physical pin connection of your modem to your board
887// NOTE: Use -1 for pins that do not apply
888// Example pins are for a Sodaq uBee R410M with a Mayfly 0.x
889const int8_t modemVccPin = 23; // MCU pin controlling modem power
890const int8_t modemStatusPin = 19; // MCU pin used to read modem status
891const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
892const int8_t modemSleepRqPin = 20; // MCU pin for modem sleep/wake request
893const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
894 // status
895
896// Network connection information
897const char* apn = CELLULAR_APN; // APN for GPRS connection
898
899// Create the modem object
900SodaqUBeeR410M modemR410(&modemSerial, modemVccPin, modemStatusPin,
901 modemResetPin, modemSleepRqPin, apn);
902// Create an extra reference to the modem by a generic name
903SodaqUBeeR410M modem = modemR410;
904/** End [sodaq_ubee_r410m] */
905// ==========================================================================
906
907
908#elif defined(BUILD_MODEM_SODAQ_UBEE_U201)
909#define BUILD_HAS_MODEM
910/** Start [sodaq_ubee_u201] */
911// For the Sodaq UBee based on the 3G u-blox SARA U201
912#include <modems/SodaqUBeeU201.h>
913
914// NOTE: Extra hardware and software serial ports are created in the "Settings
915// for Additional Serial Ports" section
916const int32_t modemBaud =
917 9600; // SARA U2xx module does auto-bauding by default
918
919// Modem Pins - Describe the physical pin connection of your modem to your board
920// NOTE: Use -1 for pins that do not apply
921// Example pins are for a Sodaq uBee U201 with a Mayfly 0.x
922const int8_t modemVccPin = 23; // MCU pin controlling modem power
923const int8_t modemStatusPin = 19; // MCU pin used to read modem status
924const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin
925const int8_t modemSleepRqPin = 20; // MCU pin for modem sleep/wake request
926const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem
927 // status
928
929// Network connection information
930const char* apn = CELLULAR_APN; // APN for GPRS connection
931
932// Create the modem object
933SodaqUBeeU201 modemU201(&modemSerial, modemVccPin, modemStatusPin,
934 modemResetPin, modemSleepRqPin, apn);
935// Create an extra reference to the modem by a generic name
936SodaqUBeeU201 modem = modemU201;
937/** End [sodaq_ubee_u201] */
938// ==========================================================================
939#endif
940
941#if !defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM)
942/** Start [modem_variables] */
943// Create RSSI and signal strength variable pointers for the modem
944Variable* modemRSSI =
945 new Modem_RSSI(&modem, "12345678-abcd-1234-ef00-1234567890ab", "RSSI");
946Variable* modemSignalPct = new Modem_SignalPercent(
947 &modem, "12345678-abcd-1234-ef00-1234567890ab", "signalPercent");
948Variable* modemBatteryState = new Modem_BatteryState(
949 &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatteryCS");
950Variable* modemBatteryPct = new Modem_BatteryPercent(
951 &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatteryPct");
952Variable* modemBatteryVoltage = new Modem_BatteryVoltage(
953 &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatterymV");
954Variable* modemTemperature =
955 new Modem_Temp(&modem, "12345678-abcd-1234-ef00-1234567890ab", "modemTemp");
956/** End [modem_variables] */
957#endif
958
959
960// ==========================================================================
961// Using the Processor as a Sensor
962// ==========================================================================
963/** Start [processor_stats] */
964#include <sensors/ProcessorStats.h>
965
966// Create the main processor chip "sensor" - for general metadata
967#if defined(ENVIRODIY_STONEFLY_M4)
968const char* mcuBoardVersion = "v0.1";
969#elif defined(ARDUINO_AVR_ENVIRODIY_MAYFLY)
970const char* mcuBoardVersion = "v1.1";
971#else
972const char* mcuBoardVersion = "unknown";
973#endif
974ProcessorStats mcuBoard(mcuBoardVersion, 5);
975
976// Create sample number, battery voltage, free RAM, and reset cause variable
977// pointers for the processor
978Variable* mcuBoardBatt = new ProcessorStats_Battery(
979 &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab");
980Variable* mcuBoardAvailableRAM = new ProcessorStats_FreeRam(
981 &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab");
982Variable* mcuBoardSampNo = new ProcessorStats_SampleNumber(
983 &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab");
984Variable* mcuBoardReset = new ProcessorStats_ResetCode(
985 &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab");
986/** End [processor_stats] */
987
988
989#if defined(MS_USE_DS3231)
990// ==========================================================================
991// Maxim DS3231 RTC (Real Time Clock)
992// ==========================================================================
993/** Start [maxim_ds3231] */
994#include <sensors/MaximDS3231.h>
995
996// Create a DS3231 sensor object
997MaximDS3231 ds3231(1);
998
999// Create a temperature variable pointer for the DS3231
1000Variable* ds3231Temp =
1001 new MaximDS3231_Temp(&ds3231, "12345678-abcd-1234-ef00-1234567890ab");
1002/** End [maxim_ds3231] */
1003#endif
1004
1005
1006#if defined(BUILD_SENSOR_ALPHASENSE_CO2)
1007// ==========================================================================
1008// Alphasense CO2 Sensor
1009// ==========================================================================
1010/** Start [alphasense_co2] */
1011#include <sensors/AlphasenseCO2.h>
1012
1013// NOTE: Use -1 for any pins that don't apply or aren't being used.
1014const int8_t AlphasenseCO2Power = sensorPowerPin; // Power pin
1015aco2_adsDiffMux_t AlphasenseDiffMux =
1016 DIFF_MUX_2_3; // Differential voltage config
1017const uint8_t AlphasenseCO2ADSi2c_addr =
1018 0x48; // The I2C address of the ADS1115 ADC
1019
1020// Create an Alphasense CO2 sensor object
1021AlphasenseCO2 alphasenseCO2(AlphasenseCO2Power, AlphasenseDiffMux,
1022 AlphasenseCO2ADSi2c_addr);
1023
1024// Create PAR and raw voltage variable pointers for the CO2
1025Variable* asCO2 = new AlphasenseCO2_CO2(&alphasenseCO2,
1026 "12345678-abcd-1234-ef00-1234567890ab");
1027Variable* asco2voltage = new AlphasenseCO2_Voltage(
1028 &alphasenseCO2, "12345678-abcd-1234-ef00-1234567890ab");
1029/** End [alphasense_co2] */
1030#endif
1031
1032
1033#if defined(BUILD_SENSOR_ANB_PH)
1034#ifndef BUILD_MODBUS_SENSOR
1035#define BUILD_MODBUS_SENSOR
1036#endif
1037// ==========================================================================
1038// ANB Sensors pH Sensor
1039// ==========================================================================
1040/** Start [anb_ph] */
1041#include <sensors/ANBpH.h>
1042
1043// NOTE: Extra hardware and software serial ports are created in the "Settings
1044// for Additional Serial Ports" section
1045
1046// NOTE: Use -1 for any pins that don't apply or aren't being used.
1047byte anbModbusAddress =
1048 0x55; // The modbus address of ANB pH Sensor (0x55 is the default)
1049const int8_t anbPower = sensorPowerPin; // ANB pH Sensor power pin
1050const int8_t alAdapterPower = sensorPowerPin; // RS485 adapter power pin
1051const int8_t al485EnablePin = -1; // Adapter RE/DE pin
1052const uint8_t anbNumberReadings = 1;
1053
1054// Create an ANB pH sensor object
1055ANBpH anbPH(anbModbusAddress, modbusSerial, anbPower, alAdapterPower,
1056 al485EnablePin, anbNumberReadings);
1057
1058// Create all of the variable pointers for the ANB pH sensor
1059Variable* anbPHValue = new ANBpH_pH(&anbPH,
1060 "12345678-abcd-1234-ef00-1234567890ab");
1061Variable* anbPHTemp = new ANBpH_Temp(&anbPH,
1062 "12345678-abcd-1234-ef00-1234567890ab");
1063Variable* anbPHSal = new ANBpH_Salinity(&anbPH,
1064 "12345678-abcd-1234-ef00-1234567890ab");
1065Variable* anbPHSpCond =
1066 new ANBpH_SpCond(&anbPH, "12345678-abcd-1234-ef00-1234567890ab");
1067Variable* anbPHEC = new ANBpH_EC(&anbPH,
1068 "12345678-abcd-1234-ef00-1234567890ab");
1069Variable* anbPHHealth =
1070 new ANBpH_HealthCode(&anbPH, "12345678-abcd-1234-ef00-1234567890ab");
1071Variable* anbPHDiagnostic =
1072 new ANBpH_DiagnosticCode(&anbPH, "12345678-abcd-1234-ef00-1234567890ab");
1073Variable* anbPHStatus =
1074 new ANBpH_StatusCode(&anbPH, "12345678-abcd-1234-ef00-1234567890ab");
1075/** End [anb_ph] */
1076#endif
1077
1078
1079#if defined(BUILD_SENSOR_AO_SONG_AM2315)
1080// ==========================================================================
1081// AOSong AM2315 Digital Humidity and Temperature Sensor
1082// ==========================================================================
1083/** Start [ao_song_am2315] */
1084#include <sensors/AOSongAM2315.h>
1085
1086// NOTE: Use -1 for any pins that don't apply or aren't being used.
1087const int8_t AM2315Power = sensorPowerPin; // Power pin
1088
1089// Create an AOSong AM2315 sensor object
1090AOSongAM2315 am2315(AM2315Power);
1091
1092// Create humidity and temperature variable pointers for the AM2315
1093Variable* am2315Humid =
1094 new AOSongAM2315_Humidity(&am2315, "12345678-abcd-1234-ef00-1234567890ab");
1095Variable* am2315Temp =
1096 new AOSongAM2315_Temp(&am2315, "12345678-abcd-1234-ef00-1234567890ab");
1097/** End [ao_song_am2315] */
1098#endif
1099
1100
1101#if defined(BUILD_SENSOR_AO_SONG_DHT)
1102// ==========================================================================
1103// AOSong DHT 11/21 (AM2301)/22 (AM2302) Digital Humidity and Temperature
1104// ==========================================================================
1105/** Start [ao_song_dht] */
1106#include <sensors/AOSongDHT.h>
1107
1108// NOTE: Use -1 for any pins that don't apply or aren't being used.
1109const int8_t DHTPower = sensorPowerPin; // Power pin
1110const int8_t DHTPin = 10; // DHT data pin
1111const int8_t dhtType =
1112 DHT11; // DHT type, one of DHT11, DHT12, DHT21, DHT22, or AM2301
1113
1114// Create an AOSong DHT sensor object
1115AOSongDHT dht(DHTPower, DHTPin, dhtType);
1116
1117// Create humidity, temperature, and heat index variable pointers for the DHT
1118Variable* dhtHumid =
1119 new AOSongDHT_Humidity(&dht, "12345678-abcd-1234-ef00-1234567890ab");
1120Variable* dhtTemp = new AOSongDHT_Temp(&dht,
1121 "12345678-abcd-1234-ef00-1234567890ab");
1122Variable* dhtHI = new AOSongDHT_HI(&dht,
1123 "12345678-abcd-1234-ef00-1234567890ab");
1124/** End [ao_song_dht] */
1125#endif
1126
1127
1128#if defined(BUILD_SENSOR_APOGEE_SQ212)
1129// ==========================================================================
1130// Apogee SQ-212 Photosynthetically Active Radiation (PAR) Sensor
1131// ==========================================================================
1132/** Start [apogee_sq212] */
1133#include <sensors/ApogeeSQ212.h>
1134
1135// NOTE: Use -1 for any pins that don't apply or aren't being used.
1136const int8_t SQ212Power = sensorPowerPin; // Power pin
1137const int8_t SQ212ADSChannel = 3; // The ADS channel for the SQ212
1138const uint8_t SQ212ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
1139
1140// Create an Apogee SQ212 sensor object
1141ApogeeSQ212 SQ212(SQ212Power, SQ212ADSChannel, SQ212ADSi2c_addr);
1142
1143// Create PAR and raw voltage variable pointers for the SQ212
1144Variable* sq212PAR =
1145 new ApogeeSQ212_PAR(&SQ212, "12345678-abcd-1234-ef00-1234567890ab");
1146Variable* sq212voltage =
1147 new ApogeeSQ212_Voltage(&SQ212, "12345678-abcd-1234-ef00-1234567890ab");
1148/** End [apogee_sq212] */
1149#endif
1150
1151
1152#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_CO2)
1153// ==========================================================================
1154// Atlas Scientific EZO-CO2 Embedded NDIR Carbon Dioxide Sensor
1155// ==========================================================================
1156/** Start [atlas_scientific_co2] */
1157#include <sensors/AtlasScientificCO2.h>
1158
1159// NOTE: Use -1 for any pins that don't apply or aren't being used.
1160const int8_t AtlasCO2Power = sensorPowerPin; // Power pin
1161uint8_t AtlasCO2i2c_addr = 0x69; // Default for CO2-EZO is 0x69 (105)
1162// All Atlas sensors have different default I2C addresses, but any of them can
1163// be re-addressed to any 8 bit number. If using the default address for any
1164// Atlas Scientific sensor, you may omit this argument.
1165
1166// Create an Atlas Scientific CO2 sensor object
1167// AtlasScientificCO2 atlasCO2(AtlasCO2Power, AtlasCO2i2c_addr);
1168AtlasScientificCO2 atlasCO2(AtlasCO2Power);
1169
1170// Create concentration and temperature variable pointers for the EZO-CO2
1171Variable* atlasCO2CO2 = new AtlasScientificCO2_CO2(
1172 &atlasCO2, "12345678-abcd-1234-ef00-1234567890ab");
1173Variable* atlasCO2Temp = new AtlasScientificCO2_Temp(
1174 &atlasCO2, "12345678-abcd-1234-ef00-1234567890ab");
1175/** End [atlas_scientific_co2] */
1176#endif
1177
1178
1179#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_DO)
1180// ==========================================================================
1181// Atlas Scientific EZO-DO Dissolved Oxygen Sensor
1182// ==========================================================================
1183/** Start [atlas_scientific_do] */
1184#include <sensors/AtlasScientificDO.h>
1185
1186// NOTE: Use -1 for any pins that don't apply or aren't being used.
1187const int8_t AtlasDOPower = sensorPowerPin; // Power pin
1188uint8_t AtlasDOi2c_addr = 0x61; // Default for DO is 0x61 (97)
1189// All Atlas sensors have different default I2C addresses, but any of them can
1190// be re-addressed to any 8 bit number. If using the default address for any
1191// Atlas Scientific sensor, you may omit this argument.
1192
1193// Create an Atlas Scientific DO sensor object
1194// AtlasScientificDO atlasDO(AtlasDOPower, AtlasDOi2c_addr);
1195AtlasScientificDO atlasDO(AtlasDOPower);
1196
1197// Create concentration and percent saturation variable pointers for the EZO-DO
1198Variable* atlasDOconc = new AtlasScientificDO_DOmgL(
1199 &atlasDO, "12345678-abcd-1234-ef00-1234567890ab");
1200Variable* atlasDOpct = new AtlasScientificDO_DOpct(
1201 &atlasDO, "12345678-abcd-1234-ef00-1234567890ab");
1202/** End [atlas_scientific_do] */
1203#endif
1204
1205
1206#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_ORP)
1207// ==========================================================================
1208// Atlas Scientific EZO-ORP Oxidation/Reduction Potential Sensor
1209// ==========================================================================
1210/** Start [atlas_scientific_orp] */
1211#include <sensors/AtlasScientificORP.h>
1212
1213// NOTE: Use -1 for any pins that don't apply or aren't being used.
1214const int8_t AtlasORPPower = sensorPowerPin; // Power pin
1215uint8_t AtlasORPi2c_addr = 0x62; // Default for ORP is 0x62 (98)
1216// All Atlas sensors have different default I2C addresses, but any of them can
1217// be re-addressed to any 8 bit number. If using the default address for any
1218// Atlas Scientific sensor, you may omit this argument.
1219
1220// Create an Atlas Scientific ORP sensor object
1221// AtlasScientificORP atlasORP(AtlasORPPower, AtlasORPi2c_addr);
1222AtlasScientificORP atlasORP(AtlasORPPower);
1223
1224// Create a potential variable pointer for the ORP
1225Variable* atlasORPot = new AtlasScientificORP_Potential(
1226 &atlasORP, "12345678-abcd-1234-ef00-1234567890ab");
1227/** End [atlas_scientific_orp] */
1228#endif
1229
1230
1231#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_PH)
1232// ==========================================================================
1233// Atlas Scientific EZO-pH Sensor
1234// ==========================================================================
1235/** Start [atlas_scientific_ph] */
1236#include <sensors/AtlasScientificpH.h>
1237
1238// NOTE: Use -1 for any pins that don't apply or aren't being used.
1239const int8_t AtlaspHPower = sensorPowerPin; // Power pin
1240uint8_t AtlaspHi2c_addr = 0x63; // Default for pH is 0x63 (99)
1241// All Atlas sensors have different default I2C addresses, but any of them can
1242// be re-addressed to any 8 bit number. If using the default address for any
1243// Atlas Scientific sensor, you may omit this argument.
1244
1245// Create an Atlas Scientific pH sensor object
1246// AtlasScientificpH atlaspH(AtlaspHPower, AtlaspHi2c_addr);
1247AtlasScientificpH atlaspH(AtlaspHPower);
1248
1249// Create a pH variable pointer for the pH sensor
1250Variable* atlaspHpH =
1251 new AtlasScientificpH_pH(&atlaspH, "12345678-abcd-1234-ef00-1234567890ab");
1252/** End [atlas_scientific_ph] */
1253#endif
1254
1255
1256#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_RTD) || \
1257 defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_EC)
1258// ==========================================================================
1259// Atlas Scientific EZO-RTD Temperature Sensor
1260// ==========================================================================
1261/** Start [atlas_scientific_rtd] */
1262#include <sensors/AtlasScientificRTD.h>
1263
1264// NOTE: Use -1 for any pins that don't apply or aren't being used.
1265const int8_t AtlasRTDPower = sensorPowerPin; // Power pin
1266uint8_t AtlasRTDi2c_addr = 0x66; // Default for RTD is 0x66 (102)
1267// All Atlas sensors have different default I2C addresses, but any of them can
1268// be re-addressed to any 8 bit number. If using the default address for any
1269// Atlas Scientific sensor, you may omit this argument.
1270
1271// Create an Atlas Scientific RTD sensor object
1272// AtlasScientificRTD atlasRTD(AtlasRTDPower, AtlasRTDi2c_addr);
1273AtlasScientificRTD atlasRTD(AtlasRTDPower);
1274
1275// Create a temperature variable pointer for the RTD
1276Variable* atlasTemp = new AtlasScientificRTD_Temp(
1277 &atlasRTD, "12345678-abcd-1234-ef00-1234567890ab");
1278/** End [atlas_scientific_rtd] */
1279#endif
1280
1281
1282#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_EC)
1283// ==========================================================================
1284// Atlas Scientific EZO-EC Conductivity Sensor
1285// ==========================================================================
1286/** Start [atlas_scientific_ec] */
1287#include <sensors/AtlasScientificEC.h>
1288
1289// NOTE: Use -1 for any pins that don't apply or aren't being used.
1290const int8_t AtlasECPower = sensorPowerPin; // Power pin
1291uint8_t AtlasECi2c_addr = 0x64; // Default for EC is 0x64 (100)
1292// All Atlas sensors have different default I2C addresses, but any of them can
1293// be re-addressed to any 8 bit number. If using the default address for any
1294// Atlas Scientific sensor, you may omit this argument.
1295
1296// Create an Atlas Scientific Conductivity sensor object
1297// AtlasScientificEC atlasEC(AtlasECPower, AtlasECi2c_addr);
1298AtlasScientificEC atlasEC(AtlasECPower);
1299
1300// Create four variable pointers for the EZO-ES
1301Variable* atlasCond = new AtlasScientificEC_Cond(
1302 &atlasEC, "12345678-abcd-1234-ef00-1234567890ab");
1303Variable* atlasTDS =
1304 new AtlasScientificEC_TDS(&atlasEC, "12345678-abcd-1234-ef00-1234567890ab");
1305Variable* atlasSal = new AtlasScientificEC_Salinity(
1306 &atlasEC, "12345678-abcd-1234-ef00-1234567890ab");
1307Variable* atlasGrav = new AtlasScientificEC_SpecificGravity(
1308 &atlasEC, "12345678-abcd-1234-ef00-1234567890ab");
1309
1310// Create a calculated variable for the temperature compensated conductivity
1311// (that is, the specific conductance). For this example, we will use the
1312// temperature measured by the Atlas RTD above this. You could use the
1313// temperature returned by any other water temperature sensor if desired.
1314// **DO NOT** use your logger board temperature (ie, from the DS3231) to
1315// calculate specific conductance!
1316float calculateAtlasSpCond() {
1317 float spCond = -9999; // Always safest to start with a bad value
1318 float waterTemp = atlasTemp->getValue();
1319 float rawCond = atlasCond->getValue();
1320 // ^^ Linearized temperature correction coefficient per degrees Celsius.
1321 // The value of 0.019 comes from measurements reported here:
1322 // Hayashi M. Temperature-electrical conductivity relation of water for
1323 // environmental monitoring and geophysical data inversion. Environ Monit
1324 // Assess. 2004 Aug-Sep;96(1-3):119-28.
1325 // doi: 10.1023/b:emas.0000031719.83065.68. PMID: 15327152.
1326 if (waterTemp != -9999 && rawCond != -9999) {
1327 // make sure both inputs are good
1328 float temperatureCoef = 0.019;
1329 spCond = rawCond / (1 + temperatureCoef * (waterTemp - 25.0));
1330 }
1331 return spCond;
1332}
1333
1334// Properties of the calculated variable
1335// The number of digits after the decimal place
1336const uint8_t atlasSpCondResolution = 0;
1337// This must be a value from http://vocabulary.odm2.org/variablename/
1338const char* atlasSpCondName = "specificConductance";
1339// This must be a value from http://vocabulary.odm2.org/units/
1340const char* atlasSpCondUnit = "microsiemenPerCentimeter";
1341// A short code for the variable
1342const char* atlasSpCondCode = "atlasSpCond";
1343// The (optional) universally unique identifier
1344const char* atlasSpCondUUID = "12345678-abcd-1234-ef00-1234567890ab";
1345
1346// Finally, create the specific conductance variable and return a pointer to it
1347Variable* atlasSpCond =
1348 new Variable(calculateAtlasSpCond, atlasSpCondResolution, atlasSpCondName,
1349 atlasSpCondUnit, atlasSpCondCode, atlasSpCondUUID);
1350/** End [atlas_scientific_ec] */
1351#endif
1352
1353
1354#if defined(BUILD_SENSOR_BOSCH_BME280)
1355// ==========================================================================
1356// Bosch BME280 Environmental Sensor
1357// ==========================================================================
1358/** Start [bosch_bme280] */
1359#include <sensors/BoschBME280.h>
1360
1361// NOTE: Use -1 for any pins that don't apply or aren't being used.
1362const int8_t BME280Power = sensorPowerPin; // Power pin
1363uint8_t BMEi2c_addr = 0x76;
1364// The BME280 can be addressed either as 0x77 (Adafruit default) or 0x76 (Grove
1365// default) Either can be physically modified for the other address
1366
1367// Create a Bosch BME280 sensor object
1368BoschBME280 bme280(BME280Power, BMEi2c_addr);
1369
1370// Create four variable pointers for the BME280
1371Variable* bme280Humid =
1372 new BoschBME280_Humidity(&bme280, "12345678-abcd-1234-ef00-1234567890ab");
1373Variable* bme280Temp =
1374 new BoschBME280_Temp(&bme280, "12345678-abcd-1234-ef00-1234567890ab");
1375Variable* bme280Press =
1376 new BoschBME280_Pressure(&bme280, "12345678-abcd-1234-ef00-1234567890ab");
1377Variable* bme280Alt =
1378 new BoschBME280_Altitude(&bme280, "12345678-abcd-1234-ef00-1234567890ab");
1379/** End [bosch_bme280] */
1380#endif
1381
1382
1383#if defined(BUILD_SENSOR_BOSCH_BMP3XX)
1384// ==========================================================================
1385// Bosch BMP 3xx Barometric Pressure Sensor
1386// ==========================================================================
1387/** Start [bosch_bmp3xx] */
1388#include <sensors/BoschBMP3xx.h>
1389
1390// NOTE: Use -1 for any pins that don't apply or aren't being used.
1391const int8_t bmp3xxPower = -1; // Power pin
1392Mode bmpMode = FORCED_MODE; // The operating mode of the BMP; normal or forced
1393Oversampling bmpPressureOversample = OVERSAMPLING_X32;
1394Oversampling bmpTempOversample = OVERSAMPLING_X2;
1395IIRFilter bmpFilterCoeff = IIR_FILTER_OFF;
1396TimeStandby bmpTimeStandby = TIME_STANDBY_5MS;
1397uint8_t bmpI2C_addr = 0x77;
1398// The BMP3xx can be addressed either as 0x77 or 0x76
1399
1400// Create a Bosch BMP3xx sensor object
1401BoschBMP3xx bmp3xx(bmp3xxPower, bmpMode, bmpPressureOversample,
1402 bmpTempOversample, bmpFilterCoeff, bmpTimeStandby,
1403 bmpI2C_addr);
1404
1405// Create the variable pointers for the BMP3xx
1406Variable* bmp3xxTemp =
1407 new BoschBMP3xx_Temp(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab");
1408Variable* bmp3xxPress =
1409 new BoschBMP3xx_Pressure(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab");
1410Variable* bmp3xxAlt =
1411 new BoschBMP3xx_Altitude(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab");
1412/** End [bosch_bmp3xx] */
1413#endif
1414
1415
1416#if defined(BUILD_SENSOR_CAMPBELL_CLARI_VUE10)
1417// ==========================================================================
1418// Campbell ClariVUE Turbidity Sensor
1419// ==========================================================================
1420/** Start [campbell_clari_vue10] */
1421#include <sensors/CampbellClariVUE10.h>
1422
1423// NOTE: Use -1 for any pins that don't apply or aren't being used.
1424const char* ClariVUESDI12address = "0"; // The SDI-12 Address of the ClariVUE10
1425const int8_t ClariVUEPower = sensorPowerPin; // Power pin
1426const int8_t ClariVUEData = sdi12DataPin; // The SDI-12 data pin
1427// NOTE: you should NOT take more than one readings. THe sensor already takes
1428// and averages 8 by default.
1429
1430// Create a Campbell ClariVUE10 sensor object
1431CampbellClariVUE10 clarivue(*ClariVUESDI12address, ClariVUEPower, ClariVUEData);
1432
1433// Create turbidity, temperature, and error variable pointers for the ClariVUE10
1434Variable* clarivueTurbidity = new CampbellClariVUE10_Turbidity(
1435 &clarivue, "12345678-abcd-1234-ef00-1234567890ab");
1436Variable* clarivueTemp = new CampbellClariVUE10_Temp(
1437 &clarivue, "12345678-abcd-1234-ef00-1234567890ab");
1438Variable* clarivueError = new CampbellClariVUE10_ErrorCode(
1439 &clarivue, "12345678-abcd-1234-ef00-1234567890ab");
1440/** End [campbell_clari_vue10] */
1441#endif
1442
1443
1444#if defined(BUILD_SENSOR_CAMPBELL_OBS3)
1445// ==========================================================================
1446// Campbell OBS 3 / OBS 3+ Analog Turbidity Sensor
1447// ==========================================================================
1448/** Start [campbell_obs3] */
1449#include <sensors/CampbellOBS3.h>
1450
1451// NOTE: Use -1 for any pins that don't apply or aren't being used.
1452const int8_t OBS3Power = sensorPowerPin; // Power pin
1453const uint8_t OBS3NumberReadings = 10;
1454const uint8_t OBS3ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
1455
1456const int8_t OBSLowADSChannel = 0; // ADS channel for *low* range output
1457
1458// Campbell OBS 3+ *Low* Range Calibration in Volts
1459const float OBSLow_A = 0.000E+00; // "A" value (X^2) [*low* range]
1460const float OBSLow_B = 1.000E+00; // "B" value (X) [*low* range]
1461const float OBSLow_C = 0.000E+00; // "C" value [*low* range]
1462
1463// Create a Campbell OBS3+ *low* range sensor object
1464CampbellOBS3 osb3low(OBS3Power, OBSLowADSChannel, OBSLow_A, OBSLow_B, OBSLow_C,
1465 OBS3ADSi2c_addr, OBS3NumberReadings);
1466
1467// Create turbidity and voltage variable pointers for the low range of the OBS3
1468Variable* obs3TurbLow = new CampbellOBS3_Turbidity(
1469 &osb3low, "12345678-abcd-1234-ef00-1234567890ab", "TurbLow");
1470Variable* obs3VoltLow = new CampbellOBS3_Voltage(
1471 &osb3low, "12345678-abcd-1234-ef00-1234567890ab", "TurbLowV");
1472
1473
1474const int8_t OBSHighADSChannel = 1; // ADS channel for *high* range output
1475
1476// Campbell OBS 3+ *High* Range Calibration in Volts
1477const float OBSHigh_A = 0.000E+00; // "A" value (X^2) [*high* range]
1478const float OBSHigh_B = 1.000E+00; // "B" value (X) [*high* range]
1479const float OBSHigh_C = 0.000E+00; // "C" value [*high* range]
1480
1481// Create a Campbell OBS3+ *high* range sensor object
1482CampbellOBS3 osb3high(OBS3Power, OBSHighADSChannel, OBSHigh_A, OBSHigh_B,
1483 OBSHigh_C, OBS3ADSi2c_addr, OBS3NumberReadings);
1484
1485// Create turbidity and voltage variable pointers for the high range of the OBS3
1486Variable* obs3TurbHigh = new CampbellOBS3_Turbidity(
1487 &osb3high, "12345678-abcd-1234-ef00-1234567890ab", "TurbHigh");
1488Variable* obs3VoltHigh = new CampbellOBS3_Voltage(
1489 &osb3high, "12345678-abcd-1234-ef00-1234567890ab", "TurbHighV");
1490/** End [campbell_obs3] */
1491#endif
1492
1493#if defined(BUILD_SENSOR_CAMPBELL_RAIN_VUE10)
1494// ==========================================================================
1495// Campbell RainVUE Precipitation Sensor
1496// ==========================================================================
1497/** Start [campbell_rain_vue10] */
1498#include <sensors/CampbellRainVUE10.h>
1499
1500// NOTE: Use -1 for any pins that don't apply or aren't being used.
1501const char* RainVUESDI12address = "0"; // The SDI-12 Address of the RainVUE10
1502const int8_t RainVUEPower = -1; // Power pin, for continuous power
1503const int8_t RainVUEData = 5; // The SDI-12 data pin, for continuous power
1504// NOTE: you should NOT take more than one readings. The sensor counts
1505// cumulative tips and rain accumulation since the last measurement.
1506
1507// Create a Campbell RainVUE10 sensor object
1508CampbellRainVUE10 rainvue(*RainVUESDI12address, RainVUEPower, RainVUEData);
1509
1510// Create turbidity, temperature, and error variable pointers for the RainVUE10
1511Variable* rainvuePrecipitation = new CampbellRainVUE10_Precipitation(
1512 &rainvue, "12345678-abcd-1234-ef00-1234567890ab");
1513Variable* rainvueTips = new CampbellRainVUE10_Tips(
1514 &rainvue, "12345678-abcd-1234-ef00-1234567890ab");
1515Variable* rainvueRainRateAve = new CampbellRainVUE10_RainRateAve(
1516 &rainvue, "12345678-abcd-1234-ef00-1234567890ab");
1517Variable* rainvueRainRateMax = new CampbellRainVUE10_RainRateMax(
1518 &rainvue, "12345678-abcd-1234-ef00-1234567890ab");
1519/** End [campbell_rain_vue10] */
1520#endif
1521
1522
1523#if defined(BUILD_SENSOR_DECAGON_CTD)
1524// ==========================================================================
1525// Decagon CTD-10 Conductivity, Temperature, and Depth Sensor
1526// ==========================================================================
1527/** Start [decagon_ctd] */
1528#include <sensors/DecagonCTD.h>
1529
1530// NOTE: Use -1 for any pins that don't apply or aren't being used.
1531const char* CTDSDI12address = "1"; // The SDI-12 Address of the CTD
1532const uint8_t CTDNumberReadings = 6; // The number of readings to average
1533const int8_t CTDPower = sensorPowerPin; // Power pin
1534const int8_t CTDData = sdi12DataPin; // The SDI-12 data pin
1535
1536// Create a Decagon CTD sensor object
1537DecagonCTD ctd(*CTDSDI12address, CTDPower, CTDData, CTDNumberReadings);
1538
1539// Create conductivity, temperature, and depth variable pointers for the CTD
1540Variable* ctdCond = new DecagonCTD_Cond(&ctd,
1541 "12345678-abcd-1234-ef00-1234567890ab");
1542Variable* ctdTemp = new DecagonCTD_Temp(&ctd,
1543 "12345678-abcd-1234-ef00-1234567890ab");
1544Variable* ctdDepth =
1545 new DecagonCTD_Depth(&ctd, "12345678-abcd-1234-ef00-1234567890ab");
1546/** End [decagon_ctd] */
1547#endif
1548
1549
1550#if defined(BUILD_SENSOR_DECAGON_ES2)
1551// ==========================================================================
1552// Decagon ES2 Conductivity and Temperature Sensor
1553// ==========================================================================
1554/** Start [decagon_es2] */
1555#include <sensors/DecagonES2.h>
1556
1557// NOTE: Use -1 for any pins that don't apply or aren't being used.
1558const char* ES2SDI12address = "3"; // The SDI-12 Address of the ES2
1559const int8_t ES2Power = sensorPowerPin; // Power pin
1560const int8_t ES2Data = sdi12DataPin; // The SDI-12 data pin
1561const uint8_t ES2NumberReadings = 5;
1562
1563// Create a Decagon ES2 sensor object
1564DecagonES2 es2(*ES2SDI12address, ES2Power, ES2Data, ES2NumberReadings);
1565
1566// Create specific conductance and temperature variable pointers for the ES2
1567Variable* es2Cond = new DecagonES2_Cond(&es2,
1568 "12345678-abcd-1234-ef00-1234567890ab");
1569Variable* es2Temp = new DecagonES2_Temp(&es2,
1570 "12345678-abcd-1234-ef00-1234567890ab");
1571/** End [decagon_es2] */
1572#endif
1573
1574
1575#if defined(BUILD_SENSOR_EVERLIGHT_ALSPT19)
1576// ==========================================================================
1577// Everlight ALS-PT19 Ambient Light Sensor
1578// ==========================================================================
1579/** Start [everlight_alspt19] */
1580#include <sensors/EverlightALSPT19.h>
1581
1582// NOTE: Use -1 for any pins that don't apply or aren't being used.
1583const int8_t alsPower = sensorPowerPin; // Power pin
1584#if defined(ENVIRODIY_STONEFLY_M4)
1585const int8_t alsData = A8; // The ALS PT-19 data pin
1586#else
1587const int8_t alsData = A4; // The ALS PT-19 data pin
1588#endif
1589const int8_t alsSupply = 3.3; // The ALS PT-19 supply power voltage
1590const int8_t alsResistance = 10; // The ALS PT-19 loading resistance (in kΩ)
1591const uint8_t alsNumberReadings = 10;
1592
1593// Create a Everlight ALS-PT19 sensor object
1594EverlightALSPT19 alsPt19(alsPower, alsData, alsSupply, alsResistance,
1595 alsNumberReadings);
1596
1597// For an EnviroDIY Mayfly, you can use the abbreviated version
1598// EverlightALSPT19 alsPt19(alsNumberReadings);
1599
1600// Create voltage, current, and illuminance variable pointers for the ALS-PT19
1601Variable* alsPt19Volt = new EverlightALSPT19_Voltage(
1602 &alsPt19, "12345678-abcd-1234-ef00-1234567890ab");
1603Variable* alsPt19Current = new EverlightALSPT19_Current(
1604 &alsPt19, "12345678-abcd-1234-ef00-1234567890ab");
1605Variable* alsPt19Lux = new EverlightALSPT19_Illuminance(
1606 &alsPt19, "12345678-abcd-1234-ef00-1234567890ab");
1607/** End [everlight_alspt19] */
1608#endif
1609
1610
1611#if defined(BUILD_SENSOR_TIADS1X15)
1612// ==========================================================================
1613// External Voltage via TI ADS1115
1614// ==========================================================================
1615/** Start [tiads1x15] */
1616#include <sensors/TIADS1x15.h>
1617
1618// NOTE: Use -1 for any pins that don't apply or aren't being used.
1619const int8_t ADSPower = sensorPowerPin; // Power pin
1620const int8_t ADSChannel = 2; // The ADS channel of interest
1621const float dividerGain = 10; // Gain setting if using a voltage divider
1622const uint8_t evADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
1623const uint8_t VoltReadsToAvg = 1; // Only read one sample
1624
1625// Create an External Voltage sensor object
1626TIADS1x15 ads1x15(ADSPower, ADSChannel, dividerGain, evADSi2c_addr,
1627 VoltReadsToAvg);
1628
1629// Create a voltage variable pointer
1630Variable* ads1x15Volt =
1631 new TIADS1x15_Voltage(&ads1x15, "12345678-abcd-1234-ef00-1234567890ab");
1632/** End [tiads1x15] */
1633#endif
1634
1635
1636#if defined(BUILD_SENSOR_FREESCALE_MPL115A2)
1637// ==========================================================================
1638// Freescale Semiconductor MPL115A2 Barometer
1639// ==========================================================================
1640/** Start [freescale_mpl115a2] */
1641#include <sensors/FreescaleMPL115A2.h>
1642
1643// NOTE: Use -1 for any pins that don't apply or aren't being used.
1644const int8_t MPLPower = sensorPowerPin; // Power pin
1645const uint8_t MPL115A2ReadingsToAvg = 1;
1646
1647// Create a FreescaleMPL115A2 barometer sensor object
1648FreescaleMPL115A2 mpl115a2(MPLPower, MPL115A2ReadingsToAvg);
1649
1650// Create pressure and temperature variable pointers for the MPL
1651Variable* mplPress = new FreescaleMPL115A2_Pressure(
1652 &mpl115a2, "12345678-abcd-1234-ef00-1234567890ab");
1653Variable* mplTemp = new FreescaleMPL115A2_Temp(
1654 &mpl115a2, "12345678-abcd-1234-ef00-1234567890ab");
1655/** End [freescale_mpl115a2] */
1656#endif
1657
1658
1659#if defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
1660// ==========================================================================
1661// Geolux HydroCam camera
1662// ==========================================================================
1663/** Start [geolux_hydro_cam] */
1664#include <sensors/GeoluxHydroCam.h>
1665
1666// NOTE: Use -1 for any pins that don't apply or aren't being used.
1667const int8_t cameraPower = sensorPowerPin; // Power pin
1668const int8_t cameraAdapterPower = sensorPowerPin; // RS232 adapter power pin
1669const char* imageResolution = "800x600";
1670const char* filePrefix = LoggerID;
1671bool alwaysAutoFocus = false;
1672
1673// Create a GeoluxHydroCam sensor object
1674GeoluxHydroCam hydrocam(cameraSerial, cameraPower, dataLogger,
1675 cameraAdapterPower, imageResolution, filePrefix,
1676 alwaysAutoFocus);
1677
1678// Create image size and byte error variables for the Geolux HydroCam
1679Variable* hydrocamImageSize = new GeoluxHydroCam_ImageSize(
1680 &hydrocam, "12345678-abcd-1234-ef00-1234567890ab");
1681Variable* hydrocamByteError = new GeoluxHydroCam_ByteError(
1682 &hydrocam, "12345678-abcd-1234-ef00-1234567890ab");
1683/** End [geolux_hydro_cam] */
1684#endif
1685
1686
1687#if defined(BUILD_SENSOR_GRO_POINT_GPLP8)
1688#ifndef BUILD_MODBUS_SENSOR
1689#define BUILD_MODBUS_SENSOR
1690#endif
1691// ==========================================================================
1692// GroPoint Profile GPLP-8 Soil Moisture and Temperature Sensor
1693// ==========================================================================
1694/** Start [gro_point_gplp8] */
1695#include <sensors/GroPointGPLP8.h>
1696
1697// NOTE: Extra hardware and software serial ports are created in the "Settings
1698// for Additional Serial Ports" section
1699
1700// NOTE: Use -1 for any pins that don't apply or aren't being used.
1701byte gplp8ModbusAddress = 0x19; // The modbus address of the gplp8
1702// Raw Request >>> {0x19, 0x03, 0x00, 0xC8, 0x00, 0x01, 0x06, 0x2C}
1703const int8_t gplp8AdapterPower = sensorPowerPin; // RS485 adapter power pin
1704const int8_t gplp8SensorPower = relayPowerPin; // Sensor power pin
1705const int8_t gplp8EnablePin = -1; // Adapter RE/DE pin
1706const uint8_t gplp8NumberReadings = 1;
1707// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
1708// power consumption
1709
1710// Create a GroPoint Profile GPLP-8 sensor object
1711GroPointGPLP8 gplp8(gplp8ModbusAddress, modbusSerial, gplp8AdapterPower,
1712 gplp8SensorPower, gplp8EnablePin, gplp8NumberReadings);
1713
1714// Create moisture variable pointers for each segment of the GPLP-8
1715Variable* gplp8Moist1 = new GroPointGPLP8_Moist(
1716 &gplp8, 0, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist1");
1717Variable* gplp8Moist2 = new GroPointGPLP8_Moist(
1718 &gplp8, 1, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist2");
1719Variable* gplp8Moist3 = new GroPointGPLP8_Moist(
1720 &gplp8, 2, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist3");
1721Variable* gplp8Moist4 = new GroPointGPLP8_Moist(
1722 &gplp8, 3, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist4");
1723Variable* gplp8Moist5 = new GroPointGPLP8_Moist(
1724 &gplp8, 4, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist5");
1725Variable* gplp8Moist6 = new GroPointGPLP8_Moist(
1726 &gplp8, 5, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist6");
1727Variable* gplp8Moist7 = new GroPointGPLP8_Moist(
1728 &gplp8, 6, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist7");
1729Variable* gplp8Moist8 = new GroPointGPLP8_Moist(
1730 &gplp8, 7, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist8");
1731
1732// Create temperature variable pointers for each sensor of the GPLP-8
1733Variable* gplp8Temp1 = new GroPointGPLP8_Temp(
1734 &gplp8, 8, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp1");
1735Variable* gplp8Temp2 = new GroPointGPLP8_Temp(
1736 &gplp8, 9, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp1");
1737Variable* gplp8Temp3 = new GroPointGPLP8_Temp(
1738 &gplp8, 10, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp3");
1739Variable* gplp8Temp4 = new GroPointGPLP8_Temp(
1740 &gplp8, 11, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp4");
1741Variable* gplp8Temp5 = new GroPointGPLP8_Temp(
1742 &gplp8, 12, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp5");
1743Variable* gplp8Temp6 = new GroPointGPLP8_Temp(
1744 &gplp8, 13, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp6");
1745Variable* gplp8Temp7 = new GroPointGPLP8_Temp(
1746 &gplp8, 14, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp7");
1747Variable* gplp8Temp8 = new GroPointGPLP8_Temp(
1748 &gplp8, 15, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp8");
1749Variable* gplp8Temp9 = new GroPointGPLP8_Temp(
1750 &gplp8, 16, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp9");
1751Variable* gplp8Temp10 = new GroPointGPLP8_Temp(
1752 &gplp8, 17, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp10");
1753Variable* gplp8Temp11 = new GroPointGPLP8_Temp(
1754 &gplp8, 18, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp11");
1755Variable* gplp8Temp12 = new GroPointGPLP8_Temp(
1756 &gplp8, 19, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp12");
1757Variable* gplp8Temp13 = new GroPointGPLP8_Temp(
1758 &gplp8, 20, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp13");
1759/** End [gro_point_gplp8] */
1760#endif
1761
1762
1763#if defined(BUILD_SENSOR_IN_SITU_RDO)
1764// ==========================================================================
1765// In-Situ RDO PRO-X Rugged Dissolved Oxygen Probe
1766// ==========================================================================
1767/** Start [in_situ_rdo] */
1768#include <sensors/InSituRDO.h>
1769
1770// NOTE: Use -1 for any pins that don't apply or aren't being used.
1771const char* RDOSDI12address = "5"; // The SDI-12 Address of the RDO PRO-X
1772const int8_t RDOPower = sensorPowerPin; // Power pin
1773const int8_t RDOData = sdi12DataPin; // The SDI-12 data pin
1774const uint8_t RDONumberReadings = 3;
1775
1776// Create an In-Situ RDO PRO-X dissolved oxygen sensor object
1777InSituRDO insituRDO(*RDOSDI12address, RDOPower, RDOData, RDONumberReadings);
1778
1779// Create dissolved oxygen percent, dissolved oxygen concentration, temperature,
1780// and oxygen partial pressure variable pointers for the RDO PRO-X
1781Variable* rdoDOpct =
1782 new InSituRDO_DOpct(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab");
1783Variable* rdoDOmgL =
1784 new InSituRDO_DOmgL(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab");
1785Variable* rdoTemp = new InSituRDO_Temp(&insituRDO,
1786 "12345678-abcd-1234-ef00-1234567890ab");
1787Variable* rdoO2pp =
1788 new InSituRDO_Pressure(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab");
1789/** End [in_situ_rdo] */
1790#endif
1791
1792
1793#if defined(BUILD_SENSOR_IN_SITU_TROLL_SDI12A)
1794// ==========================================================================
1795// In-Situ Aqua/Level TROLL Pressure, Temperature, and Depth Sensor
1796// ==========================================================================
1797/** Start [in_situ_troll_sdi12a] */
1798#include <sensors/InSituTrollSdi12a.h>
1799
1800// NOTE: Use -1 for any pins that don't apply or aren't being used.
1801const char* TROLLSDI12address =
1802 "1"; // The SDI-12 Address of the Aqua/Level TROLL
1803const int8_t TROLLPower =
1804 sensorPowerPin; // Pin to switch power on and off (-1 if unconnected)
1805const int8_t TROLLData = sdi12DataPin; // The SDI-12 data pin
1806const uint8_t TROLLNumberReadings = 2; // The number of readings to average
1807
1808// Create an In-Situ TROLL sensor object
1809InSituTrollSdi12a insituTROLL(*TROLLSDI12address, TROLLPower, TROLLData,
1810 TROLLNumberReadings);
1811
1812// Create pressure, temperature, and depth variable pointers for the TROLL
1813Variable* trollPressure = new InSituTrollSdi12a_Pressure(
1814 &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab");
1815Variable* trollTemp = new InSituTrollSdi12a_Temp(
1816 &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab");
1817Variable* trollDepth = new InSituTrollSdi12a_Depth(
1818 &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab");
1819/** End [in_situ_troll_sdi12a] */
1820#endif
1821
1822
1823#if defined(BUILD_SENSOR_KELLER_ACCULEVEL)
1824#ifndef BUILD_MODBUS_SENSOR
1825#define BUILD_MODBUS_SENSOR
1826#endif
1827// ==========================================================================
1828// Keller Acculevel High Accuracy Submersible Level Transmitter
1829// ==========================================================================
1830/** Start [keller_acculevel] */
1831#include <sensors/KellerAcculevel.h>
1832
1833// NOTE: Extra hardware and software serial ports are created in the "Settings
1834// for Additional Serial Ports" section
1835
1836// NOTE: Use -1 for any pins that don't apply or aren't being used.
1837byte acculevelModbusAddress = 0x01; // The modbus address of KellerAcculevel
1838const int8_t acculevelPower = relayPowerPin; // Acculevel Sensor power pin
1839const int8_t alAdapterPower = sensorPowerPin; // RS485 adapter power pin
1840const int8_t al485EnablePin = -1; // Adapter RE/DE pin
1841const uint8_t acculevelNumberReadings = 5;
1842// The manufacturer recommends taking and averaging a few readings
1843
1844// Create a Keller Acculevel sensor object
1845KellerAcculevel acculevel(acculevelModbusAddress, modbusSerial, alAdapterPower,
1846 acculevelPower, al485EnablePin,
1847 acculevelNumberReadings);
1848
1849// Create pressure, temperature, and height variable pointers for the Acculevel
1850Variable* acculevPress = new KellerAcculevel_Pressure(
1851 &acculevel, "12345678-abcd-1234-ef00-1234567890ab");
1852Variable* acculevTemp = new KellerAcculevel_Temp(
1853 &acculevel, "12345678-abcd-1234-ef00-1234567890ab");
1854Variable* acculevHeight = new KellerAcculevel_Height(
1855 &acculevel, "12345678-abcd-1234-ef00-1234567890ab");
1856/** End [keller_acculevel] */
1857#endif
1858
1859
1860#if defined(BUILD_SENSOR_KELLER_NANOLEVEL)
1861#ifndef BUILD_MODBUS_SENSOR
1862#define BUILD_MODBUS_SENSOR
1863#endif
1864// ==========================================================================
1865// Keller Nanolevel High Accuracy Submersible Level Transmitter
1866// ==========================================================================
1867/** Start [keller_nanolevel] */
1868#include <sensors/KellerNanolevel.h>
1869
1870// NOTE: Extra hardware and software serial ports are created in the "Settings
1871// for Additional Serial Ports" section
1872
1873// NOTE: Use -1 for any pins that don't apply or aren't being used.
1874byte nanolevelModbusAddress = 0x01; // The modbus address of KellerNanolevel
1875const int8_t nlAdapterPower = sensorPowerPin; // RS485 adapter power pin
1876const int8_t nanolevelPower = relayPowerPin; // Sensor power pin
1877const int8_t nl485EnablePin = -1; // Adapter RE/DE pin
1878const uint8_t nanolevelNumberReadings = 5;
1879// The manufacturer recommends taking and averaging a few readings
1880
1881// Create a Keller Nanolevel sensor object
1882KellerNanolevel nanolevel(nanolevelModbusAddress, modbusSerial, nlAdapterPower,
1883 nanolevelPower, nl485EnablePin,
1884 nanolevelNumberReadings);
1885
1886// Create pressure, temperature, and height variable pointers for the Nanolevel
1887Variable* nanolevPress = new KellerNanolevel_Pressure(
1888 &nanolevel, "12345678-abcd-1234-ef00-1234567890ab");
1889Variable* nanolevTemp = new KellerNanolevel_Temp(
1890 &nanolevel, "12345678-abcd-1234-ef00-1234567890ab");
1891Variable* nanolevHeight = new KellerNanolevel_Height(
1892 &nanolevel, "12345678-abcd-1234-ef00-1234567890ab");
1893/** End [keller_nanolevel] */
1894#endif
1895
1896
1897#if defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
1898// ==========================================================================
1899// Maxbotix HRXL Ultrasonic Range Finder
1900// ==========================================================================
1901/** Start [max_botix_sonar] */
1902#include <sensors/MaxBotixSonar.h>
1903
1904// A Maxbotix sonar with the trigger pin disconnect CANNOT share the serial port
1905// A Maxbotix sonar using the trigger may be able to share but YMMV
1906
1907// NOTE: Extra hardware and software serial ports are created in the "Settings
1908// for Additional Serial Ports" section
1909
1910// NOTE: Use -1 for any pins that don't apply or aren't being used.
1911const int8_t SonarPower = sensorPowerPin; // Excite (power) pin
1912const int8_t Sonar1Trigger = -1; // Trigger pin
1913// Trigger should be a *unique* negative number if unconnected
1914const int16_t Sonar1MaxRange = 9999; // Maximum range of sonar
1915const uint8_t sonar1NumberReadings = 3; // The number of readings to average
1916
1917// Create a MaxBotix Sonar sensor object
1918MaxBotixSonar sonar1(sonarSerial, SonarPower, Sonar1Trigger, Sonar1MaxRange,
1919 sonar1NumberReadings);
1920
1921// Create an ultrasonic range variable pointer
1922Variable* sonar1Range =
1923 new MaxBotixSonar_Range(&sonar1, "12345678-abcd-1234-ef00-1234567890ab");
1924/** End [max_botix_sonar] */
1925#endif
1926
1927
1928#if defined(BUILD_SENSOR_MAXIM_DS18) || \
1929 defined(BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY)
1930// ==========================================================================
1931// Maxim DS18 One Wire Temperature Sensor
1932// ==========================================================================
1933/** Start [maxim_ds18] */
1934#include <sensors/MaximDS18.h>
1935
1936// OneWire Address [array of 8 hex characters]
1937// If only using a single sensor on the OneWire bus, you may omit the address
1938DeviceAddress OneWireAddress1 = {0x28, 0xFF, 0xBD, 0xBA,
1939 0x81, 0x16, 0x03, 0x0C};
1940// NOTE: Use -1 for any pins that don't apply or aren't being used.
1941const int8_t OneWirePower = sensorPowerPin; // Power pin
1942const int8_t OneWireBus = A0; // OneWire Bus Pin
1943const int8_t ds18NumberReadings = 3;
1944
1945// Create a Maxim DS18 sensor objects (use this form for a known address)
1946MaximDS18 ds18(OneWireAddress1, OneWirePower, OneWireBus, ds18NumberReadings);
1947
1948// Create a Maxim DS18 sensor object (use this form for a single sensor on bus
1949// with an unknown address)
1950// MaximDS18 ds18(OneWirePower, OneWireBus);
1951
1952// Create a temperature variable pointer for the DS18
1953Variable* ds18Temp = new MaximDS18_Temp(&ds18,
1954 "12345678-abcd-1234-ef00-1234567890ab");
1955/** End [maxim_ds18] */
1956#endif
1957
1958
1959#if defined(BUILD_SENSOR_MEA_SPEC_MS5803)
1960// ==========================================================================
1961// Measurement Specialties MS5803-14BA pressure sensor
1962// ==========================================================================
1963/** Start [mea_spec_ms5803] */
1964#include <sensors/MeaSpecMS5803.h>
1965
1966// NOTE: Use -1 for any pins that don't apply or aren't being used.
1967const int8_t MS5803Power = sensorPowerPin; // Power pin
1968const uint8_t MS5803i2c_addr =
1969 0x76; // The MS5803 can be addressed either as 0x76 (default) or 0x77
1970const int16_t MS5803maxPressure =
1971 14; // The maximum pressure measurable by the specific MS5803 model
1972const uint8_t MS5803ReadingsToAvg = 1;
1973
1974// Create a MeaSpec MS5803 pressure and temperature sensor object
1975MeaSpecMS5803 ms5803(MS5803Power, MS5803i2c_addr, MS5803maxPressure,
1976 MS5803ReadingsToAvg);
1977
1978// Create pressure and temperature variable pointers for the MS5803
1979Variable* ms5803Press =
1980 new MeaSpecMS5803_Pressure(&ms5803, "12345678-abcd-1234-ef00-1234567890ab");
1981Variable* ms5803Temp =
1982 new MeaSpecMS5803_Temp(&ms5803, "12345678-abcd-1234-ef00-1234567890ab");
1983/** End [mea_spec_ms5803] */
1984#endif
1985
1986
1987#if defined(BUILD_SENSOR_DECAGON_5TM)
1988// ==========================================================================
1989// Meter ECH2O Soil Moisture Sensor
1990// ==========================================================================
1991/** Start [decagon_5tm] */
1992#include <sensors/Decagon5TM.h>
1993
1994// NOTE: Use -1 for any pins that don't apply or aren't being used.
1995const char* TMSDI12address = "2"; // The SDI-12 Address of the 5-TM
1996const int8_t TMPower = sensorPowerPin; // Power pin
1997const int8_t TMData = sdi12DataPin; // The SDI-12 data pin
1998
1999// Create a Decagon 5TM sensor object
2000Decagon5TM fivetm(*TMSDI12address, TMPower, TMData);
2001
2002// Create the matric potential, volumetric water content, and temperature
2003// variable pointers for the 5TM
2004Variable* fivetmEa = new Decagon5TM_Ea(&fivetm,
2005 "12345678-abcd-1234-ef00-1234567890ab");
2006Variable* fivetmVWC =
2007 new Decagon5TM_VWC(&fivetm, "12345678-abcd-1234-ef00-1234567890ab");
2008Variable* fivetmTemp =
2009 new Decagon5TM_Temp(&fivetm, "12345678-abcd-1234-ef00-1234567890ab");
2010/** End [decagon_5tm] */
2011#endif
2012
2013
2014#if defined(BUILD_SENSOR_METER_HYDROS21)
2015// ==========================================================================
2016// Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
2017// ==========================================================================
2018/** Start [meter_hydros21] */
2019#include <sensors/MeterHydros21.h>
2020
2021// NOTE: Use -1 for any pins that don't apply or aren't being used.
2022const char* hydros21SDI12address = "1"; // The SDI-12 Address of the Hydros21
2023const uint8_t hydros21NumberReadings = 6; // The number of readings to average
2024const int8_t hydros21Power = sensorPowerPin; // Power pin
2025const int8_t hydros21Data = sdi12DataPin; // The SDI-12 data pin
2026
2027// Create a Decagon Hydros21 sensor object
2028MeterHydros21 hydros21(*hydros21SDI12address, hydros21Power, hydros21Data,
2029 hydros21NumberReadings);
2030
2031// Create conductivity, temperature, and depth variable pointers for the
2032// Hydros21
2033Variable* hydros21Cond =
2034 new MeterHydros21_Cond(&hydros21, "12345678-abcd-1234-ef00-1234567890ab");
2035Variable* hydros21Temp =
2036 new MeterHydros21_Temp(&hydros21, "12345678-abcd-1234-ef00-1234567890ab");
2037Variable* hydros21Depth =
2038 new MeterHydros21_Depth(&hydros21, "12345678-abcd-1234-ef00-1234567890ab");
2039/** End [meter_hydros21] */
2040#endif
2041
2042
2043#if defined(BUILD_SENSOR_METER_TEROS11)
2044// ==========================================================================
2045// Meter Teros 11 Soil Moisture Sensor
2046// ==========================================================================
2047/** Start [meter_teros11] */
2048#include <sensors/MeterTeros11.h>
2049
2050// NOTE: Use -1 for any pins that don't apply or aren't being used.
2051const char* teros11SDI12address = "4"; // The SDI-12 Address of the Teros 11
2052const int8_t terosPower = sensorPowerPin; // Power pin
2053const int8_t terosData = sdi12DataPin; // The SDI-12 data pin
2054const uint8_t teros11NumberReadings = 3; // The number of readings to average
2055
2056// Create a METER TEROS 11 sensor object
2057MeterTeros11 teros11(*teros11SDI12address, terosPower, terosData,
2058 teros11NumberReadings);
2059
2060// Create the matric potential, volumetric water content, and temperature
2061// variable pointers for the Teros 11
2062Variable* teros11Ea =
2063 new MeterTeros11_Ea(&teros11, "12345678-abcd-1234-ef00-1234567890ab");
2064Variable* teros11Temp =
2065 new MeterTeros11_Temp(&teros11, "12345678-abcd-1234-ef00-1234567890ab");
2066Variable* teros11VWC =
2067 new MeterTeros11_VWC(&teros11, "12345678-abcd-1234-ef00-1234567890ab");
2068Variable* teros11Count =
2069 new MeterTeros11_Count(&teros11, "12345678-abcd-1234-ef00-1234567890ab");
2070/** End [meter_teros11] */
2071#endif
2072
2073
2074#if defined(BUILD_SENSOR_PALEO_TERRA_REDOX)
2075// ==========================================================================
2076// PaleoTerra Redox Sensors
2077// ==========================================================================
2078/** Start [paleo_terra_redox] */
2079#include <sensors/PaleoTerraRedox.h>
2080
2081// NOTE: Use -1 for any pins that don't apply or aren't being used.
2082int8_t paleoTerraPower = sensorPowerPin; // Power pin
2083uint8_t paleoI2CAddress = 0x68; // the I2C address of the redox sensor
2084
2085// Create the PaleoTerra sensor object
2086#if defined(MS_PALEOTERRA_SOFTWAREWIRE)
2087PaleoTerraRedox ptRedox(&softI2C, paleoTerraPower, paleoI2CAddress);
2088// PaleoTerraRedox ptRedox(paleoTerraPower, softwareSDA, softwareSCL,
2089// paleoI2CAddress);
2090#else
2091PaleoTerraRedox ptRedox(paleoTerraPower, paleoI2CAddress);
2092#endif
2093
2094// Create the voltage variable for the redox sensor
2095Variable* ptVolt = new PaleoTerraRedox_Voltage(
2096 &ptRedox, "12345678-abcd-1234-ef00-1234567890ab");
2097/** End [paleo_terra_redox] */
2098#endif
2099
2100
2101#if defined(BUILD_SENSOR_RAIN_COUNTER_I2C)
2102// ==========================================================================
2103// External I2C Rain Tipping Bucket Counter
2104// ==========================================================================
2105/** Start [rain_counter_i2c] */
2106#include <sensors/RainCounterI2C.h>
2107
2108const uint8_t RainCounterI2CAddress = 0x08;
2109// I2C Address for EnviroDIY external tip counter; 0x08 by default
2110const float depthPerTipEvent = 0.2; // rain depth in mm per tip event
2111
2112// Create a Rain Counter sensor object
2113#if defined(MS_RAIN_SOFTWAREWIRE)
2114RainCounterI2C tbi2c(&softI2C, RainCounterI2CAddress, depthPerTipEvent);
2115// RainCounterI2C tbi2c(softwareSDA, softwareSCL, RainCounterI2CAddress,
2116// depthPerTipEvent);
2117#else
2118RainCounterI2C tbi2c(RainCounterI2CAddress, depthPerTipEvent);
2119#endif
2120
2121// Create number of tips and rain depth variable pointers for the tipping bucket
2122Variable* tbi2cTips =
2123 new RainCounterI2C_Tips(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab");
2124Variable* tbi2cDepth =
2125 new RainCounterI2C_Depth(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab");
2126/** End [rain_counter_i2c] */
2127#endif
2128
2129
2130#if defined(BUILD_SENSOR_SENSIRION_SHT4X)
2131// ==========================================================================
2132// Sensirion SHT4X Digital Humidity and Temperature Sensor
2133// ==========================================================================
2134/** Start [sensirion_sht4x] */
2135#include <sensors/SensirionSHT4x.h>
2136
2137// NOTE: Use -1 for any pins that don't apply or aren't being used.
2138const int8_t SHT4xPower = sensorPowerPin; // Power pin
2139const bool SHT4xUseHeater = true;
2140
2141// Create an Sensirion SHT4X sensor object
2142SensirionSHT4x sht4x(SHT4xPower, SHT4xUseHeater);
2143
2144// Create humidity and temperature variable pointers for the SHT4X
2145Variable* sht4xHumid =
2146 new SensirionSHT4x_Humidity(&sht4x, "12345678-abcd-1234-ef00-1234567890ab");
2147Variable* sht4xTemp =
2148 new SensirionSHT4x_Temp(&sht4x, "12345678-abcd-1234-ef00-1234567890ab");
2149/** End [sensirion_sht4x] */
2150#endif
2151
2152
2153#if defined(BUILD_SENSOR_TALLY_COUNTER_I2C)
2154// ==========================================================================
2155// Tally I2C Event Counter for rain or wind reed-switch sensors
2156// ==========================================================================
2157/** Start [tally_counter_i2c] */
2158#include <sensors/TallyCounterI2C.h>
2159
2160const int8_t TallyPower = -1; // Power pin (-1 if continuously powered)
2161// NorthernWidget Tally I2CPower is -1 by default because it is often deployed
2162// with power always on, but Tally also has a super capacitor that enables it
2163// to be self powered between readings/recharge as described at
2164// https://github.com/EnviroDIY/Project-Tally
2165
2166const uint8_t TallyCounterI2CAddress = 0x33;
2167// NorthernWidget Tally I2C address is 0x33 by default
2168
2169// Create a Tally Counter sensor object
2170TallyCounterI2C tallyi2c(TallyPower, TallyCounterI2CAddress);
2171
2172// Create variable pointers for the Tally event counter
2173Variable* tallyEvents = new TallyCounterI2C_Events(
2174 &tallyi2c, "12345678-abcd-1234-ef00-1234567890ab");
2175
2176// For Wind Speed, create a Calculated Variable that converts, similar to:
2177// period = loggingInterval * 60.0; // in seconds
2178// frequency = tallyEventCount/period; // average event frequency in Hz
2179// tallyWindSpeed = frequency * 2.5 * 1.60934; // in km/h
2180// 2.5 mph/Hz & 1.60934 kmph/mph and 2.5 mph/Hz conversion factor from
2181// web: Inspeed-Version-II-Reed-Switch-Anemometer-Sensor-Only-WS2R
2182/** End [tally_counter_i2c] */
2183#endif
2184
2185
2186#if defined(BUILD_SENSOR_TI_INA219)
2187// ==========================================================================
2188// TI INA219 High Side Current/Voltage Sensor (Current mA, Voltage, Power)
2189// ==========================================================================
2190/** Start [ti_ina219] */
2191#include <sensors/TIINA219.h>
2192
2193// NOTE: Use -1 for any pins that don't apply or aren't being used.
2194const int8_t INA219Power = sensorPowerPin; // Power pin
2195uint8_t INA219i2c_addr = 0x40; // 1000000 (Board A0+A1=GND)
2196// The INA219 can have one of 16 addresses, depending on the connections of A0
2197// and A1
2198const uint8_t INA219ReadingsToAvg = 1;
2199
2200// Create an INA219 sensor object
2201TIINA219 ina219(INA219Power, INA219i2c_addr, INA219ReadingsToAvg);
2202
2203// Create current, voltage, and power variable pointers for the INA219
2204Variable* inaCurrent =
2205 new TIINA219_Current(&ina219, "12345678-abcd-1234-ef00-1234567890ab");
2206Variable* inaVolt =
2207 new TIINA219_Voltage(&ina219, "12345678-abcd-1234-ef00-1234567890ab");
2208Variable* inaPower = new TIINA219_Power(&ina219,
2209 "12345678-abcd-1234-ef00-1234567890ab");
2210/** End [ti_ina219] */
2211#endif
2212
2213
2214#if defined(BUILD_SENSOR_TURNER_CYCLOPS)
2215// ==========================================================================
2216// Turner Cyclops-7F Submersible Fluorometer
2217// ==========================================================================
2218/** Start [turner_cyclops] */
2219#include <sensors/TurnerCyclops.h>
2220
2221// NOTE: Use -1 for any pins that don't apply or aren't being used.
2222const int8_t cyclopsPower = sensorPowerPin; // Power pin
2223const uint8_t cyclopsNumberReadings = 10;
2224const uint8_t cyclopsADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
2225const int8_t cyclopsADSChannel = 0; // ADS channel
2226
2227// Cyclops calibration information
2228const float cyclopsStdConc = 1.000; // Concentration of the standard used
2229 // for a 1-point sensor calibration.
2230const float cyclopsStdVolt =
2231 1.000; // The voltage (in volts) measured for the conc_std.
2232const float cyclopsBlankVolt =
2233 0.000; // The voltage (in volts) measured for a blank.
2234
2235// Create a Turner Cyclops sensor object
2236TurnerCyclops cyclops(cyclopsPower, cyclopsADSChannel, cyclopsStdConc,
2237 cyclopsStdVolt, cyclopsBlankVolt, cyclopsADSi2c_addr,
2238 cyclopsNumberReadings);
2239
2240// Create the voltage variable pointer - used for any type of Cyclops
2241Variable* cyclopsVoltage =
2242 new TurnerCyclops_Voltage(&cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2243
2244// Create the variable pointer for the primary output parameter. Only use
2245// **ONE** of these! Which is possible depends on your specific sensor!
2246Variable* cyclopsChloro = new TurnerCyclops_Chlorophyll(
2247 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2248Variable* cyclopsRWT = new TurnerCyclops_Rhodamine(
2249 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2250Variable* cyclopsFluoroscein = new TurnerCyclops_Fluorescein(
2251 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2252Variable* cyclopsPhycocyanin = new TurnerCyclops_Phycocyanin(
2253 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2254Variable* cyclopsPhycoerythrin = new TurnerCyclops_Phycoerythrin(
2255 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2256Variable* cyclopsCDOM =
2257 new TurnerCyclops_CDOM(&cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2258Variable* cyclopsCrudeOil = new TurnerCyclops_CrudeOil(
2259 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2260Variable* cyclopsBrighteners = new TurnerCyclops_Brighteners(
2261 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2262Variable* cyclopsTurbidity = new TurnerCyclops_Turbidity(
2263 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2264Variable* cyclopsPTSA =
2265 new TurnerCyclops_PTSA(&cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2266Variable* cyclopsBTEX =
2267 new TurnerCyclops_BTEX(&cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2268Variable* cyclopsTryptophan = new TurnerCyclops_Tryptophan(
2269 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2270Variable* cyclopsRedChloro = new TurnerCyclops_RedChlorophyll(
2271 &cyclops, "12345678-abcd-1234-ef00-1234567890ab");
2272/** End [turner_cyclops] */
2273#endif
2274
2275
2276#if defined(BUILD_SENSOR_TURNER_TURBIDITY_PLUS)
2277// ==========================================================================
2278// Turner Turbidity Plus Turbidity Sensor
2279// ==========================================================================
2280/** Start [turner_turbidity_plus] */
2281#include <sensors/TurnerTurbidityPlus.h>
2282
2283// NOTE: Use -1 for any pins that don't apply or aren't being used.
2284const int8_t turbidityPlusPower = sensorPowerPin; // Power pin
2285const int8_t turbidityPlusWiper = relayPowerPin; // Wiper pin
2286ttp_adsDiffMux_t turbidityPlusDiffMux =
2287 DIFF_MUX_2_3; // Differential voltage config
2288const uint8_t turbidityPlusNumberReadings = 10;
2289const uint8_t turbidityPlusADSi2c_addr =
2290 0x48; // The I2C address of the ADS1115 ADC
2291adsGain_t turbidityPlusGain = GAIN_ONE; // The gain of the ADS
2292float tpVoltageDividerFactor = 1; // The factor for a voltage divider, if any
2293
2294// Turbidity Plus calibration information
2295const float turbidityPlusStdConc = 1.000; // Concentration of the standard used
2296 // for a 1-point sensor calibration.
2297const float turbidityPlusStdVolt =
2298 1.000; // The voltage (in volts) measured for the conc_std.
2299const float turbidityPlusBlankVolt =
2300 0.000; // The voltage (in volts) measured for a blank.
2301
2302// Create a Turner Turbidity Plus sensor object
2303TurnerTurbidityPlus turbidityPlus(turbidityPlusPower, turbidityPlusWiper,
2304 turbidityPlusDiffMux, turbidityPlusStdConc,
2305 turbidityPlusStdVolt, turbidityPlusBlankVolt,
2306 turbidityPlusADSi2c_addr, turbidityPlusGain,
2307 turbidityPlusNumberReadings,
2308 tpVoltageDividerFactor);
2309
2310// Create the variable pointers
2311Variable* turbidityPlusVoltage = new TurnerTurbidityPlus_Voltage(
2312 &turbidityPlus, "12345678-abcd-1234-ef00-1234567890ab");
2313Variable* turbidityPlusTurbidity = new TurnerTurbidityPlus_Turbidity(
2314 &turbidityPlus, "12345678-abcd-1234-ef00-1234567890ab");
2315/** End [turner_turbidity_plus] */
2316#endif
2317
2318
2319#if defined(BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY)
2320// ==========================================================================
2321// Analog Electrical Conductivity using the Processor's Analog Pins
2322// ==========================================================================
2323/** Start [analog_elec_conductivity] */
2324#include <sensors/AnalogElecConductivity.h>
2325
2326const int8_t ECpwrPin = A4; // Power pin (-1 if continuously powered)
2327const int8_t ECdataPin1 = A0; // Data pin (must be an analog pin, ie A#)
2328
2329// Create an Analog Electrical Conductivity sensor object
2330AnalogElecConductivity analogEC_phy(ECpwrPin, ECdataPin1);
2331
2332// Create a conductivity variable pointer for the analog sensor
2333Variable* analogEc_cond = new AnalogElecConductivity_EC(
2334 &analogEC_phy, "12345678-abcd-1234-ef00-1234567890ab");
2335
2336// Create a calculated variable for the temperature compensated conductivity
2337// (that is, the specific conductance). For this example, we will use the
2338// temperature measured by the Maxim DS18 saved as ds18Temp several sections
2339// above this. You could use the temperature returned by any other water
2340// temperature sensor if desired. **DO NOT** use your logger board temperature
2341// (ie, from the DS3231) to calculate specific conductance!
2342float calculateAnalogSpCond() {
2343 float spCond = -9999; // Always safest to start with a bad value
2344 float waterTemp = ds18Temp->getValue();
2345 float rawCond = analogEc_cond->getValue();
2346 float temperatureCoef = 0.019;
2347 // ^^ Linearized temperature correction coefficient per degrees Celsius.
2348 // The value of 0.019 comes from measurements reported here:
2349 // Hayashi M. Temperature-electrical conductivity relation of water for
2350 // environmental monitoring and geophysical data inversion. Environ Monit
2351 // Assess. 2004 Aug-Sep;96(1-3):119-28.
2352 // doi: 10.1023/b:emas.0000031719.83065.68. PMID: 15327152.
2353 if (waterTemp != -9999 && rawCond != -9999) {
2354 // make sure both inputs are good
2355 spCond = rawCond / (1 + temperatureCoef * (waterTemp - 25.0));
2356 }
2357 return spCond;
2358}
2359
2360// Properties of the calculated variable
2361// The number of digits after the decimal place
2362const uint8_t analogSpCondResolution = 0;
2363// This must be a value from http://vocabulary.odm2.org/variablename/
2364const char* analogSpCondName = "specificConductance";
2365// This must be a value from http://vocabulary.odm2.org/units/
2366const char* analogSpCondUnit = "microsiemenPerCentimeter";
2367// A short code for the variable
2368const char* analogSpCondCode = "anlgSpCond";
2369// The (optional) universally unique identifier
2370const char* analogSpCondUUID = "12345678-abcd-1234-ef00-1234567890ab";
2371
2372// Finally, Create the specific conductance variable and return a pointer to it
2373Variable* analogEc_spcond = new Variable(
2374 calculateAnalogSpCond, analogSpCondResolution, analogSpCondName,
2375 analogSpCondUnit, analogSpCondCode, analogSpCondUUID);
2376/** End [analog_elec_conductivity] */
2377#endif
2378
2379
2380#if defined(BUILD_SENSOR_VEGA_PULS21)
2381// ==========================================================================
2382// VEGA PULS 21 Radar Sensor
2383// ==========================================================================
2384/** Start [vega_puls21] */
2385#include <sensors/VegaPuls21.h>
2386
2387// NOTE: Use -1 for any pins that don't apply or aren't being used.
2388const char* VegaPulsSDI12address = "0"; // The SDI-12 Address of the VegaPuls21
2389const int8_t VegaPulsPower = sensorPowerPin; // Power pin
2390const int8_t VegaPulsData = sdi12DataPin; // The SDI-12 data pin
2391// NOTE: you should NOT take more than one readings. THe sensor already takes
2392// and averages 8 by default.
2393
2394// Create a Vega Puls21 sensor object
2395VegaPuls21 VegaPuls(*VegaPulsSDI12address, VegaPulsPower, VegaPulsData);
2396
2397// Create stage, distance, temperature, reliability, and error variable pointers
2398// for the VegaPuls21
2399Variable* VegaPulsStage =
2400 new VegaPuls21_Stage(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab");
2401Variable* VegaPulsDistance =
2402 new VegaPuls21_Distance(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab");
2403Variable* VegaPulsTemp =
2404 new VegaPuls21_Temp(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab");
2405Variable* VegaPulsRelia = new VegaPuls21_Reliability(
2406 &VegaPuls, "12345678-abcd-1234-ef00-1234567890ab");
2407Variable* VegaPulsError =
2408 new VegaPuls21_ErrorCode(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab");
2409/** End [vega_puls21] */
2410#endif
2411
2412
2413#if defined(BUILD_SENSOR_YOSEMITECH_Y504)
2414#ifndef BUILD_MODBUS_SENSOR
2415#define BUILD_MODBUS_SENSOR
2416#endif
2417// ==========================================================================
2418// Yosemitech Y504 Dissolved Oxygen Sensor
2419// ==========================================================================
2420/** Start [yosemitech_y504] */
2421#include <sensors/YosemitechY504.h>
2422
2423// NOTE: Extra hardware and software serial ports are created in the "Settings
2424// for Additional Serial Ports" section
2425
2426// NOTE: Use -1 for any pins that don't apply or aren't being used.
2427byte y504ModbusAddress = 0x04; // The modbus address of the Y504
2428const int8_t y504AdapterPower = sensorPowerPin; // RS485 adapter power pin
2429const int8_t y504SensorPower = relayPowerPin; // Sensor power pin
2430const int8_t y504EnablePin = -1; // Adapter RE/DE pin
2431const uint8_t y504NumberReadings = 5;
2432// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2433// power consumption
2434
2435// Create a Yosemitech Y504 dissolved oxygen sensor object
2436YosemitechY504 y504(y504ModbusAddress, modbusSerial, y504AdapterPower,
2437 y504SensorPower, y504EnablePin, y504NumberReadings);
2438
2439// Create the dissolved oxygen percent, dissolved oxygen concentration, and
2440// temperature variable pointers for the Y504
2441Variable* y504DOpct =
2442 new YosemitechY504_DOpct(&y504, "12345678-abcd-1234-ef00-1234567890ab");
2443Variable* y504DOmgL =
2444 new YosemitechY504_DOmgL(&y504, "12345678-abcd-1234-ef00-1234567890ab");
2445Variable* y504Temp =
2446 new YosemitechY504_Temp(&y504, "12345678-abcd-1234-ef00-1234567890ab");
2447/** End [yosemitech_y504] */
2448#endif
2449
2450
2451#if defined(BUILD_SENSOR_YOSEMITECH_Y510)
2452#ifndef BUILD_MODBUS_SENSOR
2453#define BUILD_MODBUS_SENSOR
2454#endif
2455// ==========================================================================
2456// Yosemitech Y510 Turbidity Sensor
2457// ==========================================================================
2458/** Start [yosemitech_y510] */
2459#include <sensors/YosemitechY510.h>
2460
2461// NOTE: Extra hardware and software serial ports are created in the "Settings
2462// for Additional Serial Ports" section
2463
2464// NOTE: Use -1 for any pins that don't apply or aren't being used.
2465byte y510ModbusAddress = 0x0B; // The modbus address of the Y510
2466const int8_t y510AdapterPower = sensorPowerPin; // RS485 adapter power pin
2467const int8_t y510SensorPower = relayPowerPin; // Sensor power pin
2468const int8_t y510EnablePin = -1; // Adapter RE/DE pin
2469const uint8_t y510NumberReadings = 5;
2470// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2471// power consumption
2472
2473// Create a Y510-B Turbidity sensor object
2474YosemitechY510 y510(y510ModbusAddress, modbusSerial, y510AdapterPower,
2475 y510SensorPower, y510EnablePin, y510NumberReadings);
2476
2477// Create turbidity and temperature variable pointers for the Y510
2478Variable* y510Turb =
2479 new YosemitechY510_Turbidity(&y510, "12345678-abcd-1234-ef00-1234567890ab");
2480Variable* y510Temp =
2481 new YosemitechY510_Temp(&y510, "12345678-abcd-1234-ef00-1234567890ab");
2482/** End [yosemitech_y510] */
2483#endif
2484
2485
2486#if defined(BUILD_SENSOR_YOSEMITECH_Y511)
2487#ifndef BUILD_MODBUS_SENSOR
2488#define BUILD_MODBUS_SENSOR
2489#endif
2490// ==========================================================================
2491// Yosemitech Y511 Turbidity Sensor with Wiper
2492// ==========================================================================
2493/** Start [yosemitech_y511] */
2494#include <sensors/YosemitechY511.h>
2495
2496// NOTE: Extra hardware and software serial ports are created in the "Settings
2497// for Additional Serial Ports" section
2498
2499// NOTE: Use -1 for any pins that don't apply or aren't being used.
2500byte y511ModbusAddress = 0x1A; // The modbus address of the Y511
2501const int8_t y511AdapterPower = sensorPowerPin; // RS485 adapter power pin
2502const int8_t y511SensorPower = relayPowerPin; // Sensor power pin
2503const int8_t y511EnablePin = -1; // Adapter RE/DE pin
2504const uint8_t y511NumberReadings = 5;
2505// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2506// power consumption
2507
2508// Create a Y511-A Turbidity sensor object
2509YosemitechY511 y511(y511ModbusAddress, modbusSerial, y511AdapterPower,
2510 y511SensorPower, y511EnablePin, y511NumberReadings);
2511
2512// Create turbidity and temperature variable pointers for the Y511
2513Variable* y511Turb =
2514 new YosemitechY511_Turbidity(&y511, "12345678-abcd-1234-ef00-1234567890ab");
2515Variable* y511Temp =
2516 new YosemitechY511_Temp(&y511, "12345678-abcd-1234-ef00-1234567890ab");
2517/** End [yosemitech_y511] */
2518#endif
2519
2520
2521#if defined(BUILD_SENSOR_YOSEMITECH_Y513)
2522#ifndef BUILD_MODBUS_SENSOR
2523#define BUILD_MODBUS_SENSOR
2524#endif
2525// ==========================================================================
2526// Yosemitech Y513 Blue Green Algae (BGA) Sensor
2527// ==========================================================================
2528/** Start [yosemitech_y513] */
2529#include <sensors/YosemitechY513.h>
2530
2531// NOTE: Extra hardware and software serial ports are created in the "Settings
2532// for Additional Serial Ports" section
2533
2534// NOTE: Use -1 for any pins that don't apply or aren't being used.
2535byte y513ModbusAddress = 0x13; // The modbus address of the Y513
2536const int8_t y513AdapterPower = sensorPowerPin; // RS485 adapter power pin
2537const int8_t y513SensorPower = relayPowerPin; // Sensor power pin
2538const int8_t y513EnablePin = -1; // Adapter RE/DE pin
2539const uint8_t y513NumberReadings = 5;
2540// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2541// power consumption
2542
2543// Create a Y513 Blue Green Algae (BGA) sensor object
2544YosemitechY513 y513(y513ModbusAddress, modbusSerial, y513AdapterPower,
2545 y513SensorPower, y513EnablePin, y513NumberReadings);
2546
2547// Create Blue Green Algae (BGA) concentration and temperature variable
2548// pointers for the Y513
2549Variable* y513BGA =
2550 new YosemitechY513_BGA(&y513, "12345678-abcd-1234-ef00-1234567890ab");
2551Variable* y513Temp =
2552 new YosemitechY513_Temp(&y513, "12345678-abcd-1234-ef00-1234567890ab");
2553/** End [yosemitech_y513] */
2554#endif
2555
2556#if defined(BUILD_SENSOR_YOSEMITECH_Y514)
2557#ifndef BUILD_MODBUS_SENSOR
2558#define BUILD_MODBUS_SENSOR
2559#endif
2560// ==========================================================================
2561// Yosemitech Y514 Chlorophyll Sensor
2562// ==========================================================================
2563/** Start [yosemitech_y514] */
2564#include <sensors/YosemitechY514.h>
2565
2566// NOTE: Extra hardware and software serial ports are created in the "Settings
2567// for Additional Serial Ports" section
2568
2569// NOTE: Use -1 for any pins that don't apply or aren't being used.
2570byte y514ModbusAddress = 0x14; // The modbus address of the Y514
2571const int8_t y514AdapterPower = sensorPowerPin; // RS485 adapter power pin
2572const int8_t y514SensorPower = relayPowerPin; // Sensor power pin
2573const int8_t y514EnablePin = -1; // Adapter RE/DE pin
2574const uint8_t y514NumberReadings = 5;
2575// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2576// power consumption
2577
2578// Create a Y514 chlorophyll sensor object
2579YosemitechY514 y514(y514ModbusAddress, modbusSerial, y514AdapterPower,
2580 y514SensorPower, y514EnablePin, y514NumberReadings);
2581
2582// Create chlorophyll concentration and temperature variable pointers for the
2583// Y514
2584Variable* y514Chloro = new YosemitechY514_Chlorophyll(
2585 &y514, "12345678-abcd-1234-ef00-1234567890ab");
2586Variable* y514Temp =
2587 new YosemitechY514_Temp(&y514, "12345678-abcd-1234-ef00-1234567890ab");
2588/** End [yosemitech_y514] */
2589#endif
2590
2591
2592#if defined(BUILD_SENSOR_YOSEMITECH_Y520)
2593#ifndef BUILD_MODBUS_SENSOR
2594#define BUILD_MODBUS_SENSOR
2595#endif
2596// ==========================================================================
2597// Yosemitech Y520 Conductivity Sensor
2598// ==========================================================================
2599/** Start [yosemitech_y520] */
2600#include <sensors/YosemitechY520.h>
2601
2602// NOTE: Extra hardware and software serial ports are created in the "Settings
2603// for Additional Serial Ports" section
2604
2605// NOTE: Use -1 for any pins that don't apply or aren't being used.
2606byte y520ModbusAddress = 0x20; // The modbus address of the Y520
2607const int8_t y520AdapterPower = sensorPowerPin; // RS485 adapter power pin
2608const int8_t y520SensorPower = relayPowerPin; // Sensor power pin
2609const int8_t y520EnablePin = -1; // Adapter RE/DE pin
2610const uint8_t y520NumberReadings = 5;
2611// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2612// power consumption
2613
2614// Create a Y520 conductivity sensor object
2615YosemitechY520 y520(y520ModbusAddress, modbusSerial, y520AdapterPower,
2616 y520SensorPower, y520EnablePin, y520NumberReadings);
2617
2618// Create specific conductance and temperature variable pointers for the Y520
2619Variable* y520Cond =
2620 new YosemitechY520_Cond(&y520, "12345678-abcd-1234-ef00-1234567890ab");
2621Variable* y520Temp =
2622 new YosemitechY520_Temp(&y520, "12345678-abcd-1234-ef00-1234567890ab");
2623/** End [yosemitech_y520] */
2624#endif
2625
2626
2627#if defined(BUILD_SENSOR_YOSEMITECH_Y532)
2628#ifndef BUILD_MODBUS_SENSOR
2629#define BUILD_MODBUS_SENSOR
2630#endif
2631// ==========================================================================
2632// Yosemitech Y532 pH
2633// ==========================================================================
2634/** Start [yosemitech_y532] */
2635#include <sensors/YosemitechY532.h>
2636
2637// NOTE: Extra hardware and software serial ports are created in the "Settings
2638// for Additional Serial Ports" section
2639
2640// NOTE: Use -1 for any pins that don't apply or aren't being used.
2641byte y532ModbusAddress = 0x32; // The modbus address of the Y532
2642const int8_t y532AdapterPower = sensorPowerPin; // RS485 adapter power pin
2643const int8_t y532SensorPower = relayPowerPin; // Sensor power pin
2644const int8_t y532EnablePin = 4; // Adapter RE/DE pin
2645const uint8_t y532NumberReadings = 1;
2646// The manufacturer actually doesn't mention averaging for this one
2647
2648// Create a Yosemitech Y532 pH sensor object
2649YosemitechY532 y532(y532ModbusAddress, modbusSerial, y532AdapterPower,
2650 y532SensorPower, y532EnablePin, y532NumberReadings);
2651
2652// Create pH, electrical potential, and temperature variable pointers for the
2653// Y532
2654Variable* y532Voltage =
2655 new YosemitechY532_Voltage(&y532, "12345678-abcd-1234-ef00-1234567890ab");
2656Variable* y532pH =
2657 new YosemitechY532_pH(&y532, "12345678-abcd-1234-ef00-1234567890ab");
2658Variable* y532Temp =
2659 new YosemitechY532_Temp(&y532, "12345678-abcd-1234-ef00-1234567890ab");
2660/** End [yosemitech_y532] */
2661#endif
2662
2663
2664#if defined(BUILD_SENSOR_YOSEMITECH_Y533)
2665#ifndef BUILD_MODBUS_SENSOR
2666#define BUILD_MODBUS_SENSOR
2667#endif
2668// ==========================================================================
2669// Yosemitech Y533 Oxidation Reduction Potential (ORP)
2670// ==========================================================================
2671/** Start [yosemitech_y533] */
2672#include <sensors/YosemitechY533.h>
2673
2674// NOTE: Extra hardware and software serial ports are created in the "Settings
2675// for Additional Serial Ports" section
2676
2677// NOTE: Use -1 for any pins that don't apply or aren't being used.
2678byte y533ModbusAddress = 0x32; // The modbus address of the Y533
2679const int8_t y533AdapterPower = sensorPowerPin; // RS485 adapter power pin
2680const int8_t y533SensorPower = relayPowerPin; // Sensor power pin
2681const int8_t y533EnablePin = 4; // Adapter RE/DE pin
2682const uint8_t y533NumberReadings = 1;
2683// The manufacturer actually doesn't mention averaging for this one
2684
2685// Create a Yosemitech Y533 ORP sensor object
2686YosemitechY533 y533(y533ModbusAddress, modbusSerial, y533AdapterPower,
2687 y533SensorPower, y533EnablePin, y533NumberReadings);
2688
2689// Create ORP and temperature variable pointers for the Y533
2690Variable* y533ORP =
2691 new YosemitechY533_ORP(&y533, "12345678-abcd-1234-ef00-1234567890ab");
2692Variable* y533Temp =
2693 new YosemitechY533_Temp(&y533, "12345678-abcd-1234-ef00-1234567890ab");
2694/** End [yosemitech_y533] */
2695#endif
2696
2697
2698#if defined(BUILD_SENSOR_YOSEMITECH_Y551)
2699#ifndef BUILD_MODBUS_SENSOR
2700#define BUILD_MODBUS_SENSOR
2701#endif
2702// ==========================================================================
2703// Yosemitech Y551 COD Sensor with Wiper
2704// ==========================================================================
2705/** Start [yosemitech_y551] */
2706#include <sensors/YosemitechY551.h>
2707
2708// NOTE: Extra hardware and software serial ports are created in the "Settings
2709// for Additional Serial Ports" section
2710
2711// NOTE: Use -1 for any pins that don't apply or aren't being used.
2712byte y551ModbusAddress = 0x50; // The modbus address of the Y551
2713const int8_t y551AdapterPower = sensorPowerPin; // RS485 adapter power pin
2714const int8_t y551SensorPower = relayPowerPin; // Sensor power pin
2715const int8_t y551EnablePin = -1; // Adapter RE/DE pin
2716const uint8_t y551NumberReadings = 5;
2717// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2718// power consumption
2719
2720// Create a Y551 chemical oxygen demand sensor object
2721YosemitechY551 y551(y551ModbusAddress, modbusSerial, y551AdapterPower,
2722 y551SensorPower, y551EnablePin, y551NumberReadings);
2723
2724// Create COD, turbidity, and temperature variable pointers for the Y551
2725Variable* y551COD =
2726 new YosemitechY551_COD(&y551, "12345678-abcd-1234-ef00-1234567890ab");
2727Variable* y551Turbid =
2728 new YosemitechY551_Turbidity(&y551, "12345678-abcd-1234-ef00-1234567890ab");
2729Variable* y551Temp =
2730 new YosemitechY551_Temp(&y551, "12345678-abcd-1234-ef00-1234567890ab");
2731/** End [yosemitech_y551] */
2732#endif
2733
2734
2735#if defined(BUILD_SENSOR_YOSEMITECH_Y560)
2736#ifndef BUILD_MODBUS_SENSOR
2737#define BUILD_MODBUS_SENSOR
2738#endif
2739// ==========================================================================
2740// Yosemitech Y560 Ammonium Probe with Wiper
2741// ==========================================================================
2742/** Start [yosemitech_y560] */
2743#include <sensors/YosemitechY560.h>
2744
2745// NOTE: Extra hardware and software serial ports are created in the "Settings
2746// for Additional Serial Ports" section
2747
2748// NOTE: Use -1 for any pins that don't apply or aren't being used.
2749byte y560ModbusAddress =
2750 0x60; // The modbus address of the Y560.
2751 // NOTE: Hexidecimal 0x60 = 96 decimal used by Yosemitech SmartPC
2752const int8_t y560AdapterPower = sensorPowerPin; // RS485 adapter power pin
2753const int8_t y560SensorPower = relayPowerPin; // Sensor power pin
2754const int8_t y560EnablePin = -1; // Adapter RE/DE pin
2755const uint8_t y560NumberReadings = 3;
2756// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2757// power consumption
2758
2759// Create a Y560 Ammonium Probe object
2760YosemitechY560 y560(y560ModbusAddress, modbusSerial, y560AdapterPower,
2761 y560SensorPower, y560EnablePin, y560NumberReadings);
2762
2763// Create COD, turbidity, and temperature variable pointers for the Y560
2764Variable* y560NH4_N =
2765 new YosemitechY560_NH4_N(&y560, "12345678-abcd-1234-ef00-1234567890ab");
2766Variable* y560pH =
2767 new YosemitechY560_pH(&y560, "12345678-abcd-1234-ef00-1234567890ab");
2768Variable* y560Temp =
2769 new YosemitechY560_Temp(&y560, "12345678-abcd-1234-ef00-1234567890ab");
2770/** End [yosemitech_y560] */
2771#endif
2772
2773
2774#if defined(BUILD_SENSOR_YOSEMITECH_Y700)
2775#ifndef BUILD_MODBUS_SENSOR
2776#define BUILD_MODBUS_SENSOR
2777#endif
2778// ==========================================================================
2779// Yosemitech Y700 Pressure Sensor
2780// ==========================================================================
2781/** Start [yosemitech_y700] */
2782#include <sensors/YosemitechY700.h>
2783
2784// NOTE: Extra hardware and software serial ports are created in the "Settings
2785// for Additional Serial Ports" section
2786
2787// NOTE: Use -1 for any pins that don't apply or aren't being used.
2788byte y700ModbusAddress = 0x70; // The modbus address of the Y700
2789const int8_t y700AdapterPower = sensorPowerPin; // RS485 adapter power pin
2790const int8_t y700SensorPower = relayPowerPin; // Sensor power pin
2791const int8_t y700EnablePin = -1; // Adapter RE/DE pin
2792const uint8_t y700NumberReadings = 5;
2793// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2794// power consumption
2795
2796// Create a Y700 pressure sensor object
2797YosemitechY700 y700(y700ModbusAddress, modbusSerial, y700AdapterPower,
2798 y700SensorPower, y700EnablePin, y700NumberReadings);
2799
2800// Create pressure and temperature variable pointers for the Y700
2801Variable* y700Pres =
2802 new YosemitechY700_Pressure(&y700, "12345678-abcd-1234-ef00-1234567890ab");
2803Variable* y700Temp =
2804 new YosemitechY700_Temp(&y700, "12345678-abcd-1234-ef00-1234567890ab");
2805/** End [yosemitech_y700] */
2806#endif
2807
2808
2809#if defined(BUILD_SENSOR_YOSEMITECH_Y4000)
2810#ifndef BUILD_MODBUS_SENSOR
2811#define BUILD_MODBUS_SENSOR
2812#endif
2813// ==========================================================================
2814// Yosemitech Y4000 Multiparameter Sonde (DOmgL, Turbidity, Cond, pH, Temp,
2815// ORP, Chlorophyll, BGA)
2816// ==========================================================================
2817/** Start [yosemitech_y4000] */
2818#include <sensors/YosemitechY4000.h>
2819
2820// NOTE: Extra hardware and software serial ports are created in the "Settings
2821// for Additional Serial Ports" section
2822
2823// NOTE: Use -1 for any pins that don't apply or aren't being used.
2824byte y4000ModbusAddress = 0x05; // The modbus address of the Y4000
2825const int8_t y4000AdapterPower = sensorPowerPin; // RS485 adapter power pin
2826const int8_t y4000SensorPower = relayPowerPin; // Sensor power pin
2827const int8_t y4000EnablePin = -1; // Adapter RE/DE pin
2828const uint8_t y4000NumberReadings = 5;
2829// The manufacturer recommends averaging 10 readings, but we take 5 to minimize
2830// power consumption
2831
2832// Create a Yosemitech Y4000 multi-parameter sensor object
2833YosemitechY4000 y4000(y4000ModbusAddress, modbusSerial, y4000AdapterPower,
2834 y4000SensorPower, y4000EnablePin, y4000NumberReadings);
2835
2836// Create all of the variable pointers for the Y4000
2837Variable* y4000DO =
2838 new YosemitechY4000_DOmgL(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2839Variable* y4000Turb = new YosemitechY4000_Turbidity(
2840 &y4000, "12345678-abcd-1234-ef00-1234567890ab");
2841Variable* y4000Cond =
2842 new YosemitechY4000_Cond(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2843Variable* y4000pH =
2844 new YosemitechY4000_pH(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2845Variable* y4000Temp =
2846 new YosemitechY4000_Temp(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2847Variable* y4000ORP =
2848 new YosemitechY4000_ORP(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2849Variable* y4000Chloro = new YosemitechY4000_Chlorophyll(
2850 &y4000, "12345678-abcd-1234-ef00-1234567890ab");
2851Variable* y4000BGA =
2852 new YosemitechY4000_BGA(&y4000, "12345678-abcd-1234-ef00-1234567890ab");
2853/** End [yosemitech_y4000] */
2854#endif
2855
2856
2857#if defined(BUILD_SENSOR_ZEBRA_TECH_D_OPTO)
2858#ifndef BUILD_MODBUS_SENSOR
2859#define BUILD_MODBUS_SENSOR
2860#endif
2861// ==========================================================================
2862// Zebra Tech D-Opto Dissolved Oxygen Sensor
2863// ==========================================================================
2864/** Start [zebra_tech_d_opto] */
2865#include <sensors/ZebraTechDOpto.h>
2866
2867// NOTE: Use -1 for any pins that don't apply or aren't being used.
2868const char* DOptoSDI12address = "5"; // The SDI-12 Address of the D-Opto
2869const int8_t ZTPower = sensorPowerPin; // Power pin
2870const int8_t ZTData = sdi12DataPin; // The SDI-12 data pin
2871
2872// Create a Zebra Tech DOpto dissolved oxygen sensor object
2873ZebraTechDOpto dopto(*DOptoSDI12address, ZTPower, ZTData);
2874
2875// Create dissolved oxygen percent, dissolved oxygen concentration, and
2876// temperature variable pointers for the Zebra Tech
2877Variable* dOptoDOpct =
2878 new ZebraTechDOpto_DOpct(&dopto, "12345678-abcd-1234-ef00-1234567890ab");
2879Variable* dOptoDOmgL =
2880 new ZebraTechDOpto_DOmgL(&dopto, "12345678-abcd-1234-ef00-1234567890ab");
2881Variable* dOptoTemp =
2882 new ZebraTechDOpto_Temp(&dopto, "12345678-abcd-1234-ef00-1234567890ab");
2883/** End [zebra_tech_d_opto] */
2884#endif
2885
2886
2887// ==========================================================================
2888// Calculated Variable[s]
2889// ==========================================================================
2890/** Start [calculated_variables] */
2891// Create the function to give your calculated result.
2892// The function should take no input (void) and return a float.
2893// You can use any named variable pointers to access values by way of
2894// variable->getValue()
2895
2896float calculateVariableValue() {
2897 float calculatedResult = -9999; // Always safest to start with a bad value
2898 // float inputVar1 = variable1->getValue();
2899 // float inputVar2 = variable2->getValue();
2900 // make sure both inputs are good
2901 // if (inputVar1 != -9999 && inputVar2 != -9999) {
2902 // calculatedResult = inputVar1 + inputVar2;
2903 // }
2904 return calculatedResult;
2905}
2906
2907// Properties of the calculated variable
2908// The number of digits after the decimal place
2909const uint8_t calculatedVarResolution = 3;
2910// This must be a value from http://vocabulary.odm2.org/variablename/
2911const char* calculatedVarName = "varName";
2912// This must be a value from http://vocabulary.odm2.org/units/
2913const char* calculatedVarUnit = "varUnit";
2914// A short code for the variable
2915const char* calculatedVarCode = "calcVar";
2916// The (optional) universally unique identifier
2917const char* calculatedVarUUID = "12345678-abcd-1234-ef00-1234567890ab";
2918
2919// Finally, Create a calculated variable and return a variable pointer to it
2920Variable* calculatedVar = new Variable(
2921 calculateVariableValue, calculatedVarResolution, calculatedVarName,
2922 calculatedVarUnit, calculatedVarCode, calculatedVarUUID);
2923/** End [calculated_variables] */
2924
2925
2926#if defined(BUILD_TEST_CREATE_IN_ARRAY)
2927// ==========================================================================
2928// Creating the Variable Array[s] and Filling with Variable Objects
2929// NOTE: This shows three different ways of creating the same variable array
2930// and filling it with variables
2931// ==========================================================================
2932/** Start [variables_create_in_array] */
2933// Version 1: Create pointers for all of the variables from the sensors,
2934// at the same time putting them into an array
2935Variable* variableList[] = {
2936 new ProcessorStats_SampleNumber(&mcuBoard,
2937 "12345678-abcd-1234-ef00-1234567890ab"),
2938 new ProcessorStats_FreeRam(&mcuBoard,
2939 "12345678-abcd-1234-ef00-1234567890ab"),
2940 new ProcessorStats_Battery(&mcuBoard,
2941 "12345678-abcd-1234-ef00-1234567890ab"),
2942 // ... Add more variables as needed!
2943 new Modem_RSSI(&modem, "12345678-abcd-1234-ef00-1234567890ab"),
2944 new Modem_SignalPercent(&modem, "12345678-abcd-1234-ef00-1234567890ab"),
2945 new Modem_Temp(&modem, "12345678-abcd-1234-ef00-1234567890ab"),
2946 new Variable(calculateVariableValue, calculatedVarResolution,
2947 calculatedVarName, calculatedVarUnit, calculatedVarCode,
2948 calculatedVarUUID),
2949};
2950// Count up the number of pointers in the array
2951int variableCount = sizeof(variableList) / sizeof(variableList[0]);
2952// Create the VariableArray object
2953VariableArray varArray(variableCount, variableList);
2954/** End [variables_create_in_array] */
2955// ==========================================================================
2956
2957
2958#elif defined(BUILD_TEST_SEPARATE_UUIDS)
2959/** Start [variables_separate_uuids] */
2960// Version 2: Create two separate arrays, on for the variables and a separate
2961// one for the UUID's, then give both as input to the variable array
2962// constructor. Be cautious when doing this though because order is CRUCIAL!
2963Variable* variableList[] = {
2964 new ProcessorStats_SampleNumber(&mcuBoard),
2965 new ProcessorStats_FreeRam(&mcuBoard),
2966 new ProcessorStats_Battery(&mcuBoard),
2967 // new MaximDS3231_Temp(&ds3231),
2968 // ... Add all of your variables!
2969 new Modem_RSSI(&modem),
2970 new Modem_SignalPercent(&modem),
2971 new Modem_Temp(&modem),
2972 new Variable(calculateVariableValue, calculatedVarResolution,
2973 calculatedVarName, calculatedVarUnit, calculatedVarCode),
2974};
2975const char* UUIDs[] = {
2976 "12345678-abcd-1234-ef00-1234567890ab",
2977 "12345678-abcd-1234-ef00-1234567890ab",
2978 "12345678-abcd-1234-ef00-1234567890ab",
2979 "12345678-abcd-1234-ef00-1234567890ab",
2980 // ... The number of UUID's must match the number of variables!
2981 "12345678-abcd-1234-ef00-1234567890ab",
2982 "12345678-abcd-1234-ef00-1234567890ab",
2983 "12345678-abcd-1234-ef00-1234567890ab",
2984 "12345678-abcd-1234-ef00-1234567890ab",
2985};
2986// Count up the number of pointers in the array
2987int variableCount = sizeof(variableList) / sizeof(variableList[0]);
2988// Create the VariableArray object and attach the UUID's
2989VariableArray varArray(variableCount, variableList, UUIDs);
2990/** End [variables_separate_uuids] */
2991// ==========================================================================
2992
2993
2994#else
2995//^^ BUILD_TEST_PRE_NAMED_VARS
2996/** Start [variables_pre_named] */
2997// Version 3: Fill array with already created and named variable pointers
2998Variable* variableList[] = {
2999#if defined(MS_USE_DS3231)
3000 ds3231Temp,
3001#endif
3002#if defined(BUILD_SENSOR_ALPHASENSE_CO2)
3003 asCO2,
3004 asco2voltage,
3005#endif
3006#if defined(BUILD_SENSOR_ANB_PH)
3007 anbPHValue,
3008 anbPHTemp,
3009 anbPHSal,
3010 anbPHSpCond,
3011 anbPHEC,
3012 anbPHHealth,
3013 anbPHDiagnostic,
3014 anbPHStatus,
3015#endif
3016#if defined(BUILD_SENSOR_AO_SONG_AM2315)
3017 am2315Humid,
3018 am2315Temp,
3019#endif
3020#if defined(BUILD_SENSOR_AO_SONG_DHT)
3021 dhtHumid,
3022 dhtTemp,
3023 dhtHI,
3024#endif
3025#if defined(BUILD_SENSOR_APOGEE_SQ212)
3026 sq212PAR,
3027 sq212voltage,
3028#endif
3029#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_CO2)
3030 atlasCO2CO2,
3031 atlasCO2Temp,
3032#endif
3033#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_DO)
3034 atlasDOconc,
3035 atlasDOpct,
3036#endif
3037#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_ORP)
3038 atlasORPot,
3039#endif
3040#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_PH)
3041 atlaspHpH,
3042#endif
3043#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_RTD)
3044 atlasTemp,
3045#endif
3046#if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_EC)
3047 atlasCond,
3048 atlasTDS,
3049 atlasSal,
3050 atlasGrav,
3051 atlasSpCond,
3052#endif
3053#if defined(BUILD_SENSOR_BOSCH_BME280)
3054 bme280Temp,
3055 bme280Humid,
3056 bme280Press,
3057 bme280Alt,
3058#endif
3059#if defined(BUILD_SENSOR_BOSCH_BMP3XX)
3060 bmp3xxTemp,
3061 bmp3xxPress,
3062 bmp3xxAlt,
3063#endif
3064#if defined(BUILD_SENSOR_CAMPBELL_CLARI_VUE10)
3065 clarivueTurbidity,
3066 clarivueTemp,
3067 clarivueError,
3068#endif
3069#if defined(BUILD_SENSOR_CAMPBELL_OBS3)
3070 obs3TurbLow,
3071 obs3VoltLow,
3072 obs3TurbHigh,
3073 obs3VoltHigh,
3074#endif
3075#if defined(BUILD_SENSOR_CAMPBELL_RAIN_VUE10)
3076 rainvuePrecipitation,
3077 rainvueTips,
3078 rainvueRainRateAve,
3079 rainvueRainRateMax,
3080#endif
3081#if defined(BUILD_SENSOR_DECAGON_CTD)
3082 ctdCond,
3083 ctdTemp,
3084 ctdDepth,
3085#endif
3086#if defined(BUILD_SENSOR_DECAGON_ES2)
3087 es2Cond,
3088 es2Temp,
3089#endif
3090#if defined(BUILD_SENSOR_EVERLIGHT_ALSPT19)
3091 alsPt19Volt,
3092 alsPt19Current,
3093 alsPt19Lux,
3094#endif
3095#if defined(BUILD_SENSOR_TIADS1X15)
3096 ads1x15Volt,
3097#endif
3098#if defined(BUILD_SENSOR_FREESCALE_MPL115A2)
3099 mplTemp,
3100 mplPress,
3101#endif
3102#if defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
3103 hydrocamImageSize,
3104 hydrocamByteError,
3105#endif
3106#if defined(BUILD_SENSOR_GRO_POINT_GPLP8)
3107 gplp8Moist1,
3108 gplp8Moist2,
3109 gplp8Moist3,
3110 gplp8Moist4,
3111 gplp8Moist5,
3112 gplp8Moist6,
3113 gplp8Moist7,
3114 gplp8Moist8,
3115 gplp8Temp1,
3116 gplp8Temp2,
3117 gplp8Temp3,
3118 gplp8Temp4,
3119 gplp8Temp5,
3120 gplp8Temp6,
3121 gplp8Temp7,
3122 gplp8Temp8,
3123 gplp8Temp9,
3124 gplp8Temp10,
3125 gplp8Temp11,
3126 gplp8Temp12,
3127 gplp8Temp13,
3128#endif
3129#if defined(BUILD_SENSOR_IN_SITU_RDO)
3130 rdoTemp,
3131 rdoDOpct,
3132 rdoDOmgL,
3133 rdoO2pp,
3134#endif
3135#if defined(BUILD_SENSOR_IN_SITU_TROLL_SDI12A)
3136 trollPressure,
3137 trollTemp,
3138 trollDepth,
3139#endif
3140#if defined(BUILD_SENSOR_KELLER_ACCULEVEL)
3141 acculevPress,
3142 acculevTemp,
3143 acculevHeight,
3144#endif
3145#if defined(BUILD_SENSOR_KELLER_NANOLEVEL)
3146 nanolevPress,
3147 nanolevTemp,
3148 nanolevHeight,
3149#endif
3150#if defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
3151 sonar1Range,
3152#endif
3153#if defined(BUILD_SENSOR_MAXIM_DS18)
3154 ds18Temp,
3155#endif
3156#if defined(BUILD_SENSOR_MEA_SPEC_MS5803)
3157 ms5803Temp,
3158 ms5803Press,
3159#endif
3160#if defined(BUILD_SENSOR_DECAGON_5TM)
3161 fivetmEa,
3162 fivetmVWC,
3163 fivetmTemp,
3164#endif
3165#if defined(BUILD_SENSOR_METER_HYDROS21)
3166 hydros21Cond,
3167 hydros21Temp,
3168 hydros21Depth,
3169#endif
3170#if defined(BUILD_SENSOR_METER_TEROS11)
3171 teros11Ea,
3172 teros11Temp,
3173 teros11VWC,
3174 teros11Count,
3175#endif
3176#if defined(BUILD_SENSOR_PALEO_TERRA_REDOX)
3177 ptVolt,
3178#endif
3179#if defined(BUILD_SENSOR_RAIN_COUNTER_I2C)
3180 tbi2cTips,
3181 tbi2cDepth,
3182#endif
3183#if defined(BUILD_SENSOR_SENSIRION_SHT4X)
3184 sht4xHumid,
3185 sht4xTemp,
3186#endif
3187#if defined(BUILD_SENSOR_TALLY_COUNTER_I2C)
3188 tallyEvents,
3189#endif
3190#if defined(BUILD_SENSOR_TI_INA219)
3191 inaVolt,
3192 inaCurrent,
3193 inaPower,
3194#endif
3195#if defined(BUILD_SENSOR_TURNER_CYCLOPS)
3196 cyclopsVoltage,
3197 cyclopsChloro,
3198 cyclopsRWT,
3199 cyclopsFluoroscein,
3200 cyclopsPhycocyanin,
3201 cyclopsPhycoerythrin,
3202 cyclopsCDOM,
3203 cyclopsCrudeOil,
3204 cyclopsBrighteners,
3205 cyclopsTurbidity,
3206 cyclopsPTSA,
3207 cyclopsBTEX,
3208 cyclopsTryptophan,
3209 cyclopsRedChloro,
3210#endif
3211#if defined(BUILD_SENSOR_TURNER_TURBIDITY_PLUS)
3212 turbidityPlusVoltage,
3213 turbidityPlusTurbidity,
3214#endif
3215#if defined(BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY)
3216 analogEc_cond,
3217 analogEc_spcond,
3218#endif
3219#if defined(BUILD_SENSOR_VEGA_PULS21)
3220 VegaPulsStage,
3221 VegaPulsDistance,
3222 VegaPulsTemp,
3223 VegaPulsRelia,
3224 VegaPulsError,
3225#endif
3226#if defined(BUILD_SENSOR_YOSEMITECH_Y504)
3227 y504DOpct,
3228 y504DOmgL,
3229 y504Temp,
3230#endif
3231#if defined(BUILD_SENSOR_YOSEMITECH_Y510)
3232 y510Turb,
3233 y510Temp,
3234#endif
3235#if defined(BUILD_SENSOR_YOSEMITECH_Y511)
3236 y511Turb,
3237 y511Temp,
3238#endif
3239#if defined(BUILD_SENSOR_YOSEMITECH_Y513)
3240 y513BGA,
3241 y513Temp,
3242#endif
3243#if defined(BUILD_SENSOR_YOSEMITECH_Y514)
3244 y514Chloro,
3245 y514Temp,
3246#endif
3247#if defined(BUILD_SENSOR_YOSEMITECH_Y520)
3248 y520Cond,
3249 y520Temp,
3250#endif
3251#if defined(BUILD_SENSOR_YOSEMITECH_Y532)
3252 y532Voltage,
3253 y532pH,
3254 y532Temp,
3255#endif
3256#if defined(BUILD_SENSOR_YOSEMITECH_Y533)
3257 y533ORP,
3258 y533Temp,
3259#endif
3260#if defined(BUILD_SENSOR_YOSEMITECH_Y551)
3261 y551COD,
3262 y551Turbid,
3263 y551Temp,
3264#endif
3265#if defined(BUILD_SENSOR_YOSEMITECH_Y560)
3266 y560NH4_N,
3267 y560pH,
3268 y560Temp,
3269#endif
3270#if defined(BUILD_SENSOR_YOSEMITECH_Y700)
3271 y700Pres,
3272 y700Temp,
3273#endif
3274#if defined(BUILD_SENSOR_YOSEMITECH_Y4000)
3275 y4000DO,
3276 y4000Turb,
3277 y4000Cond,
3278 y4000pH,
3279 y4000Temp,
3280 y4000ORP,
3281 y4000Chloro,
3282 y4000BGA,
3283#endif
3284#if defined(BUILD_SENSOR_ZEBRA_TECH_D_OPTO)
3285 dOptoDOpct,
3286 dOptoDOmgL,
3287 dOptoTemp,
3288#endif
3289#if !defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM)
3290 modemRSSI,
3291 modemSignalPct,
3292#if defined(TINY_GSM_MODEM_HAS_BATTERY)
3293 modemBatteryState,
3294 modemBatteryPct,
3295 modemBatteryVoltage,
3296#endif
3297#if defined(TINY_GSM_MODEM_HAS_TEMPERATURE)
3298 modemTemperature,
3299#endif
3300#endif
3301 mcuBoardSampNo,
3302#if !defined(__SAMD51__)
3303 mcuBoardAvailableRAM,
3304#endif
3305 mcuBoardBatt,
3306 mcuBoardReset,
3307 calculatedVar,
3308};
3309// Count up the number of pointers in the array
3310int variableCount = sizeof(variableList) / sizeof(variableList[0]);
3311// Create the VariableArray object
3312VariableArray varArray(variableCount, variableList);
3313/** End [variables_pre_named] */
3314#endif
3315
3316
3317#if defined(BUILD_PUB_ENVIRO_DIY_PUBLISHER) && \
3318 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3319// ==========================================================================
3320// A Publisher to Monitor My Watershed / EnviroDIY Data Sharing Portal
3321// ==========================================================================
3322/** Start [enviro_diy_publisher] */
3323// Device registration and sampling feature information can be obtained after
3324// registration at https://monitormywatershed.org or https://data.envirodiy.org
3325const char* registrationToken =
3326 "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token
3327// NOTE: Because we already set the sampling feature with the logger
3328// constructor, don't do it here.
3329// const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; //
3330// Sampling feature UUID
3331
3332// Create a data publisher for the Monitor My Watershed/EnviroDIY POST endpoint
3333#include <publishers/EnviroDIYPublisher.h>
3334EnviroDIYPublisher EnviroDIYPost(dataLogger, registrationToken);
3335/** End [enviro_diy_publisher] */
3336#endif
3337
3338
3339#if defined(BUILD_PUB_DREAM_HOST_PUBLISHER) && \
3340 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3341// ==========================================================================
3342// A Publisher to DreamHost
3343// ==========================================================================
3344/** Start [dream_host_publisher] */
3345// NOTE: This is an outdated data collection tool used by the Stroud Center.
3346// It very, very unlikely that you will use this.
3347
3348const char* DreamHostPortalRX = "xxxx";
3349
3350// Create a data publisher to DreamHost
3351#include <publishers/DreamHostPublisher.h>
3352DreamHostPublisher DreamHostGET(dataLogger, DreamHostPortalRX);
3353/** End [dream_host_publisher] */
3354#endif
3355
3356
3357#if defined(BUILD_PUB_THING_SPEAK_PUBLISHER) && \
3358 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3359// ==========================================================================
3360// ThingSpeak Data Publisher
3361// ==========================================================================
3362/** Start [thing_speak_publisher] */
3363// Create a channel with fields on ThingSpeak in advance.
3364// The fields will be sent in exactly the order they are in the variable array.
3365// Any custom name or identifier given to the field on ThingSpeak is irrelevant.
3366// No more than 8 fields of data can go to any one channel. Any fields beyond
3367// the eighth in the array will be ignored.
3368const char* thingSpeakClientName =
3369 "XXXXXXXXXXXXXXXX"; // The client name for your MQTT device
3370const char* thingSpeakMQTTUser =
3371 "XXXXXXXXXXXXXXXX"; // The user name for your MQTT device.
3372const char* thingSpeakMQTTPassword =
3373 "XXXXXXXXXXXXXXXX"; // The password for your MQTT device
3374const char* thingSpeakChannelID =
3375 "######"; // The numeric channel id for your channel
3376const char* thingSpeakAPIKey =
3377 "XXXXXXXXXXXXXXXX"; // The ThingSpeak user REST API key
3378
3379// Create a data publisher for ThingSpeak
3380#include <publishers/ThingSpeakPublisher.h>
3381ThingSpeakPublisher TsMqtt(dataLogger, thingSpeakClientName, thingSpeakMQTTUser,
3382 thingSpeakMQTTPassword, thingSpeakChannelID);
3383/** End [thing_speak_publisher] */
3384#endif
3385
3386
3387#if defined(BUILD_PUB_UBIDOTS_PUBLISHER) && \
3388 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3389// ==========================================================================
3390// Ubidots Data Publisher
3391// ==========================================================================
3392/** Start [ubidots_publisher] */
3393// The authentication token from Ubidots, either the Organization's Integration
3394// Token (under Users > Organization menu,visible by Admin only) OR the STEM
3395// User's Device Token (under the specific device's setup panel).
3396const char* ubidotsToken = "XXXXXXXXXXXXXXXX";
3397// The device API Label from Ubidots, derived from the user-specified device
3398// name.
3399const char* ubidotsDeviceID = "######";
3400
3401// Create a data publisher for Ubidots
3402#include <publishers/UbidotsPublisher.h>
3403UbidotsPublisher ubidots(dataLogger, ubidotsToken, ubidotsDeviceID);
3404/** End [ubidots_publisher] */
3405#endif
3406
3407
3408#if defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER) && \
3409 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3410// ==========================================================================
3411// AWS S3 Pre-signed URL Publisher
3412// ==========================================================================
3413/** Start [s3_presigned_publisher] */
3414#ifdef BUILD_MODEM_ESPRESSIF_ESP32
3415// For Espressif modules, only two certificate sets are supported and the
3416// certificates must be named "client_ca.{0|1}", "client_cert.{0|1}", or
3417// "client_key.{0|1}"
3418const char* caCertName = "client_ca.0";
3419#else
3420// The name of your certificate authority certificate file
3421const char* caCertName = "AmazonRootCA1.pem";
3422#endif
3423
3424// The S3 host (need for region specific requests)
3425const char* s3Host = "s3.YOUR-REGION.amazonaws.com";
3426// Expand the expected S3 publish topic into a buffer
3427String s3URLPubTopic = "$aws/rules/GetUploadURL/" + String(LoggerID);
3428// Expand the expected S3 subscribe topic into a buffer
3429String s3URLSubTopic = String(LoggerID) + "/upload_url";
3430// A function for the IoT core publisher to call to get the message content for
3431// a new URL request
3432#if defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
3433String s3URLMsgGetter() {
3434 return String("{\"file\": \"") + hydrocam.getLastSavedImageName() +
3435 String("\"}");
3436}
3437#else
3438String s3URLMsgGetter() {
3439 return String("{\"file\": \"image.jpg\"}");
3440}
3441#endif
3442
3443// Create a data publisher for AWS IoT Core
3444#include <publishers/S3PresignedPublisher.h>
3445S3PresignedPublisher s3pub;
3446/** End [s3_presigned_publisher] */
3447#endif
3448
3449
3450#if defined(BUILD_PUB_AWS_IO_T_PUBLISHER) && \
3451 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3452// ==========================================================================
3453// AWS IoT Core MQTT Publisher
3454// ==========================================================================
3455/** Start [aws_io_t_publisher] */
3456// The endpoint for your AWS IoT instance
3457const char* awsIoTEndpoint = "xxx-ats.iot.xxx.amazonaws.com";
3458// Sampling feature UUID, this will be the sub-topic for your data
3459// NOTE: Because we already set the sampling feature with the logger
3460// constructor, don't do it here.
3461// const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab";
3462#ifdef BUILD_MODEM_ESPRESSIF_ESP32
3463// For Espressif modules, only two certificate sets are supported and the
3464// certificates must be named "client_ca.{0|1}", "client_cert.{0|1}", or
3465// "client_key.{0|1}"
3466#if !defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER)
3467const char* caCertName = "client_ca.0";
3468#endif
3469const char* clientCertName = "client_cert.0";
3470const char* clientKeyName = "client_key.0";
3471#else
3472#if !defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER)
3473// The name of your certificate authority certificate file
3474const char* caCertName = "AmazonRootCA1.pem";
3475#endif
3476// The name of your client certificate file
3477const char* clientCertName = "thing-certificate.pem.crt";
3478// The name of your client private key file
3479const char* clientKeyName = "thing-private.pem.key";
3480#endif
3481
3482// Create a data publisher for AWS IoT Core
3483#include <publishers/AWS_IoT_Publisher.h>
3484AWS_IoT_Publisher awsIoTPub(dataLogger, awsIoTEndpoint, caCertName,
3485 clientCertName, clientKeyName);
3486
3487#if defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER)
3488// Callback function
3489void IoTCallback(char* topic, byte* payload, unsigned int length) {
3490 PRINTOUT(F("Got message of length"), length, F("on topic"), topic);
3491 // the topic is a char and guaranteed to be null-terminated, so we can
3492 // directly convert to a String
3493 if (String(topic) == s3URLSubTopic) {
3494 PRINTOUT(F("Received data on pre-signed URL topic from AWS IoT Core"));
3495 // Allocate the correct amount of memory for the payload copy
3496 // We CANNOT directly convert it to a string because it's not guaranteed
3497 // to be null-terminated
3498 char* rx_url = (char*)malloc(length + 1);
3499 // Copy the payload to the new buffer
3500 memcpy(rx_url, payload, length);
3501 // Null terminate the string
3502 memset(rx_url + length, '\0', 1);
3503 PRINTOUT(F("Setting S3 URL to:"), rx_url);
3504 s3pub.setPreSignedURL(String(rx_url));
3505 // Free the memory now that the URL has been copied into a new String
3506 free(rx_url);
3507 // let the publisher know we got what we expected and it can stop
3508 // waiting
3509 awsIoTPub.closeConnection();
3510 }
3511}
3512#endif
3513/** End [aws_io_t_publisher] */
3514#endif
3515
3516
3517// ==========================================================================
3518// Working Functions
3519// ==========================================================================
3520/** Start [working_functions] */
3521
3522#if defined(PIN_NEOPIXEL)
3523#include <Adafruit_NeoPixel.h>
3524// Declare our NeoPixel strip object:
3525Adafruit_NeoPixel pixels(1, PIN_NEOPIXEL);
3526// Flashes the LED's on the primary board
3527void greenRedFlash(uint8_t numFlash = 4, uint8_t rate = 75) {
3528#if defined(PIN_NEOPIXEL_POWER)
3529 pinMode(PIN_NEOPIXEL_POWER, OUTPUT);
3530 digitalWrite(PIN_NEOPIXEL_POWER, HIGH);
3531#endif
3532 for (uint8_t i = 0; i < numFlash; i++) {
3533 pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // set to green
3534 pixels.show(); // Send the updated pixel colors to the hardware.
3535 delay(rate);
3536 pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // set to red
3537 pixels.show(); // Send the updated pixel colors to the hardware.
3538 delay(rate);
3539 }
3540 pixels.clear(); // Set all pixel colors to 'off'
3541#if defined(PIN_NEOPIXEL_POWER)
3542 digitalWrite(PIN_NEOPIXEL_POWER, LOW);
3543#endif
3544}
3545#else
3546// Flashes the LED's on the primary board
3547void greenRedFlash(uint8_t numFlash = 4, uint8_t rate = 75) {
3548 // Set up pins for the LED's
3549 pinMode(greenLED, OUTPUT);
3550 digitalWrite(greenLED, LOW);
3551 pinMode(redLED, OUTPUT);
3552 digitalWrite(redLED, LOW);
3553 // Flash the lights
3554 for (uint8_t i = 0; i < numFlash; i++) {
3555 digitalWrite(greenLED, HIGH);
3556 digitalWrite(redLED, LOW);
3557 delay(rate);
3558 digitalWrite(greenLED, LOW);
3559 digitalWrite(redLED, HIGH);
3560 delay(rate);
3561 }
3562 digitalWrite(redLED, LOW);
3563}
3564#endif
3565
3566// Uses the processor sensor object to read the battery voltage
3567// NOTE: This will actually return the battery level from the previous update!
3568float getBatteryVoltage() {
3569 if (mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM] == -9999 ||
3570 mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM] == 0) {
3571 mcuBoard.update();
3572 }
3573 return mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM];
3574}
3575/** End [working_functions] */
3576
3577
3578// ==========================================================================
3579// Arduino Setup Function
3580// ==========================================================================
3581void setup() {
3582 /** Start [setup_flashing_led] */
3583 // Blink the LEDs to show the board is on and starting up
3584 greenRedFlash(3, 35);
3585 /** End [setup_flashing_led] */
3586
3587/** Start [setup_wait] */
3588// Wait for USB connection to be established by PC
3589// NOTE: Only use this when debugging - if not connected to a PC, this adds an
3590// unnecessary startup delay
3591#if defined(SERIAL_PORT_USBVIRTUAL)
3592 while (!SERIAL_PORT_USBVIRTUAL && (millis() < 10000L)) {
3593 // wait
3594 }
3595#endif
3596 /** End [setup_wait] */
3597
3598 /** Start [setup_prints] */
3599 // Start the primary serial connection
3600 Serial.begin(serialBaud);
3601#if defined(MS_2ND_OUTPUT)
3602 MS_2ND_OUTPUT.begin(serialBaud);
3603#endif
3604 greenRedFlash(5, 50);
3605
3606 // Print a start-up note to the first serial port
3607 PRINTOUT("\n\n\n=============================");
3608 PRINTOUT("=============================");
3609 PRINTOUT("=============================");
3610 PRINTOUT(F("\n\nNow running"), sketchName, F("on Logger"), LoggerID, '\n');
3611
3612 PRINTOUT(F("Using ModularSensors Library version"),
3613 MODULAR_SENSORS_VERSION);
3614#if !defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM)
3615 PRINTOUT(F("TinyGSM Library version"), TINYGSM_VERSION, '\n');
3616#endif
3617 PRINTOUT(F("Processor:"), mcuBoard.getSensorLocation());
3618 PRINTOUT(F("The most recent reset cause was"), mcuBoard.getLastResetCode(),
3619 '(', mcuBoard.getLastResetCause(), ")\n");
3620 /** End [setup_prints] */
3621
3622/** Start [setup_softserial] */
3623// Allow interrupts for software serial
3624#if defined(BUILD_TEST_SOFTSERIAL)
3625 PRINTOUT(F("Enabling interrupts for SoftwareSerial"));
3626 enableInterrupt(softSerialRx, SoftwareSerial_ExtInts::handle_interrupt,
3627 CHANGE);
3628#endif
3629#if defined(BUILD_TEST_NEOSWSERIAL)
3630 PRINTOUT(F("Enabling interrupts for NeoSoftSerial"));
3631 enableInterrupt(neoSSerial1Rx, neoSSerial1ISR, CHANGE);
3632#endif
3633/** End [setup_softserial] */
3634
3635/** Start [setup_serial_begins] */
3636// Start the serial connection with the modem
3637#if !defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM)
3638 PRINTOUT(F("Starting modem connection on"), STR(modemSerial), F("at"),
3639 modemBaud, F(" baud"));
3640 modemSerial.begin(modemBaud);
3641#endif
3642
3643#if defined(BUILD_MODBUS_SENSOR)
3644 // Start the stream for the modbus sensors;
3645 // modbusSerial.begin(57600); // 57600 is the default for ANB pH sensors
3646 modbusSerial.begin(9600); // All other modbus sensors use 9600 baud
3647#endif
3648
3649#if defined(BUILD_SENSOR_MAX_BOTIX_SONAR)
3650 // Start the stream for the sonar; it will always be at 9600 baud
3651 sonarSerial.begin(9600);
3652#endif
3653
3654#if defined(BUILD_SENSOR_GEOLUX_HYDRO_CAM)
3655 // Start the stream for the camera; it will always be at 115200 baud
3656 cameraSerial.begin(115200);
3657#endif
3658/** End [setup_serial_begins] */
3659
3660// Assign pins SERCOM functionality for SAMD boards
3661// NOTE: This must happen *after* the various serial.begin statements
3662/** Start [setup_samd_pins] */
3663#if defined(ARDUINO_SAMD_FEATHER_M0)
3664 PRINTOUT(F("Setting SAMD21 SERCOM pin peripherals"));
3665 // Serial2
3666 pinPeripheral(10, PIO_SERCOM); // Serial2 Tx/Dout = SERCOM1 Pad #2
3667 pinPeripheral(11, PIO_SERCOM); // Serial2 Rx/Din = SERCOM1 Pad #0
3668 // Serial 3
3669 pinPeripheral(2, PIO_SERCOM); // Serial3 Tx/Dout = SERCOM2 Pad #2
3670 pinPeripheral(5, PIO_SERCOM); // Serial3 Rx/Din = SERCOM2 Pad #3
3671#endif
3672 /** End [setup_samd_pins] */
3673
3674 // Start the SPI library
3675 PRINTOUT(F("Starting SPI"));
3676 SPI.begin();
3677
3678#if defined(EXTERNAL_FLASH_DEVICES)
3679 PRINTOUT(F("Setting onboard flash pin modes"));
3680 pinMode(flashSSPin,
3681 OUTPUT); // for proper operation of the onboard flash memory
3682#endif
3683
3684 PRINTOUT(F("Starting I2C (Wire)"));
3685 Wire.begin();
3686
3687 /** Start [setup_logger] */
3688
3689 // set the logger ID
3690 PRINTOUT(F("Setting logger id to"), LoggerID);
3691 dataLogger.setLoggerID(LoggerID);
3692 PRINTOUT(F("Setting the sampling feature UUID to"), LoggerID);
3693 dataLogger.setSamplingFeatureUUID(samplingFeature);
3694 // set the logging interval
3695 PRINTOUT(F("Setting logging interval to"), loggingInterval, F("minutes"));
3696 dataLogger.setLoggingInterval(loggingInterval);
3697 PRINTOUT(F("Setting number of initial 1 minute intervals to 10"));
3698 dataLogger.setinitialShortIntervals(10);
3699 // Attach the variable array to the logger
3700 PRINTOUT(F("Attaching the variable array"));
3701 dataLogger.setVariableArray(&varArray);
3702 // set logger pins
3703 PRINTOUT(F("Setting logger pins"));
3704 dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,
3705 greenLED, wakePinMode, buttonPinMode);
3706
3707 // Set the timezones for the logger/data and the RTC
3708 // Logging in the given time zone
3709 PRINTOUT(F("Setting logger time zone"));
3710 Logger::setLoggerTimeZone(timeZone);
3711 // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)
3712 PRINTOUT(F("Setting RTC time zone"));
3713 loggerClock::setRTCOffset(0);
3714
3715#if !defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM)
3716 // Attach the modem and information pins to the logger
3717 PRINTOUT(F("Attaching the modem"));
3718 dataLogger.attachModem(modem);
3719 PRINTOUT(F("Setting modem LEDs"));
3720 modem.setModemLED(modemLEDPin);
3721#endif
3722
3723#if defined(BUILD_PUB_THING_SPEAK_PUBLISHER) && \
3724 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3725 // Set the ThingSpeak MQTT client name
3726 TsMqtt.setRESTAPIKey(thingSpeakAPIKey);
3727#endif
3728
3729#if defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER)
3730 // Set the S3 host and certificate authority name
3731 s3pub.setHost(s3Host);
3732 s3pub.setCACertName(caCertName);
3733 // Attach to the logger
3734 s3pub.attachToLogger(dataLogger);
3735#endif
3736
3737#if defined(BUILD_PUB_AWS_IO_T_PUBLISHER) && \
3738 defined(BUILD_PUB_S3_PRESIGNED_PUBLISHER) && \
3739 (!defined(BUILD_MODEM_NO_MODEM) && defined(BUILD_HAS_MODEM))
3740 // Set the callback function for the AWS IoT Core MQTT connection
3741 awsIoTPub.setCallback(IoTCallback);
3742 awsIoTPub.addSubTopic(s3URLSubTopic.c_str());
3743 awsIoTPub.addPublishRequest(s3URLPubTopic.c_str(), s3URLMsgGetter);
3744#endif
3745
3746 // Begin the logger
3747 PRINTOUT(F("Beginning the logger"));
3748 dataLogger.begin();
3749 /** End [setup_logger] */
3750
3751 /** Start [setup_sensors] */
3752 // Note: Please change these battery voltages to match your battery
3753 // Set up the sensors, except at lowest battery level
3754 if (getBatteryVoltage() > 3.4) {
3755 PRINTOUT(F("Setting up sensors..."));
3756 varArray.sensorsPowerUp(); // only needed if you have sensors that need
3757 // power for setups
3758 varArray.setupSensors();
3759 varArray.sensorsPowerDown(); // only needed if you have sensors that
3760 // need power for setups
3761 }
3762 /** End [setup_sensors] */
3763
3764#if (defined BUILD_MODEM_ESPRESSIF_ESP8266 || \
3765 defined BUILD_MODEM_ESPRESSIF_ESP32)
3766 /** Start [setup_esp] */
3767 PRINTOUT(F("Waking the modem.."));
3768 PRINTOUT(F("Attempting to begin modem communication at"), modemBaud,
3769 F("baud. This will fail if the baud is mismatched.."));
3770 modemSerial.begin(modemBaud);
3771 modem.modemWake(); // NOTE: This will also set up the modem
3772 // WARNING: PLEASE REMOVE AUTOBAUDING FOR PRODUCTION CODE!
3773 if (!modem.gsmModem.testAT()) {
3774 PRINTOUT(F("Attempting autobauding.."));
3775 uint32_t foundBaud = TinyGsmAutoBaud(modemSerial);
3776 if (foundBaud != 0 || (modemBaud > 57600 && F_CPU == 8000000L)) {
3777 PRINTOUT(F("Got modem response at baud of"), foundBaud,
3778 F("Firing an attempt to change the baud rate to"),
3779 modemBaud);
3780 modem.gsmModem.sendAT(GF("+UART_DEF="), modemBaud, F(",8,1,0,0"));
3781 modem.gsmModem.waitResponse();
3782 modemSerial.end();
3783 modemSerial.begin(modemBaud);
3784 }
3785 }
3786/** End [setup_esp] */
3787#endif
3788
3789#if defined(BUILD_TEST_SKYWIRE)
3790 /** Start [setup_skywire] */
3791 modem.setModemStatusLevel(LOW); // If using CTS, LOW
3792 modem.setModemWakeLevel(HIGH); // Skywire dev board inverts the signal
3793 modem.setModemResetLevel(HIGH); // Skywire dev board inverts the signal
3794 /** End [setup_skywire] */
3795#endif
3796
3797#if defined(BUILD_MODEM_SIM_COM_SIM7080)
3798 /** Start [setup_sim7080] */
3799 modem.setModemWakeLevel(HIGH); // ModuleFun Bee inverts the signal
3800 modem.setModemResetLevel(HIGH); // ModuleFun Bee inverts the signal
3801 PRINTOUT(F("Waking modem and setting Cellular Carrier Options..."));
3802 modem.modemWake(); // NOTE: This will also set up the modem
3803 // WARNING: PLEASE REMOVE AUTOBAUDING FOR PRODUCTION CODE!
3804 if (!modem.gsmModem.testAT()) {
3805 PRINTOUT(F("Attempting autobauding.."));
3806 uint32_t foundBaud = TinyGsmAutoBaud(modemSerial);
3807 if (foundBaud != 0 && !(F_CPU <= 8000000L && foundBaud >= 115200) &&
3808 !(F_CPU <= 16000000L && foundBaud > 115200)) {
3809 PRINTOUT(F("Got modem response at baud of"), foundBaud,
3810 F("Firing an attempt to change the baud rate to"),
3811 modemBaud);
3812 modem.gsmModem.setBaud(
3813 modemBaud); // Make sure we're *NOT* auto-bauding!
3814 modem.gsmModem.waitResponse();
3815 modemSerial.end();
3816 modemSerial.begin(modemBaud);
3817 }
3818 }
3819 modem.gsmModem.setBaud(modemBaud); // Make sure we're *NOT* auto-bauding!
3820 modem.gsmModem.setNetworkMode(38); // set to LTE only
3821 // 2 Automatic
3822 // 13 GSM only
3823 // 38 LTE only
3824 // 51 GSM and LTE only
3825 modem.gsmModem.setPreferredMode(1); // set to CAT-M
3826 // 1 CAT-M
3827 // 2 NB-IoT
3828 // 3 CAT-M and NB-IoT
3829 /** End [setup_sim7080] */
3830#endif
3831
3832#if defined(BUILD_MODEM_DIGI_XBEE_CELLULAR_TRANSPARENT)
3833 /** Start [setup_xbeec_carrier] */
3834 // Extra modem set-up
3835 PRINTOUT(F("Waking modem and setting Cellular Carrier Options..."));
3836 modem.modemWake(); // NOTE: This will also set up the modem
3837 // Go back to command mode to set carrier options
3838 modem.gsmModem.commandMode();
3839 // Carrier Profile - 0 = Automatic selection
3840 // - 1 = No profile/SIM ICCID selected
3841 // - 2 = AT&T
3842 // - 3 = Verizon
3843 // NOTE: To select T-Mobile, you must enter bypass mode!
3844 modem.gsmModem.sendAT(GF("CP"), 2);
3845 modem.gsmModem.waitResponse();
3846 // Cellular network technology - 0 = LTE-M with NB-IoT fallback
3847 // - 1 = NB-IoT with LTE-M fallback
3848 // - 2 = LTE-M only
3849 // - 3 = NB-IoT only
3850 // NOTE: As of 2020 in the USA, AT&T and Verizon only use LTE-M
3851 // T-Mobile uses NB-IOT
3852 modem.gsmModem.sendAT(GF("N#"), 2);
3853 modem.gsmModem.waitResponse();
3854 // Write changes to flash and apply them
3855 PRINTOUT(F("Wait while applying changes..."));
3856 // Write changes to flash
3857 modem.gsmModem.writeChanges();
3858 // Reset the cellular component to ensure network settings are changed
3859 modem.gsmModem.sendAT(GF("!R"));
3860 modem.gsmModem.waitResponse(30000L);
3861 // Force reset of the Digi component as well
3862 // This effectively exits command mode
3863 modem.gsmModem.sendAT(GF("FR"));
3864 modem.gsmModem.waitResponse(5000L);
3865/** End [setup_xbeec_carrier] */
3866#endif
3867
3868#if defined(BUILD_MODEM_DIGI_XBEE_LTE_BYPASS)
3869 /** Start [setup_r4_carrier] */
3870 // Extra modem set-up
3871 PRINTOUT(F("Waking modem and setting Cellular Carrier Options..."));
3872 modem.modemWake(); // NOTE: This will also set up the modem
3873 // Turn off the cellular radio while making network changes
3874 modem.gsmModem.sendAT(GF("+CFUN=0"));
3875 modem.gsmModem.waitResponse();
3876 // Mobile Network Operator Profile - 0 = SW default
3877 // - 1 = SIM ICCID selected
3878 // - 2: ATT
3879 // - 6: China Telecom
3880 // - 100: Standard Europe
3881 // - 4: Telstra
3882 // - 5: T-Mobile US
3883 // - 19: Vodafone
3884 // - 3: Verizon
3885 // - 31: Deutsche Telekom
3886 modem.gsmModem.sendAT(GF("+UMNOPROF="), 2);
3887 modem.gsmModem.waitResponse();
3888 // Selected network technology - 7: LTE Cat.M1
3889 // - 8: LTE Cat.NB1
3890 // Fallback network technology - 7: LTE Cat.M1
3891 // - 8: LTE Cat.NB1
3892 // NOTE: As of 2020 in the USA, AT&T and Verizon only use LTE-M
3893 // T-Mobile uses NB-IOT
3894 modem.gsmModem.sendAT(GF("+URAT="), 7, ',', 8);
3895 modem.gsmModem.waitResponse();
3896 // Restart the module to apply changes
3897 modem.gsmModem.sendAT(GF("+CFUN=1,1"));
3898 modem.gsmModem.waitResponse(10000L);
3899/** End [setup_r4_carrier] */
3900#endif
3901
3902 /** Start [setup_clock] */
3903 // Sync the clock if it isn't valid or we have battery to spare
3904 if (getBatteryVoltage() > 3.55 || !loggerClock::isRTCSane()) {
3905 // Set up the modem, synchronize the RTC with NIST, and publish
3906 // configuration information to publishers that support it.
3907 dataLogger.makeInitialConnections();
3908 }
3909 /** End [setup_clock] */
3910
3911 /** Start [setup_file] */
3912 // Create the log file, adding the default header to it
3913 // Do this last so we have the best chance of getting the time correct and
3914 // all sensor names correct.
3915 // Writing to the SD card can be power intensive, so if we're skipping the
3916 // sensor setup we'll skip this too.
3917 if (getBatteryVoltage() > 3.4) {
3918 PRINTOUT(F("Setting up file on SD card"));
3919 dataLogger.turnOnSDcard(true);
3920 // true = wait for card to settle after power up
3921 dataLogger.createLogFile(true); // true = write a new header
3922 dataLogger.turnOffSDcard(true);
3923 // true = wait for internal housekeeping after write
3924 }
3925 /** End [setup_file] */
3926
3927 /** Start [setup_sleep] */
3928 // Call the processor sleep
3929 PRINTOUT(F("Putting processor to sleep\n"));
3930 dataLogger.systemSleep();
3931 /** End [setup_sleep] */
3932}
3933
3934
3935// ==========================================================================
3936// Arduino Loop Function
3937// ==========================================================================
3938#ifndef BUILD_TEST_COMPLEX_LOOP
3939// Use this short loop for simple data logging and sending
3940/** Start [simple_loop] */
3941void loop() {
3942 // Note: Please change these battery voltages to match your battery
3943 // At very low battery, just go back to sleep
3944 if (getBatteryVoltage() < 3.4) {
3945 PRINTOUT(F("Battery too low, ("),
3946 mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM],
3947 F("V) going back to sleep."));
3948 dataLogger.systemSleep();
3949 } else if (getBatteryVoltage() < 3.55) {
3950 // At moderate voltage, log data but don't send it over the modem
3951 PRINTOUT(F("Battery at"),
3952 mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM],
3953 F("V; high enough to log, but will not publish!"));
3954 dataLogger.logData();
3955 } else {
3956 // If the battery is good, send the data to the world
3957 PRINTOUT(F("Battery at"),
3958 mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM],
3959 F("V; high enough to log and publish data"));
3960 dataLogger.logDataAndPublish();
3961 }
3962}
3963
3964/** End [simple_loop] */
3965
3966#else
3967/** Start [complex_loop] */
3968// Use this long loop when you want to do something special
3969// Because of the way alarms work on the RTC, it will wake the processor and
3970// start the loop every minute exactly on the minute.
3971// The processor may also be woken up by another interrupt or level change on a
3972// pin - from a button or some other input.
3973// The "if" statements in the loop determine what will happen - whether the
3974// sensors update, testing mode starts, or it goes back to sleep.
3975void loop() {
3976 // Reset the watchdog
3977 extendedWatchDog::resetWatchDog();
3978
3979 // Assuming we were woken up by the clock, check if the current time is an
3980 // even interval of the logging interval
3981 // We're only doing anything at all if the battery is above 3.4V
3982 if (dataLogger.checkInterval() && getBatteryVoltage() > 3.4) {
3983 // Flag to notify that we're in already awake and logging a point
3984 Logger::isLoggingNow = true;
3985 extendedWatchDog::resetWatchDog();
3986
3987 // Print a line to show new reading
3988 PRINTOUT(F("------------------------------------------"));
3989 // Turn on the LED to show we're taking a reading
3990 dataLogger.alertOn();
3991 // Power up the SD Card, but skip any waits after power up
3992 dataLogger.turnOnSDcard(false);
3993 extendedWatchDog::resetWatchDog();
3994
3995 // Turn on the modem to let it start searching for the network
3996 // Only turn the modem on if the battery at the last interval was high
3997 // enough
3998 // NOTE: if the modemPowerUp function is not run before the
3999 // completeUpdate
4000 // function is run, the modem will not be powered and will not
4001 // return a signal strength reading.
4002 if (getBatteryVoltage() > 3.55) modem.modemPowerUp();
4003
4004#if defined(BUILD_TEST_ALTSOFTSERIAL)
4005 // Start the stream for the modbus sensors, if your RS485 adapter bleeds
4006 // current from data pins when powered off & you stop modbus serial
4007 // connection with digitalWrite(5, LOW), below.
4008 // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833
4009 altSoftSerial.begin(9600);
4010#endif
4011
4012 // Do a complete update on the variable array.
4013 // This this includes powering all of the sensors, getting updated
4014 // values, and turing them back off.
4015 // NOTE: The wake function for each sensor should force sensor setup
4016 // to run if the sensor was not previously set up.
4017 varArray.completeUpdate();
4018
4019 extendedWatchDog::resetWatchDog();
4020
4021#if defined(BUILD_TEST_ALTSOFTSERIAL)
4022 // Reset modbus serial pins to LOW, if your RS485 adapter bleeds power
4023 // on sleep, because Modbus Stop bit leaves these pins HIGH.
4024 // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833
4025 digitalWrite(5, LOW); // Reset AltSoftSerial Tx pin to LOW
4026 digitalWrite(6, LOW); // Reset AltSoftSerial Rx pin to LOW
4027#endif
4028
4029 // Create a csv data record and save it to the log file
4030 dataLogger.logToSD();
4031 extendedWatchDog::resetWatchDog();
4032
4033 // Connect to the network
4034 // Again, we're only doing this if the battery is doing well
4035 if (getBatteryVoltage() > 3.55) {
4036 extendedWatchDog::resetWatchDog();
4037 if (modem.connectInternet()) {
4038 extendedWatchDog::resetWatchDog();
4039 // Publish data to remotes
4040 PRINTOUT(F("Modem connected to internet."));
4041 dataLogger.publishDataToRemotes();
4042
4043 // Sync the clock at noon
4044 extendedWatchDog::resetWatchDog();
4045 if ((Logger::markedLocalUnixTime != 0 &&
4046 Logger::markedLocalUnixTime % 86400 == 43200) ||
4047 !loggerClock::isRTCSane()) {
4048 PRINTOUT(F("Running a daily clock sync..."));
4049 loggerClock::setRTClock(modem.getNISTTime(), 0,
4050 epochStart::unix_epoch);
4051 extendedWatchDog::resetWatchDog();
4052 modem.updateModemMetadata();
4053 extendedWatchDog::resetWatchDog();
4054 }
4055
4056 // Disconnect from the network
4057 modem.disconnectInternet();
4058 extendedWatchDog::resetWatchDog();
4059 }
4060 // Turn the modem off
4061 modem.modemSleepPowerDown();
4062 extendedWatchDog::resetWatchDog();
4063 }
4064
4065 // Cut power from the SD card - without additional housekeeping wait
4066 dataLogger.turnOffSDcard(false);
4067 extendedWatchDog::resetWatchDog();
4068 // Turn off the LED
4069 dataLogger.alertOff();
4070 // Print a line to show reading ended
4071 PRINTOUT(F("------------------------------------------\n"));
4072
4073 // Unset flag
4074 Logger::isLoggingNow = false;
4075 }
4076
4077 // Check if it was instead the testing interrupt that woke us up
4078 if (Logger::startTesting) {
4079#if defined(BUILD_TEST_ALTSOFTSERIAL)
4080 // Start the stream for the modbus sensors, if your RS485 adapter bleeds
4081 // current from data pins when powered off & you stop modbus serial
4082 // connection with digitalWrite(5, LOW), below.
4083 // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833
4084 altSoftSerial.begin(9600);
4085#endif
4086
4087 dataLogger.benchTestingMode();
4088 }
4089
4090#if defined(BUILD_TEST_ALTSOFTSERIAL)
4091 // Reset modbus serial pins to LOW, if your RS485 adapter bleeds power
4092 // on sleep, because Modbus Stop bit leaves these pins HIGH.
4093 // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833
4094 digitalWrite(5, LOW); // Reset AltSoftSerial Tx pin to LOW
4095 digitalWrite(6, LOW); // Reset AltSoftSerial Rx pin to LOW
4096#endif
4097
4098 // Call the processor sleep
4099 dataLogger.systemSleep();
4100}
4101#endif
4102/** End [complex_loop] */
4103
4104
4105// cspell: ignore EDBG XBCT XBLTEB XBWF SVZM BatterymV Atlasp oversample
4106// cspell: ignore asco2voltage atlasGrav Hayashi emas PMID temperatureCoef
4107// cspell: ignore ClariVUESDI12address RainVUESDI12address Turb CTDSDI
4108// cspell: ignore RDOSDI TROLLSDI acculev nanolev TMSDI ELEC fivetm tallyi
4109// cspell: ignore kmph TIINA Chloro Fluoroscein PTSA BTEX ECpwrPin anlg spcond
4110// cspell: ignore Relia NEOPIXEL RESTAPI autobauding xbeec
4111// cspell: ignore CFUN UMNOPROF URAT PHEC