-
Notifications
You must be signed in to change notification settings - Fork 274
New Dallas temperature sensor example #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 <SPI.h> | ||
#include <MySensors.h> | ||
#include <MySensors.h> | ||
#include <DallasTemperature.h> | ||
#include <OneWire.h> | ||
|
||
#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<maxAttachedDS18B20; i++) | ||
{ | ||
lastTemperature[i] = 0; //Pre-filling array with 0's. | ||
} | ||
sensors.setWaitForConversion(false); // requestTemperatures() will not block current thread | ||
|
||
#ifdef BATTERY_POWERED // If batterypowered, 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. | ||
#endif | ||
|
||
Serial.begin(115200); // for serial debugging. | ||
Serial.print("Hello world, I am a sensor. \n"); | ||
} | ||
|
||
void presentation() { | ||
// Send the sketch version information to the gateway and Controller | ||
sendSketchInfo("Temperature Sensor", "1.1"); | ||
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<maxAttachedDS18B20; i++) | ||
{ | ||
present(i, S_TEMP); // Present all sensors to controller (16 maximum). | ||
} | ||
} | ||
|
||
// Fetch the number of attached temperature sensors | ||
numSensors = sensors.getDeviceCount(); | ||
|
||
// Present all sensors to controller | ||
for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) { | ||
present(i, S_TEMP); | ||
} | ||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to make this static as it will be initialized to millis() a few lines down. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not my code :-) but fixed . |
||
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. | ||
//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 ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't work when millis wrap(). Do the same type of check as above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't know that, interesting. I had read that during a millis wrap the subtract function still works. But I now realise that that won't work in this case. Very sharp! fixed. |
||
{ | ||
isCalculating = false; // We're doing this now, so check calculating off the to-do list too. | ||
for (int i=0; i<numSensors && i<maxAttachedDS18B20; i++) // Loop through all the attached temperature sensors. | ||
{ | ||
|
||
#ifdef FAHRENHEIT // Arduino's pre-processor selects which code gets added to the sensor based on which define is set in the settings at the top of this sketch. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would hard-code conversion setting. The examples normally uses Which allows you to change setting from controller. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, that explains why that was in there. I'm putting it back. Fixed. Out of curiosity: the original sketch used the booleans receivedConfig and metric |
||
float temperature = sensors.getTempFByIndex(i); | ||
#else | ||
float temperature = sensors.getTempCByIndex(i); | ||
#endif | ||
|
||
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) // Avoids working with measurement errors. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should use: which one depends on if getTempCByIndex / getTempFByIndex was called. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know what you mean. Would it be ok not to? :-D |
||
{ | ||
//if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature) | ||
if (COMPARE_TEMP == 1 && abs(temperature - lastTemperature[i]) < tempThreshold) | ||
{ | ||
Serial.print(temperature - lastTemperature[i]); | ||
Serial.print("- difference too small, so not sending the new measurement to the gateway.\n"); | ||
} | ||
else | ||
{ | ||
Serial.print(temperature - lastTemperature[i]); | ||
Serial.print("Sending the new 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; | ||
} | ||
} | ||
|
||
void loop() | ||
{ | ||
// Fetch temperatures from Dallas sensors | ||
sensors.requestTemperatures(); | ||
|
||
// query conversion time and sleep until conversion completed | ||
int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution()); | ||
// sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater) | ||
sleep(conversionTime); | ||
|
||
// Read temperatures and send them to controller | ||
for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) { | ||
|
||
// Fetch and round temperature to one decimal | ||
float temperature = static_cast<float>(static_cast<int>((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; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bracket placement does not confirm with coding standard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, misunderstood the standard. fixed.