New non-blocking temperature sensor code


  • Plugin Developer

    I rewrote the temperature sensor code.

    • It no longer uses Sleep, so it can be used as a repeater.
    • It's now cleaner and documented.
    • It now has serial debugging features.

    Could someone place this code on the website?

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
     * http://www.mysensors.org/build/temp
     * 
     * The cool thing about this temperature sensor (pun intended) is thay you can attach multiple Dallas temperature sensors outputs to the same arduino pin. They will all automatically be recognised as separate sensors.
     * 
     * At the moment of writing (februari 2017) you need older versions of the Dallas and OneWire libraries. Please check the website or forum to see if this is still the case.
     * 
     * Modifications by anonymous user so that it can now simultaneously function as a MySensors repeater. 
     */
    
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RF24_PA_LEVEL RF24_PA_MIN              // This sets a low-power mode for the radio. Useful if you use the version with the bigger antenna, but don' want to power that from a separate source. It can also fix problems with fake Chinese versions of the radio.
    //#define MY_RADIO_RFM69
    
    // Choose if you want this sensor to also be a repeater.
    // #define MY_REPEATER_FEATURE                    // Just remove the two slashes at the beginning of this line to also enable this sensor to act as a repeater for other sensors.
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>                  
    #include <OneWire.h>                              
    
    // These variables can be changed:
    #define COMPARE_TEMP 1                            // Send temperature only if changed? 1 = Yes 0 = No
    #define ONE_WIRE_BUS 3                            // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 16                   // Maximum amount of teperature sensors you can connect to this arduino (16).
    unsigned long MEASUREMENT_INTERVAL = 30000;       // Time to wait between reads (in milliseconds).
    
    // You shouldn't change these:
    OneWire oneWire(ONE_WIRE_BUS);                    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire);              // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];      // creates an array to hold the previous temperature measurements for each possible sensor.
    int numSensors=0;                                 // variable to contain the number of found attached sensors.
    boolean receivedConfig = false;                   // I have no idea what this does.
    boolean metric = true;                            // Probably used by the Dallas library as an indication if the temperature should be calculated in Celsius (metric) or Fahrenheit.
    boolean CURRENTLY_MEASURING = true;               // Used to indicate when the time is right for a new measurement to be made.
    boolean CURRENTLY_CALCULATING = false;            // Used to bridge the time that is needed to calculate the temperature values by the Dallas library.
    unsigned long CURRENT_MILLIS = 0;                 // The millisecond clock in the main loop.
    unsigned long PREVIOUS_MEASUREMENT_MILLIS = 0;    // Used to remember the time of the last temperature measurement.
    int16_t CONVERSION_TIME = 0;                      // Used to store the time needed to calculate the temperature from measurements.
    
    // Mysensors settings
    MyMessage msg(0,V_TEMP);
    
    void before()
    {
      sensors.begin();                                // Startup up the OneWire library
    }
    
    void setup()  
    { 
      for(int i=0;i<MAX_ATTACHED_DS18B20;i++){lastTemperature[i] = 0;} //Pre-filling array with 0's.
      sensors.setWaitForConversion(false);            // requestTemperatures() will not block current thread
      Serial.begin(115200);                           // for serial debugging.
      Serial.print("Hello world, I am a sensor. \n ");
    
    }
    
    void presentation() {
      sendSketchInfo("Temperature Sensor", "1.2");    // Send the sketch version information to the gateway and Controller
      numSensors = sensors.getDeviceCount();          // Fetch the number of attached temperature sensors  
    
      
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i, S_TEMP);                          // Present all sensors to controller (16 maximum).
      }
    }
    
    void loop(){     
    
      CURRENT_MILLIS = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
    
    
      // Let's measure the temperature
      if(CURRENTLY_MEASURING == true && CURRENT_MILLIS - PREVIOUS_MEASUREMENT_MILLIS >= MEASUREMENT_INTERVAL){ // If we'e not calculating, and enough time has passed, we'll start again.
        CURRENTLY_MEASURING == false; // We're measuring, so let's take it off our to-do list.
        Serial.print("Starting new measurement(s)\n");
        PREVIOUS_MEASUREMENT_MILLIS = CURRENT_MILLIS; // Mark the time of the initialiation of this measurement.
       
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
        
        // query conversion time. Apparently it takes a while to calculate?
        CONVERSION_TIME = sensors.millisToWaitForConversion(sensors.getResolution());
    
        CURRENTLY_CALCULATING = true; //Next step is to re-calculate the temperature again.
      }
    
    
      // Let's calculate and send the temperature
      if(CURRENTLY_CALCULATING == true && CURRENT_MILLIS > PREVIOUS_MEASUREMENT_MILLIS + CONVERSION_TIME ){
        CURRENTLY_CALCULATING = false; // check calculating off the to-do list too.
        for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {    // Loop through all the attached temperatur sensors.
        
          float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;   // Fetch and round temperature to one decimal
          
          Serial.print("Sensor #");
          Serial.print(i);
          Serial.print(" says it is ");
          Serial.print(temperature);
          Serial.print(" degrees\n");
          
          if(temperature != -127.00 && temperature != 85.00){ // avoid working with measurement errors.
            if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature){
              Serial.print("Not sending it though, because it's the same temperature as before.\n");
            }
            else
            {
              Serial.print("Sending the temperature to the gateway.\n");
              send(msg.setSensor(i).set(temperature,1));
              lastTemperature[i] = temperature; // Save new temperatures to be able to compare in the next round.
            }
          }  
        }
        CURRENTLY_MEASURING = true; // Both tasks are done. Now we'll just wait for the measurement interval to be over.
        Serial.print("zzzzZZZZzzzzZZZZzzzz\n");
      }
    
    }
    


  • Cleaner ? Really ? πŸ˜†


  • Plugin Developer

    I've created a pull-request for the final version of this new example sketch.

    This version of the temperature example has some advantages over the old one:

    • Can now be used as a repeater.
    • Toggle battery powered mode (which uses deep Sleep to save power) or State Machine (necessary if you want to use repeater mode).
    • Has a copy of a small function from an older Dallas library internally so that the latest version of that library can be used.
    • Is now also compatible with the latest oneWire library.
    • Cleaned up the code and added comments. Still messy, but les messy than before.

  • Hardware Contributor

    @alowhum
    hi

    This is a good idea. So I've just taken a quick look (when i'll have time i'll try it but i miss time actually)

    Note a better sketch is always subjective. Some feedbacks if i can help you to improve your sketch πŸ™‚

    • not related to the sketch, but both battery & repeater mode are state machine based πŸ˜‰
    • why uppercase for variables? when i read it i always think this is a define or const. And others variables in the sketch are camelCase though, which i prefer imho.
    • i think maybe some variables could be static instead of global. but that won't hurt here sure
    • if i remember when i used onewire, i just used OneWire.h and did a little function for the non blocking read. I'll take a look when i can. But this looks good too with DallasTemperature lib. Maybe this is using a little bit more mem like this?? but sure this is a minor detail as it's only a temperature sketch
    • imho it's different sketch as the original Sleeping temperature sketch; I mean you removed the sleep function, so not really the same. What could be done perhaps, for user friendly, is to add both option : a define to enable sleep mode, something like MY_SLEEP_NODE.
      So you would have the repeater define, if so repeater mode. If not defined, normal mode without sleep. Or #Ifdef MY_SLEEP_NODE, use sleep mode ..

    I like comments too πŸ‘

    my 2cents


  • Hero Member

    @alowhum Nice... I like non-blocking code. Think @scalz did look at the sketch in this posting (not the pull request ;-)). A few suggestions:

    • As the Dallas reports in float it would be better to compare with previous measurements using a threshold. i.e. if ( abs(temperature - lastTemperature[i]) >= tempThreshold))
    • take a look at the MySensors Coding Guidelines for some guidance on syntax (needs a little broader attention).

  • Hardware Contributor

    rooo you're right @AWI i've wasted my time, i thought it was updated here too lol i'm joking 😜
    Looks good πŸ‘

    So, to be forgiven, i've very quickly reviewed the right code this time.

    In this example, i've just Astyle-ized the code and changed the "ugly" uppercase vars

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
     * http://www.mysensors.org/build/temp
     *
     * The cool thing about this temperature sensor (pun intended) is thay you can attach multiple Dallas temperature sensors outputs to the same arduino pin. They will all automatically be recognised as separate sensors.
     *
     * At the moment of writing (februari 2017) you need older versions of the Dallas and OneWire libraries. Please check the website or forum to see if this is still the case.
     *
     * Modifications by anonymous user so that it can now simultaneously function as a MySensors repeater.
     */
    
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24                            // A 2.4Ghz transmitter and receiver, often used with MySensors.
    #define MY_RF24_PA_LEVEL RF24_PA_MIN              // This sets a low-power mode for the radio. Useful if you use the verison with the bigger antenna, but don' want to power that from a separate source. It can also fix problems with fake Chinese versions of the radio.
    //#define MY_RADIO_RFM69                          // 433Mhz transmitter and reveiver.
    
    // Choose if you want this sensor to also be a repeater.
    // #define MY_REPEATER_FEATURE                    // Just remove the two slashes at the beginning of this line to also enable this sensor to act as a repeater for other sensors. If this node is on battery power, you probably shouldn't enable this.
    // Are you using this sensor on battery power?
    const int BATTERY_POWERED = false;                // Set this to 'true' if your node is battery powered. It will then go into deep sleep as much as possible. But when it' sleeping it can' work as a repeater.
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    
    // These variables can be changed:
    #define COMPARE_TEMP 1                            // Send temperature only if changed? 1 = Yes 0 = No. Can save battery.
    #define ONE_WIRE_BUS 3                            // Pin where Dallas sensor(s) is/are connected.
    #define MAX_ATTACHED_DS18B20 16                   // Maximum amount of teperature sensors you can connect to this arduino (16).
    unsigned long measurementInterval = 30000;        // Time to wait between reads (in milliseconds).
    
    // You should not change these:
    OneWire oneWire(ONE_WIRE_BUS);                    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire);              // Pass the oneWire reference to Dallas Temperature.
    float lastTemperature[MAX_ATTACHED_DS18B20];      // creates an array to hold the previous temperature measurements for each possible sensor.
    int numSensors=0;                                 // variable to contain the number of found attached sensors.
    boolean metric = true;                            // old mysensors stuff..
    boolean isMeasuring = true;							  // Used to indicate when the time is right for a new measurement to be made.
    boolean isCalculating = false;                    // Used to bridge the time that is needed to calculate the temperature values by the Dallas library.
    unsigned long currentMillis = 0;                  // The millisecond clock in the main loop.
    unsigned long previousMeasurementMillis = 0;      // Used to remember the time of the last temperature measurement.
    unsigned long measurementSleepTime = 0;           // variable to store the Sleep time if the node is battery powered.
    int16_t conversionTime = 0;                       // Used to store the time needed to calculate the temperature from measurements.
    
    // Mysensors settings
    MyMessage msg(0,V_TEMP);                          // Sets up the message format that we'l be sending to the MySensors gateway later.
    
    
    void before()
    {
       sensors.begin();                              // Startup up the OneWire library. It allows multiple sensors to talk over one wire (one pin).
    }
    
    void setup()
    {
       for(int i=0; i<MAX_ATTACHED_DS18B20; i++) {
          lastTemperature[i] = 0;  //Pre-filling array with 0's.
       }
       sensors.setWaitForConversion(false);            // requestTemperatures() will not block current thread
       if (BATTERY_POWERED == true) {
          measurementSleepTime = measurementInterval;
          measurementInterval = 1;                    // We'll let Sleep take over the scheduling. When the arduino is asleep, millis doesn't increment anymore (time stops as it were). To fix this, we'l set the measurement interval time to 1, so that when the arduino wakes up it will immediately try to measure again.
       }
       Serial.begin(115200);                           // for serial debugging.
       Serial.print("Hello world, I am a sensor. \n ");
    
    }
    
    void presentation()
    {
       sendSketchInfo("Temperature Sensor", "1.2");    // Send the sketch version information to the gateway and Controller
       numSensors = sensors.getDeviceCount();          // Fetch the number of attached temperature sensors
       for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
          present(i, S_TEMP);                          // Present all sensors to controller (16 maximum).
       }
    }
    
    
    void loop()
    {
    
       currentMillis = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
    
    
       // Let's measure the temperature
       if(isMeasuring == true && currentMillis - previousMeasurementMillis >= measurementInterval) { // If we're not calculating, and enough time has passed, we'll start again.
          isMeasuring = false; // We're measuring, so let's take it off our to-do list.
          Serial.print("Starting new measurement(s)\n");
          previousMeasurementMillis = currentMillis; // Mark the time of the initialiation of this measurement.
    
          // Fetch temperatures from Dallas sensors
          sensors.requestTemperatures();
    
          // query conversion time. Apparently it takes a while to calculate.
          //CONVERSION_TIME = sensors.millisToWaitForConversion(sensors.getResolution());
          conversionTime = millisToWaitForConversion(sensors.getResolution());
          isCalculating = true; //Next step is to re-calculate the temperature again.
       }
    
    
       // Next, let's calculate and send the temperature
       if(isCalculating == true && currentMillis > previousMeasurementMillis + conversionTime ) {
          isCalculating = false; // check calculating off the to-do list too.
    
          for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {    // Loop through all the attached temperatur sensors.
             float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;   // Fetch and round temperature to one decimal
             Serial.print("Sensor #");
             Serial.print(i);
             Serial.print(" says it is ");
             Serial.print(temperature);
             Serial.print(" degrees\n");
             if(temperature != -127.00 && temperature != 85.00) { // avoid working with measurement errors.
                if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature) {
                   Serial.print("Not sending it though, because it's the same temperature as before.\n");
                } else {
                   Serial.print("Sending the temperature to the gateway.\n");
                   send(msg.setSensor(i).set(temperature,1));
                   lastTemperature[i] = temperature; // Save new temperatures to be able to compare in the next round.
                }
             }
          }
    
          // Both tasks are done. Time to wait until we should measure again.
          Serial.print("zzzzZZZZzzzzZZZZzzzz\n");
          if(BATTERY_POWERED == true) {
             unsigned long quicktimecheck = millis(); // check how much time has passed during the measurement (can be up to 750 milliseconds), and then calculate from that how long to sleep until the next intended measuring time.
             unsigned long sleeptime = measurementSleepTime - (quicktimecheck - previousMeasurementMillis); //How much time has passed already during the calculating? Subtract that from the intended interval time.
             sleep (sleeptime);
          }
          isMeasuring = true;
       }
    }
    
    
    // This function helps to avoid a problem with the latest Dallas temperature library.
    int16_t millisToWaitForConversion(uint8_t bitResolution)
    {
       switch (bitResolution) {
       case 9:
          return 94;
       case 10:
          return 188;
       case 11:
          return 375;
       default:
          return 750;
       }
    }
    

    Finally was tempting to optimize a very little bit few things like conditional compilation if not using sleep mode, some statics vars etc.. not really useful here, sure, but still good to have in mind when you learn, you look at code and then try to understand. And then when you want to add more sensors, you need more memory so..

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
     * http://www.mysensors.org/build/temp
     *
     * The cool thing about this temperature sensor (pun intended) is thay you can attach multiple Dallas temperature sensors outputs to the same arduino pin. They will all automatically be recognised as separate sensors.
     *
     * At the moment of writing (februari 2017) you need older versions of the Dallas and OneWire libraries. Please check the website or forum to see if this is still the case.
     *
     * Modifications by anonymous user so that it can now simultaneously function as a MySensors repeater.
     */
    
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24                            // A 2.4Ghz transmitter and receiver, often used with MySensors.
    #define MY_RF24_PA_LEVEL RF24_PA_MIN              // This sets a low-power mode for the radio. Useful if you use the verison with the bigger antenna, but don' want to power that from a separate source. It can also fix problems with fake Chinese versions of the radio.
    //#define MY_RADIO_RFM69                          // 433Mhz transmitter and reveiver.
    
    // Choose if you want this sensor to also be a repeater.
    // #define MY_REPEATER_FEATURE                    // Just remove the two slashes at the beginning of this line to also enable this sensor to act as a repeater for other sensors. If this node is on battery power, you probably shouldn't enable this.
    // Are you using this sensor on battery power?
    #define BATTERY_POWERED									 // Just remove the two slashes at the beginning of this line if your node is battery powered. It will then go into deep sleep as much as possible. But when it' sleeping it can' work as a repeater.
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    
    // These defines and variables can be changed:
    #define COMPARE_TEMP 1                            // Send temperature only if changed? 1 = Yes 0 = No. Can save battery.
    #define ONE_WIRE_BUS 3                            // Pin where Dallas sensor(s) is/are connected.
    #define MAX_ATTACHED_DS18B20 16                   // Maximum amount of teperature sensors you can connect to this arduino (16).
    
    unsigned long measurementInterval = 30000;        // Time to wait between reads (in milliseconds).
    
    // You should not change these:
    OneWire oneWire(ONE_WIRE_BUS);                    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire);              // Pass the oneWire reference to Dallas Temperature.
    float lastTemperature[MAX_ATTACHED_DS18B20];      // creates an array to hold the previous temperature measurements for each possible sensor.
    int numSensors=0;                                 // variable to contain the number of found attached sensors.
    boolean metric = true;                            // old Mysensors??
    unsigned long measurementSleepTime = 0;           // variable to store the Sleep time if the node is battery powered.
    
    
    // Mysensors settings
    MyMessage msg(0,V_TEMP);                          // Sets up the message format that we'l be sending to the MySensors gateway later.
    
    
    void before()
    {
       sensors.begin();                              // Startup up the OneWire library. It allows multiple sensors to talk over one wire (one pin).
    }
    
    void setup()
    {
       for(int i=0; i<MAX_ATTACHED_DS18B20; i++) {
          lastTemperature[i] = 0;  //Pre-filling array with 0's.
       }
       sensors.setWaitForConversion(false);            // requestTemperatures() will not block current thread
    
    #ifdef BATTERY_POWERED
       measurementSleepTime = measurementInterval;
       measurementInterval = 1;                    // We'll let Sleep take over the scheduling. When the arduino is asleep, millis doesn't increment anymore (time stops as it were). To fix this, we'l set the measurement interval time to 1, so that when the arduino wakes up it will immediately try to measure again.
    #endif
    
       Serial.begin(115200);                           // for serial debugging.
       Serial.print("Hello world, I am a sensor. \n ");
    
    }
    
    void presentation()
    {
       sendSketchInfo("Temperature Sensor", "1.2");    // Send the sketch version information to the gateway and Controller
       numSensors = sensors.getDeviceCount();          // Fetch the number of attached temperature sensors
       for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
          present(i, S_TEMP);                          // Present all sensors to controller (16 maximum).
       }
    }
    
    
    void loop()
    {
    
       // You should not change these variables:
       static boolean isMeasuring = true;		             // Used to indicate when the time is right for a new measurement to be made.
       static boolean isCalculating = false;                     // Used to bridge the time that is needed to calculate the temperature values by the Dallas library.
       static unsigned long currentMillis = 0;                   // The millisecond clock in the main loop.
       static unsigned long previousMeasurementMillis = 0;       // Used to remember the time of the last temperature measurement.
       static int16_t conversionTime = 0;                        // Used to store the time needed to calculate the temperature from measurements.
    
       currentMillis = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
    
       // Let's measure the temperature
       if(isMeasuring == true && currentMillis - previousMeasurementMillis >= measurementInterval) { // If we're not calculating, and enough time has passed, we'll start again.
          isMeasuring = false; // We're measuring, so let's take it off our to-do list.
          Serial.print("Starting new measurement(s)\n");
          previousMeasurementMillis = currentMillis; // Mark the time of the initialiation of this measurement.
    
          // Fetch temperatures from Dallas sensors
          sensors.requestTemperatures();
    
          // query conversion time. Apparently it takes a while to calculate.
          //CONVERSION_TIME = sensors.millisToWaitForConversion(sensors.getResolution());
          conversionTime = millisToWaitForConversion(sensors.getResolution());
          isCalculating = true; //Next step is to re-calculate the temperature again.
       }
    
    
       // Next, let's calculate and send the temperature
       if(isCalculating == true && currentMillis > previousMeasurementMillis + conversionTime ) {
          isCalculating = false; // check calculating off the to-do list too.
    
          for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {    // Loop through all the attached temperatur sensors.
             float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;   // Fetch and round temperature to one decimal
             Serial.print("Sensor #");
             Serial.print(i);
             Serial.print(" says it is ");
             Serial.print(temperature);
             Serial.print(" degrees\n");
             if(temperature != -127.00 && temperature != 85.00) { // avoid working with measurement errors.
                if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature) {
                   Serial.print("Not sending it though, because it's the same temperature as before.\n");
                } else {
                   Serial.print("Sending the temperature to the gateway.\n");
                   send(msg.setSensor(i).set(temperature,1));
                   lastTemperature[i] = temperature; // Save new temperatures to be able to compare in the next round.
                }
             }
          }
    
          // Both tasks are done. Time to wait until we should measure again.
          Serial.print("zzzzZZZZzzzzZZZZzzzz\n");
    
    #ifdef BATTERY_POWERED
          unsigned long quicktimecheck = millis(); // check how much time has passed during the measurement (can be up to 750 milliseconds), and then calculate from that how long to sleep until the next intended measuring time.
          unsigned long sleeptime = measurementSleepTime - (quicktimecheck - previousMeasurementMillis); //How much time has passed already during the calculating? Subtract that from the intended interval time.
          sleep (sleeptime);
    #endif
    
          isMeasuring = true;
       }
    }
    
    
    // This function helps to avoid a problem with the latest Dallas temperature library.
    int16_t millisToWaitForConversion(uint8_t bitResolution)
    {
       switch (bitResolution) {
       case 9:
          return 94;
       case 10:
          return 188;
       case 11:
          return 375;
       default:
          return 750;
       }
    }
    

    Last note : celsius/farenheit in dallatemperature lib is not handled by the metric variable. To get the conversion you need to use C or F functions as below. I've not checked how you handle this in sketch.

        // returns temperature in degrees C
        float getTempC(const uint8_t*);
    
        // returns temperature in degrees F
        float getTempF(const uint8_t*);
    
        // Get temperature for device index (slow)
        float getTempCByIndex(uint8_t);
    
        // Get temperature for device index (slow)
    float getTempFByIndex(uint8_t);
    

    I've not compiled anything, have been lazy πŸ™‚
    So, if that can be helpful, i let you diffcheck and improve/decide what you need, these are just ideas, there are always others small things which can been improved πŸ˜‰


  • Plugin Developer

    Wow, great stuff! Thanks everyone! I'll try and make a new version with your suggestions.


  • Plugin Developer

    I've added your suggestions, cleaned the code to conform to standards better, and tested the new version in various configurations.

    I've created a pull request on Github for this to become the new code. And a few days ago I created a page on OpenHardware.io that could be the start of a new page about the sensor, if need be.

    Once my BME280 sensor arrives, I will create a new seperate version based on that. My suggestion is that the MySensors homepage should somehow point to two temperature sensors:

    • One for mass sensor network deployment (this one, based on the cheap Dallas).
    • One for home automation (the more expensive but awesome BME280).

  • Hero Member

    @alowhum πŸ‘ The BME280 and/or sI7021 are also well suited to replace the overpopular (but outdated) DHT11/22 sensors/ examples. The difference in price is minimal and reliability; power requirements and interface (i2c) much better suited for MySensors (& battery) operation.
    So while you are at it πŸ˜‰


  • Plugin Developer

    Yes, exactly. @hek mentioned replacing that one with the BME280. The only thought I had there was: people looking for a temperature sensor may not find it there if it's just labeled as a humidity sensor. If we can call it "temperature & humidity & barometric pressure sensor", then I'm all for replacing that one with the BME code.

    And having both of them point to each other as a possible alternative.



  • @alowhum - thanks for your code! I was just seeking for ideas for such non-blocking sensor code and found this. I saw only a little cosmetic problem with formatting of message printed on serial line (space missing) but technically all seems to be working fine (tested for sensor powered by PSU, not battery) . It saved my time! πŸ‘


  • Plugin Developer

    @ferro glad to hear it!


  • Plugin Developer

    I've also created some code for use with the much nicer BME280 sensor. It's on the github, under MySensors examples, as a pull request. Hopefully it will become a part of those examples.


Log in to reply
 

Suggested Topics

29
Online

11.2k
Users

11.1k
Topics

112.5k
Posts