Example showing all possible functionality
-
Walking Through the Code
- Defines and Includes
- Logger Settings
-
WiFi/Cellular Modem Options
- Digi XBee Cellular - Transparent Mode
- Digi XBee3 LTE-M - Bypass Mode
- Digi XBee 3G - Bypass Mode
- Digi XBee S6B WiFi
- Espressif ESP8266
- Espressif ESP32
- Quectel BG96
- Sequans Monarch
- SIMCom SIM800
- SIMCom SIM7000
- SIMCom SIM7080G (EnviroDIY LTE Bee])
- Sodaq GPRSBee
- u-blox SARA R410M
- u-blox SARA U201
- Modem Measured Variables
-
Sensors and Measured Variables
- The processor as a sensor
- Maxim DS3231 RTC as a sensor
- Alphasense CO2
- ANB Sensors pH Sensor
- AOSong AM2315
- AOSong DHT
- Apogee SQ-212 Quantum Light Sensor
- Atlas Scientific EZO Circuits
- Bosch BME280 Environmental Sensor
- Bosch BMP388 and BMP398 Pressure Sensors
- Campbell OBS3+ Analog Turbidity Sensor
- Decagon ES2 Conductivity and Temperature Sensor
- External Voltage via TI ADS1x15
- Freescale Semiconductor MPL115A2 Miniature I2C Digital Barometer
- Geolux HydroCam Camera
- GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe
- Keller RS485/Modbus Water Level Sensors
- Maxbotix HRXL Ultrasonic Range Finder
- Maxim DS18 One Wire Temperature Sensor
- Measurement Specialties MS5803-14BA Pressure Sensor
- Meter SDI-12 Sensors
- PaleoTerra Redox Sensors
- Trinket-Based Tipping Bucket Rain Gauge
- PlatformIO Configuration
- The Complete Code
This shows most of the functionality of the library at once. It has code in it for every possible sensor and modem and for both AVR and SAMD boards. This example should never be used directly; it is intended to document all possibilities and to verify compilation.
To create your own code, I recommend starting from a much simpler targeted example, like the Logging to MMW example, and then adding to it based on only the parts of this menu example that apply to you.
Walking Through the Code
Defines and Includes
Defines for the Arduino IDE
The top few lines of the examples set defines of buffer sizes and yields needed for the Arduino IDE. That IDE read any defines within the top few lines and applies them as build flags for the processor. This is not standard behavior for C++ (which is what Arduino code really is) - this is a unique aspect of the Arduino IDE.
If you are using PlatformIO, you should instead set these as global build flags in your platformio.ini. This is standard behavior for C++.
Library Includes
Next, include the libraries needed for every program using ModularSensors.
Logger Settings
Creating Extra Serial Ports
This section of the example has all the code to create and link to serial ports for both AVR and SAMD based boards. The EnviroDIY Mayfly, the Arduino Mega, UNO, and Leonardo are all AVR boards. The Arduino Zero, the M0 and the Sodaq Autonomo are all SAMD boards.
Many different sensors communicate using some sort of serial or transistor-transistor-logic (TTL) protocol. Among these are any sensors using RS232, RS485, RS422. Generally each serial variant (or sometimes each sensor) needs a dedicated serial "port" - its own connection to the processor. Most processors have built in dedicated wires for serial communication - "Hardware" serial. See the page on Arduino streams for much more detail about serial connections with Arduino processors.
AVR Boards
Most Arduino AVR style boards have very few (ie, one, or none) dedicated serial ports available after counting out the programming serial port. So to connect anything else, we need to try to emulate the processor serial functionality with a software library. This example shows three possible libraries that can be used to emulate a serial port on an AVR board.
AltSoftSerial
AltSoftSerial by Paul Stoffregen 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. See the processor compatibility page for more information on which pins are used on supported boards.
NeoSWSerial
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 want. Each instance requires two pins, one for data in and another for data out. If you only want to use the serial line for incoming or outgoing data, set the other pin to -1. Not all AVR boards are supported by NeoSWSerial.
When using NeoSWSerial we will also have to actually set the data receiving (Rx) pin modes for interrupt in the setup function.
SoftwareSerial with External Interrupts
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 but it is still far from ideal. This should be used only use if necessary. It is not a very accurate serial port!
Accepting its poor quality, you can use as many instances of SoftwareSerial as you want. Each instance requires two pins, one for data in and another for data out. If you only want to use the serial line for incoming or outgoing data, set the other pin to -1.
When using SoftwareSerial with External Interrupts we will also have to actually set the data receiving (Rx) pin modes for interrupt in the setup function.
Software I2C/Wire
This creates a software I2C (wire) instance that can be shared between multiple sensors. Only Testato's SoftwareWire library is supported.
SAMD Boards
The SAMD21 supports up to 6 hardware serial ports, which is awesome. But, the Arduino core doesn't make use of all of them, so we have to assign them ourselves.
This section of code assigns SERCOM's 1 and 2 to act as Serial2 and Serial3 on pins 10/11 and 5/2 respectively. These pin selections are based on the Adafruit Feather M0.
In addition to creating the extra SERCOM ports here, the pins must be set up as the proper pin peripherals after the serial ports are begun. This is shown in the SAMD Pin Peripherals section of the setup function.
NOTE: The SAMD51 board has an amazing 8 available SERCOM's, but I do not have any example code for using them.
Assigning Serial Port Functionality
This section just assigns all the serial ports from the Creating Extra Serial Ports section above to specific functionality. For a board with the option of up to 4 hardware serial ports, like the SAMD21 or Arduino Mega, we use the Serial1 to talk to the modem, Serial2 for modbus, and Serial3 for the Maxbotix.
For an AVR board where we're relying on a mix of hardware and software ports, we use hardware Serial 1 for the modem, AltSoftSerial for modbus, and NeoSWSerial for the Maxbotix. Depending on how you rank the importance of each component, you can adjust these to your liking.
Logging Options
Here we set options for the logging and dataLogger object. This includes setting the time zone (daylight savings time is NOT applied) and setting all of the input and output pins related to the logger.
WiFi/Cellular Modem Options
This modem section is very lengthy because it contains the code with the constructor for every possible supported modem module. Do NOT try to use more than one modem at a time - it will NOT work.
To create any of the modems, we follow a similar pattern:
First, we'll create a pointer to the serial port (Arduino Stream object) that we'll use for communication between the modem and the MCU. We also assign the baud rate to a variable here. There is a table of Default baud rates of supported modules on the Notes about Modems page. The baud rate of any of the modules can be changed using AT commands or the modem.gsmModem.setBaud(uint32_t baud)
function.
Next, we'll assign all the pin numbers for all the other pins connected between the modem and the MCU. Pins that do not apply should be set as -1. There is a table of general Sleep and Reset Pin Labels and Pin Numbers to Use when Connecting to a Mayfly 0.x on the Notes about Modems page.
All the modems also need some sort of network credentials for internet access. For WiFi modems, you need the network name and password (assuming WPA2). For cellular models, you will need the APN assigned to you by the carrier you bought your SIM card from.
Digi XBee Cellular - Transparent Mode
This is the code to use for any of Digi's cellular XBee or XBee3 modules. All of them can be implemented as a DigiXBeeCellularTransparent object - a subclass of DigiXBee and loggerModem. To create a DigiXBeeCellularTransparent object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the status pin,
- whether the status pin is the true status pin (
ON/SLEEP_N/DIO9
) or theCTS_N/DIO7
pin, - the MCU pin connected to the
RESET_N
pin, - the
DTR_N/SLEEP_RQ/DIO8
pin, - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the EnviroDIY Mayfly is available on the Modem Notes page.
[!NOTE] The u-blox based Digi XBee's (3G global and LTE-M global) may be more stable used in bypass mode (below). The Telit based Digi XBees (LTE Cat1 both Verizon and AT&T) can only use this mode.
Depending on your cellular carrier, it is best to select the proper carrier profile and network. Setting these helps the modem to connect to network faster. This is shows in the XBee Cellular Carrier chunk of the setup function.
Digi XBee3 LTE-M - Bypass Mode
This code is for Digi's LTE-M XBee3 based on the u-blox SARA R410M - used in bypass mode. To create a DigiXBeeLTEBypass object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the status pin,
- whether the status pin is the true status pin (
ON/SLEEP_N/DIO9
) or theCTS_N/DIO7
pin, - the MCU pin connected to the
RESET_N
pin, - the
DTR_N/SLEEP_RQ/DIO8
pin, - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the EnviroDIY Mayfly is available on the Modem Notes page.
Depending on your cellular carrier, it is best to select the proper carrier profile and network. Setting these helps the modem to connect to network faster. This is shows in the SARA R4 Cellular Carrier chunk of the setup function.
Digi XBee 3G - Bypass Mode
This code is for Digi's 3G/2G XBee based on the u-blox SARA U201 - used in bypass mode. To create a DigiXBee3GBypass object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the status pin,
- whether the status pin is the "true" status pin (
ON/SLEEP_N/DIO9
) or theCTS_N/DIO7
pin, - the MCU pin connected to the
RESET_N
pin, - the
DTR_N/SLEEP_RQ/DIO8
pin, - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the EnviroDIY Mayfly is available on the Modem Notes page.
Digi XBee S6B WiFi
This code is for the Digi's S6B wifi module. To create a DigiXBeeWiFi object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the status pin,
- whether the status pin is the "true" status pin (
ON/SLEEP_N/DIO9
) or theCTS_N/DIO7
pin, - the MCU pin connected to the
RESET_N
pin, - the
DTR_N/SLEEP_RQ/DIO8
pin, - the wifi access point name,
- and the wifi WPA2 password.
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the EnviroDIY Mayfly is available on the Modem Notes page.
Espressif ESP8266
This code is for the Espressif ESP8266 operating with "AT" firmware. To create a EspressifESP8266 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the reset pin (MCU pin connected to the ESP's
RSTB/DIO16
), - the wifi access point name,
- and the wifi WPA2 password.
Pins that do not apply should be set as -1.
Espressif ESP32
This code is for the Espressif ESP32 operating with "AT" firmware. To create a EspressifESP32 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the reset pin (MCU pin connected to the ESP's
RSTB/DIO16
), - the wifi access point name,
- and the wifi WPA2 password.
Pins that do not apply should be set as -1.
Because the ESP32's default baud rate is too fast for an 8MHz board like the Mayfly, to use it you need to drop the baud rate down for successful communication. You can set the slower baud rate using some external method, or using the code from the ESP8266 Baud Rate(https://envirodiy.github.io/ModularSensors/menu_
Quectel BG96
This code is for the Dragino, Nimbelink or other boards based on the Quectel BG96. To create a QuectelBG96 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
STATUS
pin, - the MCU pin connected to the
RESET_N
pin, - the MCU pin connected to the
PWRKEY
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1.
If you are interfacing with a Nimbelink Skywire board via the Skywire development board, you also need to handle the fact that the development board reverses the levels of the status, wake, and reset pins. Code to invert the pin levels is in the Skywire Pin Inversions part of the setup function below.
Sequans Monarch
This code is for the Nimbelink LTE-M Verizon/Sequans or other boards based on the Sequans Monarch series SoC. To create a SequansMonarch object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to either the
GPIO3/STATUS_LED
orPOWER_MON
pin, - the MCU pin connected to the
RESETN
pin, - the MCU pin connected to the
RTS
orRTS0
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1.
If you are interfacing with a Nimbelink Skywire board via the Skywire development board, you also need to handle the fact that the development board reverses the levels of the status, wake, and reset pins. Code to invert the pin levels is in the Skywire Pin Inversions part of the setup function below.
The default baud rate of the SVZM20 is much too fast for almost all Arduino boards. Before attempting to connect a SVZM20 to an Arduino you should connect it to your computer and use AT commands to decrease the baud rate. The proper command to decrease the baud rate to 9600 (8N1) is: AT+IPR=9600
.
SIMCom SIM800
This code is for a SIMCom SIM800 or SIM900 or one of their many variants, including the Adafruit Fona and the Sodaq 2GBee R4. To create a SIMComSIM800 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
STATUS
pin, - the MCU pin connected to the
RESET
pin, - the MCU pin connected to the
PWRKEY
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1.
NOTE: This is NOT the correct form for a Sodaq 2GBee R6 or R7. See the section for a 2GBee R6.
SIMCom SIM7000
This code is for a SIMCom SIM7000 or one of its variants. To create a SIMComSIM7000 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
STATUS
pin, - the MCU pin connected to the
RESET
pin, - the MCU pin connected to the
PWRKEY
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1.
SIMCom SIM7080G (EnviroDIY LTE Bee])
This code is for a SIMCom SIM7080G or one of its variants, including the EnviroDIY LTE Bee.
To create a SIMComSIM7080 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
STATUS
pin, - the MCU pin connected to the
PWRKEY
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the EnviroDIY LTE Bee and the EnviroDIY Mayfly is available on the Modem Notes page.
Sodaq GPRSBee
This code is for the Sodaq 2GBee R6 and R7 based on the SIMCom SIM800. To create a Sodaq2GBeeR6 object we need to know
- the serial object name,
- the MCU pin controlling modem power, (NOTE: On the GPRSBee R6 and R7 the pin labeled as ON/OFF in Sodaq's diagrams is tied to both the SIM800 power supply and the (inverted) SIM800
PWRKEY
. You should enter this pin as the power pin.) - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. The GPRSBee R6/R7 does not expose the RESET
pin of the SIM800. The PWRKEY
is held LOW
as long as the SIM800 is powered (as mentioned above). A helpful table detailing the pins to use with the Sodaq GPRSBee and the EnviroDIY Mayfly is available on the Modem Notes page.
u-blox SARA R410M
This code is for modules based on the 4G LTE-M u-blox SARA R410M including the Sodaq UBee. To create a SodaqUBeeR410M object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
V_INT
pin (for status), - the MCU pin connected to the
RESET_N
pin, - the MCU pin connected to the
PWR_ON
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the UBee R410M and the EnviroDIY Mayfly is available on the Modem Notes page.
Depending on your cellular carrier, it is best to select the proper carrier profile and network. Setting these helps the modem to connect to network faster. This is shows in the SARA R4 Cellular Carrier chunk of the setup function.
u-blox SARA U201
This code is for modules based on the 3G/2G u-blox SARA U201 including the Sodaq UBee or the Sodaq 3GBee. To create a SodaqUBeeU201 object we need to know
- the serial object name,
- the MCU pin controlling modem power,
- the MCU pin connected to the
V_INT
pin (for status), - the MCU pin connected to the
RESET_N
pin, - the MCU pin connected to the
PWR_ON
pin (for sleep request), - and the SIM card's cellular access point name (APN).
Pins that do not apply should be set as -1. A helpful table detailing the pins to use with the Sodaq UBee U201 and the EnviroDIY Mayfly is available on the Modem Notes page.
Modem Measured Variables
After creating the modem object, we can create Variable objects for each of the variables the modem is capable of measuring (Modem_
Sensors and Measured Variables
The processor as a sensor
Set options and create the objects for using the processor as a sensor to report battery level, processor free ram, and sample number.
The processor can return the number of "samples" it has taken, the amount of RAM it has available and, for some boards, the battery voltage (EnviroDIY Mayfly, Sodaq Mbili, Ndogo, Autonomo, and One, Adafruit Feathers). The version of the board is required as input (ie, for a EnviroDIY Mayfly: "v0.3" or "v0.4" or "v0.5"). Use a blank value (ie, "") for un-versioned boards. Please note that while you can opt to average more than one sample, it really makes no sense to do so for the processor. The number of "samples" taken will increase by one for each time another processor "measurement" is taken so averaging multiple measurements from the processor will result in the number of samples increasing by more than one with each loop.
Maxim DS3231 RTC as a sensor
In addition to the time, we can also use the required DS3231 real time clock to report the temperature of the circuit board. This temperature is not equivalent to an environmental temperature measurement and should only be used to as a diagnostic. As above, we create both the sensor and the variables measured by it.
Alphasense CO2
ANB Sensors pH Sensor
AOSong AM2315
Here is the code for the AOSong AM2315 temperature and humidity sensor. This is an I2C sensor with only one possible address so the only argument required for the constructor is the pin on the MCU controlling power to the AM2315 (AM2315Power). The number of readings to average from the sensor is optional, but can be supplied as the second argument for the constructor if desired.
AOSong DHT
Here is the code for the AOSong DHT temperature and humidity sensor. To create the DHT Sensor we need the power pin, the data pin, and the DHT type. The number of readings to average from the sensor is optional, but can be supplied as the fourth argument for the constructor if desired.
Apogee SQ-212 Quantum Light Sensor
Here is the code for the Apogee SQ-212 Quantum Light Sensor. The SQ-212 is not directly connected to the MCU, but rather to an TI ADS1115 that communicates with the MCU. The Arduino pin controlling power on/off and the analog data channel on the TI ADS1115 are required for the sensor constructor. If your ADD converter is not at the standard address of 0x48, you can enter its actual address as the third argument. The number of readings to average from the sensor is optional, but can be supplied as the fourth argument for the constructor if desired.
Atlas Scientific EZO Circuits
The next several sections are for Atlas Scientific EZO circuits and sensors. The sensor class constructors for each are nearly identical, except for the class name. In the most common setup, with hardware I2C, the only required argument for the constructor is the Arduino pin controlling power on/off; the i2cAddressHex is optional as is the number of readings to average.
The default I2C addresses for the circuits are:
- CO2: 0x69 (105)
- DO: 0x61 (97)
- EC (conductivity): 0x64 (100)
- ORP (redox): 0x62 (98)
- pH: 0x63 (99)
- RTD (temperature): 0x66 (102) All of the circuits can be re-addressed to any other 8 bit number if desired. To use multiple circuits of the same type, re-address them.
Atlas Scientific EZO-CO2 Embedded NDIR Carbon Dioxide Sensor
Atlas Scientific EZO-DO Dissolved Oxygen Sensor
Atlas Scientific EZO-ORP Oxidation/Reduction Potential Sensor
Atlas Scientific EZO-pH Sensor
Atlas Scientific EZO-RTD Temperature Sensor
Atlas Scientific EZO-EC Conductivity Sensor
Bosch BME280 Environmental Sensor
Here is the code for the Bosch BME280 environmental sensor. The only input needed is the Arduino pin controlling power on/off; the i2cAddressHex is optional as is the number of readings to average. Keep in mind that the possible I2C addresses of the BME280 match those of the MS5803; when using those sensors together, make sure they are set to opposite addresses.
Bosch BMP388 and BMP398 Pressure Sensors
Campbell ClariVUE SDI-12 Turbidity Sensor
Campbell OBS3+ Analog Turbidity Sensor
This is the code for the Campbell OBS3+. The Arduino pin controlling power on/off, analog data channel on the TI ADS1115, and calibration values in Volts for Ax^2 + Bx + C are required for the sensor constructor. A custom variable code can be entered as a second argument in the variable constructors, and it is very strongly recommended that you use this otherwise it will be very difficult to determine which return is high and which is low range on the sensor. If your ADD converter is not at the standard address of 0x48, you can enter its actual address as the third argument. Do NOT forget that if you want to give a number of measurements to average, that comes after the i2c address in the constructor!
Note that to access both the high and low range returns, two instances must be created, one at the low range return pin and one at the high pin.
Campbell RainVUE SDI-12 Precipitation Sensor
Decagon CTD-10 Conductivity, Temperature, and Depth Sensor
Decagon ES2 Conductivity and Temperature Sensor
The SDI-12 address of the sensor, the Arduino pin controlling power on/off, and the Arduino pin sending and receiving data are required for the sensor constructor. Optionally, you can include a number of distinct readings to average. The data pin must be a pin that supports pin-change interrupts.
Everlight ALS-PT19 Ambient Light Sensor
External Voltage via TI ADS1x15
The Arduino pin controlling power on/off and the analog data channel on the TI ADS1115 are required for the sensor constructor. If using a voltage divider to increase the measurable voltage range, enter the gain multiplier as the third argument. If your ADD converter is not at the standard address of 0x48, you can enter its actual address as the fourth argument. The number of measurements to average, if more than one is desired, goes as the fifth argument.
Freescale Semiconductor MPL115A2 Miniature I2C Digital Barometer
The only input needed for the sensor constructor is the Arduino pin controlling power on/off and optionally the number of readings to average. Because this sensor can have only one I2C address (0x60), it is only possible to connect one of these sensors to your system.
Geolux HydroCam Camera
GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe
In-Situ Aqua/Level TROLL Pressure, Temperature, and Depth Sensor
In-Situ RDO PRO-X Rugged Dissolved Oxygen Probe
Keller RS485/Modbus Water Level Sensors
The next two sections are for Keller RS485/Modbus water level sensors. The sensor class constructors for each are nearly identical, except for the class name. The sensor constructors require as input: the sensor modbus address, a stream instance for data (ie, Serial
), and one or two power pins. The Arduino pin controlling the receive and data enable on your RS485-to-TTL adapter and the number of readings to average are optional. (Use -1 for the second power pin and -1 for the enable pin if these don't apply and you want to average more than one reading.) Please see the section "[Notes on Arduino Streams and Software Serial](@ref page_arduino_streams)" for more information about what streams can be used along with this library. In tests on these sensors, SoftwareSerial_ExtInts did not work to communicate with these sensors, because it isn't stable enough. AltSoftSerial and HardwareSerial work fine.
The serial ports for this example are created in the Creating Extra Serial Ports section and then assigned to modbus functionality in the Assigning Serial Port Functionality section.
Up to two power pins are provided so that the RS485 adapter, the sensor and/or an external power relay can be controlled separately. If the power to everything is controlled by the same pin, use -1 for the second power pin or omit the argument. If they are controlled by different pins and no other sensors are dependent on power from either pin then the order of the pins doesn't matter. If the RS485 adapter, sensor, or relay are controlled by different pins and any other sensors are controlled by the same pins you should put the shared pin first and the un-shared pin second. Both pins cannot be shared pins.
Keller Acculevel High Accuracy Submersible Level Transmitter
Keller Nanolevel Level Transmitter
Maxbotix HRXL Ultrasonic Range Finder
The Arduino pin controlling power on/off, a stream instance for received data (ie, Serial
), and the Arduino pin controlling the trigger are required for the sensor constructor. (Use -1 for the trigger pin if you do not have it connected.) Please see the section "[Notes on Arduino Streams and Software Serial](@ref page_arduino_streams)" for more information about what streams can be used along with this library.
The serial ports for this example are created in the Creating Extra Serial Ports section and then assigned to the sonar functionality in the Assigning Serial Port Functionality section.
Maxim DS18 One Wire Temperature Sensor
The OneWire hex address of the sensor, the Arduino pin controlling power on/off, and the Arduino pin sending and receiving data are required for the sensor constructor, though the address can be omitted if only one sensor is used. The OneWire address is an array of 8 hex values, for example: {0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0}. To get the address of your sensor, plug a single sensor into your device and run the oneWireSearch example or the Single example provided within the Dallas Temperature library. The sensor address is programmed at the factory and cannot be changed.
Measurement Specialties MS5803-14BA Pressure Sensor
The only input needed is the Arduino pin controlling power on/off; the i2cAddressHex and maximum pressure are optional as is the number of readings to average. Keep in mind that the possible I2C addresses of the MS5803 match those of the BME280.
Meter SDI-12 Sensors
The next few sections are for Meter SDI-12 sensors. The SDI-12 address of the sensor, the Arduino pin controlling power on/off, and the Arduino pin sending and receiving data are required for the sensor constructor. Optionally, you can include a number of distinct readings to average. The data pin must be a pin that supports pin-change interrupts.
Meter ECH2O Soil Moisture Sensor
Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
Meter Teros 11 Soil Moisture Sensor
PaleoTerra Redox Sensors
Because older versions of these sensors all ship with the same I2C address, and more than one is frequently used at different soil depths in the same profile, this module has an optional dependence on Testato's SoftwareWire library for software I2C.
To use software I2C, compile with the build flag -D MS_PALEOTERRA_SOFTWAREWIRE
. See the software wire section for an example of creating a software I2C instance to share between sensors.
The constructors for the software I2C implementation requires either the SCL and SDA pin numbers or a reference to the I2C object as arguments. All variants of the constructor require the Arduino power pin. The I2C address can be given if it the sensor is not set to the default of 0x68. A number of readings to average can also be given.
Trinket-Based Tipping Bucket Rain Gauge
This is for use with a simple external I2C tipping bucket counter based on the Adafruit Trinket. All constructor arguments are optional, but the first argument is for the I2C address of the tip counter (if not 0x08) and the second is for the depth of rain (in mm) per tip event (if not 0.2mm). Most metric tipping buckets are calibrated to have 1 tip per 0.2mm of rain. Most English tipping buckets are calibrated to have 1 tip per 0.01" of rain, which is 0.254mm.
Note that you cannot input a number of measurements to average because averaging does not make sense with this kind of counted variable.
@see @ref sensor_i2c_rain
@snippet{lineno} menu_a_la_carte.ino rain_counter_i2c
<hr>
@paragraph menu_walk_sensirion_sht4x Sensirion SHT4X Digital Humidity and Temperature Sensor
@see @ref sensor_sht4x
@snippet{lineno} menu_a_la_carte.ino sensirion_sht4x
<hr>
@subsubsection menu_walk_tally Northern Widget Tally Event Counter
This is for use with Northern Widget's Tally event counter
\attention
Northern Widget considers this sensor to be one of their "bleeding edge" sensors.
As such, it is subject to change at any time.
This library may not be updated immediately to reflect changes on the part of Northern Widget.
The only option for the constructor is an optional setting for the I2C address, if the counter is not set at the default of 0x33.
The counter should be continuously powered.
@see @ref sensor_tally
@snippet{lineno} menu_a_la_carte.ino tally_counter_i2c
<hr>
@subsubsection menu_walk_ti_ina219 TI INA219 High Side Current Sensor
This is the code for the TI INA219 high side current and voltage sensor.
The Arduino pin controlling power on/off is all that is required for the constructor.
If your INA219 is not at the standard address of 0x40, you can enter its actual address as the fourth argument.
The number of measurements to average, if more than one is desired, goes as the fifth argument.
@see @ref sensor_ina219
@snippet{lineno} menu_a_la_carte.ino ti_ina219
<hr>
@subsubsection menu_walk_turner_cyclops Turner Cyclops-7F Submersible Fluorometer
This is the code for the Turner Cyclops-7F submersible fluorometer.
The Arduino pin controlling power on/off and all calibration information is needed for the constructor.
The address of the ADS1x15, if it is different than the default of 0x48, can be entered after the calibration information.
The number of measurements to average, if more than one is desired, is the last argument.
The Cyclops sensors are <em>NOT</em> pre-calibrated and must be calibrated prior to deployment.
@see @ref sensor_cyclops
@snippet{lineno} menu_a_la_carte.ino turner_cyclops
<hr>
@subsubsection menu_walk_turner_turbidity_plus Turner Turbidity Plus with Integrated Wiper
This is the code for the Turner Turbidity Plus analog turbidity sensor.
The Turbidity Plus sensors are <em>NOT</em> pre-calibrated and must be calibrated prior to deployment.
@see @ref sensor_turbidity_plus
@snippet{lineno} menu_a_la_carte.ino turner_turbidity_plus
<hr>
@subsubsection menu_walk_analog_elec_conductivity Analog Electrical Conductivity using the Processor's Analog Pins
This is the code for the measuring electrical conductivity using the processor's internal ADC and analog input pins.
The Arduino pin controlling power on/off and the sensing pin are required for the constructor.
The power supply for the sensor <em>absolutely must be switched on and off between readings</em>!
The resistance of your in-circuit resistor, the cell constant for your power cord, and the number of measurements to average are the optional third, fourth, and fifth arguments.
For best results, you should also connect the AREF pin of your processors ADC to the power supply for the and compile with the build flag <tt>-D MS_PROCESSOR_ADC_REFERENCE_MODE=EXTERNAL</tt>.
@see @ref sensor_analog_cond
@snippet{lineno} menu_a_la_carte.ino analog_elec_conductivity
<hr>
@paragraph menu_walk_vega_puls21 VEGA VEGA PULS 21
@see @ref sensor_vega_puls21
@snippet{lineno} menu_a_la_carte.ino vega_puls21
<hr>
@subsubsection menu_walk_yosemitech_sensors Yosemitech RS485/Modbus Environmental Sensors
The next several sections are for Yosemitech brand sensors.
The sensor class constructors for each are nearly identical, except for the class name.
The sensor constructor requires as input: the sensor modbus address, a stream instance for data (ie, <tt>Serial</tt>), and one or two power pins.
The Arduino pin controlling the receive and data enable on your RS485-to-TTL adapter and the number of readings to average are optional.
(Use -1 for the second power pin and -1 for the enable pin if these don't apply and you want to average more than one reading.)
For most of the sensors, Yosemitech strongly recommends averaging multiple (in most cases 10) readings for each measurement.
Please see the section "[Notes on Arduino Streams and Software Serial](Notes on Arduino Streams and Software Serial)" for more information about what streams can be used along with this library.
In tests on these sensors, SoftwareSerial_ExtInts <em>did not work</em> to communicate with these sensors, because it isn't stable enough.
AltSoftSerial and HardwareSerial work fine.
NeoSWSerial is a bit hit or miss, but can be used in a pinch.
The serial ports for this example are created in the @ref menu_walk_serial_ports section and then assigned to modbus functionality in the @ref menu_walk_assign_ports_sw section.
@see @ref yosemitech_group
@paragraph menu_walk_yosemitech_y504 Yosemitech Y504 Dissolved Oxygen Sensor
@see @ref sensor_y504
@snippet{lineno} menu_a_la_carte.ino yosemitech_y504
<hr>
@paragraph menu_walk_yosemitech_y510 Yosemitech Y510 Turbidity Sensor
@see @ref sensor_y510
@snippet{lineno} menu_a_la_carte.ino yosemitech_y510
<hr>
@paragraph menu_walk_yosemitech_y511 Yosemitech Y511 Turbidity Sensor with Wiper
@see @ref sensor_y511
@snippet{lineno} menu_a_la_carte.ino yosemitech_y511
<hr>
@paragraph menu_walk_yosemitech_y513 Yosemitech Y513 Blue-Green Algae Sensor
@see @ref sensor_y513
@snippet{lineno} menu_a_la_carte.ino yosemitech_y513
<hr>
@paragraph menu_walk_yosemitech_y514 Yosemitech Y514 Chlorophyll Sensor
@see @ref sensor_y514
@snippet{lineno} menu_a_la_carte.ino yosemitech_y514
<hr>
@paragraph menu_walk_yosemitech_y520 Yosemitech Y520 Conductivity Sensor
@see @ref sensor_y520
@snippet{lineno} menu_a_la_carte.ino yosemitech_y520
<hr>
@paragraph menu_walk_yosemitech_y532 Yosemitech Y532 pH Sensor
@see @ref sensor_y532
@snippet{lineno} menu_a_la_carte.ino yosemitech_y532
<hr>
@paragraph menu_walk_yosemitech_y533 Yosemitech Y533 Oxidation Reduction Potential (ORP) Sensor
@see @ref sensor_y533
@snippet{lineno} menu_a_la_carte.ino yosemitech_y533
<hr>
@paragraph menu_walk_yosemitech_y551 Yosemitech Y551 Carbon Oxygen Demand (COD) Sensor with Wiper
@see @ref sensor_y551
@snippet{lineno} menu_a_la_carte.ino yosemitech_y551
<hr>
@paragraph menu_walk_yosemitech_y560 Yosemitech Y560 Ammonium Sensor
@see @ref sensor_y551
@snippet{lineno} menu_a_la_carte.ino yosemitech_y560
<hr>
@paragraph menu_walk_yosemitech_y700 Yosemitech Y700 Pressure Sensor
@see @ref sensor_y700
@snippet{lineno} menu_a_la_carte.ino yosemitech_y700
<hr>
@paragraph menu_walk_yosemitech_y4000 Yosemitech Y4000 Multi-Parameter Sonde
@see @ref sensor_y4000
@snippet{lineno} menu_a_la_carte.ino yosemitech_y4000
<hr>
@subsubsection menu_walk_zebra_tech_d_opto Zebra Tech D-Opto Dissolved Oxygen Sensor
The SDI-12 address of the sensor, the Arduino pin controlling power on/off, and the Arduino pin sending and receiving data are required for the sensor constructor.
Optionally, you can include a number of distinct readings to average.
The data pin must be a pin that supports pin-change interrupts.
@see @ref sensor_dopto
@snippet{lineno} menu_a_la_carte.ino zebra_tech_d_opto
<hr>
@subsection menu_walk_calculated_variables Calculated Variables
Create new Variable objects calculated from the measured variables.
For these calculate variables, we must not only supply a function for the calculation, but also all of the metadata about the variable - like the name of the variable and its units.
@snippet{lineno} menu_a_la_carte.ino calculated_variables
<hr>
@subsection menu_walk_create_objs Creating the array, logger, publishers
@subsubsection menu_walk_variable_array The variable array
Create a VariableArray containing all of the Variable objects that we are logging the values of.
This shows three different ways of creating the same variable array and filling it with variables.
You should only use <strong>ONE</strong> of these in your own code
@paragraph menu_walk_variables_create_in_array Creating Variables within an Array
Here we use the <tt>new</tt> keyword to create multiple variables and get pointers to them all at the same time within the array.
@snippet{lineno} menu_a_la_carte.ino variables_create_in_array
@paragraph menu_walk_variables_separate_uuids Creating Variables and Pasting UUIDs from MonitorMyWatershed
If you are sending data to monitor my watershed, it is much easier to create the variables in an array and then to paste the UUID's all together as copied from the "View Token UUID List" link for a site.
If using this method, be very, very, very careful to make sure the order of your variables exactly matches the order of your UUID's.
@snippet{lineno} menu_a_la_carte.ino variables_separate_uuids
@paragraph menu_walk_variables_pre_named Using Pre-Named Variables within an Array
You can also create and name variable pointer objects outside of the array (as is demonstrated in all of the code chunks here) and then reference those pointers inside of the array like so:
@snippet{lineno} menu_a_la_carte.ino variables_pre_named
<hr>
@subsubsection menu_walk_logger_obj The Logger Object
Now that we've created the array, we can actually create the #Logger object.
@snippet{lineno} menu_a_la_carte.ino loggers
<hr>
@subsubsection menu_walk_data_publisher Data Publishers
Here we set up all three possible data publishers and link all of them to the same Logger object.
@paragraph menu_walk_enviro_diy_publisher Monitor My Watershed
To publish data to the Monitor My Watershed / EnviroDIY Data Sharing Portal first you must register yourself as a user at <https://monitormywatershed.org> or <https://data.envirodiy.org>.
Then you must register your site.
After registering your site, a sampling feature and registration token for that site should be visible on the site page.
@snippet{lineno} menu_a_la_carte.ino enviro_diy_publisher
<hr>
@paragraph menu_walk_dream_host_publisher DreamHost
It is extremely unlikely you will use this.
You should ignore this section.
@snippet{lineno} menu_a_la_carte.ino dream_host_publisher
<hr>
@paragraph menu_walk_thing_speak_publisher ThingSpeak
After you have set up a channel and MQTT device on ThingSpeak, you can use this code to publish your data to it.
Keep in mind that the order of variables in the VariableArray is <strong>crucial</strong> when publishing to ThingSpeak.
If you set a user API key, this library will attempt to update your channel name and your field names with the logger ID and the variable names at boot-up.
@snippet{lineno} menu_a_la_carte.ino thing_speak_publisher
<hr>
@paragraph menu_walk_ubidots_publisher Ubidots
Use this to publish data to Ubidots.
@snippet{lineno} menu_a_la_carte.ino ubidots_publisher
<hr>
@paragraph menu_walk_s3_presigned_publisher AWS S3
Use this to publish data S3 using a pre-signed URL.
Getting this to work requires you to set up an endpoint and parse an incoming S3 URL to publish to.
Unlike the other publishers, this S3 publisher is <strong>not</strong> meant to be used to publish numeric sensor data.
This is intended to send image data from the Geolux HydroCam or any future sensors that generate image or other large binary data.
See the separate AWS examples for how to use this.
@snippet{lineno} menu_a_la_carte.ino s3_presigned_publisher
<hr>
@paragraph menu_walk_aws_io_t_publisher AWS IoT Core
Use this to publish data to AWS IoT Core.
This can also be used to fetch a pre-signed URL to publish to S3 - if you have the proper IoT Core rules and a lambda function set up.
See the separate AWS examples for how to use this.
@snippet{lineno} menu_a_la_carte.ino aws_io_t_publisher
<hr>
@subsection menu_walk_working Extra Working Functions
Here we're creating a few extra functions on the global scope.
The flash function is used at board start up just to give an indication that the board has restarted.
The battery function calls the #ProcessorStats sensor to check the battery level before attempting to log or publish data.
@snippet{lineno} menu_a_la_carte.ino working_functions
<hr>
@subsection menu_walk_setup Arduino Setup Function
This is our setup function.
In Arduino coding, the classic "main" function is replaced by two functions: setup() and loop().
The setup() function runs once when the board boots or restarts.
It usually contains many functions that set the mode of input and output pins and prints out some debugging information to the serial port.
These functions are frequently named "begin".
Because we have a <em>lot</em> of parts to set up, there's a lot going on in this function!
Let's break it down.
@subsubsection menu_walk_setup_open Starting the Function
First we just open the function definitions:
@code{cpp}
void setup() {
@endcode
@subsubsection menu_walk_setup_wait Wait for USB
Next we wait for the USB debugging port to initialize.
This only applies to SAMD and 32U4 boards that have built-in USB support.
This code should not be used for deployed loggers; it's only for using a USB for debugging.
@snippet{lineno} menu_a_la_carte.ino setup_wait
@subsubsection menu_walk_setup_prints Printing a Hello
Next we print a message out to the debugging port.
This is also just for debugging - it's very helpful when connected to the logger via USB to see a clear indication that the board is starting
@snippet{lineno} menu_a_la_carte.ino setup_prints
@subsubsection menu_walk_setup_serial_interrupts Serial Interrupts
If we're using either NeoSWSerial or SoftwareSerial_ExtInts we need to assign the data receiver pins to interrupt functionality here in the setup.
The <a href="https://envirodiy.github.io/ModularSensors/menu_