From d54ecd019ab472455bd39284f59f795d568672b7 Mon Sep 17 00:00:00 2001 From: flatsiedatsie Date: Sun, 19 Mar 2017 13:34:07 +0100 Subject: [PATCH 1/4] New Dallas temperature sensor After some useful feedback and co-authoring on the forum, the sketch is now even better. - Conforms better to MySensors coding standards. - Added option to choose sensor precision (also useful starting point for other sensors). - Clearer option to choose between Celsius and Fahrenheit. Old features remain: - non-blocking - option to use sleep to preserve battery - Now compatible with latest OneWire and Dallas libraries - Lots more explanatory/educational comments, and cleaner code than before. --- .../DallasTemperatureSensor.ino | 215 +++++++++++++----- 1 file changed, 153 insertions(+), 62 deletions(-) diff --git a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino index cdcc31c..4b8b86e 100644 --- a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino +++ b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -22,88 +22,179 @@ * * 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 +// if you uncomment this, you can get test and debug updates about everything the sensor is doing by using the serial monitor tool. +#define MY_DEBUG // Enable and select radio type attached -#define MY_RADIO_NRF24 -//#define MY_RADIO_RFM69 +#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't want to power that from a separate power 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 -#include +#include #include #include -#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 -unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds) -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]; -int numSensors=0; -bool receivedConfig = false; -bool metric = true; -// Initialize temperature message -MyMessage msg(0,V_TEMP); +// 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 maxAttachedDS18B20 16 // Maximum amount of teperature sensors you can connect to this arduino (16). +// #define FAHRENHEIT // Remove the two slashes at the beginning of the line if you want to get the temperature in Fahrenheit. +unsigned long measurementInterval = 60000; // Time to wait between reads (in milliseconds). +float tempThreshold = 0.1; // The how big a temperature difference has to be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery. + +// 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[maxAttachedDS18B20]; // 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. +unsigned long measurementSleepTime = 0; // variable to store the calculated 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() { - // Startup up the OneWire library - sensors.begin(); + sensors.begin(); // Startup up the OneWire library. It allows multiple sensors to talk over one wire (one pin). } -void setup() -{ - // requestTemperatures() will not block current thread - sensors.setWaitForConversion(false); +void setup() +{ + for(int i=0; i= 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. + //ConversionTime = sensors.millisToWaitForConversion(sensors.getResolution()); + conversionTime = millisToWaitForConversion(sensors.getResolution()); // This is a modified version of the line above, to deal with the problem in the current Dallas library. + 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; // We're doing this now, so check calculating off the to-do list too. + for (int i=0; i(static_cast((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.; - - // Only send data if temperature has changed and no error - #if COMPARE_TEMP == 1 - if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) { - #else - if (temperature != -127.00 && temperature != 85.00) { - #endif - - // Send in the new temperature - send(msg.setSensor(i).set(temperature,1)); - // Save new temperatures for next compare - lastTemperature[i]=temperature; - } - } - sleep(SLEEP_TIME); + +// 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; + } } From 1d868de5ed53aa2515cddc16e0dd9ff04b13cbf7 Mon Sep 17 00:00:00 2001 From: flatsiedatsie Date: Thu, 23 Mar 2017 21:48:45 +0100 Subject: [PATCH 2/4] Update DallasTemperatureSensor.ino --- .../DallasTemperatureSensor.ino | 46 +++++++------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino index 4b8b86e..6ded12c 100644 --- a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino +++ b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -36,14 +36,14 @@ // 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't want to power that from a separate power source. It can also fix problems with fake Chinese versions of the radio. -// #define MY_RADIO_RFM69 // 433Mhz transmitter and reveiver. +// #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't want to power that from a separate power 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. +// #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. While it's sleeping it can't work as a repeater! #include #include @@ -55,7 +55,6 @@ #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 maxAttachedDS18B20 16 // Maximum amount of teperature sensors you can connect to this arduino (16). -// #define FAHRENHEIT // Remove the two slashes at the beginning of the line if you want to get the temperature in Fahrenheit. unsigned long measurementInterval = 60000; // Time to wait between reads (in milliseconds). float tempThreshold = 0.1; // The how big a temperature difference has to be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery. @@ -65,6 +64,8 @@ DallasTemperature sensors(&oneWire); // Pass the oneWire reference float lastTemperature[maxAttachedDS18B20]; // 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. unsigned long measurementSleepTime = 0; // variable to store the calculated Sleep time if the node is battery powered. +bool metric = true; // Variable that stores if the sensor will output the temperature in Fahrenheit of Celsius. The gateway sends this preference to the node. +bool receivedConfig = false; // This is not used in the code, but perhaps MySensors requires this? // Mysensors settings @@ -90,15 +91,14 @@ void setup() #endif Serial.begin(115200); // for serial debugging. - Serial.print("Hello world, I am a sensor. \n"); + 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= measurementInterval) // If we're not calculating, and enough time has passed, we'll start again. - { + 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. @@ -134,34 +133,21 @@ void loop() // Next, let's calculate and send the temperature - if(isCalculating == true && currentMillis > previousMeasurementMillis + conversionTime ) - { + if(isCalculating == true && currentMillis - conversionTime > previousMeasurementMillis) { isCalculating = false; // We're doing this now, so check calculating off the to-do list too. - for (int i=0; i Date: Thu, 23 Mar 2017 21:52:26 +0100 Subject: [PATCH 3/4] Dallas temperature sensor example update Added one space :-) Forgot to mention details about the previous commit: it changed a number of things based on feedback from Hek. Including spotting a millis wrap bug, very impressive. --- examples/DallasTemperatureSensor/DallasTemperatureSensor.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino index 6ded12c..a166059 100644 --- a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino +++ b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -136,7 +136,7 @@ void loop() if(isCalculating == true && currentMillis - conversionTime > previousMeasurementMillis) { isCalculating = false; // We're doing this now, so check calculating off the to-do list too. for (int i=0; i Date: Fri, 14 Apr 2017 10:07:36 +0200 Subject: [PATCH 4/4] Newer version this follows some conventions which may make it slightly easier to integrate it with other sensor modules. --- .../DallasTemperatureSensor.ino | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino index a166059..320eb7b 100644 --- a/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino +++ b/examples/DallasTemperatureSensor/DallasTemperatureSensor.ino @@ -1,4 +1,4 @@ -/** +m/** * 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 @@ -23,9 +23,10 @@ * 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. + * 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. */ @@ -45,31 +46,35 @@ // 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. While it's sleeping it can't work as a repeater! + +// LIBRARIES (in the Arduino IDE go to Sketch -> Include Library -> Manage Libraries to add these if you don't have them installed yet.) #include #include #include #include -// These defines and variables can be changed: +// VARIABLES YOU CAN CHANGE #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 ONE_WIRE_BUS 3 // Digital pin where Dallas sensor(s) is/are connected. #define maxAttachedDS18B20 16 // Maximum amount of teperature sensors you can connect to this arduino (16). unsigned long measurementInterval = 60000; // Time to wait between reads (in milliseconds). -float tempThreshold = 0.1; // The how big a temperature difference has to be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery. +float tempThreshold = 0.1; // How big a temperature difference has to be before an update is sent. Makes the sensor less precise, but also less jittery, and can save battery. + -// You should not change these: +//VARIABLES YOU PROBABLY SHOULDN'T CHANGE +#define TEMP_CHILD_ID 0 // for MySensors. Within this node each sensortype should have its own ID number. 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[maxAttachedDS18B20]; // 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. +int numSensors = 0; // variable to contain the number of found attached sensors. unsigned long measurementSleepTime = 0; // variable to store the calculated Sleep time if the node is battery powered. bool metric = true; // Variable that stores if the sensor will output the temperature in Fahrenheit of Celsius. The gateway sends this preference to the node. bool receivedConfig = false; // This is not used in the code, but perhaps MySensors requires this? // Mysensors settings -MyMessage msg(0,V_TEMP); // Sets up the message format that we'l be sending to the MySensors gateway later. +MyMessage msg(TEMP_CHILD_ID,V_TEMP); // Sets up the message format that we'l be sending to the MySensors gateway later. The first part is the ID of the specific sensor module on this node. The second part tells the gateway what kind of data to expect. void before() @@ -85,13 +90,13 @@ void setup() } sensors.setWaitForConversion(false); // requestTemperatures() will not block current thread -#ifdef BATTERY_POWERED // If batterypowered, we'll let Sleep take over the scheduling. +#ifdef BATTERY_POWERED // If the node is batter ypowered, we'll let Sleep take over the scheduling. measurementSleepTime = measurementInterval; - measurementInterval = 1; // When the Arduino is asleep, millis doesn't increment anymore (time stops as it were). To fix this, we'll set the measurement interval time to 1, so that when the arduino wakes up it will immediately try to measure again. + measurementInterval = 0; // When the Arduino is asleep, millis doesn't increment anymore (time stops as it were). To fix this, we'll 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 "); + Serial.println("Hello world, I am a sensor node."); } void presentation() @@ -99,7 +104,7 @@ 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= 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"); + if(dallasIsMeasuring == true && currentMillis - previousMeasurementMillis >= measurementInterval) { // If we're not calculating, and enough time has passed, we'll start again. + dallasIsMeasuring = false; // We're measuring, so let's take it off our to-do list. + Serial.println("Starting new measurement(s)"); previousMeasurementMillis = currentMillis; // Mark the time of the initialiation of this measurement. // Fetch temperatures from Dallas sensors @@ -128,20 +133,20 @@ void loop() // query conversion time. Apparently it takes a while to calculate. //ConversionTime = sensors.millisToWaitForConversion(sensors.getResolution()); conversionTime = millisToWaitForConversion(sensors.getResolution()); // This is a modified version of the line above, to deal with the problem in the current Dallas library. - isCalculating = true; //Next step is to re-calculate the temperature again. + dallasIsCalculating = true; //Next step is to re-calculate the temperature again. } // Next, let's calculate and send the temperature - if(isCalculating == true && currentMillis - conversionTime > previousMeasurementMillis) { - isCalculating = false; // We're doing this now, so check calculating off the to-do list too. + if(dallasIsCalculating == true && currentMillis - conversionTime > previousMeasurementMillis) { + dallasIsCalculating = false; // We're doing this now, so check calculating off the to-do list too. for (int i=0; i