Welcome to EnviroDIY, a community for do-it-yourself environmental science and monitoring. EnviroDIY is part of WikiWatershed, an initiative of Stroud Water Research Center designed to help people advance knowledge and stewardship of fresh water.
New to EnviroDIY? Start here

Reply To: XBee Networks of Mayfly Loggers – 900Mhz

Home Forums Mayfly Data Logger XBee Networks of Mayfly Loggers – 900Mhz Reply To: XBee Networks of Mayfly Loggers – 900Mhz


    Hi there! I’m hoping to do something similar to what David is doing. I’m using a couple Xbee Pro 900HP modules and couple Mayfly’s. I’m setting up the network using PlatformIO and the Monitoring Station Manual, and I came across a roadblock when I updated the code with some of the Xbee lines. The code runs, printing data to the Mayfly’s SD card until I add the the Xbee code to the loop(). Once I added the Xbee code, the SD card printing prompts don’t pop up in the Serial Monitor (only the “Wake up the Xbee” and “Putting the Xbee to sleep” prompts).

    I feel like it’s an ordering issue in the loop() from when I updated the code, but I’m not sure. Any help is greatly appreciated! Thanks!

    Also, while I’m here, I also have been struggling on how to take the sensor measurements that are printed to the SD card and communicate them to the Xbee (with the Serial1.println() line in the loop() command). I’m pretty new to Arduino programming, so I feel like I’m probably overcomplicating it.

    /** =========================================================================
    * @file DRWI_NoCellular.ino
    * @brief Example for DRWI CitSci without cellular service.
    * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org>
    * @copyright (c) 2017-2020 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
    * ======================================================================= */

    // ==========================================================================
    // 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>

    // To get all of the base classes for ModularSensors, include LoggerBase.
    // NOTE: Individual sensor definitions must be included separately.
    #include <LoggerBase.h>
    /** End [includes] */

    //Defines the XBEE Sleep pin
    #define XBEE_SleepPin 23

    // ==========================================================================
    // Data Logging Options
    // ==========================================================================
    /** Start [logging_options] */
    // The name of this program file
    const char* sketchName = “sensor_test.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 = 1;
    // 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 = A7; // MCU interrupt/alarm pin to wake from sleep
    // 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] */

    // ==========================================================================
    // Using the Processor as a Sensor
    // ==========================================================================
    /** Start [processor_sensor] */
    #include <sensors/ProcessorStats.h>

    // Create the main processor chip “sensor” – for general metadata
    const char* mcuBoardVersion = “v0.5b”;
    ProcessorStats mcuBoard(mcuBoardVersion);
    /** End [processor_sensor] */

    // ==========================================================================
    // Maxim DS3231 RTC (Real Time Clock)
    // ==========================================================================
    /** Start [ds3231] */
    #include <sensors/MaximDS3231.h>

    // Create a DS3231 sensor object
    MaximDS3231 ds3231(1);
    /** End [ds3231] */

    // ==========================================================================
    // Campbell OBS 3 / OBS 3+ Analog Turbidity Sensor
    // ==========================================================================
    /** Start [obs3] */
    #include <sensors/CampbellOBS3.h>

    const int8_t OBS3Power = sensorPowerPin; // Power pin (-1 if unconnected)
    const uint8_t OBS3NumberReadings = 10;
    const uint8_t ADSi2c_addr = 0x48; // The I2C address of the ADS1115 ADC
    // Campbell OBS 3+ *Low* Range Calibration in Volts
    const int8_t OBSLowADSChannel = 0; // ADS channel for *low* range output
    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,
    ADSi2c_addr, OBS3NumberReadings);

    // Campbell OBS 3+ *High* Range Calibration in Volts
    const int8_t OBSHighADSChannel = 1; // ADS channel for *high* range output
    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, ADSi2c_addr, OBS3NumberReadings);
    /** End [obs3] */

    // ==========================================================================
    // Meter Hydros 21 Conductivity, Temperature, and Depth Sensor
    // ==========================================================================
    /** Start [decagon_ctd] */
    #include <sensors/DecagonCTD.h>

    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 SDI12Power = sensorPowerPin; // Power pin (-1 if unconnected)
    const int8_t SDI12Data = 7; // The SDI12 data pin

    // Create a Decagon CTD sensor object
    DecagonCTD ctd(*CTDSDI12address, SDI12Power, SDI12Data, CTDNumberReadings);
    /** End [decagon_ctd] */

    // ==========================================================================
    // Creating the Variable Array[s] and Filling with Variable Objects
    // ==========================================================================
    /** Start [variable_arrays] */
    Variable* variableList[] = {
    new DecagonCTD_Cond(&ctd),
    new DecagonCTD_Temp(&ctd),
    new DecagonCTD_Depth(&ctd),
    new CampbellOBS3_Turbidity(&osb3low, “”, “TurbLow”),
    new CampbellOBS3_Turbidity(&osb3high, “”, “TurbHigh”),
    new ProcessorStats_Battery(&mcuBoard),
    new MaximDS3231_Temp(&ds3231),

    // All UUID’s, device registration, and sampling feature information can be
    // pasted directly from Monitor My Watershed. To get the list, click the “View
    // token UUID list” button on the upper right of the site page.
    // Even if not publishing live data, this is needed so the logger file will be
    // “drag-and-drop” ready for manual upload to the portal.

    // Check the order of your variables in the variable list!!!
    // Be VERY certain that they match the order of your UUID’s!
    // Rearrange the variables in the variable list if necessary to match!
    const char* UUIDs[] = {
    “12345678-abcd-1234-ef00-1234567890ab”, // Electrical conductivity
    // (Decagon_CTD-10_Cond)
    “12345678-abcd-1234-ef00-1234567890ab”, // Temperature
    // (Decagon_CTD-10_Temp)
    “12345678-abcd-1234-ef00-1234567890ab”, // Water depth
    // (Decagon_CTD-10_Depth)
    “12345678-abcd-1234-ef00-1234567890ab”, // Turbidity (Campbell_OBS3_Turb)
    “12345678-abcd-1234-ef00-1234567890ab”, // Turbidity (Campbell_OBS3_Turb)
    “12345678-abcd-1234-ef00-1234567890ab”, // Battery voltage
    // (EnviroDIY_Mayfly_Batt)
    “12345678-abcd-1234-ef00-1234567890ab” // Temperature
    // (EnviroDIY_Mayfly_Temp)
    const char* registrationToken =
    “12345678-abcd-1234-ef00-1234567890ab”; // Device registration token
    const char* samplingFeature =
    “12345678-abcd-1234-ef00-1234567890ab”; // Sampling feature UUID

    // Count up the number of pointers in the array
    int variableCount = sizeof(variableList) / sizeof(variableList[0]);

    // Create the VariableArray object
    VariableArray varArray(variableCount, variableList, UUIDs);
    /** End [variable_arrays] */

    // ==========================================================================
    // The Logger Object[s]
    // ==========================================================================
    /** Start [loggers] */
    // Create a new logger instance
    Logger dataLogger(LoggerID, loggingInterval, &varArray);
    /** End [loggers] */

    // ==========================================================================
    // 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);
    digitalWrite(greenLED, LOW);
    digitalWrite(redLED, HIGH);
    digitalWrite(redLED, LOW);

    // Reads 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
    // ==========================================================================
    /** Start [setup] */
    void setup() {
    // Start the primary serial connection

    //Sets up the baud rate for the XBEE

    // Print a start-up note to the first serial port
    Serial.print(F(“Now running “));
    Serial.print(F(” on Logger “));

    Serial.print(F(“Using ModularSensors Library version “));

    // Set up pins for the LED’s
    pinMode(greenLED, OUTPUT);
    digitalWrite(greenLED, LOW);
    pinMode(redLED, OUTPUT);
    digitalWrite(redLED, LOW);

    //Sets up pins for the XBEE
    pinMode(XBEE_SleepPin,OUTPUT); //Setting XBEE sleep pin as an output
    digitalWrite(XBEE_SleepPin, LOW); //Start with XBEE awake
    Serial.println(“Xbee is now set up”);

    // Blink the LEDs to show the board is on and starting up

    // Set the timezones for the logger/data and the RTC
    // Logging in the given time zone
    // It is STRONGLY RECOMMENDED that you set the RTC to be in UTC (UTC+0)

    // Attach information pins to the logger
    dataLogger.setLoggerPins(wakePin, sdCardSSPin, sdCardPwrPin, buttonPin,

    // Begin the logger

    // 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…”));

    // 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”));
    true); // true = wait for card to settle after power up
    dataLogger.createLogFile(true); // true = write a new header
    true); // true = wait for internal housekeeping after write

    // Call the processor sleep
    Serial.println(F(“Putting processor to sleep\n”));
    /** End [setup] */

    // ==========================================================================
    // Arduino Loop Function
    // ==========================================================================
    /** Start [loop] */
    // Use this short loop for simple data logging and sending
    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) {
    // If the battery is OK, log data
    else {
    wakeXbee(); //Wakes up XBEE
    delay(3000); //Gives XBEE time to be seen by the network
    Serial1.println(); //Text being sent by XBEE module
    delay(3000); //Gives XBEE a bit before sending it back to sleep
    sleepXbee(); //Puts Xbee to sleep

    delay(10000); //wait 10 seconds, then repeat loop


    void sleepXbee() {
    Serial.println(“Putting the Xbee to sleep”);
    pinMode(XBEE_SleepPin,INPUT_PULLUP); // Set the “wake-up pin” to input and enable the internal pullup
    digitalWrite(XBEE_SleepPin,HIGH); //put the Xbee to sleep
    digitalWrite(9, LOW); //turn off the RED LED when the Xbee is asleep

    void wakeXbee() {
    Serial.println(“Wake up the Xbee”);
    pinMode(XBEE_SleepPin,OUTPUT); // Set the “wake-up pin” to output
    digitalWrite(XBEE_SleepPin,LOW); // wake-up XBee
    digitalWrite(9, HIGH); // turn on the RED LED when the Xbee is awake
    /** End [loop] */