milesburton / arduino-temperature-control-library Goto Github PK
View Code? Open in Web Editor NEWArduino Temperature Library
Home Page: https://www.milesburton.com/w/index.php/Dallas_Temperature_Control_Library
Arduino Temperature Library
Home Page: https://www.milesburton.com/w/index.php/Dallas_Temperature_Control_Library
Hello,
after I triple checking for this, I found the bug that after using of function sensors.setResolution the resolution is change and with sensors.getResolution you will get new resolution, but for some reason sensor's delay is not changed.
For example sensor has default 12 bit, after changing to 9 bit I'm receiving only 9 bit precision but it take 750 ms.
After you will reset Arduino, then this is fixed and it take around 110 ms.
If you will test this, please note, when you open Serial console in Arduino IDE, it will always reset Arduino = you will start receiving correct delay.
So to verify this issue you need open different serial console, or you need have serial cable without possibility to reset Arduino.
For now I can solve this by adding init command
sensors.begin();
...
sensors.setResolution(insideThermometer, 9);
sensors.begin();
Strange is, when I change resolution to 9 bit, sensors.begin and then to 12 bit, Im receiving 12 bit resolution number and it take only around 110 ms.
Please investigate, thank you.
Hi all,
Am I missing out on something? I cant find any reference in the code for the function getTempByAddress (added in 3.5).
It is a feature that I would like to use in some of my code.
Am I looking in the wrong direction or is it removed in versions beyond 3.5?
Martin
According to specs of DS1822, if measuring temperature in parasite power mode the bus should be set high and keep it high until the temperature is ready, however the requestTemperaturesByAddress is calling isConnected in the mean time which breaks
the meassuring and keeps the sensor in undefined state.
Workarround could be to call isConnected before the STARTCONVO command is issued.
The library interface class has a function called isConversionComplete. However this function is not implemented in the library itself, hence it does not compile when used.
Hi,
When I connect ten DS18B20 , Adruino is getting strange readings. The readings are changening randomly for a second. Exapmle 23,4 degree in one room to -127 degree, and back to 23,4. After this the next DS18B20 do the same in another room . The readings are not changenign at the same moment on all DS18B20. Readings are changening room by room randomly. When I disconnect tenth DS18B20, everything is going back to normal. I have checked:
I is working fine only with maximum nine DS18B20
Please help me with my issue
Thanks
Pawel
Hello,
I have been reading through the source code, and I can't seem to make sense of what conversion means. Does it simply refer to a celcius to fahrenheit conversion, or something else?
The “Multibus_simple” examples tries to invoke a “setPin()” method on variable ds18x20 of type OneWire. However, this method does not appear to be defined in the OneWire library.
HI Miles,
saw this discussion - http://forum.arduino.cc/index.php?topic=179782.msg1332693#msg1332693 -
about storing data in the DS18B20 EEPROM. fix is included.
just to inform.
regards,
Rob
Hi.
Since c3e1e8f, I get following errors when compiling:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp: In member function ‘bool DallasTemperature::validAddress(const uint8_t*)’:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:67:39: error: invalid conversion from ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t* {aka unsigned char*}’ [-fpermissive]
return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]);
^
In file included from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.h:22:0,
from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:10:
/home/jerome/projets/arduino/libraries/OneWire/OneWire.h:152:20: error: initializing argument 1 of ‘static uint8_t OneWire::crc8(uint8_t*, uint8_t)’ [-fpermissive]
static uint8_t crc8( uint8_t *addr, uint8_t len);
^
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp: In member function ‘void DallasTemperature::readScratchPad(const uint8_t*, uint8_t*)’:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:107:30: error: invalid conversion from ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t* {aka unsigned char*}’ [-fpermissive]
_wire->select(deviceAddress);
^
In file included from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.h:22:0,
from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:10:
/home/jerome/projets/arduino/libraries/OneWire/OneWire.h:104:10: error: initializing argument 1 of ‘void OneWire::select(uint8_t*)’ [-fpermissive]
void select( uint8_t rom[8]);
^
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp: In member function ‘void DallasTemperature::writeScratchPad(const uint8_t*, const uint8_t*)’:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:174:30: error: invalid conversion from ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t* {aka unsigned char*}’ [-fpermissive]
_wire->select(deviceAddress);
^
In file included from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.h:22:0,
from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:10:
/home/jerome/projets/arduino/libraries/OneWire/OneWire.h:104:10: error: initializing argument 1 of ‘void OneWire::select(uint8_t*)’ [-fpermissive]
void select( uint8_t rom[8]);
^
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp: In member function ‘bool DallasTemperature::readPowerSupply(const uint8_t*)’:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:192:30: error: invalid conversion from ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t* {aka unsigned char*}’ [-fpermissive]
_wire->select(deviceAddress);
^
In file included from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.h:22:0,
from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:10:
/home/jerome/projets/arduino/libraries/OneWire/OneWire.h:104:10: error: initializing argument 1 of ‘void OneWire::select(uint8_t*)’ [-fpermissive]
void select( uint8_t rom[8]);
^
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp: In member function ‘bool DallasTemperature::requestTemperaturesByAddress(const uint8_t*)’:
/home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:342:30: error: invalid conversion from ‘const uint8_t* {aka const unsigned char*}’ to ‘uint8_t* {aka unsigned char*}’ [-fpermissive]
_wire->select(deviceAddress);
^
In file included from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.h:22:0,
from /home/jerome/projets/arduino/libraries/ArduinoTemperatureControlLibrary/DallasTemperature.cpp:10:
/home/jerome/projets/arduino/libraries/OneWire/OneWire.h:104:10: error: initializing argument 1 of ‘void OneWire::select(uint8_t*)’ [-fpermissive]
void select( uint8_t rom[8]);
^
Anything I'm doing wrong ?
Thanks.
Edit:
A bit more information about the context.
I'm using Arduino IDE with a sketch similar to this one.
Nothing really noticeable in there, just including the header and instantiating DallasTemperature:
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire);
shows how to use the library with two sensors on different pins.
useful for explicit pin to sensor relation
See this thread - http://forum.arduino.cc/index.php?topic=216835.msg1764333#msg1764333 -
//
// FILE: TwoPin_DS18B20.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: two pins for two sensors demo
// DATE: 2014-06-13
// URL:
//
// Released to the public domain
//
OneWire oneWire_in(ONE_WIRE_BUS_1);
OneWire oneWire_out(ONE_WIRE_BUS_2);
DallasTemperature sensor_inhouse(&oneWire_in);
DallasTemperature sensor_outhouse(&oneWire_out);
void setup(void)
{
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo - TwoPin_DS18B20");
sensor_inhouse.begin();
sensor_outhouse.begin();
}
void loop(void)
{
Serial.print("Requesting temperatures...");
sensor_inhouse.requestTemperatures();
sensor_outhouse.requestTemperatures();
Serial.println("DONE");
Serial.print("Inhouse: ");
Serial.println(sensor_inhouse.getTempCByIndex(0));
Serial.print("Outhouse: ");
Serial.println(sensor_outhouse.getTempCByIndex(0));
}
You released these versions, but the code still uses older ones. Which one is correct?
When calling getTempCByIndex and no sensors are available on the 1-wire network (deviceCount == 0), the call to getAddress will return false. But in the code this is never checked for.
It should return DEVICE_DISCONNECTED_C message, but now I'm simply getting 0.0
Not necessarily an issue but I thought I'd post it here as a possible design change for the default tutorial.
I noticed something very strange around the time it takes to send the requestTemperature command reading and when I made one small change the DS18B20 sped up considerably.
First I ran with the standard 5V, Gnd and input connected up as per normal with a 4.7k resistor between input and +5v. The 5v I used was just a standard board pin (Arduino Uno).
[code]
/*
Modified DS18B20 temperature reading script
This version by Tim Russell (http:.//www.russellweb.eu) and
is based on the original work from Miles Burton.
(https://github.com/milesburton/Arduino-Temperature-Control-Library)
*/
OneWire ourWire(ONE_WIRE_BUS);
DallasTemperature sensors(&ourWire);
void setup(){
delay(1000);
Serial.begin(115200);
Serial.println("Temperature Sensor DS18B20 Test Program");
delay(1000);
sensors.begin();
}
void loop(){
Serial.print(millis());
Serial.print(" ");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.print(millis());
Serial.print(" ");
Serial.print(sensors.getTempCByIndex(0));
Serial.print(" ");
Serial.println(millis());
}
[/code]
...The resulting serial print [b][color=red]showing 750ms to request the temperature[/color][/b].
[code]
Temperature Sensor DS18B20 Test Program
2061 2813 7.63 2842
2842 3595 7.63 3623
3624 4376 7.63 4406
4406 5158 7.63 5187
5187 5940 7.56 5968
5968 6721 7.63 6750
6750 7502 7.63 7531
[/code]
I then disconnected the power, made a few code changes and moved the power input to an Arduino digital pin, pin 2 in this case and ran it again.
[code]
/*
Modified DS18B20 temperature reading script
This version by Tim Russell (http:.//www.russellweb.eu) and
is based on the original work from Miles Burton.
(https://github.com/milesburton/Arduino-Temperature-Control-Library)
*/
OneWire ourWire(ONE_WIRE_BUS);
DallasTemperature sensors(&ourWire);
void setup(){
Serial.begin(115200);
Serial.println("Temperature Sensor DS18B20 Test Program");
delay(1000);
pinMode(ONE_WIRE_PWR, OUTPUT);
digitalWrite(ONE_WIRE_PWR, HIGH);
sensors.begin();
sensors.requestTemperatures(); // Send the command to get temperatures
delay(1000);
}
void loop(){
Serial.print(millis());
Serial.print(" ");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.print(millis());
Serial.print(" ");
Serial.print(sensors.getTempCByIndex(0));
Serial.print(" ");
Serial.println(millis());
}
[/code]
The serial result as you can see is quite different, [color=green][b]with less than 100 msec read[/b][/color] and I can't 'yet' explain it!!
[code]
Temperature Sensor DS18B20 Test Program
2097 2193 7.69 2222
2222 2319 7.69 2348
2348 2444 7.69 2472
2473 2570 7.69 2598
2598 2695 7.69 2723
2724 2821 7.69 2849
2849 2946 7.69 2974
2975 3072 7.69 3100
3100 3196 7.69 3225
3226 3322 7.69 3351
3351 3447 7.69 3476
[/code]
With some playing it appears there is a mismatch between the libraries and power to the sensor starting at the same time as the board. By introducing a delay to the power for the sensor it all works a lot quicker.
I'm sure someone with more time on their hands will go through the libraries and find the reason :P
My application contains the following (pseudocode) loop which is called once per second:
if (sensors.isConversionAvailable(chSensor)) {
ch.temp = sensors.getTempC(chSensor);
if (ch.temp != DEVICE_DISCONNECTED) {
. . .
}
sensors.requestTemperatures();
}
This code fails if the temperature reading is exactly 16.0 degrees C - isConversionAvailable() always returns FALSE.
Looking at the library code, isConversionAvailable() reads all of the scratchpad registers and returns TRUE if register 0 (temperature LSB) is non-zero. However a temperature of 16.0C is stored as 0x0100 in the scratchpad so the LSB will be zero and FALSE will be returned.
I have replaced isConversionAvailable() by the following, which follows the device datasheet by issuing a single read slot to test the data line, and my code now works correctly.
bool DallasTemperature::isConversionAvailable(uint8_t* deviceAddress)
{
// Check if the clock has been raised indicating the conversion is complete
_wire->reset();
uint8_t b = _wire->read_bit();
_wire->reset();
return (b == 1);
}
EDIT: Re-reading the data sheet I don't think my fix is correct. Certainly the reset() calls are not needed. However all my function does is to return 0 if any sensor on the bus has a conversion in progress - it is not possible to address a particular device. In fact I can't see from the data sheet any way of checking the status of one sensor, including the approach taken by the original function!
I see that people have been struggling with that 85 °C default temperature, most probably when they/we start to fiddle with these things. I still expect this appearing in real solutions every once and a while also, and it would be useful to neglect those values and make your application to at least raise it's eyebrown.
Having 85 °C on your operating range makes detecting the real value and default boot-up value really painful.
Would you concern implementing a default temperature value setting function? Having this boot-up temperature outside of the excpected operating range would be very helpful.
I can code "0" and "125" myself (based on the datasheet) using your scratchpad functions but no confidence to do the real comprehensive default temperature calculation for arbitrary values.
The functions *ByIndex() work correctly only when all expected sensors work correctly. If one of sensors becomes faulty (not connected), the resulting gap is filled by the next available sensor. Indexation crashes. The temperature sensors (and data) are mismatched. The last sensor(s) in the chain is falsely presented as faulty. This behavior could cause fatal problem in HVAC, engine control etc. (e.g. Inlet/Outlet Water/Oil/Air Temp …)
The root of the problem I see in the usage of getAddress() function. This function looks for sensors available ad hoc instead of the sensors really installed and defined in technology and assigned by a table.
The problem begins by begin() function which detects available sensors ad hoc. The application can compare the detected number of sensors with expected number only. And probably without *ByAddress() there is no chance to detect which of sensors disappeared.
The replacing of a faulty sensor can bring next difficult problem because the order of reading (indexation) may be different in comparison with the previous state. (I do not know rules for the order of sensor detection/reading).
For above mentioned reasons the use of actual getAddress() and *ByIndex() is very hazardous. The best solution would be to avoid the use of *ByIndex() functions (even to exclude them from the library). Apart from the fact that *ByIndex() are redundant to *ByAddress() functions.
Note: Sensors will be usually placed into a common table which assigns sensors to controlled technology. Position in the table is equal to the index. This indexation is likely “external” controlled by programmer instead of “internal”.
I imagine only one reliable solution:
I guess the price for reliability of sensors identification is acceptable.
I am unexperienced newbie in this forum. Perhaps Miles or Rob could implement presented idea..?
Is it possible to speed up? It looks like there is a delay..
Had to do async reads....
I had some problems compiling the cpp code within the ino environment and had to explicitly cast out some of the const specifications. Diff:
`79c72
return (_wire->crc8((unsigned char*)deviceAddress, 7) == deviceAddress[7]);
121c114
< _wire->select(deviceAddress);
_wire->select((unsigned char*)deviceAddress);
149c142
< _wire->select(deviceAddress);
_wire->select((unsigned char*)deviceAddress);
160c153
< _wire->select(deviceAddress);
_wire->select((unsigned char*)deviceAddress);
173c166
< _wire->select(deviceAddress);
_wire->select((unsigned char*)deviceAddress);
353c346
< _wire->select(deviceAddress);
_wire->select((unsigned char*)deviceAddress);
834c827
`
float DallasTemperature::toCelsius(float fahrenheit)
{
return (fahrenheit - 32) / 1.8;
}
as float divisions are slow this could also be
return (fahrenheit - 32) * 0.555555556;
minor
#define CONFIGURATION 4
conflicts with other libraries that use the same string "CONFIGURATION" in other places. For example: in https://github.com/marvinroger/homie-esp8266/blob/develop/src/HomieBootMode.hpp, CONFIGURATION is part of an enumeration.
Leads to compiler errors such as: "error: expected identifier before numeric constant".
rawToCelsius() and rawToFahrenheit() give wrong temperatures when temperature is negative. According to the DS18B20 datasheet, the sign bit is stored multiple times in index 11-15 of the scratchpad. Only the 16th bit (index 15) is wanted when using the direct to float casting (Celcius: (float)raw * 0.0625).
I just saw this and thought I'd mention it.
The operator new/delete
as found in DallasTemperature.cpp:828 is incorrect. According to the C++ specification of operator new/delete the operators should only allocate and free the memory regions.
The constructor and destructor calls are inserted by the compiler. As the operator delete
is calling the destructor explicitly, this will cause a double destruction of the object. Which is undefined behaviour. However as the destructor is trivial it is probably benign in that it won't cause any serious issues.
If this is some kind of a work around for a compiler but then I believe that it should be clearly stated.
@milesburton @SaintGimp @chrwei @RobTillaart @Ducatel
Why the temperature from DS18B20 by using the library is always zero? hope your reply.
I just use this method from this article:http://www.arduino.cn/thread-1345-1-1.html
Hi,
I've recently been dealing with an issue which appears to be in the DallasTemperature library. The problem occurs when I call sensors.begin() in the startup() function. I basically have a SQL database set up that is storing values to display later on a website. (EXAMPLE HERE)
The moment I un-comment the sensors.begin() line in my code, the program stops connecting to my server and does not send any more data. If I comment out the line, I can send data to my server just fine.
Is there an issue with this library and the Ethernet library I am not aware of? I've looked around and can't find a solution.
Thanks,
Luciano
See Arduino Forum
Hi,
I use the requestTemperatures() and getTempCBIndex() functions.
Ahead of that, i tried to set the resolution with setResolution(12), but it seems that it doesn't work. It should set all devices...
I used the "single" example and modified it for 12 bits resolution and that worked. This example makes use of the deviceaddress.
After that, my sketch displays OK in 12 bits resolution.
Any clue ?
I've tested it and the basics work. Have not yet tried all functions (like alarms), but Maxim datasheet says it is supposed to be drop in compatible with the DS18B20 so it should all work.
As title:
Why sensors.getDeviceCount() always returns 0?
How to debug the issue?
Cheers
in version 3.7.1 in DallasTemperature::begin()
There are the following lines (DallasTemperature.cpp:56-60):
//scratchPad is never actually used
ScratchPad scratchPad;
readScratchPad(deviceAddress, scratchPad);
//here getResolution() reads scratchPad again internally....
bitResolution = max(bitResolution, getResolution(deviceAddress));
recommendation:
remove the following unused, double called code from method
ScratchPad scratchPad;
readScratchPad(deviceAddress, scratchPad);
Hello,
I figured out that currently, the configuration is never stored in EEPROM.
There is a little burden in the library, in cpp file, in this function:
void DallasTemperature::writeScratchPad(uint8_t* deviceAddress, const uint8_t* scratchPad)
{
_wire->reset();
_wire->select(deviceAddress);
_wire->write(WRITESCRATCH);
_wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
_wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
// DS18S20 does not use the configuration register
if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
_wire->reset();
----- HERE SOMETHING MISSES ----
// save the newly written values to eeprom
_wire->write(COPYSCRATCH, parasite);
if (parasite) delay(10); // 10ms delay
_wire->reset();
}
After the second reset (before comment " // save the newly written values to eeprom") you should add that:
_wire->select(deviceAddress);
Otherwise, the copy command is never received.
Hope It helps.
Damien.
Docs imply that requestTemperatures will block until conversion is complete. I have 4 sensors (mix of MAX31820 and DS18B20) on a single 1 wire channel and was noticing frequent failures. Digging into this library, it looks like isConversionComplete returns when one of the sensors is ready rather than all of them. If there is any difference in conversion times between the sensors, subsequent getTemp calls can fail.
I've changed checkForConversion to false to workaround the problem, but either the docs and comments should be updated to be clear that requestTemperatures doesn't check for all sensors to complete or code enhanced to check all known sensors.
Hi there,
The Multibus_simple example that ships with this library fails to compile. The error code is as follows:
`Multibus_simple:7: error: no matching function for call to 'OneWire::OneWire()'
OneWire ds18x20[oneWirePinsCount];
^
In file included from D:\Arduino\libraries\DallasTemperature\examples\Multibus_simple\Multibus_simple.ino:1:0:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:269:5: note: candidate: OneWire::OneWire(uint8_t)
OneWire( uint8_t pin);
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:269:5: note: candidate expects 1 argument, 0 provided
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:254:7: note: candidate: constexpr OneWire::OneWire(const OneWire&)
class OneWire
^
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:254:7: note: candidate expects 1 argument, 0 provided
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:254:7: note: candidate: constexpr OneWire::OneWire(OneWire&&)
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire/OneWire.h:254:7: note: candidate expects 1 argument, 0 provided
Multibus_simple: In function 'void setup()':
Multibus_simple:22: error: 'class OneWire' has no member named 'setPin'
ds18x20[i].setPin(oneWirePins[i]);
^
Using library OneWire at version 2.3.2 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\OneWire
Using library DallasTemperature at version 3.7.6 in folder: D:\Arduino\libraries\DallasTemperature
no matching function for call to 'OneWire::OneWire()'`
I suspect that OneWire has changed its function names and that this library needs to be updated?
In the methods setHighAlarmTemp(const uint8_t* deviceAddress, char celsius) and
setLowAlarmTemp(const uint8_t* deviceAddress, char celsius), celsius is restricted by the if statement:
if (celsius > 125) celsius = 125;
else if (celsius < -55) celsius = -55;
Per the data sheet, the alarm temp is formed by the concatenation of the High and Low Alarm bytes so the per byte test doesn't accomplish the stated goal.
Also, per the data sheet, if you aren't using the alarm function the two bytes are fully available for user use. In my case, I am using them for shorthand device id's.
My vote is to remove the if statements, ask users to make sure the concatenation of bytes represents a valid temperature if they are using the alarm function, and not enforce any constraints if the bytes are for user data.
I have two strands of DS18B20 (almost like xmas lights). They are on a 3- conductor cable, so I'm not using parasitic power. One stand has nine DS18B20 and the other has 15. If I connect either strand to my Arduino, I can read all the sensors. But if I tie the two strands together so it looks like 24 devices to the Arduino, it doesn't see any of the devices. I have a 4.7k resistor between +5 and data line. Is there a max number of devices the library supports? If so, is this something I can change.
I have a Pro Micro ATmega32U4 (Leonardo) that has a simple sketch that simply reads the temp from A DS18B20. The sketch uploads and runs fine the first time printing out the correct temp until you restart or reset the Arduino. Then the temp prints out as -196.60 I have tried multiple sensors with the same result.
The DS18B20 is connected Red to +5v, Black to Ground and Yellow (signal) is connected to Red by 4.7K resistor and to pin 6 on the Mini.
Thanks for any help!
Bill
OneWire oneWire(6);
DallasTemperature sensors(&oneWire);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Program Start");
//initialized temp sensors
sensors.begin();
}
void loop() {
// put your main code here, to run repeatedly:
sensors.requestTemperatures();
float temp;
temp = sensors.getTempFByIndex(0);
Serial.print("Now sending ");
Serial.println(temp);
}
UPDATE 8/30/16:
If I ground pins 1 and 3 (VCC and GND) as recommended I immediately get the -196.60
I have tried this with 2 different processors with the same results.
The various ByIndex functions are susceptible to reordering if any devices are added or removed from the bus, as described in this issue.
I think it's a common use case to want a few temperatures in an ordered array, where the order can survive changes to the bus. If it's not common enough to bake into the library itself, it'd be great to have an example of that functionality!
When I am running the sample sketch SIMPLE.INO with no sensor connected to the pin I get a nice -127.
However running SINGLE.INO with no DS18B20 connected to the pin does return 0C and 32F
The problem is that the getTempC code does not detect the absence of a sensor in the function isConnected() which in his turn depends on readScratchPad's CRC
If there is nothing to be read, the scratchPad is filled with only 0's making the CRC8() result zero too. So it thinks it is connected.
The fix is to use the _wire->reset() in readScratchPad to detect the availability / absence of at least one sensor to the pin. ReadScratchPad() returns true /false which is used in isConnected(). See code below.
As far as I can see it does not fix the issue when there is "another" sensor on the pin as that one will react on the reset(). But the behaviour of the library will be better in general.
My proposal for the fix (and of course .h should follow)
// attempt to determine if the device at the given address is connected to the bus
// also allows for updating the read scratchpad
bool DallasTemperature::isConnected(const uint8_t* deviceAddress, uint8_t* scratchPad)
{
bool b = readScratchPad(deviceAddress, scratchPad);
return b && (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
}
// read device's scratch pad
bool DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad)
{
// send the command
int b = _wire->reset();
if (b == 0) return false;
_wire->select(deviceAddress);
_wire->write(READSCRATCH);
// TODO => collect all comments & use simple loop
// byte 0: temperature LSB
// byte 1: temperature MSB
// byte 2: high alarm temp
// byte 3: low alarm temp
// byte 4: DS18S20: store for crc
// DS18B20 & DS1822: configuration register
// byte 5: internal use & crc
// byte 6: DS18S20: COUNT_REMAIN
// DS18B20 & DS1822: store for crc
// byte 7: DS18S20: COUNT_PER_C
// DS18B20 & DS1822: store for crc
// byte 8: SCRATCHPAD_CRC
//
// for(int i=0; i<9; i++)
// {
// scratchPad[i] = _wire->read();
// }
// read the response
// byte 0: temperature LSB
scratchPad[TEMP_LSB] = _wire->read();
// byte 1: temperature MSB
scratchPad[TEMP_MSB] = _wire->read();
// byte 2: high alarm temp
scratchPad[HIGH_ALARM_TEMP] = _wire->read();
// byte 3: low alarm temp
scratchPad[LOW_ALARM_TEMP] = _wire->read();
// byte 4:
// DS18S20: store for crc
// DS18B20 & DS1822: configuration register
scratchPad[CONFIGURATION] = _wire->read();
// byte 5:
// internal use & crc
scratchPad[INTERNAL_BYTE] = _wire->read();
// byte 6:
// DS18S20: COUNT_REMAIN
// DS18B20 & DS1822: store for crc
scratchPad[COUNT_REMAIN] = _wire->read();
// byte 7:
// DS18S20: COUNT_PER_C
// DS18B20 & DS1822: store for crc
scratchPad[COUNT_PER_C] = _wire->read();
// byte 8:
// SCTRACHPAD_CRC
scratchPad[SCRATCHPAD_CRC] = _wire->read();
b = _wire->reset();
return (b == 1);
}
Another possible solution is to assume that the scratchpad may not be filled completely with zero's. But the datasheet does not tell unambiguously if reserved bytes of the SP can be all zero. at least how I read the datasheet. This would be a better solution (need more time to test but I don't have time now) On the other hand a pull up resistor on the line would return all 1's iso all 0's... and a floating line might even be worse....(to be elaborated)
In DallasTemperature.h header file the isConversionComplete function is defined but it is not implemented in the DallasTemperature.cpp file therefore it is not possible to use it.
Code:
// start conversion
bool cmp = tempSensor->isConversionComplete();
if(cmp == true)
{
Serial.println("Conversion complete");
// make it async
tempSensor->setWaitForConversion(false);
tempSensor->requestTemperatures();
tempSensor->setWaitForConversion(true);
}
else
{
Serial.println("Conversion not complete");
}
Error:
Compiling 'MyProject' for 'Arduino Uno'
_TempSensorController.cpp.o : : In function `_TempSensorController::run()':
_TempSensorController.cpp : isConversionComplete()'
Error creating .elf
The library use 9 bit resolution for DS18S20:
if (deviceAddress[0] == DS18S20MODEL) return 9; // this model has a fixed resolution
However, we need to set a fix resolution of 12 since:
Required fix:
if (deviceAddress[0] == DS18S20MODEL) return 12;
Temperature for DS18B20 should be calculated by the following formula:
temp = (LSB | MSB<<8) * increment
The increment is given by the current precision of 9, 10, 11, or 12 bits, corresponding to 0.5C, 0.25C, 0.125C, and 0.0625C respectively.
"count remain" and "count per c" are not defined for this processor.
Please refer to: http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
People might call "setResolution(12)" in setup or loop.
Devices that deepSleep by resetting themselves, might setup very often. This could kill the eeprom of the sensors.
The "setResolution(const uint8_t* deviceAddress, uint8_t newResolution)" method should/could check the current device resolution before actually changing it.
Same goes for every method that writes to eeprom.
hi,
I have been using your library for a few days now, and it's been working fine. But now I added another sensor chip to the circuit and, although the code recognizes both chips, the measured temperatures are about twice as much as they should be.
This is the code I am using:
definitions:
struct thermometer{ DeviceAddress deviceAddress; float measuredTemperatureC; }thermometer[32]; uint8_t oneWireDevicesCount;
using it:
` Serial.print("Requesting temperatures... ");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("Done.");
for (size_t i = 0; i < oneWireDevicesCount; i++) {
Serial.print("Device ");
Serial.print(i);
Serial.print(" temperature:\t");
thermometer[i].measuredTemperatureC = sensors.getTempC(thermometer[i].deviceAddress);
printTemperature(thermometer[i].measuredTemperatureC);
}`
This is a sample output from it:
Requesting temperatures... Done. Device 0 temperature: Temp C: 91.62 Temp F: 196.93
Even if I unplug one of them without power cycling the device, I get correct readings from the one that stayed online:
Requesting temperatures... Done.
Device 0 temperature: Temp C: 91.62 Temp F: 196.93
Device 1 temperature: Temp C: 89.56 Temp F: 193.21
Requesting temperatures... Done.
Device 0 temperature: Temp C: -127.00 Temp F: -196.60
Device 1 temperature: Temp C: 21.75 Temp F: 71.15
Requesting temperatures... Done.
Device 0 temperature: Temp C: 96.00 Temp F: 204.80
Device 1 temperature: Temp C: 86.00 Temp F: 186.80
You can clearly see that the middle sample is the one where one of the sensors were missing and the other one gave correct reading.
Any idea what might cause this?
Note that the example https://github.com/milesburton/Arduino-Temperature-Control-Library/blob/master/examples/Multibus_simple/Multibus_simple.ino does not work unless you have changes in OneWire.h
that is not yet merged in that lib.
Specifically this Pull Request has not yet been merged:
ntruchsess/arduino-OneWire#2
I wanted to hard reference my sensors, so I tried to use the
//insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
//outsideThermometer = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };
by uncommenting it. I proceeded to get the error
Multiple.pde: In function 'void setup()':
Multiple:41: error: expected primary-expression before '{' token
Multiple:41: error: expected `;' before '{' token
Based on a little digging, it seems illegal to assign a whole array in one go, after it has been initialized, in C (but I might be wrong).
By replacing
DeviceAddress insideThermometer, outsideThermometer;
with
DeviceAddress insideThermometer= {0x28, 0x55, 0xA3, 0xF2, 0x04, 0x00, 0x00, 0x4E };
DeviceAddress outsideThermometer= {0x28, 0x60, 0x22, 0xF3, 0x04, 0x00, 0x00, 0xC1 };
before the setup loop, it seemed to work fine.
Not sure the best way to correct the example, and it might be useful for others who have the same issue.
Could be an example to help people out?
just thinking out loud.
is there any way to use this library as non blocking, where i need to avoid delay in the arduino sketch where i am beginner in programing ?
Best regards,
sample code
#include <DallasTemperature.h>
void setup() {
}
void loop() {
}
when I open IDE 1.6.9 and compile code first time I always see this error
C:\Users\User\Documents\Arduino\libraries\DallasTemperature\DallasTemperature.cpp:781:6: warning: unused parameter 'deviceAddress' [-Wunused-parameter]
void DallasTemperature::defaultAlarmHandler(const uint8_t* deviceAddress){}
When I compile it again, there is no error. This error is showing always only after first compilation when IDE is opened.
Can you fix this?
Using method : Assign address manually
Ligne : 42: error: assigning to an array from an initializer list
insideThermometer = { 0x28, 0xFF, 0x19, 0x71, 0xC1, 0x15, 0x01, 0x55 };
^
Ligne : 43: error: assigning to an array from an initializer list
outsideThermometer = { 0x28, 0xFF, 0xFD, 0xAE, 0xC1, 0x15, 0x01, 0x0B };
The array can only be declared when you initialize it. It cannot be declare 1st and initialize after, it need to be declared 1 more time.
should be :
// arrays to hold device addresses
DeviceAddress insideThermometer, outsideThermometer;
[...]
// Assign address manually. The addresses below will beed to be changed
// to valid device addresses on your bus. Device address can be retrieved
// by using either oneWire.search(deviceAddress) or individually via
// sensors.getAddress(deviceAddress, index)
DeviceAddress insideThermometer = { 0x28, 0xFF, 0x19, 0x71, 0xC1, 0x15, 0x01, 0x55 };
DeviceAddress outsideThermometer = { 0x28, 0xFF, 0xFD, 0xAE, 0xC1, 0x15, 0x01, 0x0B };
Hi,
I am using XP and a DS18S20.
I have been using your v3.5 library (dated 17/02/10) for 2 years now and has worked as expected and very reliable. Recently I updated to VERSION 3.7.2 BETA.
I am not sure if this a bug or my misunderstaning something, my original code using the old library always took 750ms for a conversion as per Maxim datasheet. Using the latest library it takes 96ms, I am wondering if this is giving the sensor enough time for its conversion at 12 bit resolution?
After blocking requestForConversion
Time used: 96
Temperature: 18.50
After blocking requestForConversion
Time used: 752
Temperature: 18.44
// Data wire is plugged into port 2 on the Arduino
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature Control Library - Async Demo");
Serial.println("\nDemo shows the difference in length of the call\n\n");
// Start up the library
DeviceAddress tempDeviceAddress;
sensors.begin();
sensors.setWaitForConversion(true); // Comment this line out when used with old library
sensors.getAddress(tempDeviceAddress, 0);
sensors.setResolution(tempDeviceAddress, 12);
}
void loop(void)
{
// Request temperature conversion (traditional)
unsigned long start = millis();
sensors.requestTemperatures();
unsigned long stop = millis();
Serial.println("After blocking requestForConversion");
Serial.print("Time used: ");
Serial.println(stop - start);
// get temperature
Serial.print("Temperature: ");
Serial.println(sensors.getTempCByIndex(0));
Serial.println("\n");
delay(1000);
}
Any idea what I may be doing wrong?
I do note that you mention that the DS18S20 - appears to have a issue with this series. Although it doesn't state what the problem was?
Thanks for a great library and look forward to hearing your thoughts.
Regards
Gary
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.