menu_a_la_carte.ino example
Example with all possible functionality. See the walkthrough page for detailed instructions.
Example with all possible functionality. See the walkthrough page for detailed instructions.
/** ========================================================================= * @file menu_a_la_carte.ino * @brief Example with all possible functionality. * * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org> * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) * and the EnviroDIY Development Team * This example is published under the BSD-3 license. * * Build Environment: Visual Studios Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: * THIS CODE IS PROVIDED "AS IS" - NO WARRANTY IS GIVEN. * ======================================================================= */ // ========================================================================== // Defines for TinyGSM // ========================================================================== /** Start [defines] */ #ifndef TINY_GSM_RX_BUFFER #define TINY_GSM_RX_BUFFER 64 #endif #ifndef TINY_GSM_YIELD_MS #define TINY_GSM_YIELD_MS 2 #endif #ifndef MQTT_MAX_PACKET_SIZE #define MQTT_MAX_PACKET_SIZE 240 #endif /** End [defines] */ // ========================================================================== // Include the libraries required for any data logger // ========================================================================== /** Start [includes] */ // The Arduino library is needed for every Arduino program. #include <Arduino.h> // EnableInterrupt is used by ModularSensors for external and pin change // interrupts and must be explicitly included in the main program. #include <EnableInterrupt.h> // Include the main header for ModularSensors #include <ModularSensors.h> /** End [includes] */ // ========================================================================== // Creating Additional Serial Ports // ========================================================================== // The modem and a number of sensors communicate over UART/TTL - often called // "serial". "Hardware" serial ports (automatically controlled by the MCU) are // generally the most accurate and should be configured and used for as many // peripherals as possible. In some cases (ie, modbus communication) many // sensors can share the same serial port. #if defined(ARDUINO_ARCH_AVR) || defined(__AVR__) // For AVR boards // Unfortunately, most AVR boards have only one or two hardware serial ports, // so we'll set up three types of extra software serial ports to use #ifdef BUILD_TEST_ALTSOFTSERIAL // AltSoftSerial by Paul Stoffregen // (https://github.com/PaulStoffregen/AltSoftSerial) is the most accurate // software serial port for AVR boards. AltSoftSerial can only be used on one // set of pins on each board so only one AltSoftSerial port can be used. Not all // AVR boards are supported by AltSoftSerial. /** Start [altsoftserial] */ #include <AltSoftSerial.h> AltSoftSerial altSoftSerial; /** End [altsoftserial] */ #endif // #ifdef BUILD_TEST_ALTSOFTSERIAL #ifdef BUILD_TEST_NEOSWSERIAL // NeoSWSerial (https://github.com/SRGDamia1/NeoSWSerial) is the best software // serial that can be used on any pin supporting interrupts. // You can use as many instances of NeoSWSerial as you need. // Not all AVR boards are supported by NeoSWSerial. /** Start [neoswserial] */ #include <NeoSWSerial.h> // for the stream communication const int8_t neoSSerial1Rx = 11; // data in pin const int8_t neoSSerial1Tx = -1; // data out pin NeoSWSerial neoSSerial1(neoSSerial1Rx, neoSSerial1Tx); // To use NeoSWSerial in this library, we define a function to receive data // This is just a short-cut for later void neoSSerial1ISR() { NeoSWSerial::rxISR(*portInputRegister(digitalPinToPort(neoSSerial1Rx))); } /** End [neoswserial] */ #endif // #ifdef BUILD_TEST_NEOSWSERIAL #ifdef BUILD_TEST_SOFTSERIAL // The "standard" software serial library uses interrupts that conflict // with several other libraries used within this program. I've created a // [version of software serial that has been stripped of // interrupts](https://github.com/EnviroDIY/SoftwareSerial_ExtInts) but it is // still far from ideal. // NOTE: Only use if necessary. This is not a very accurate serial port! // You can use as many instances of SoftwareSerial as you need. /** Start [softwareserial] */ const int8_t softSerialRx = A3; // data in pin const int8_t softSerialTx = A4; // data out pin #include <SoftwareSerial_ExtInts.h> // for the stream communication SoftwareSerial_ExtInts softSerial1(softSerialRx, softSerialTx); /** End [softwareserial] */ #endif // #ifdef BUILD_TEST_SOFTSERIAL #if defined(MS_PALEOTERRA_SOFTWAREWIRE) || defined(MS_RAIN_SOFTWAREWIRE) /** Start [softwarewire] */ // A software I2C (Wire) instance using Testato's SoftwareWire // To use SoftwareWire, you must also set a define for the sensor you want to // use Software I2C for, ie: // `#define MS_RAIN_SOFTWAREWIRE` // `#define MS_PALEOTERRA_SOFTWAREWIRE` // or set the build flag(s): // `-D MS_RAIN_SOFTWAREWIRE` // `-D MS_PALEOTERRA_SOFTWAREWIRE` #include <SoftwareWire.h> // Testato's Software I2C const int8_t softwareSDA = 5; const int8_t softwareSCL = 4; SoftwareWire softI2C(softwareSDA, softwareSCL); /** End [softwarewire] */ #endif // #if defined MS_PALEOTERRA_SOFTWAREWIRE ... #endif // End software serial for avr boards #if defined ARDUINO_ARCH_SAMD /** Start [serial_ports_SAMD] */ // The SAMD21 has 6 "SERCOM" ports, any of which can be used for UART // communication. The "core" code for most boards defines one or more UART // (Serial) ports with the SERCOMs and uses others for I2C and SPI. We can // create new UART ports on any available SERCOM. The table below shows // definitions for select boards. // Board => Arduino Zero Adafruit Feather Sodaq Boards // ------- --------------- ---------------- ---------------- // SERCOM0 Serial1 (D0/D1) Serial1 (D0/D1) Serial (D0/D1) // SERCOM1 Available Available Serial3 (D12/D13) // SERCOM2 Available Available I2C (A4/A5) // SERCOM3 I2C (D20/D21) I2C (D20/D21) SPI (D11/12/13) // SERCOM4 SPI (D21/22/23) SPI (D21/22/23) SPI1/Serial2 // SERCOM5 EDBG/Serial Available Serial1 // If using a Sodaq board, do not define the new sercoms, instead: // #define ENABLE_SERIAL2 // #define ENABLE_SERIAL3 #include <wiring_private.h> // Needed for SAMD pinPeripheral() function #ifndef ENABLE_SERIAL2 // Set up a 'new' UART using SERCOM1 // The Rx will be on digital pin 11, which is SERCOM1's Pad #0 // The Tx will be on digital pin 10, which is SERCOM1's Pad #2 // NOTE: SERCOM1 is undefinied on a "standard" Arduino Zero and many clones, // but not all! Please check the variant.cpp file for you individual // board! Sodaq Autonomo's and Sodaq One's do NOT follow the 'standard' // SERCOM definitions! Uart Serial2(&sercom1, 11, 10, SERCOM_RX_PAD_0, UART_TX_PAD_2); // Hand over the interrupts to the sercom port void SERCOM1_Handler() { Serial2.IrqHandler(); } #endif #ifndef ENABLE_SERIAL3 // Set up a 'new' UART using SERCOM2 // The Rx will be on digital pin 5, which is SERCOM2's Pad #3 // The Tx will be on digital pin 2, which is SERCOM2's Pad #2 // NOTE: SERCOM2 is undefinied on a "standard" Arduino Zero and many clones, // but not all! Please check the variant.cpp file for you individual // board! Sodaq Autonomo's and Sodaq One's do NOT follow the 'standard' // SERCOM definitions! Uart Serial3(&sercom2, 5, 2, SERCOM_RX_PAD_3, UART_TX_PAD_2); // Hand over the interrupts to the sercom port void SERCOM2_Handler() { Serial3.IrqHandler(); } #endif /** End [serial_ports_SAMD] */ #endif // End hardware serial on SAMD21 boards // ========================================================================== // Assigning Serial Port Functionality // ========================================================================== #if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAMD_ZERO) || \ defined(ATMEGA2560) || defined(ARDUINO_AVR_MEGA2560) /** Start [assign_ports_hw] */ // If there are additional hardware Serial ports possible - use them! // We give the modem first priority and assign it to hardware serial // All of the supported processors have a hardware port available named Serial1 #define modemSerial Serial1 // Define the serial port for modbus // Modbus (at 9600 8N1) is used by the Keller level loggers and Yosemitech // sensors #define modbusSerial Serial2 // The Maxbotix sonar is the only sensor that communicates over a serial port // but does not use modbus #define sonarSerial Serial3 /** End [assign_ports_hw] */ #else /** Start [assign_ports_sw] */ // We give the modem first priority and assign it to hardware serial // All of the supported processors have a hardware port available named Serial1 #define modemSerial Serial1 // Define the serial port for modbus // Modbus (at 9600 8N1) is used by the Keller level loggers and Yosemitech // sensors // Since AltSoftSerial is the best software option, we use it for modbus // If AltSoftSerial (or its pins) aren't avaiable, use NeoSWSerial // SoftwareSerial **WILL NOT** work for modbus! #ifdef BUILD_TEST_ALTSOFTSERIAL #define modbusSerial altSoftSerial // For AltSoftSerial #elif defined BUILD_TEST_NEOSWSERIAL #define modbusSerial neoSSerial1 // For Neo software serial #elif defined BUILD_TEST_SOFTSERIAL #define modbusSerial softSerial1 // For software serial #else #define modbusSerial Serial1 // Hardware serial #endif // The Maxbotix sonar is the only sensor that communicates over a serial port // but does not use modbus // Since the Maxbotix only needs one-way communication and sends a simple text // string repeatedly, almost any software serial port will do for it. #ifdef BUILD_TEST_ALTSOFTSERIAL #define sonarSerial altSoftSerial // For AltSoftSerial #elif defined BUILD_TEST_NEOSWSERIAL #define sonarSerial neoSSerial1 // For Neo software serial #elif defined BUILD_TEST_SOFTSERIAL #define sonarSerial softSerial1 // For software serial #else #define sonarSerial Serial1 // Hardware serial #endif /** End [assign_ports_sw] */ #endif // ========================================================================== // Data Logging Options // ========================================================================== /** Start [logging_options] */ // The name of this program file const char* sketchName = "menu_a_la_carte.ino"; // Logger ID, also becomes the prefix for the name of the data file on SD card const char* LoggerID = "XXXXX"; // How frequently (in minutes) to log data const uint8_t loggingInterval = 15; // Your logger's timezone. const int8_t timeZone = -5; // Eastern Standard Time // NOTE: Daylight savings time will not be applied! Please use standard time! // Set the input and output pins for the logger // NOTE: Use -1 for pins that do not apply const int32_t serialBaud = 115200; // Baud rate for debugging const int8_t greenLED = 8; // Pin for the green LED const int8_t redLED = 9; // Pin for the red LED const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin) const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep // Mayfly 0.x D31 = A7 // Set the wake pin to -1 if you do not want the main processor to sleep. // In a SAMD system where you are using the built-in rtc, set wakePin to 1 const int8_t sdCardPwrPin = -1; // MCU SD card power pin const int8_t sdCardSSPin = 12; // SD card chip select/slave select pin const int8_t sensorPowerPin = 22; // MCU pin controlling main sensor power /** End [logging_options] */ // ========================================================================== // Wifi/Cellular Modem Options // NOTE: DON'T USE MORE THAN ONE MODEM OBJECT! // Delete the sections you are not using! // ========================================================================== #if defined BUILD_MODEM_DIGI_XBEE_CELLULAR_TRANSPARENT /** Start [digi_xbee_cellular_transparent] */ // For any Digi Cellular XBee's // NOTE: The u-blox based Digi XBee's (3G global and LTE-M global) can be used // in either bypass or transparent mode, each with pros and cons // The Telit based Digi XBees (LTE Cat1) can only use this mode. #include <modems/DigiXBeeCellularTransparent.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // All XBee's use 9600 by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // The pin numbers here are for a Digi XBee with a Mayfly 0.x and LTE adapter // For options https://github.com/EnviroDIY/LTEbee-Adapter/edit/master/README.md const int8_t modemVccPin = -1; // MCU pin controlling modem power // Option: modemVccPin = A5, if Mayfly SJ7 is // connected to the ASSOC pin const int8_t modemStatusPin = 19; // MCU pin used to read modem status // NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but // the CTS pin can also be used if necessary const bool useCTSforStatus = false; // Flag to use the CTS pin for status const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object DigiXBeeCellularTransparent modemXBCT(&modemSerial, modemVccPin, modemStatusPin, useCTSforStatus, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name DigiXBeeCellularTransparent modem = modemXBCT; /** End [digi_xbee_cellular_transparent] */ // ========================================================================== #elif defined BUILD_MODEM_DIGI_XBEE_LTE_BYPASS /** Start [digi_xbee_lte_bypass] */ // For the u-blox SARA R410M based Digi LTE-M XBee3 // NOTE: According to the manual, this should be less stable than transparent // mode, but my experience is the complete reverse. #include <modems/DigiXBeeLTEBypass.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // All XBee's use 9600 by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // The pin numbers here are for a Digi XBee with a Mayfly 0.x and LTE adapter const int8_t modemVccPin = A5; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status // NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but // the CTS pin can also be used if necessary const bool useCTSforStatus = false; // Flag to use the CTS pin for status const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object DigiXBeeLTEBypass modemXBLTEB(&modemSerial, modemVccPin, modemStatusPin, useCTSforStatus, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name DigiXBeeLTEBypass modem = modemXBLTEB; /** End [digi_xbee_lte_bypass] */ // ========================================================================== #elif defined BUILD_MODEM_DIGI_XBEE_3G_BYPASS /** Start [digi_xbee_3g_bypass] */ // For the u-blox SARA U201 based Digi 3G XBee with 2G fallback // NOTE: According to the manual, this should be less stable than transparent // mode, but my experience is the complete reverse. #include <modems/DigiXBee3GBypass.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // All XBee's use 9600 by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // The pin numbers here are for a Digi XBee with a Mayfly and LTE adapter const int8_t modemVccPin = A5; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status // NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but // the CTS pin can also be used if necessary const bool useCTSforStatus = false; // Flag to use the CTS pin for status const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object DigiXBee3GBypass modemXB3GB(&modemSerial, modemVccPin, modemStatusPin, useCTSforStatus, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name DigiXBee3GBypass modem = modemXB3GB; /** End [digi_xbee_3g_bypass] */ // ========================================================================== #elif defined BUILD_MODEM_DIGI_XBEE_WIFI /** Start [digi_xbee_wifi] */ // For the Digi Wifi XBee (S6B) #include <modems/DigiXBeeWifi.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // All XBee's use 9600 by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // The pin numbers here are for a Digi XBee direcly connected to a Mayfly 1.x const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status // NOTE: If possible, use the `STATUS/SLEEP_not` (XBee pin 13) for status, but // the CTS pin can also be used if necessary const bool useCTSforStatus = true; // Flag to use the CTS pin for status const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* wifiId = "xxxxx"; // WiFi access point name const char* wifiPwd = "xxxxx"; // WiFi password (WPA2) // Create the modem object DigiXBeeWifi modemXBWF(&modemSerial, modemVccPin, modemStatusPin, useCTSforStatus, modemResetPin, modemSleepRqPin, wifiId, wifiPwd); // Create an extra reference to the modem by a generic name DigiXBeeWifi modem = modemXBWF; /** End [digi_xbee_wifi] */ // ========================================================================== #elif defined BUILD_MODEM_ESPRESSIF_ESP8266 || \ defined BUILD_MODEM_ESPRESSIF_ESP32 /** Start [espressif_esp8266] */ // For almost anything based on the Espressif ESP8266 using the // AT command firmware #include <modems/EspressifESP8266.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 115200; // Communication speed of the modem // NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The // module should be programmed to a slower baud rate or set to auto-baud using // the AT+UART_CUR or AT+UART_DEF command. // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins here are for a EnviroDIY ESP32 Bluetooth/Wifi Bee with // Mayfly 1.1 const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* wifiId = "xxxxx"; // WiFi access point name const char* wifiPwd = "xxxxx"; // WiFi password (WPA2) // Create the modem object EspressifESP8266 modemESP(&modemSerial, modemVccPin, modemResetPin, wifiId, wifiPwd); // Create an extra reference to the modem by a generic name EspressifESP8266 modem = modemESP; /** End [espressif_esp8266] */ // ========================================================================== #elif defined BUILD_MODEM_QUECTEL_BG96 /** Start [quectel_bg96] */ // For the Dragino, Nimbelink or other boards based on the Quectel BG96 #include <modems/QuectelBG96.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 115200; // Communication speed of the modem // NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The // module should be programmed to a slower baud rate or set to auto-baud using // the AT+IPR=9600 command. // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins here are for a Mayfly 1.x and a Dragino IoT Bee const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemStatusPin = -1; // MCU pin used to read modem status const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = -1; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object QuectelBG96 modemBG96(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name QuectelBG96 modem = modemBG96; /** End [quectel_bg96] */ // ========================================================================== #elif defined BUILD_MODEM_SEQUANS_MONARCH /** Start [sequans_monarch] */ // For the Nimbelink LTE-M Verizon/Sequans or other boards based on the Sequans // Monarch series #include <modems/SequansMonarch.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 921600; // Default baud rate of SVZM20 is 921600 // NOTE: This baud rate is much too fast for many Arduinos! The module should // be programmed to a slower baud rate or set to auto-baud using the AT+IPR // command. // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Nimbelink Skywire (NOT directly connectable to a Mayfly!) const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = 20; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SequansMonarch modemSVZM(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SequansMonarch modem = modemSVZM; /** End [sequans_monarch] */ // ========================================================================== #elif defined BUILD_MODEM_SIM_COM_SIM800 /** Start [sim_com_sim800] */ // For almost anything based on the SIMCom SIM800 EXCEPT the Sodaq 2GBee R6 and // higher #include <modems/SIMComSIM800.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // SIM800 does auto-bauding by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins are for a Sodaq GPRSBee R4 with a Mayfly 0.x const int8_t modemVccPin = -1; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SIMComSIM800 modemS800(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SIMComSIM800 modem = modemS800; /** End [sim_com_sim800] */ // ========================================================================== #elif defined BUILD_MODEM_SIM_COM_SIM7000 /** Start [sim_com_sim7000] */ // For almost anything based on the SIMCom SIM7000 #include <modems/SIMComSIM7000.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // SIM7000 does auto-bauding by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SIMComSIM7000 modem7000(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SIMComSIM7000 modem = modem7000; /** End [sim_com_sim7000] */ // ========================================================================== #elif defined BUILD_MODEM_SIM_COM_SIM7080 /** Start [sim_com_sim7080] */ // For almost anything based on the SIMCom SIM7080G #include <modems/SIMComSIM7080.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // SIM7080 does auto-bauding by default, but I set mine to 9600 // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // and-global breakout bk-7080a const int8_t modemVccPin = 18; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemSleepRqPin = 23; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SIMComSIM7080 modem7080(&modemSerial, modemVccPin, modemStatusPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SIMComSIM7080 modem = modem7080; /** End [sim_com_sim7080] */ // ========================================================================== #elif defined BUILD_MODEM_SODAQ_2G_BEE_R6 /** Start [sodaq_2g_bee_r6] */ // For the Sodaq 2GBee R6 and R7 based on the SIMCom SIM800 // NOTE: The Sodaq GPRSBee doesn't expose the SIM800's reset pin #include <modems/Sodaq2GBeeR6.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // SIM800 does auto-bauding by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins are for a Sodaq GPRSBee R6 or R7 with a Mayfly 0.x const int8_t modemVccPin = 23; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = -1; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object Sodaq2GBeeR6 modem2GB(&modemSerial, modemVccPin, modemStatusPin, apn); // Create an extra reference to the modem by a generic name Sodaq2GBeeR6 modem = modem2GB; /** End [sodaq_2g_bee_r6] */ // ========================================================================== #elif defined BUILD_MODEM_SODAQ_UBEE_R410M /** Start [sodaq_ubee_r410m] */ // For the Sodaq UBee based on the 4G LTE-M u-blox SARA R410M #include <modems/SodaqUBeeR410M.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 115200; // Default baud rate of the SARA R410M is 115200 // NOTE: The SARA R410N DOES NOT save baud rate to non-volatile memory. After // every power loss, the module will return to the default baud rate of 115200. // NOTE: 115200 is TOO FAST for an 8MHz Arduino. This library attempts to // compensate by sending a baud rate change command in the wake function when // compiled for a 8MHz board. Because of this, 8MHz boards, LIKE THE MAYFLY, // *MUST* use a HardwareSerial instance as modemSerial. // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins are for a Sodaq uBee R410M with a Mayfly 0.x const int8_t modemVccPin = 23; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 20; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SodaqUBeeR410M modemR410(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SodaqUBeeR410M modem = modemR410; /** End [sodaq_ubee_r410m] */ // ========================================================================== #elif defined BUILD_MODEM_SODAQ_UBEE_U201 /** Start [sodaq_ubee_u201] */ // For the Sodaq UBee based on the 3G u-blox SARA U201 #include <modems/SodaqUBeeU201.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section const int32_t modemBaud = 9600; // SARA U2xx module does auto-bauding by default // Modem Pins - Describe the physical pin connection of your modem to your board // NOTE: Use -1 for pins that do not apply // Example pins are for a Sodaq uBee U201 with a Mayfly 0.x const int8_t modemVccPin = 23; // MCU pin controlling modem power const int8_t modemStatusPin = 19; // MCU pin used to read modem status const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin const int8_t modemSleepRqPin = 20; // MCU pin for modem sleep/wake request const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem // status // Network connection information const char* apn = "xxxxx"; // APN for GPRS connection // Create the modem object SodaqUBeeU201 modemU201(&modemSerial, modemVccPin, modemStatusPin, modemResetPin, modemSleepRqPin, apn); // Create an extra reference to the modem by a generic name SodaqUBeeU201 modem = modemU201; /** End [sodaq_ubee_u201] */ // ========================================================================== #endif /** Start [modem_variables] */ // Create RSSI and signal strength variable pointers for the modem Variable* modemRSSI = new Modem_RSSI(&modem, "12345678-abcd-1234-ef00-1234567890ab", "RSSI"); Variable* modemSignalPct = new Modem_SignalPercent( &modem, "12345678-abcd-1234-ef00-1234567890ab", "signalPercent"); Variable* modemBatteryState = new Modem_BatteryState( &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatteryCS"); Variable* modemBatteryPct = new Modem_BatteryPercent( &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatteryPct"); Variable* modemBatteryVoltage = new Modem_BatteryVoltage( &modem, "12345678-abcd-1234-ef00-1234567890ab", "modemBatterymV"); Variable* modemTemperature = new Modem_Temp(&modem, "12345678-abcd-1234-ef00-1234567890ab", "modemTemp"); /** End [modem_variables] */ // ========================================================================== // Using the Processor as a Sensor // ========================================================================== /** Start [processor_stats] */ #include <sensors/ProcessorStats.h> // Create the main processor chip "sensor" - for general metadata const char* mcuBoardVersion = "v1.1"; ProcessorStats mcuBoard(mcuBoardVersion); // Create sample number, battery voltage, and free RAM variable pointers for the // processor Variable* mcuBoardBatt = new ProcessorStats_Battery( &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"); Variable* mcuBoardAvailableRAM = new ProcessorStats_FreeRam( &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"); Variable* mcuBoardSampNo = new ProcessorStats_SampleNumber( &mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"); /** End [processor_stats] */ #if defined(ARDUINO_ARCH_AVR) || defined(MS_SAMD_DS3231) // ========================================================================== // Maxim DS3231 RTC (Real Time Clock) // ========================================================================== /** Start [maxim_ds3231] */ #include <sensors/MaximDS3231.h> // Create a DS3231 sensor object MaximDS3231 ds3231(1); // Create a temperature variable pointer for the DS3231 Variable* ds3231Temp = new MaximDS3231_Temp(&ds3231, "12345678-abcd-1234-ef00-1234567890ab"); /** End [maxim_ds3231] */ #endif #if defined BUILD_SENSOR_AO_SONG_AM2315 // ========================================================================== // AOSong AM2315 Digital Humidity and Temperature Sensor // ========================================================================== /** Start [ao_song_am2315] */ #include <sensors/AOSongAM2315.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AM2315Power = sensorPowerPin; // Power pin // Create an AOSong AM2315 sensor object AOSongAM2315 am2315(AM2315Power); // Create humidity and temperature variable pointers for the AM2315 Variable* am2315Humid = new AOSongAM2315_Humidity(&am2315, "12345678-abcd-1234-ef00-1234567890ab"); Variable* am2315Temp = new AOSongAM2315_Temp(&am2315, "12345678-abcd-1234-ef00-1234567890ab"); /** End [ao_song_am2315] */ #endif #if defined BUILD_SENSOR_AO_SONG_DHT // ========================================================================== // AOSong DHT 11/21 (AM2301)/22 (AM2302) Digital Humidity and Temperature // ========================================================================== /** Start [ao_song_dht] */ #include <sensors/AOSongDHT.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t DHTPower = sensorPowerPin; // Power pin const int8_t DHTPin = 10; // DHT data pin const int8_t dhtType = DHT11; // DHT type, one of DHT11, DHT12, DHT21, DHT22, or AM2301 // Create an AOSong DHT sensor object AOSongDHT dht(DHTPower, DHTPin, dhtType); // Create humidity, temperature, and heat index variable pointers for the DHT Variable* dhtHumid = new AOSongDHT_Humidity(&dht, "12345678-abcd-1234-ef00-1234567890ab"); Variable* dhtTemp = new AOSongDHT_Temp(&dht, "12345678-abcd-1234-ef00-1234567890ab"); Variable* dhtHI = new AOSongDHT_HI(&dht, "12345678-abcd-1234-ef00-1234567890ab"); /** End [ao_song_dht] */ #endif #if defined BUILD_SENSOR_APOGEE_SQ212 // ========================================================================== // Apogee SQ-212 Photosynthetically Active Radiation (PAR) Sensor // ========================================================================== /** Start [apogee_sq212] */ #include <sensors/ApogeeSQ212.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t SQ212Power = sensorPowerPin; // Power pin const int8_t SQ212ADSChannel = 3; // The ADS channel for the SQ212 const uint8_t SQ212ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC // Create an Apogee SQ212 sensor object ApogeeSQ212 SQ212(SQ212Power, SQ212ADSChannel, SQ212ADSi2c_addr); // Create PAR and raw voltage variable pointers for the SQ212 Variable* sq212PAR = new ApogeeSQ212_PAR(&SQ212, "12345678-abcd-1234-ef00-1234567890ab"); Variable* sq212voltage = new ApogeeSQ212_Voltage(&SQ212, "12345678-abcd-1234-ef00-1234567890ab"); /** End [apogee_sq212] */ #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_CO2 // ========================================================================== // Atlas Scientific EZO-CO2 Embedded NDIR Carbon Dioxide Sensor // ========================================================================== /** Start [atlas_scientific_co2] */ #include <sensors/AtlasScientificCO2.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlasCO2Power = sensorPowerPin; // Power pin uint8_t AtlasCO2i2c_addr = 0x69; // Default for CO2-EZO is 0x69 (105) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific CO2 sensor object // AtlasScientificCO2 atlasCO2(AtlasCO2Power, AtlasCO2i2c_addr); AtlasScientificCO2 atlasCO2(AtlasCO2Power); // Create concentration and temperature variable pointers for the EZO-CO2 Variable* atlasCO2CO2 = new AtlasScientificCO2_CO2( &atlasCO2, "12345678-abcd-1234-ef00-1234567890ab"); Variable* atlasCO2Temp = new AtlasScientificCO2_Temp( &atlasCO2, "12345678-abcd-1234-ef00-1234567890ab"); /** End [atlas_scientific_co2] */ #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_DO // ========================================================================== // Atlas Scientific EZO-DO Dissolved Oxygen Sensor // ========================================================================== /** Start [atlas_scientific_do] */ #include <sensors/AtlasScientificDO.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlasDOPower = sensorPowerPin; // Power pin uint8_t AtlasDOi2c_addr = 0x61; // Default for DO is 0x61 (97) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific DO sensor object // AtlasScientificDO atlasDO(AtlasDOPower, AtlasDOi2c_addr); AtlasScientificDO atlasDO(AtlasDOPower); // Create concentration and percent saturation variable pointers for the EZO-DO Variable* atlasDOconc = new AtlasScientificDO_DOmgL( &atlasDO, "12345678-abcd-1234-ef00-1234567890ab"); Variable* atlasDOpct = new AtlasScientificDO_DOpct( &atlasDO, "12345678-abcd-1234-ef00-1234567890ab"); /** End [atlas_scientific_do] */ #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_ORP // ========================================================================== // Atlas Scientific EZO-ORP Oxidation/Reduction Potential Sensor // ========================================================================== /** Start [atlas_scientific_orp] */ #include <sensors/AtlasScientificORP.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlasORPPower = sensorPowerPin; // Power pin uint8_t AtlasORPi2c_addr = 0x62; // Default for ORP is 0x62 (98) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific ORP sensor object // AtlasScientificORP atlasORP(AtlasORPPower, AtlasORPi2c_addr); AtlasScientificORP atlasORP(AtlasORPPower); // Create a potential variable pointer for the ORP Variable* atlasORPot = new AtlasScientificORP_Potential( &atlasORP, "12345678-abcd-1234-ef00-1234567890ab"); /** End [atlas_scientific_orp] */ #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_PH // ========================================================================== // Atlas Scientific EZO-pH Sensor // ========================================================================== /** Start [atlas_scientific_ph] */ #include <sensors/AtlasScientificpH.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlaspHPower = sensorPowerPin; // Power pin uint8_t AtlaspHi2c_addr = 0x63; // Default for pH is 0x63 (99) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific pH sensor object // AtlasScientificpH atlaspH(AtlaspHPower, AtlaspHi2c_addr); AtlasScientificpH atlaspH(AtlaspHPower); // Create a pH variable pointer for the pH sensor Variable* atlaspHpH = new AtlasScientificpH_pH(&atlaspH, "12345678-abcd-1234-ef00-1234567890ab"); /** End [atlas_scientific_ph] */ #endif #if defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_RTD) || \ defined(BUILD_SENSOR_ATLAS_SCIENTIFIC_EC) // ========================================================================== // Atlas Scientific EZO-RTD Temperature Sensor // ========================================================================== /** Start [atlas_scientific_rtd] */ #include <sensors/AtlasScientificRTD.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlasRTDPower = sensorPowerPin; // Power pin uint8_t AtlasRTDi2c_addr = 0x66; // Default for RTD is 0x66 (102) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific RTD sensor object // AtlasScientificRTD atlasRTD(AtlasRTDPower, AtlasRTDi2c_addr); AtlasScientificRTD atlasRTD(AtlasRTDPower); // Create a temperature variable pointer for the RTD Variable* atlasTemp = new AtlasScientificRTD_Temp( &atlasRTD, "12345678-abcd-1234-ef00-1234567890ab"); /** End [atlas_scientific_rtd] */ #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_EC // ========================================================================== // Atlas Scientific EZO-EC Conductivity Sensor // ========================================================================== /** Start [atlas_scientific_ec] */ #include <sensors/AtlasScientificEC.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t AtlasECPower = sensorPowerPin; // Power pin uint8_t AtlasECi2c_addr = 0x64; // Default for EC is 0x64 (100) // All Atlas sensors have different default I2C addresses, but any of them can // be re-addressed to any 8 bit number. If using the default address for any // Atlas Scientific sensor, you may omit this argument. // Create an Atlas Scientific Conductivity sensor object // AtlasScientificEC atlasEC(AtlasECPower, AtlasECi2c_addr); AtlasScientificEC atlasEC(AtlasECPower); // Create four variable pointers for the EZO-ES Variable* atlasCond = new AtlasScientificEC_Cond( &atlasEC, "12345678-abcd-1234-ef00-1234567890ab"); Variable* atlasTDS = new AtlasScientificEC_TDS(&atlasEC, "12345678-abcd-1234-ef00-1234567890ab"); Variable* atlasSal = new AtlasScientificEC_Salinity( &atlasEC, "12345678-abcd-1234-ef00-1234567890ab"); Variable* atlasGrav = new AtlasScientificEC_SpecificGravity( &atlasEC, "12345678-abcd-1234-ef00-1234567890ab"); // Create a calculated variable for the temperature compensated conductivity // (that is, the specific conductance). For this example, we will use the // temperature measured by the Atlas RTD above this. You could use the // temperature returned by any other water temperature sensor if desired. // **DO NOT** use your logger board temperature (ie, from the DS3231) to // calculate specific conductance! float calculateAtlasSpCond(void) { float spCond = -9999; // Always safest to start with a bad value float waterTemp = atlasTemp->getValue(); float rawCond = atlasCond->getValue(); // ^^ Linearized temperature correction coefficient per degrees Celsius. // The value of 0.019 comes from measurements reported here: // Hayashi M. Temperature-electrical conductivity relation of water for // environmental monitoring and geophysical data inversion. Environ Monit // Assess. 2004 Aug-Sep;96(1-3):119-28. // doi: 10.1023/b:emas.0000031719.83065.68. PMID: 15327152. if (waterTemp != -9999 && rawCond != -9999) { // make sure both inputs are good float temperatureCoef = 0.019; spCond = rawCond / (1 + temperatureCoef * (waterTemp - 25.0)); } return spCond; } // Properties of the calculated variable // The number of digits after the decimal place const uint8_t atlasSpCondResolution = 0; // This must be a value from http://vocabulary.odm2.org/variablename/ const char* atlasSpCondName = "specificConductance"; // This must be a value from http://vocabulary.odm2.org/units/ const char* atlasSpCondUnit = "microsiemenPerCentimeter"; // A short code for the variable const char* atlasSpCondCode = "atlasSpCond"; // The (optional) universallly unique identifier const char* atlasSpCondUUID = "12345678-abcd-1234-ef00-1234567890ab"; // Finally, create the specific conductance variable and return a pointer to it Variable* atlasSpCond = new Variable(calculateAtlasSpCond, atlasSpCondResolution, atlasSpCondName, atlasSpCondUnit, atlasSpCondCode, atlasSpCondUUID); /** End [atlas_scientific_ec] */ #endif #if defined BUILD_SENSOR_BOSCH_BME280 // ========================================================================== // Bosch BME280 Environmental Sensor // ========================================================================== /** Start [bosch_bme280] */ #include <sensors/BoschBME280.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t BME280Power = sensorPowerPin; // Power pin uint8_t BMEi2c_addr = 0x76; // The BME280 can be addressed either as 0x77 (Adafruit default) or 0x76 (Grove // default) Either can be physically mofidied for the other address // Create a Bosch BME280 sensor object BoschBME280 bme280(BME280Power, BMEi2c_addr); // Create four variable pointers for the BME280 Variable* bme280Humid = new BoschBME280_Humidity(&bme280, "12345678-abcd-1234-ef00-1234567890ab"); Variable* bme280Temp = new BoschBME280_Temp(&bme280, "12345678-abcd-1234-ef00-1234567890ab"); Variable* bme280Press = new BoschBME280_Pressure(&bme280, "12345678-abcd-1234-ef00-1234567890ab"); Variable* bme280Alt = new BoschBME280_Altitude(&bme280, "12345678-abcd-1234-ef00-1234567890ab"); /** End [bosch_bme280] */ #endif #if defined BUILD_SENSOR_BOSCH_BMP3XX // ========================================================================== // Bosch BMP 3xx Barometric Pressure Sensor // ========================================================================== /** Start [bosch_bmp3xx] */ #include <sensors/BoschBMP3xx.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t bmp3xxPower = -1; // Power pin Mode bmpMode = FORCED_MODE; // The operating mode of the BMP; normal or forced Oversampling bmpPressureOversample = OVERSAMPLING_X32; Oversampling bmpTempOversample = OVERSAMPLING_X2; IIRFilter bmpFilterCoeff = IIR_FILTER_OFF; TimeStandby bmpTimeStandby = TIME_STANDBY_5MS; uint8_t bmpI2C_addr = 0x77; // The BMP3xx can be addressed either as 0x77 or 0x76 // Create a Bosch BMP3xx sensor object BoschBMP3xx bmp3xx(bmp3xxPower, bmpMode, bmpPressureOversample, bmpTempOversample, bmpFilterCoeff, bmpTimeStandby, bmpI2C_addr); // Create the variable pointers for the BMP3xx Variable* bmp3xxTemp = new BoschBMP3xx_Temp(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab"); Variable* bmp3xxPress = new BoschBMP3xx_Pressure(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab"); Variable* bmp3xxAlt = new BoschBMP3xx_Altitude(&bmp3xx, "12345678-abcd-1234-ef00-1234567890ab"); /** End [bosch_bmp3xx] */ #endif #if defined BUILD_SENSOR_CAMPBELL_CLARI_VUE10 // ========================================================================== // Campbell ClariVUE Turbidity Sensor // ========================================================================== /** Start [campbell_clari_vue10] */ #include <sensors/CampbellClariVUE10.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* ClariVUESDI12address = "0"; // The SDI-12 Address of the ClariVUE10 const int8_t ClariVUEPower = sensorPowerPin; // Power pin const int8_t ClariVUEData = 7; // The SDI-12 data pin // NOTE: you should NOT take more than one readings. THe sensor already takes // and averages 8 by default. // Create a Campbell ClariVUE10 sensor object CampbellClariVUE10 clarivue(*ClariVUESDI12address, ClariVUEPower, ClariVUEData); // Create turbidity, temperature, and error variable pointers for the ClariVUE10 Variable* clarivueTurbidity = new CampbellClariVUE10_Turbidity( &clarivue, "12345678-abcd-1234-ef00-1234567890ab"); Variable* clarivueTemp = new CampbellClariVUE10_Temp( &clarivue, "12345678-abcd-1234-ef00-1234567890ab"); Variable* clarivueError = new CampbellClariVUE10_ErrorCode( &clarivue, "12345678-abcd-1234-ef00-1234567890ab"); /** End [campbell_clari_vue10] */ #endif #if defined BUILD_SENSOR_CAMPBELL_OBS3 // ========================================================================== // Campbell OBS 3 / OBS 3+ Analog Turbidity Sensor // ========================================================================== /** Start [campbell_obs3] */ #include <sensors/CampbellOBS3.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t OBS3Power = sensorPowerPin; // Power pin const uint8_t OBS3NumberReadings = 10; const uint8_t OBS3ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC const int8_t OBSLowADSChannel = 0; // ADS channel for *low* range output // Campbell OBS 3+ *Low* Range Calibration in Volts const float OBSLow_A = 0.000E+00; // "A" value (X^2) [*low* range] const float OBSLow_B = 1.000E+00; // "B" value (X) [*low* range] const float OBSLow_C = 0.000E+00; // "C" value [*low* range] // Create a Campbell OBS3+ *low* range sensor object CampbellOBS3 osb3low(OBS3Power, OBSLowADSChannel, OBSLow_A, OBSLow_B, OBSLow_C, OBS3ADSi2c_addr, OBS3NumberReadings); // Create turbidity and voltage variable pointers for the low range of the OBS3 Variable* obs3TurbLow = new CampbellOBS3_Turbidity( &osb3low, "12345678-abcd-1234-ef00-1234567890ab", "TurbLow"); Variable* obs3VoltLow = new CampbellOBS3_Voltage( &osb3low, "12345678-abcd-1234-ef00-1234567890ab", "TurbLowV"); const int8_t OBSHighADSChannel = 1; // ADS channel for *high* range output // Campbell OBS 3+ *High* Range Calibration in Volts const float OBSHigh_A = 0.000E+00; // "A" value (X^2) [*high* range] const float OBSHigh_B = 1.000E+00; // "B" value (X) [*high* range] const float OBSHigh_C = 0.000E+00; // "C" value [*high* range] // Create a Campbell OBS3+ *high* range sensor object CampbellOBS3 osb3high(OBS3Power, OBSHighADSChannel, OBSHigh_A, OBSHigh_B, OBSHigh_C, OBS3ADSi2c_addr, OBS3NumberReadings); // Create turbidity and voltage variable pointers for the high range of the OBS3 Variable* obs3TurbHigh = new CampbellOBS3_Turbidity( &osb3high, "12345678-abcd-1234-ef00-1234567890ab", "TurbHigh"); Variable* obs3VoltHigh = new CampbellOBS3_Voltage( &osb3high, "12345678-abcd-1234-ef00-1234567890ab", "TurbHighV"); /** End [campbell_obs3] */ #endif #if defined BUILD_SENSOR_CAMPBELL_RAIN_VUE10 // ========================================================================== // Campbell RainVUE Precipitation Sensor // ========================================================================== /** Start [campbell_rain_vue10] */ #include <sensors/CampbellRainVUE10.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* RainVUESDI12address = "0"; // The SDI-12 Address of the RainVUE10 const int8_t RainVUEPower = -1; // Power pin, for continous power const int8_t RainVUEData = 5; // The SDI-12 data pin, for continuous power // NOTE: you should NOT take more than one readings. THe sensor counts // cummulative tips and rain accumulation since the last measurement. // Create a Campbell RainVUE10 sensor object CampbellRainVUE10 rainvue(*RainVUESDI12address, RainVUEPower, RainVUEData); // Create turbidity, temperature, and error variable pointers for the RainVUE10 Variable* rainvuePrecipitation = new CampbellRainVUE10_Precipitation( &rainvue, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rainvueTips = new CampbellRainVUE10_Tips( &rainvue, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rainvueRainRateAve = new CampbellRainVUE10_RainRateAve( &rainvue, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rainvueRainRateMax = new CampbellRainVUE10_RainRateMax( &rainvue, "12345678-abcd-1234-ef00-1234567890ab"); /** End [campbell_rain_vue10] */ #endif #if defined BUILD_SENSOR_DECAGON_CTD // ========================================================================== // Decagon CTD-10 Conductivity, Temperature, and Depth Sensor // ========================================================================== /** Start [decagon_ctd] */ #include <sensors/DecagonCTD.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* CTDSDI12address = "1"; // The SDI-12 Address of the CTD const uint8_t CTDNumberReadings = 6; // The number of readings to average const int8_t CTDPower = sensorPowerPin; // Power pin const int8_t CTDData = 7; // The SDI-12 data pin // Create a Decagon CTD sensor object DecagonCTD ctd(*CTDSDI12address, CTDPower, CTDData, CTDNumberReadings); // Create conductivity, temperature, and depth variable pointers for the CTD Variable* ctdCond = new DecagonCTD_Cond(&ctd, "12345678-abcd-1234-ef00-1234567890ab"); Variable* ctdTemp = new DecagonCTD_Temp(&ctd, "12345678-abcd-1234-ef00-1234567890ab"); Variable* ctdDepth = new DecagonCTD_Depth(&ctd, "12345678-abcd-1234-ef00-1234567890ab"); /** End [decagon_ctd] */ #endif #if defined BUILD_SENSOR_DECAGON_ES2 // ========================================================================== // Decagon ES2 Conductivity and Temperature Sensor // ========================================================================== /** Start [decagon_es2] */ #include <sensors/DecagonES2.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* ES2SDI12address = "3"; // The SDI-12 Address of the ES2 const int8_t ES2Power = sensorPowerPin; // Power pin const int8_t ES2Data = 7; // The SDI-12 data pin const uint8_t ES2NumberReadings = 5; // Create a Decagon ES2 sensor object DecagonES2 es2(*ES2SDI12address, ES2Power, ES2Data, ES2NumberReadings); // Create specific conductance and temperature variable pointers for the ES2 Variable* es2Cond = new DecagonES2_Cond(&es2, "12345678-abcd-1234-ef00-1234567890ab"); Variable* es2Temp = new DecagonES2_Temp(&es2, "12345678-abcd-1234-ef00-1234567890ab"); /** End [decagon_es2] */ #endif #if defined BUILD_SENSOR_EVERLIGHT_ALSPT19 // ========================================================================== // Everlight ALS-PT19 Ambient Light Sensor // ========================================================================== /** Start [everlight_alspt19] */ #include <sensors/EverlightALSPT19.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t alsPower = sensorPowerPin; // Power pin const int8_t alsData = A4; // The ALS PT-19 data pin const int8_t alsSupply = 3.3; // The ALS PT-19 supply power voltage const int8_t alsResistance = 10; // The ALS PT-19 loading resistance (in kΩ) const uint8_t alsNumberReadings = 10; // Create a Everlight ALS-PT19 sensor object EverlightALSPT19 alsPt19(alsPower, alsData, alsSupply, alsResistance, alsNumberReadings); // For an EnviroDIY Mayfly, you can use the abbreviated version // EverlightALSPT19 alsPt19(alsNumberReadings); // Create voltage, current, and illuminance variable pointers for the ALS-PT19 Variable* alsPt19Volt = new EverlightALSPT19_Voltage( &alsPt19, "12345678-abcd-1234-ef00-1234567890ab"); Variable* alsPt19Current = new EverlightALSPT19_Current( &alsPt19, "12345678-abcd-1234-ef00-1234567890ab"); Variable* alsPt19Lux = new EverlightALSPT19_Illuminance( &alsPt19, "12345678-abcd-1234-ef00-1234567890ab"); /** End [everlight_alspt19] */ #endif #if defined BUILD_SENSOR_TIADS1X15 // ========================================================================== // External Voltage via TI ADS1115 // ========================================================================== /** Start [tiads1x15] */ #include <sensors/TIADS1x15.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t ADSPower = sensorPowerPin; // Power pin const int8_t ADSChannel = 2; // The ADS channel of interest const float dividerGain = 10; // Gain setting if using a voltage divider const uint8_t evADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC const uint8_t VoltReadsToAvg = 1; // Only read one sample // Create an External Voltage sensor object TIADS1x15 ads1x15(ADSPower, ADSChannel, dividerGain, evADSi2c_addr, VoltReadsToAvg); // Create a voltage variable pointer Variable* ads1x15Volt = new TIADS1x15_Voltage(&ads1x15, "12345678-abcd-1234-ef00-1234567890ab"); /** End [tiads1x15] */ #endif #if defined BUILD_SENSOR_FREESCALE_MPL115A2 // ========================================================================== // Freescale Semiconductor MPL115A2 Barometer // ========================================================================== /** Start [freescale_mpl115a2] */ #include <sensors/FreescaleMPL115A2.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t MPLPower = sensorPowerPin; // Power pin const uint8_t MPL115A2ReadingsToAvg = 1; // Create a FreescaleMPL115A2 barometer sensor object FreescaleMPL115A2 mpl115a2(MPLPower, MPL115A2ReadingsToAvg); // Create pressure and temperature variable pointers for the MPL Variable* mplPress = new FreescaleMPL115A2_Pressure( &mpl115a2, "12345678-abcd-1234-ef00-1234567890ab"); Variable* mplTemp = new FreescaleMPL115A2_Temp( &mpl115a2, "12345678-abcd-1234-ef00-1234567890ab"); /** End [freescale_mpl115a2] */ #endif #if defined BUILD_SENSOR_IN_SITU_RDO // ========================================================================== // In-Situ RDO PRO-X Rugged Dissolved Oxygen Probe // ========================================================================== /** Start [in_situ_rdo] */ #include <sensors/InSituRDO.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* RDOSDI12address = "5"; // The SDI-12 Address of the RDO PRO-X const int8_t RDOPower = sensorPowerPin; // Power pin const int8_t RDOData = 7; // The SDI-12 data pin const uint8_t RDONumberReadings = 3; // Create an In-Situ RDO PRO-X dissolved oxygen sensor object InSituRDO insituRDO(*RDOSDI12address, RDOPower, RDOData, RDONumberReadings); // Create dissolved oxygen percent, dissolved oxygen concentration, temperature, // and oxygen partial pressure variable pointers for the RDO PRO-X Variable* rdoDOpct = new InSituRDO_DOpct(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rdoDOmgL = new InSituRDO_DOmgL(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rdoTemp = new InSituRDO_Temp(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab"); Variable* rdoO2pp = new InSituRDO_Pressure(&insituRDO, "12345678-abcd-1234-ef00-1234567890ab"); /** End [in_situ_rdo] */ #endif #if defined BUILD_SENSOR_IN_SITU_TROLL_SDI12A // ========================================================================== // In-Situ Aqua/Level TROLL Pressure, Temperature, and Depth Sensor // ========================================================================== /** Start [in_situ_troll_sdi12a] */ #include <sensors/InSituTrollSdi12a.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* TROLLSDI12address = "1"; // The SDI-12 Address of the Aqua/Level TROLL const int8_t TROLLPower = sensorPowerPin; // Pin to switch power on and off (-1 if unconnected) const int8_t TROLLData = 7; // The SDI-12 data pin const uint8_t TROLLNumberReadings = 2; // The number of readings to average // Create an In-Situ TROLL sensor object InSituTrollSdi12a insituTROLL(*TROLLSDI12address, TROLLPower, TROLLData, TROLLNumberReadings); // Create pressure, temperature, and depth variable pointers for the TROLL Variable* trollPressure = new InSituTrollSdi12a_Pressure( &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab"); Variable* trollTemp = new InSituTrollSdi12a_Temp( &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab"); Variable* trollDepth = new InSituTrollSdi12a_Depth( &insituTROLL, "12345678-abcd-1234-ef00-1234567890ab"); /** End [in_situ_troll_sdi12a] */ #endif #if defined BUILD_SENSOR_KELLER_ACCULEVEL // ========================================================================== // Keller Acculevel High Accuracy Submersible Level Transmitter // ========================================================================== /** Start [keller_acculevel] */ #include <sensors/KellerAcculevel.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte acculevelModbusAddress = 0x01; // The modbus address of KellerAcculevel const int8_t acculevelPower = A3; // Acculevel Sensor power pin const int8_t alAdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t al485EnablePin = -1; // Adapter RE/DE pin const uint8_t acculevelNumberReadings = 5; // The manufacturer recommends taking and averaging a few readings // Create a Keller Acculevel sensor object KellerAcculevel acculevel(acculevelModbusAddress, modbusSerial, alAdapterPower, acculevelPower, al485EnablePin, acculevelNumberReadings); // Create pressure, temperature, and height variable pointers for the Acculevel Variable* acculevPress = new KellerAcculevel_Pressure( &acculevel, "12345678-abcd-1234-ef00-1234567890ab"); Variable* acculevTemp = new KellerAcculevel_Temp( &acculevel, "12345678-abcd-1234-ef00-1234567890ab"); Variable* acculevHeight = new KellerAcculevel_Height( &acculevel, "12345678-abcd-1234-ef00-1234567890ab"); /** End [keller_acculevel] */ #endif #if defined BUILD_SENSOR_KELLER_NANOLEVEL // ========================================================================== // Keller Nanolevel High Accuracy Submersible Level Transmitter // ========================================================================== /** Start [keller_nanolevel] */ #include <sensors/KellerNanolevel.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte nanolevelModbusAddress = 0x01; // The modbus address of KellerNanolevel const int8_t nlAdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t nanolevelPower = A3; // Sensor power pin const int8_t nl485EnablePin = -1; // Adapter RE/DE pin const uint8_t nanolevelNumberReadings = 5; // The manufacturer recommends taking and averaging a few readings // Create a Keller Nanolevel sensor object KellerNanolevel nanolevel(nanolevelModbusAddress, modbusSerial, nlAdapterPower, nanolevelPower, nl485EnablePin, nanolevelNumberReadings); // Create pressure, temperature, and height variable pointers for the Nanolevel Variable* nanolevPress = new KellerNanolevel_Pressure( &nanolevel, "12345678-abcd-1234-ef00-1234567890ab"); Variable* nanolevTemp = new KellerNanolevel_Temp( &nanolevel, "12345678-abcd-1234-ef00-1234567890ab"); Variable* nanolevHeight = new KellerNanolevel_Height( &nanolevel, "12345678-abcd-1234-ef00-1234567890ab"); /** End [keller_nanolevel] */ #endif #if defined BUILD_SENSOR_MAX_BOTIX_SONAR // ========================================================================== // Maxbotix HRXL Ultrasonic Range Finder // ========================================================================== /** Start [max_botix_sonar] */ #include <sensors/MaxBotixSonar.h> // A Maxbotix sonar with the trigger pin disconnect CANNOT share the serial port // A Maxbotix sonar using the trigger may be able to share but YMMV // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t SonarPower = sensorPowerPin; // Excite (power) pin const int8_t Sonar1Trigger = -1; // Trigger pin // Trigger should be a *unique* negative number if unconnected const uint8_t sonar1NumberReadings = 3; // The number of readings to average // Create a MaxBotix Sonar sensor object MaxBotixSonar sonar1(sonarSerial, SonarPower, Sonar1Trigger, sonar1NumberReadings); // Create an ultrasonic range variable pointer Variable* sonar1Range = new MaxBotixSonar_Range(&sonar1, "12345678-abcd-1234-ef00-1234567890ab"); /** End [max_botix_sonar] */ #endif #if defined(BUILD_SENSOR_MAXIM_DS18) || \ defined(BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY) // ========================================================================== // Maxim DS18 One Wire Temperature Sensor // ========================================================================== /** Start [maxim_ds18] */ #include <sensors/MaximDS18.h> // OneWire Address [array of 8 hex characters] // If only using a single sensor on the OneWire bus, you may omit the address DeviceAddress OneWireAddress1 = {0x28, 0xFF, 0xBD, 0xBA, 0x81, 0x16, 0x03, 0x0C}; // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t OneWirePower = sensorPowerPin; // Power pin const int8_t OneWireBus = A0; // OneWire Bus Pin const int8_t ds18NumberReadings = 3; // Create a Maxim DS18 sensor objects (use this form for a known address) MaximDS18 ds18(OneWireAddress1, OneWirePower, OneWireBus, ds18NumberReadings); // Create a Maxim DS18 sensor object (use this form for a single sensor on bus // with an unknown address) // MaximDS18 ds18(OneWirePower, OneWireBus); // Create a temperature variable pointer for the DS18 Variable* ds18Temp = new MaximDS18_Temp(&ds18, "12345678-abcd-1234-ef00-1234567890ab"); /** End [maxim_ds18] */ #endif #if defined BUILD_SENSOR_MEA_SPEC_MS5803 // ========================================================================== // Measurement Specialties MS5803-14BA pressure sensor // ========================================================================== /** Start [mea_spec_ms5803] */ #include <sensors/MeaSpecMS5803.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t MS5803Power = sensorPowerPin; // Power pin const uint8_t MS5803i2c_addr = 0x76; // The MS5803 can be addressed either as 0x76 (default) or 0x77 const int16_t MS5803maxPressure = 14; // The maximum pressure measurable by the specific MS5803 model const uint8_t MS5803ReadingsToAvg = 1; // Create a MeaSpec MS5803 pressure and temperature sensor object MeaSpecMS5803 ms5803(MS5803Power, MS5803i2c_addr, MS5803maxPressure, MS5803ReadingsToAvg); // Create pressure and temperature variable pointers for the MS5803 Variable* ms5803Press = new MeaSpecMS5803_Pressure(&ms5803, "12345678-abcd-1234-ef00-1234567890ab"); Variable* ms5803Temp = new MeaSpecMS5803_Temp(&ms5803, "12345678-abcd-1234-ef00-1234567890ab"); /** End [mea_spec_ms5803] */ #endif #if defined BUILD_SENSOR_DECAGON_5TM // ========================================================================== // Meter ECH2O Soil Moisture Sensor // ========================================================================== /** Start [decagon_5tm] */ #include <sensors/Decagon5TM.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* TMSDI12address = "2"; // The SDI-12 Address of the 5-TM const int8_t TMPower = sensorPowerPin; // Power pin const int8_t TMData = 7; // The SDI-12 data pin // Create a Decagon 5TM sensor object Decagon5TM fivetm(*TMSDI12address, TMPower, TMData); // Create the matric potential, volumetric water content, and temperature // variable pointers for the 5TM Variable* fivetmEa = new Decagon5TM_Ea(&fivetm, "12345678-abcd-1234-ef00-1234567890ab"); Variable* fivetmVWC = new Decagon5TM_VWC(&fivetm, "12345678-abcd-1234-ef00-1234567890ab"); Variable* fivetmTemp = new Decagon5TM_Temp(&fivetm, "12345678-abcd-1234-ef00-1234567890ab"); /** End [decagon_5tm] */ #endif #if defined BUILD_SENSOR_METER_HYDROS21 // ========================================================================== // Meter Hydros 21 Conductivity, Temperature, and Depth Sensor // ========================================================================== /** Start [meter_hydros21] */ #include <sensors/MeterHydros21.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* hydros21SDI12address = "1"; // The SDI-12 Address of the Hydros21 const uint8_t hydros21NumberReadings = 6; // The number of readings to average const int8_t hydros21Power = sensorPowerPin; // Power pin const int8_t hydros21Data = 7; // The SDI-12 data pin // Create a Decagon Hydros21 sensor object MeterHydros21 hydros21(*hydros21SDI12address, hydros21Power, hydros21Data, hydros21NumberReadings); // Create conductivity, temperature, and depth variable pointers for the // Hydros21 Variable* hydros21Cond = new MeterHydros21_Cond(&hydros21, "12345678-abcd-1234-ef00-1234567890ab"); Variable* hydros21Temp = new MeterHydros21_Temp(&hydros21, "12345678-abcd-1234-ef00-1234567890ab"); Variable* hydros21Depth = new MeterHydros21_Depth(&hydros21, "12345678-abcd-1234-ef00-1234567890ab"); /** End [meter_hydros21] */ #endif #if defined BUILD_SENSOR_METER_TEROS11 // ========================================================================== // Meter Teros 11 Soil Moisture Sensor // ========================================================================== /** Start [meter_teros11] */ #include <sensors/MeterTeros11.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* teros11SDI12address = "4"; // The SDI-12 Address of the Teros 11 const int8_t terosPower = sensorPowerPin; // Power pin const int8_t terosData = 7; // The SDI-12 data pin const uint8_t teros11NumberReadings = 3; // The number of readings to average // Create a METER TEROS 11 sensor object MeterTeros11 teros11(*teros11SDI12address, terosPower, terosData, teros11NumberReadings); // Create the matric potential, volumetric water content, and temperature // variable pointers for the Teros 11 Variable* teros11Ea = new MeterTeros11_Ea(&teros11, "12345678-abcd-1234-ef00-1234567890ab"); Variable* teros11Temp = new MeterTeros11_Temp(&teros11, "12345678-abcd-1234-ef00-1234567890ab"); Variable* teros11VWC = new MeterTeros11_VWC(&teros11, "12345678-abcd-1234-ef00-1234567890ab"); Variable* teros11Count = new MeterTeros11_Count(&teros11, "12345678-abcd-1234-ef00-1234567890ab"); /** End [meter_teros11] */ #endif #if defined BUILD_SENSOR_PALEO_TERRA_REDOX // ========================================================================== // PaleoTerra Redox Sensors // ========================================================================== /** Start [paleo_terra_redox] */ #include <sensors/PaleoTerraRedox.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. int8_t paleoTerraPower = sensorPowerPin; // Power pin uint8_t paleoI2CAddress = 0x68; // the I2C address of the redox sensor // Create the PaleoTerra sensor object #ifdef MS_PALEOTERRA_SOFTWAREWIRE PaleoTerraRedox ptRedox(&softI2C, paleoTerraPower, paleoI2CAddress); // PaleoTerraRedox ptRedox(paleoTerraPower, softwareSDA, softwareSCL, // paleoI2CAddress); #else PaleoTerraRedox ptRedox(paleoTerraPower, paleoI2CAddress); #endif // Create the voltage variable for the redox sensor Variable* ptVolt = new PaleoTerraRedox_Voltage( &ptRedox, "12345678-abcd-1234-ef00-1234567890ab"); /** End [paleo_terra_redox] */ #endif #if defined BUILD_SENSOR_RAIN_COUNTER_I2C // ========================================================================== // External I2C Rain Tipping Bucket Counter // ========================================================================== /** Start [rain_counter_i2c] */ #include <sensors/RainCounterI2C.h> const uint8_t RainCounterI2CAddress = 0x08; // I2C Address for EnviroDIY external tip counter; 0x08 by default const float depthPerTipEvent = 0.2; // rain depth in mm per tip event // Create a Rain Counter sensor object #ifdef MS_RAIN_SOFTWAREWIRE RainCounterI2C tbi2c(&softI2C, RainCounterI2CAddress, depthPerTipEvent); // RainCounterI2C tbi2c(softwareSDA, softwareSCL, RainCounterI2CAddress, // depthPerTipEvent); #else RainCounterI2C tbi2c(RainCounterI2CAddress, depthPerTipEvent); #endif // Create number of tips and rain depth variable pointers for the tipping bucket Variable* tbi2cTips = new RainCounterI2C_Tips(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab"); Variable* tbi2cDepth = new RainCounterI2C_Depth(&tbi2c, "12345678-abcd-1234-ef00-1234567890ab"); /** End [rain_counter_i2c] */ #endif #if defined BUILD_SENSOR_SENSIRION_SHT4X // ========================================================================== // Sensirion SHT4X Digital Humidity and Temperature Sensor // ========================================================================== /** Start [sensirion_sht4x] */ #include <sensors/SensirionSHT4x.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t SHT4xPower = sensorPowerPin; // Power pin const bool SHT4xUseHeater = true; // Create an Sensirion SHT4X sensor object SensirionSHT4x sht4x(SHT4xPower, SHT4xUseHeater); // Create humidity and temperature variable pointers for the SHT4X Variable* sht4xHumid = new SensirionSHT4x_Humidity(&sht4x, "12345678-abcd-1234-ef00-1234567890ab"); Variable* sht4xTemp = new SensirionSHT4x_Temp(&sht4x, "12345678-abcd-1234-ef00-1234567890ab"); /** End [sensirion_sht4x] */ #endif #if defined BUILD_SENSOR_TALLY_COUNTER_I2C // ========================================================================== // Tally I2C Event Counter for rain or wind reed-switch sensors // ========================================================================== /** Start [tally_counter_i2c] */ #include <sensors/TallyCounterI2C.h> const int8_t TallyPower = -1; // Power pin (-1 if continuously powered) // NorthernWidget Tally I2CPower is -1 by default because it is often deployed // with power always on, but Tally also has a super capacitor that enables it // to be self powered between readings/recharge as described at // https://github.com/EnviroDIY/Project-Tally const uint8_t TallyCounterI2CAddress = 0x33; // NorthernWidget Tally I2C address is 0x33 by default // Create a Tally Counter sensor object TallyCounterI2C tallyi2c(TallyPower, TallyCounterI2CAddress); // Create variable pointers for the Tally event counter Variable* tallyEvents = new TallyCounterI2C_Events( &tallyi2c, "12345678-abcd-1234-ef00-1234567890ab"); // For Wind Speed, create a Calculated Variable that converts, similar to: // period = loggingInterval * 60.0; // in seconds // frequency = tallyEventCount/period; // average event frequency in Hz // tallyWindSpeed = frequency * 2.5 * 1.60934; // in km/h // 2.5 mph/Hz & 1.60934 kmph/mph and 2.5 mph/Hz conversion factor from // web: Inspeed-Version-II-Reed-Switch-Anemometer-Sensor-Only-WS2R /** End [tally_counter_i2c] */ #endif #if defined BUILD_SENSOR_TI_INA219 // ========================================================================== // TI INA219 High Side Current/Voltage Sensor (Current mA, Voltage, Power) // ========================================================================== /** Start [ti_ina219] */ #include <sensors/TIINA219.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t INA219Power = sensorPowerPin; // Power pin uint8_t INA219i2c_addr = 0x40; // 1000000 (Board A0+A1=GND) // The INA219 can have one of 16 addresses, depending on the connections of A0 // and A1 const uint8_t INA219ReadingsToAvg = 1; // Create an INA219 sensor object TIINA219 ina219(INA219Power, INA219i2c_addr, INA219ReadingsToAvg); // Create current, voltage, and power variable pointers for the INA219 Variable* inaCurrent = new TIINA219_Current(&ina219, "12345678-abcd-1234-ef00-1234567890ab"); Variable* inaVolt = new TIINA219_Voltage(&ina219, "12345678-abcd-1234-ef00-1234567890ab"); Variable* inaPower = new TIINA219_Power(&ina219, "12345678-abcd-1234-ef00-1234567890ab"); /** End [ti_ina219] */ #endif #if defined BUILD_SENSOR_TURNER_CYCLOPS // ========================================================================== // Turner Cyclops-7F Submersible Fluorometer // ========================================================================== /** Start [turner_cyclops] */ #include <sensors/TurnerCyclops.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const int8_t cyclopsPower = sensorPowerPin; // Power pin const uint8_t cyclopsNumberReadings = 10; const uint8_t cyclopsADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC const int8_t cyclopsADSChannel = 0; // ADS channel // Cyclops calibration information const float cyclopsStdConc = 1.000; // Concentration of the standard used // for a 1-point sensor calibration. const float cyclopsStdVolt = 1.000; // The voltage (in volts) measured for the conc_std. const float cyclopsBlankVolt = 0.000; // The voltage (in volts) measured for a blank. // Create a Turner Cyclops sensor object TurnerCyclops cyclops(cyclopsPower, cyclopsADSChannel, cyclopsStdConc, cyclopsStdVolt, cyclopsBlankVolt, cyclopsADSi2c_addr, cyclopsNumberReadings); // Create the voltage variable pointer - used for any type of Cyclops Variable* cyclopsVoltage = new TurnerCyclops_Voltage(&cyclops, "12345678-abcd-1234-ef00-1234567890ab"); // Create the variable pointer for the primary output parameter. Only use // **ONE** of these! Which is possible depends on your specific sensor! Variable* cyclopsChloro = new TurnerCyclops_Chlorophyll( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsRWT = new TurnerCyclops_Rhodamine( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsFluoroscein = new TurnerCyclops_Fluorescein( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsPhycocyanin = new TurnerCyclops_Phycocyanin( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsPhycoerythrin = new TurnerCyclops_Phycoerythrin( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsCDOM = new TurnerCyclops_CDOM(&cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsCrudeOil = new TurnerCyclops_CrudeOil( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsBrighteners = new TurnerCyclops_Brighteners( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsTurbidity = new TurnerCyclops_Turbidity( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsPTSA = new TurnerCyclops_PTSA(&cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsBTEX = new TurnerCyclops_BTEX(&cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsTryptophan = new TurnerCyclops_Tryptophan( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); Variable* cyclopsRedChloro = new TurnerCyclops_RedChlorophyll( &cyclops, "12345678-abcd-1234-ef00-1234567890ab"); /** End [turner_cyclops] */ #endif #if defined BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY // ========================================================================== // Analog Electrical Conductivity using the Processor's Analog Pins // ========================================================================== /** Start [analog_elec_conductivity] */ #include <sensors/AnalogElecConductivity.h> const int8_t ECpwrPin = A4; // Power pin (-1 if continuously powered) const int8_t ECdataPin1 = A0; // Data pin (must be an analog pin, ie A#) // Create an Analog Electrical Conductivity sensor object AnalogElecConductivity analogEC_phy(ECpwrPin, ECdataPin1); // Create a conductivity variable pointer for the analog sensor Variable* analogEc_cond = new AnalogElecConductivity_EC( &analogEC_phy, "12345678-abcd-1234-ef00-1234567890ab"); // Create a calculated variable for the temperature compensated conductivity // (that is, the specific conductance). For this example, we will use the // temperature measured by the Maxim DS18 saved as ds18Temp several sections // above this. You could use the temperature returned by any other water // temperature sensor if desired. **DO NOT** use your logger board temperature // (ie, from the DS3231) to calculate specific conductance! float calculateAnalogSpCond(void) { float spCond = -9999; // Always safest to start with a bad value float waterTemp = ds18Temp->getValue(); float rawCond = analogEc_cond->getValue(); float temperatureCoef = 0.019; // ^^ Linearized temperature correction coefficient per degrees Celsius. // The value of 0.019 comes from measurements reported here: // Hayashi M. Temperature-electrical conductivity relation of water for // environmental monitoring and geophysical data inversion. Environ Monit // Assess. 2004 Aug-Sep;96(1-3):119-28. // doi: 10.1023/b:emas.0000031719.83065.68. PMID: 15327152. if (waterTemp != -9999 && rawCond != -9999) { // make sure both inputs are good spCond = rawCond / (1 + temperatureCoef * (waterTemp - 25.0)); } return spCond; } // Properties of the calculated variable // The number of digits after the decimal place const uint8_t analogSpCondResolution = 0; // This must be a value from http://vocabulary.odm2.org/variablename/ const char* analogSpCondName = "specificConductance"; // This must be a value from http://vocabulary.odm2.org/units/ const char* analogSpCondUnit = "microsiemenPerCentimeter"; // A short code for the variable const char* analogSpCondCode = "anlgSpCond"; // The (optional) universallly unique identifier const char* analogSpCondUUID = "12345678-abcd-1234-ef00-1234567890ab"; // Finally, Create the specific conductance variable and return a pointer to it Variable* analogEc_spcond = new Variable( calculateAnalogSpCond, analogSpCondResolution, analogSpCondName, analogSpCondUnit, analogSpCondCode, analogSpCondUUID); /** End [analog_elec_conductivity] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y504 // ========================================================================== // Yosemitech Y504 Dissolved Oxygen Sensor // ========================================================================== /** Start [yosemitech_y504] */ #include <sensors/YosemitechY504.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y504ModbusAddress = 0x04; // The modbus address of the Y504 const int8_t y504AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y504SensorPower = A3; // Sensor power pin const int8_t y504EnablePin = -1; // Adapter RE/DE pin const uint8_t y504NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Yosemitech Y504 dissolved oxygen sensor object YosemitechY504 y504(y504ModbusAddress, modbusSerial, y504AdapterPower, y504SensorPower, y504EnablePin, y504NumberReadings); // Create the dissolved oxygen percent, dissolved oxygen concentration, and // temperature variable pointers for the Y504 Variable* y504DOpct = new YosemitechY504_DOpct(&y504, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y504DOmgL = new YosemitechY504_DOmgL(&y504, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y504Temp = new YosemitechY504_Temp(&y504, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y504] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y510 // ========================================================================== // Yosemitech Y510 Turbidity Sensor // ========================================================================== /** Start [yosemitech_y510] */ #include <sensors/YosemitechY510.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y510ModbusAddress = 0x0B; // The modbus address of the Y510 const int8_t y510AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y510SensorPower = A3; // Sensor power pin const int8_t y510EnablePin = -1; // Adapter RE/DE pin const uint8_t y510NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y510-B Turbidity sensor object YosemitechY510 y510(y510ModbusAddress, modbusSerial, y510AdapterPower, y510SensorPower, y510EnablePin, y510NumberReadings); // Create turbidity and temperature variable pointers for the Y510 Variable* y510Turb = new YosemitechY510_Turbidity(&y510, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y510Temp = new YosemitechY510_Temp(&y510, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y510] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y511 // ========================================================================== // Yosemitech Y511 Turbidity Sensor with Wiper // ========================================================================== /** Start [yosemitech_y511] */ #include <sensors/YosemitechY511.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y511ModbusAddress = 0x1A; // The modbus address of the Y511 const int8_t y511AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y511SensorPower = A3; // Sensor power pin const int8_t y511EnablePin = -1; // Adapter RE/DE pin const uint8_t y511NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y511-A Turbidity sensor object YosemitechY511 y511(y511ModbusAddress, modbusSerial, y511AdapterPower, y511SensorPower, y511EnablePin, y511NumberReadings); // Create turbidity and temperature variable pointers for the Y511 Variable* y511Turb = new YosemitechY511_Turbidity(&y511, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y511Temp = new YosemitechY511_Temp(&y511, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y511] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y514 // ========================================================================== // Yosemitech Y514 Chlorophyll Sensor // ========================================================================== /** Start [yosemitech_y514] */ #include <sensors/YosemitechY514.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y514ModbusAddress = 0x14; // The modbus address of the Y514 const int8_t y514AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y514SensorPower = A3; // Sensor power pin const int8_t y514EnablePin = -1; // Adapter RE/DE pin const uint8_t y514NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y514 chlorophyll sensor object YosemitechY514 y514(y514ModbusAddress, modbusSerial, y514AdapterPower, y514SensorPower, y514EnablePin, y514NumberReadings); // Create chlorophyll concentration and temperature variable pointers for the // Y514 Variable* y514Chloro = new YosemitechY514_Chlorophyll( &y514, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y514Temp = new YosemitechY514_Temp(&y514, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y514] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y520 // ========================================================================== // Yosemitech Y520 Conductivity Sensor // ========================================================================== /** Start [yosemitech_y520] */ #include <sensors/YosemitechY520.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y520ModbusAddress = 0x20; // The modbus address of the Y520 const int8_t y520AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y520SensorPower = A3; // Sensor power pin const int8_t y520EnablePin = -1; // Adapter RE/DE pin const uint8_t y520NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y520 conductivity sensor object YosemitechY520 y520(y520ModbusAddress, modbusSerial, y520AdapterPower, y520SensorPower, y520EnablePin, y520NumberReadings); // Create specific conductance and temperature variable pointers for the Y520 Variable* y520Cond = new YosemitechY520_Cond(&y520, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y520Temp = new YosemitechY520_Temp(&y520, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y520] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y532 // ========================================================================== // Yosemitech Y532 pH // ========================================================================== /** Start [yosemitech_y532] */ #include <sensors/YosemitechY532.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y532ModbusAddress = 0x32; // The modbus address of the Y532 const int8_t y532AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y532SensorPower = A3; // Sensor power pin const int8_t y532EnablePin = 4; // Adapter RE/DE pin const uint8_t y532NumberReadings = 1; // The manufacturer actually doesn't mention averaging for this one // Create a Yosemitech Y532 pH sensor object YosemitechY532 y532(y532ModbusAddress, modbusSerial, y532AdapterPower, y532SensorPower, y532EnablePin, y532NumberReadings); // Create pH, electrical potential, and temperature variable pointers for the // Y532 Variable* y532Voltage = new YosemitechY532_Voltage(&y532, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y532pH = new YosemitechY532_pH(&y532, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y532Temp = new YosemitechY532_Temp(&y532, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y532] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y533 // ========================================================================== // Yosemitech Y533 Oxidation Reduction Potential (ORP) // ========================================================================== /** Start [yosemitech_y533] */ #include <sensors/YosemitechY533.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y533ModbusAddress = 0x32; // The modbus address of the Y533 const int8_t y533AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y533SensorPower = A3; // Sensor power pin const int8_t y533EnablePin = 4; // Adapter RE/DE pin const uint8_t y533NumberReadings = 1; // The manufacturer actually doesn't mention averaging for this one // Create a Yosemitech Y533 ORP sensor object YosemitechY533 y533(y533ModbusAddress, modbusSerial, y533AdapterPower, y533SensorPower, y533EnablePin, y533NumberReadings); // Create ORP and temperature variable pointers for the Y533 Variable* y533ORP = new YosemitechY533_ORP(&y533, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y533Temp = new YosemitechY533_Temp(&y533, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y533] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y551 // ========================================================================== // Yosemitech Y551 COD Sensor with Wiper // ========================================================================== /** Start [yosemitech_y551] */ #include <sensors/YosemitechY551.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y551ModbusAddress = 0x50; // The modbus address of the Y551 const int8_t y551AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y551SensorPower = A3; // Sensor power pin const int8_t y551EnablePin = -1; // Adapter RE/DE pin const uint8_t y551NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y551 chemical oxygen demand sensor object YosemitechY551 y551(y551ModbusAddress, modbusSerial, y551AdapterPower, y551SensorPower, y551EnablePin, y551NumberReadings); // Create COD, turbidity, and temperature variable pointers for the Y551 Variable* y551COD = new YosemitechY551_COD(&y551, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y551Turbid = new YosemitechY551_Turbidity(&y551, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y551Temp = new YosemitechY551_Temp(&y551, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y551] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y560 // ========================================================================== // Yosemitech Y560 Ammonium Probe with Wiper // ========================================================================== /** Start [yosemitech_y560] */ #include <sensors/YosemitechY560.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y560ModbusAddress = 0x60; // The modbus address of the Y560. // NOTE: Hexidecimal 0x60 = 96 decimal used by Yosemitech SmartPC const int8_t y560AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y560SensorPower = A3; // Sensor power pin const int8_t y560EnablePin = -1; // Adapter RE/DE pin const uint8_t y560NumberReadings = 3; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y560 Ammonium Probe object YosemitechY560 y560(y560ModbusAddress, modbusSerial, y560AdapterPower, y560SensorPower, y560EnablePin, y560NumberReadings); // Create COD, turbidity, and temperature variable pointers for the Y560 Variable* y560NH4_N = new YosemitechY560_NH4_N(&y560, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y560pH = new YosemitechY560_pH(&y560, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y560Temp = new YosemitechY560_Temp(&y560, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y560] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y700 // ========================================================================== // Yosemitech Y700 Pressure Sensor // ========================================================================== /** Start [yosemitech_y700] */ #include <sensors/YosemitechY700.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y700ModbusAddress = 0x70; // The modbus address of the Y700 const int8_t y700AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y700SensorPower = A3; // Sensor power pin const int8_t y700EnablePin = -1; // Adapter RE/DE pin const uint8_t y700NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Y700 pressure sensor object YosemitechY700 y700(y700ModbusAddress, modbusSerial, y700AdapterPower, y700SensorPower, y700EnablePin, y700NumberReadings); // Create pressure and temperature variable pointers for the Y700 Variable* y700Pres = new YosemitechY700_Pressure(&y700, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y700Temp = new YosemitechY700_Temp(&y700, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y700] */ #endif #if defined BUILD_SENSOR_YOSEMITECH_Y4000 // ========================================================================== // Yosemitech Y4000 Multiparameter Sonde (DOmgL, Turbidity, Cond, pH, Temp, // ORP, Chlorophyll, BGA) // ========================================================================== /** Start [yosemitech_y4000] */ #include <sensors/YosemitechY4000.h> // NOTE: Extra hardware and software serial ports are created in the "Settings // for Additional Serial Ports" section // NOTE: Use -1 for any pins that don't apply or aren't being used. byte y4000ModbusAddress = 0x05; // The modbus address of the Y4000 const int8_t y4000AdapterPower = sensorPowerPin; // RS485 adapter power pin const int8_t y4000SensorPower = A3; // Sensor power pin const int8_t y4000EnablePin = -1; // Adapter RE/DE pin const uint8_t y4000NumberReadings = 5; // The manufacturer recommends averaging 10 readings, but we take 5 to minimize // power consumption // Create a Yosemitech Y4000 multi-parameter sensor object YosemitechY4000 y4000(y4000ModbusAddress, modbusSerial, y4000AdapterPower, y4000SensorPower, y4000EnablePin, y4000NumberReadings); // Create all of the variable pointers for the Y4000 Variable* y4000DO = new YosemitechY4000_DOmgL(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000Turb = new YosemitechY4000_Turbidity( &y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000Cond = new YosemitechY4000_Cond(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000pH = new YosemitechY4000_pH(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000Temp = new YosemitechY4000_Temp(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000ORP = new YosemitechY4000_ORP(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000Chloro = new YosemitechY4000_Chlorophyll( &y4000, "12345678-abcd-1234-ef00-1234567890ab"); Variable* y4000BGA = new YosemitechY4000_BGA(&y4000, "12345678-abcd-1234-ef00-1234567890ab"); /** End [yosemitech_y4000] */ #endif #if defined BUILD_SENSOR_ZEBRA_TECH_D_OPTO // ========================================================================== // Zebra Tech D-Opto Dissolved Oxygen Sensor // ========================================================================== /** Start [zebra_tech_d_opto] */ #include <sensors/ZebraTechDOpto.h> // NOTE: Use -1 for any pins that don't apply or aren't being used. const char* DOptoSDI12address = "5"; // The SDI-12 Address of the D-Opto const int8_t ZTPower = sensorPowerPin; // Power pin const int8_t ZTData = 7; // The SDI-12 data pin // Create a Zebra Tech DOpto dissolved oxygen sensor object ZebraTechDOpto dopto(*DOptoSDI12address, ZTPower, ZTData); // Create dissolved oxygen percent, dissolved oxygen concentration, and // temperature variable pointers for the Zebra Tech Variable* dOptoDOpct = new ZebraTechDOpto_DOpct(&dopto, "12345678-abcd-1234-ef00-1234567890ab"); Variable* dOptoDOmgL = new ZebraTechDOpto_DOmgL(&dopto, "12345678-abcd-1234-ef00-1234567890ab"); Variable* dOptoTemp = new ZebraTechDOpto_Temp(&dopto, "12345678-abcd-1234-ef00-1234567890ab"); /** End [zebra_tech_d_opto] */ #endif // ========================================================================== // Calculated Variable[s] // ========================================================================== /** Start [calculated_variables] */ // Create the function to give your calculated result. // The function should take no input (void) and return a float. // You can use any named variable pointers to access values by way of // variable->getValue() float calculateVariableValue(void) { float calculatedResult = -9999; // Always safest to start with a bad value // float inputVar1 = variable1->getValue(); // float inputVar2 = variable2->getValue(); // make sure both inputs are good // if (inputVar1 != -9999 && inputVar2 != -9999) { // calculatedResult = inputVar1 + inputVar2; // } return calculatedResult; } // Properties of the calculated variable // The number of digits after the decimal place const uint8_t calculatedVarResolution = 3; // This must be a value from http://vocabulary.odm2.org/variablename/ const char* calculatedVarName = "varName"; // This must be a value from http://vocabulary.odm2.org/units/ const char* calculatedVarUnit = "varUnit"; // A short code for the variable const char* calculatedVarCode = "calcVar"; // The (optional) universallly unique identifier const char* calculatedVarUUID = "12345678-abcd-1234-ef00-1234567890ab"; // Finally, Create a calculated variable and return a variable pointer to it Variable* calculatedVar = new Variable( calculateVariableValue, calculatedVarResolution, calculatedVarName, calculatedVarUnit, calculatedVarCode, calculatedVarUUID); /** End [calculated_variables] */ #if defined BUILD_TEST_CREATE_IN_ARRAY // ========================================================================== // Creating the Variable Array[s] and Filling with Variable Objects // NOTE: This shows three differnt ways of creating the same variable array // and filling it with variables // ========================================================================== /** Start [variables_create_in_array] */ // Version 1: Create pointers for all of the variables from the sensors, // at the same time putting them into an array Variable* variableList[] = { new ProcessorStats_SampleNumber(&mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"), new ProcessorStats_FreeRam(&mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"), new ProcessorStats_Battery(&mcuBoard, "12345678-abcd-1234-ef00-1234567890ab"), // new MaximDS3231_Temp(&ds3231, "12345678-abcd-1234-ef00-1234567890ab"), // ... Add more variables as needed! new Modem_RSSI(&modem, "12345678-abcd-1234-ef00-1234567890ab"), new Modem_SignalPercent(&modem, "12345678-abcd-1234-ef00-1234567890ab"), new Modem_Temp(&modem, "12345678-abcd-1234-ef00-1234567890ab"), new Variable(calculateVariableValue, calculatedVarResolution, calculatedVarName, calculatedVarUnit, calculatedVarCode, calculatedVarUUID), }; // Count up the number of pointers in the array int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); /** End [variables_create_in_array] */ // ========================================================================== #elif defined BUILD_TEST_SEPARATE_UUIDS /** Start [variables_separate_uuids] */ // Version 2: Create two separate arrays, on for the variables and a separate // one for the UUID's, then give both as input to the variable array // constructor. Be cautious when doing this though because order is CRUCIAL! Variable* variableList[] = { new ProcessorStats_SampleNumber(&mcuBoard), new ProcessorStats_FreeRam(&mcuBoard), new ProcessorStats_Battery(&mcuBoard), // new MaximDS3231_Temp(&ds3231), // ... Add all of your variables! new Modem_RSSI(&modem), new Modem_SignalPercent(&modem), new Modem_Temp(&modem), new Variable(calculateVariableValue, calculatedVarResolution, calculatedVarName, calculatedVarUnit, calculatedVarCode), }; const char* UUIDs[] = { "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", // ... The number of UUID's must match the number of variables! "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", "12345678-abcd-1234-ef00-1234567890ab", }; // Count up the number of pointers in the array int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object and attach the UUID's VariableArray varArray(variableCount, variableList, UUIDs); /** End [variables_separate_uuids] */ // ========================================================================== #else // BUILD_TEST_PRE_NAMED_VARS /** Start [variables_pre_named] */ // Version 3: Fill array with already created and named variable pointers Variable* variableList[] = { mcuBoardSampNo, mcuBoardAvailableRAM, mcuBoardBatt, calculatedVar, #if defined(ARDUINO_ARCH_AVR) || defined(MS_SAMD_DS3231) ds3231Temp, #endif #if defined BUILD_SENSOR_AO_SONG_AM2315 am2315Humid, am2315Temp, #endif #if defined BUILD_SENSOR_AO_SONG_DHT dhtHumid, dhtTemp, dhtHI, #endif #if defined BUILD_SENSOR_APOGEE_SQ212 sq212PAR, sq212voltage, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_CO2 atlasCO2CO2, atlasCO2Temp, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_DO atlasDOconc, atlasDOpct, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_ORP atlasORPot, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_PH atlaspHpH, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_RTD atlasTemp, #endif #if defined BUILD_SENSOR_ATLAS_SCIENTIFIC_EC atlasCond, atlasTDS, atlasSal, atlasGrav, atlasSpCond, #endif #if defined BUILD_SENSOR_BOSCH_BME280 bme280Temp, bme280Humid, bme280Press, bme280Alt, #endif #if defined BUILD_SENSOR_BOSCH_BMP3XX bmp3xxTemp, bmp3xxPress, bmp3xxAlt, #endif #if defined BUILD_SENSOR_CAMPBELL_CLARI_VUE10 clarivueTurbidity, clarivueTemp, clarivueError, #endif #if defined BUILD_SENSOR_CAMPBELL_OBS3 obs3TurbLow, obs3VoltLow, obs3TurbHigh, obs3VoltHigh, #endif #if defined BUILD_SENSOR_CAMPBELL_RAIN_VUE10 rainvuePrecipitation, rainvueTips, rainvueRainRateAve, rainvueRainRateMax, #endif #if defined BUILD_SENSOR_DECAGON_CTD ctdCond, ctdTemp, ctdDepth, #endif #if defined BUILD_SENSOR_DECAGON_ES2 es2Cond, es2Temp, #endif #if defined BUILD_SENSOR_EVERLIGHT_ALSPT19 alsPt19Volt, alsPt19Current, alsPt19Lux, #endif #if defined BUILD_SENSOR_TIADS1X15 ads1x15Volt, #endif #if defined BUILD_SENSOR_FREESCALE_MPL115A2 mplTemp, mplPress, #endif #if defined BUILD_SENSOR_IN_SITU_RDO rdoTemp, rdoDOpct, rdoDOmgL, rdoO2pp, #endif #if defined BUILD_SENSOR_IN_SITU_TROLL_SDI12A trollPressure, trollTemp, trollDepth, #endif #if defined BUILD_SENSOR_KELLER_ACCULEVEL acculevPress, acculevTemp, acculevHeight, #endif #if defined BUILD_SENSOR_KELLER_NANOLEVEL nanolevPress, nanolevTemp, nanolevHeight, #endif #if defined BUILD_SENSOR_MAX_BOTIX_SONAR sonar1Range, #endif #if defined BUILD_SENSOR_MAXIM_DS18 ds18Temp, #endif #if defined BUILD_SENSOR_MEA_SPEC_MS5803 ms5803Temp, ms5803Press, #endif #if defined BUILD_SENSOR_DECAGON_5TM fivetmEa, fivetmVWC, fivetmTemp, #endif #if defined BUILD_SENSOR_METER_HYDROS21 hydros21Cond, hydros21Temp, hydros21Depth, #endif #if defined BUILD_SENSOR_METER_TEROS11 teros11Ea, teros11Temp, teros11VWC, teros11Count, #endif #if defined BUILD_SENSOR_PALEO_TERRA_REDOX ptVolt, #endif #if defined BUILD_SENSOR_RAIN_COUNTER_I2C tbi2cTips, tbi2cDepth, #endif #if defined BUILD_SENSOR_SENSIRION_SHT4X sht4xHumid, sht4xTemp, #endif #if defined BUILD_SENSOR_TALLY_COUNTER_I2C tallyEvents, #endif #if defined BUILD_SENSOR_TI_INA219 inaVolt, inaCurrent, inaPower, #endif #if defined BUILD_SENSOR_TURNER_CYCLOPS cyclopsVoltage, cyclopsChloro, cyclopsRWT, cyclopsFluoroscein, cyclopsPhycocyanin, cyclopsPhycoerythrin, cyclopsCDOM, cyclopsCrudeOil, cyclopsBrighteners, cyclopsTurbidity, cyclopsPTSA, cyclopsBTEX, cyclopsTryptophan, cyclopsRedChloro, #endif #if defined BUILD_SENSOR_ANALOG_ELEC_CONDUCTIVITY analogEc_cond, analogEc_spcond, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y504 y504DOpct, y504DOmgL, y504Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y510 y510Turb, y510Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y511 y511Turb, y511Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y514 y514Chloro, y514Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y520 y520Cond, y520Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y532 y532Voltage, y532pH, y532Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y533 y533ORP, y533Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y551 y551COD, y551Turbid, y551Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y560 y560NH4_N, y560pH, y560Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y700 y700Pres, y700Temp, #endif #if defined BUILD_SENSOR_YOSEMITECH_Y4000 y4000DO, y4000Turb, y4000Cond, y4000pH, y4000Temp, y4000ORP, y4000Chloro, y4000BGA, #endif #if defined BUILD_SENSOR_ZEBRA_TECH_D_OPTO dOptoDOpct, dOptoDOmgL, dOptoTemp, #endif modemRSSI, modemSignalPct, #ifdef TINY_GSM_MODEM_HAS_BATTERY modemBatteryState, modemBatteryPct, modemBatteryVoltage, #endif #ifdef TINY_GSM_MODEM_HAS_TEMPERATURE modemTemperature, #endif }; // Count up the number of pointers in the array int variableCount = sizeof(variableList) / sizeof(variableList[0]); // Create the VariableArray object VariableArray varArray(variableCount, variableList); /** End [variables_pre_named] */ #endif // ========================================================================== // The Logger Object[s] // ========================================================================== /** Start [loggers] */ // Create a new logger instance Logger dataLogger(LoggerID, loggingInterval, &varArray); /** End [loggers] */ #if defined BUILD_PUB_ENVIRO_DIY_PUBLISHER // ========================================================================== // A Publisher to Monitor My Watershed / EnviroDIY Data Sharing Portal // ========================================================================== /** Start [enviro_diy_publisher] */ // Device registration and sampling feature information can be obtained after // registration at https://monitormywatershed.org or https://data.envirodiy.org const char* registrationToken = "12345678-abcd-1234-ef00-1234567890ab"; // Device registration token const char* samplingFeature = "12345678-abcd-1234-ef00-1234567890ab"; // Sampling feature UUID // Create a data publisher for the Monitor My Watershed/EnviroDIY POST endpoint #include <publishers/EnviroDIYPublisher.h> EnviroDIYPublisher EnviroDIYPOST(dataLogger, &modem.gsmClient, registrationToken, samplingFeature); /** End [enviro_diy_publisher] */ #endif #if defined BUILD_PUB_DREAM_HOST_PUBLISHER // ========================================================================== // A Publisher to DreamHost // ========================================================================== /** Start [dream_host_publisher] */ // NOTE: This is an outdated data collection tool used by the Stroud Center. // It very, very unlikely that you will use this. const char* DreamHostPortalRX = "xxxx"; // Create a data publisher to DreamHost #include <publishers/DreamHostPublisher.h> DreamHostPublisher DreamHostGET(dataLogger, &modem.gsmClient, DreamHostPortalRX); /** End [dream_host_publisher] */ #endif #if defined BUILD_PUB_THING_SPEAK_PUBLISHER // ========================================================================== // ThingSpeak Data Publisher // ========================================================================== /** Start [thing_speak_publisher] */ // Create a channel with fields on ThingSpeak in advance. // The fields will be sent in exactly the order they are in the variable array. // Any custom name or identifier given to the field on ThingSpeak is irrelevant. // No more than 8 fields of data can go to any one channel. Any fields beyond // the eighth in the array will be ignored. const char* thingSpeakMQTTKey = "XXXXXXXXXXXXXXXX"; // Your MQTT API Key from Account > MyProfile. const char* thingSpeakChannelID = "######"; // The numeric channel id for your channel const char* thingSpeakChannelKey = "XXXXXXXXXXXXXXXX"; // The Write API Key for your channel // Create a data publisher for ThingSpeak #include <publishers/ThingSpeakPublisher.h> ThingSpeakPublisher TsMqtt(dataLogger, &modem.gsmClient, thingSpeakMQTTKey, thingSpeakChannelID, thingSpeakChannelKey); /** End [thing_speak_publisher] */ #endif #if defined BUILD_PUB_UBIDOTS_PUBLISHER // ========================================================================== // Ubidots Data Publisher // ========================================================================== /** Start [ubidots_publisher] */ // The authentication token from Ubdots, either the Organization's Integration // Token (under Users > Organization menu,visible by Admin only) OR the STEM // User's Device Token (under the specific evice's setup panel). const char* ubidotsToken = "XXXXXXXXXXXXXXXX"; // The device API Label from Ubidots, derived from the user-specified device // name. const char* ubidotsDeviceID = "######"; // Create a data publisher for ThingSpeak #include <publishers/UbidotsPublisher.h> UbidotsPublisher ubidots(dataLogger, &modem.gsmClient, ubidotsToken, ubidotsDeviceID); /** End [ubidots_publisher] */ #endif // ========================================================================== // Working Functions // ========================================================================== /** Start [working_functions] */ // Flashes the LED's on the primary board void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) { for (uint8_t i = 0; i < numFlash; i++) { digitalWrite(greenLED, HIGH); digitalWrite(redLED, LOW); delay(rate); digitalWrite(greenLED, LOW); digitalWrite(redLED, HIGH); delay(rate); } digitalWrite(redLED, LOW); } // Uses the processor sensor object to read the battery voltage // NOTE: This will actually return the battery level from the previous update! float getBatteryVoltage() { if (mcuBoard.sensorValues[0] == -9999) mcuBoard.update(); return mcuBoard.sensorValues[0]; } /** End [working_functions] */ // ========================================================================== // Arduino Setup Function // ========================================================================== void setup() { /** Start [setup_wait] */ // Wait for USB connection to be established by PC // NOTE: Only use this when debugging - if not connected to a PC, this // could prevent the script from starting #if defined SERIAL_PORT_USBVIRTUAL while (!SERIAL_PORT_USBVIRTUAL && (millis() < 10000L)) { // wait } #endif /** End [setup_wait] */ /** Start [setup_prints] */ // Start the primary serial connection Serial.begin(serialBaud); // Print a start-up note to the first serial port Serial.print(F("\n\nNow running ")); Serial.print(sketchName); Serial.print(F(" on Logger ")); Serial.println(LoggerID); Serial.println(); Serial.print(F("Using ModularSensors Library version ")); Serial.println(MODULAR_SENSORS_VERSION); Serial.print(F("TinyGSM Library version ")); Serial.println(TINYGSM_VERSION); Serial.println(); /** End [setup_prints] */ /** Start [setup_softserial] */ // Allow interrupts for software serial #if defined SoftwareSerial_ExtInts_h enableInterrupt(softSerialRx, SoftwareSerial_ExtInts::handle_interrupt, CHANGE); #endif #if defined NeoSWSerial_h enableInterrupt(neoSSerial1Rx, neoSSerial1ISR, CHANGE); #endif /** End [setup_softserial] */ /** Start [setup_serial_begins] */ // Start the serial connection with the modem modemSerial.begin(modemBaud); // Start the stream for the modbus sensors; // all currently supported modbus sensors use 9600 baud modbusSerial.begin(9600); #if defined BUILD_SENSOR_MAX_BOTIX_SONAR // Start the SoftwareSerial stream for the sonar; it will always be at 9600 // baud sonarSerial.begin(9600); #endif /** End [setup_serial_begins] */ // Assign pins SERCOM functionality for SAMD boards // NOTE: This must happen *after* the various serial.begin statements /** Start [setup_samd_pins] */ #if defined ARDUINO_ARCH_SAMD #ifndef ENABLE_SERIAL2 pinPeripheral(10, PIO_SERCOM); // Serial2 Tx/Dout = SERCOM1 Pad #2 pinPeripheral(11, PIO_SERCOM); // Serial2 Rx/Din = SERCOM1 Pad #0 #endif #ifndef ENABLE_SERIAL3 pinPeripheral(2, PIO_SERCOM); // Serial3 Tx/Dout = SERCOM2 Pad #2 pinPeripheral(5, PIO_SERCOM); // Serial3 Rx/Din = SERCOM2 Pad #3 #endif #endif /** End [setup_samd_pins] */ /** Start [setup_flashing_led] */ // Set up pins for the LED's pinMode(greenLED, OUTPUT); digitalWrite(greenLED, LOW); pinMode(redLED, OUTPUT); digitalWrite(redLED, LOW); // Blink the LEDs to show the board is on and starting up greenredflash(); /** End [setup_flashing_led] */ /** Start [setup_logger] */ // Set the timezones for the logger/data and the RTC // Logging in the given time zone Logger::setLoggerTimeZone(timeZone); // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0) Logger::setRTCTimeZone(0); // Attach the modem and information pins to the logger dataLogger.attachModem(modem); modem.setModemLED(modemLEDPin); dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin, greenLED); // Begin the logger dataLogger.begin(); /** End [setup_logger] */ /** Start [setup_sensors] */ // Note: Please change these battery voltages to match your battery // Set up the sensors, except at lowest battery level if (getBatteryVoltage() > 3.4) { Serial.println(F("Setting up sensors...")); varArray.setupSensors(); } /** End [setup_sensors] */ #if (defined BUILD_MODEM_ESPRESSIF_ESP8266 || \ defined BUILD_MODEM_ESPRESSIF_ESP32) && \ F_CPU == 8000000L /** Start [setup_esp] */ if (modemBaud > 57600) { modem.modemWake(); // NOTE: This will also set up the modem modemSerial.begin(modemBaud); modem.gsmModem.sendAT(GF("+UART_DEF=9600,8,1,0,0")); modem.gsmModem.waitResponse(); modemSerial.end(); modemSerial.begin(9600); } /** End [setup_esp] */ #endif #if defined BUILD_TEST_SKYWIRE /** Start [setup_skywire] */ modem.setModemStatusLevel(LOW); // If using CTS, LOW modem.setModemWakeLevel(HIGH); // Skywire dev board inverts the signal modem.setModemResetLevel(HIGH); // Skywire dev board inverts the signal /** End [setup_skywire] */ #endif #if defined BUILD_MODEM_SIM_COM_SIM7080 /** Start [setup_sim7080] */ modem.setModemWakeLevel(HIGH); // ModuleFun Bee inverts the signal modem.setModemResetLevel(HIGH); // ModuleFun Bee inverts the signal Serial.println(F("Waking modem and setting Cellular Carrier Options...")); modem.modemWake(); // NOTE: This will also set up the modem modem.gsmModem.setBaud(modemBaud); // Make sure we're *NOT* auto-bauding! modem.gsmModem.setNetworkMode(38); // set to LTE only // 2 Automatic // 13 GSM only // 38 LTE only // 51 GSM and LTE only modem.gsmModem.setPreferredMode(1); // set to CAT-M // 1 CAT-M // 2 NB-IoT // 3 CAT-M and NB-IoT /** End [setup_sim7080] */ #endif #if defined BUILD_MODEM_DIGI_XBEE_CELLULAR_TRANSPARENT /** Start [setup_xbeec_carrier] */ // Extra modem set-up Serial.println(F("Waking modem and setting Cellular Carrier Options...")); modem.modemWake(); // NOTE: This will also set up the modem // Go back to command mode to set carrier options modem.gsmModem.commandMode(); // Carrier Profile - 0 = Automatic selection // - 1 = No profile/SIM ICCID selected // - 2 = AT&T // - 3 = Verizon // NOTE: To select T-Mobile, you must enter bypass mode! modem.gsmModem.sendAT(GF("CP"), 2); modem.gsmModem.waitResponse(); // Cellular network technology - 0 = LTE-M with NB-IoT fallback // - 1 = NB-IoT with LTE-M fallback // - 2 = LTE-M only // - 3 = NB-IoT only // NOTE: As of 2020 in the USA, AT&T and Verizon only use LTE-M // T-Mobile uses NB-IOT modem.gsmModem.sendAT(GF("N#"), 2); modem.gsmModem.waitResponse(); // Write changes to flash and apply them Serial.println(F("Wait while applying changes...")); // Write changes to flash modem.gsmModem.writeChanges(); // Reset the cellular component to ensure network settings are changed modem.gsmModem.sendAT(GF("!R")); modem.gsmModem.waitResponse(30000L); // Force reset of the Digi component as well // This effectively exits command mode modem.gsmModem.sendAT(GF("FR")); modem.gsmModem.waitResponse(5000L); /** End [setup_xbeec_carrier] */ #endif #if defined BUILD_MODEM_DIGI_XBEE_LTE_BYPASS /** Start [setup_r4_carrrier] */ // Extra modem set-up Serial.println(F("Waking modem and setting Cellular Carrier Options...")); modem.modemWake(); // NOTE: This will also set up the modem // Turn off the cellular radio while making network changes modem.gsmModem.sendAT(GF("+CFUN=0")); modem.gsmModem.waitResponse(); // Mobile Network Operator Profile - 0 = SW default // - 1 = SIM ICCID selected // - 2: ATT // - 6: China Telecom // - 100: Standard Europe // - 4: Telstra // - 5: T-Mobile US // - 19: Vodafone // - 3: Verizon // - 31: Deutsche Telekom modem.gsmModem.sendAT(GF("+UMNOPROF="), 2); modem.gsmModem.waitResponse(); // Selected network technology - 7: LTE Cat.M1 // - 8: LTE Cat.NB1 // Fallback network technology - 7: LTE Cat.M1 // - 8: LTE Cat.NB1 // NOTE: As of 2020 in the USA, AT&T and Verizon only use LTE-M // T-Mobile uses NB-IOT modem.gsmModem.sendAT(GF("+URAT="), 7, ',', 8); modem.gsmModem.waitResponse(); // Restart the module to apply changes modem.gsmModem.sendAT(GF("+CFUN=1,1")); modem.gsmModem.waitResponse(10000L); /** End [setup_r4_carrrier] */ #endif /** Start [setup_clock] */ // Sync the clock if it isn't valid or we have battery to spare if (getBatteryVoltage() > 3.55 || !dataLogger.isRTCSane()) { // Synchronize the RTC with NIST // This will also set up the modem dataLogger.syncRTC(); } /** End [setup_clock] */ /** Start [setup_file] */ // Create the log file, adding the default header to it // Do this last so we have the best chance of getting the time correct and // all sensor names correct // Writing to the SD card can be power intensive, so if we're skipping // the sensor setup we'll skip this too. if (getBatteryVoltage() > 3.4) { Serial.println(F("Setting up file on SD card")); dataLogger.turnOnSDcard(true); // true = wait for card to settle after power up dataLogger.createLogFile(true); // true = write a new header dataLogger.turnOffSDcard(true); // true = wait for internal housekeeping after write } /** End [setup_file] */ /** Start [setup_sleep] */ // Call the processor sleep Serial.println(F("Putting processor to sleep\n")); dataLogger.systemSleep(); /** End [setup_sleep] */ } // ========================================================================== // Arduino Loop Function // ========================================================================== #ifndef BUILD_TEST_COMPLEX_LOOP // Use this short loop for simple data logging and sending /** Start [simple_loop] */ void loop() { // Note: Please change these battery voltages to match your battery // At very low battery, just go back to sleep if (getBatteryVoltage() < 3.4) { dataLogger.systemSleep(); } else if (getBatteryVoltage() < 3.55) { // At moderate voltage, log data but don't send it over the modem dataLogger.logData(); } else { // If the battery is good, send the data to the world dataLogger.logDataAndPublish(); } } /** End [simple_loop] */ #else /** Start [complex_loop] */ // Use this long loop when you want to do something special // Because of the way alarms work on the RTC, it will wake the processor and // start the loop every minute exactly on the minute. // The processor may also be woken up by another interrupt or level change on a // pin - from a button or some other input. // The "if" statements in the loop determine what will happen - whether the // sensors update, testing mode starts, or it goes back to sleep. void loop() { // Reset the watchdog dataLogger.watchDogTimer.resetWatchDog(); // Assuming we were woken up by the clock, check if the current time is an // even interval of the logging interval // We're only doing anything at all if the battery is above 3.4V if (dataLogger.checkInterval() && getBatteryVoltage() > 3.4) { // Flag to notify that we're in already awake and logging a point Logger::isLoggingNow = true; dataLogger.watchDogTimer.resetWatchDog(); // Print a line to show new reading Serial.println(F("------------------------------------------")); // Turn on the LED to show we're taking a reading dataLogger.alertOn(); // Power up the SD Card, but skip any waits after power up dataLogger.turnOnSDcard(false); dataLogger.watchDogTimer.resetWatchDog(); // Turn on the modem to let it start searching for the network // Only turn the modem on if the battery at the last interval was high // enough // NOTE: if the modemPowerUp function is not run before the // completeUpdate // function is run, the modem will not be powered and will not // return a signal strength reading. if (getBatteryVoltage() > 3.6) modem.modemPowerUp(); #ifdef BUILD_TEST_ALTSOFTSERIAL // Start the stream for the modbus sensors, if your RS485 adapter bleeds // current from data pins when powered off & you stop modbus serial // connection with digitalWrite(5, LOW), below. // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833 altSoftSerial.begin(9600); #endif // Do a complete update on the variable array. // This this includes powering all of the sensors, getting updated // values, and turing them back off. // NOTE: The wake function for each sensor should force sensor setup // to run if the sensor was not previously set up. varArray.completeUpdate(); dataLogger.watchDogTimer.resetWatchDog(); #ifdef BUILD_TEST_ALTSOFTSERIAL // Reset modbus serial pins to LOW, if your RS485 adapter bleeds power // on sleep, because Modbus Stop bit leaves these pins HIGH. // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833 digitalWrite(5, LOW); // Reset AltSoftSerial Tx pin to LOW digitalWrite(6, LOW); // Reset AltSoftSerial Rx pin to LOW #endif // Create a csv data record and save it to the log file dataLogger.logToSD(); dataLogger.watchDogTimer.resetWatchDog(); // Connect to the network // Again, we're only doing this if the battery is doing well if (getBatteryVoltage() > 3.55) { dataLogger.watchDogTimer.resetWatchDog(); if (modem.connectInternet()) { dataLogger.watchDogTimer.resetWatchDog(); // Publish data to remotes Serial.println(F("Modem connected to internet.")); dataLogger.publishDataToRemotes(); // Sync the clock at noon dataLogger.watchDogTimer.resetWatchDog(); if (Logger::markedLocalEpochTime != 0 && Logger::markedLocalEpochTime % 86400 == 43200) { Serial.println(F("Running a daily clock sync...")); dataLogger.setRTClock(modem.getNISTTime()); dataLogger.watchDogTimer.resetWatchDog(); modem.updateModemMetadata(); dataLogger.watchDogTimer.resetWatchDog(); } // Disconnect from the network modem.disconnectInternet(); dataLogger.watchDogTimer.resetWatchDog(); } // Turn the modem off modem.modemSleepPowerDown(); dataLogger.watchDogTimer.resetWatchDog(); } // Cut power from the SD card - without additional housekeeping wait dataLogger.turnOffSDcard(false); dataLogger.watchDogTimer.resetWatchDog(); // Turn off the LED dataLogger.alertOff(); // Print a line to show reading ended Serial.println(F("------------------------------------------\n")); // Unset flag Logger::isLoggingNow = false; } // Check if it was instead the testing interrupt that woke us up if (Logger::startTesting) { #ifdef BUILD_TEST_ALTSOFTSERIAL // Start the stream for the modbus sensors, if your RS485 adapter bleeds // current from data pins when powered off & you stop modbus serial // connection with digitalWrite(5, LOW), below. // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833 altSoftSerial.begin(9600); #endif dataLogger.testingMode(); } #ifdef BUILD_TEST_ALTSOFTSERIAL // Reset modbus serial pins to LOW, if your RS485 adapter bleeds power // on sleep, because Modbus Stop bit leaves these pins HIGH. // https://github.com/EnviroDIY/ModularSensors/issues/140#issuecomment-389380833 digitalWrite(5, LOW); // Reset AltSoftSerial Tx pin to LOW digitalWrite(6, LOW); // Reset AltSoftSerial Rx pin to LOW #endif // Call the processor sleep dataLogger.systemSleep(); } #endif /** End [complex_loop] */