I am trying to get proper temperature readings for both of these one-wire sensors (not at the same time). They are connected in parasite mode as described on Arduino Playground - OneWire. Along with the sketch on that page.
The problem is that both the DS18S20 and DS18B20 are about 5 degrees too high when compared to a calibrated digital thermometer with probe. To check this I have put the one-wire sensors along with the thermometer probe in ice water. The probe gave me a reading of 0-1 while both one-wire sensors gave a reading of 3-4 degrees. All sensors were in ice water for several minutes.
When everything is at room temperature the probe gives me a reading of 19 while the one-wire sensors give a reading of 23.xx. I have tried two different DS18S20 sensors and two different DS18B20 but no joy for me.
I have absolutely no idea why I'm reading the temperature with such an offset. Does anyone know what could cause this?
I've tried the normal power mode as well, forgot to mention that. With both modes I get the same reading. I know that the DS18B20 and DS18S20 are suppose to be calibrated already and I trust that mine are too. My guess is that the error comes from somewhere else but I don't understand where.
I've tried changing the cables but that doesn't change anything.
With normal power you have decoupling on the chip? It does sound like they are out of spec (are they genuine parts or clones? Were they soldered for too long causing thermal stress perhaps?)
(Also double check your caclulations - print the raw temperature value and do the conversion by hand to check)
MarkT:
With normal power you have decoupling on the chip? It does sound like they are out of spec (are they genuine parts or clones? Were they soldered for too long causing thermal stress perhaps?)
(Also double check your caclulations - print the raw temperature value and do the conversion by hand to check)
I don't think I understand your first quetion about decoupling on the chip.
The parts I'm using are genuine dallas chips. I have the same issue with multiple chips, two were ordered last week and the other two were ordered a year or two ago. The chips are never soldered and were stored in anti-static bags.
WillR:
Maybe there should be "post the code" reminder?
And a good question is -- are you using the Dallas One-Wire code found here or where is it from?
I've tried several different codes, as I mentioned in the first post I've used the code found on the arduino playground. As well as the dallas library. They all give me the same readings. I even tried different wires and different values of pull-up resistors but no luck so far.
I am having the same problem!
I have two different sensors, both from Sparkfun (legit).
Everything is wired up correctly and the temperature is 5 degrees too high.
Emailed them about whether the batch had been tested.
I have the same issue, I have a pair that both read a little high. Never been that bothered by it - they're just reporting temperature in the house to a web server. Now I'm intrigued though. This:
print the raw temperature value and do the conversion by hand to check)
I know why XD !
The sensor was too close to the arduino.
When I keep them apart ( sensor and board), the temperature is good.
As soon as I take it close to the arduino the temperature shoots up!
I do not know why this happens but it's clear that it does influence my results.
I would like to report I see the same problem.
I tested with code that use the OnWrite library only and code that use OnWire and the DallasTemperature library and the problem is the same the temperature is 5 degree Celsius off
Hi All,
For what it's worth I have used the DS18b20 lots of times, without any problems.
I have just checked the one on my seed propagator with the thermocopule on my DMM and its within 0.42 of a degree. Perhaps check the maths, also how many bits are you reading??
I'm running in to the same problem. Problem started when running it on a ESP8266 stand alone. I was thinking maybe it is due to programming errors. So lets check it on my Arduino, but here i get the same results. I have tested two DS18B20 sensors, and both on Arduino as on NODEMCU i get a reading which is 5 degrees to high. On the arduino i used to sketch the following sketch:
// This Arduino sketch reads DS18B20 "1-Wire" digital
// temperature sensors.
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
DeviceAddress insideThermometer = { 0x28, 0xFF, 0xBB, 0xC9, 0x61, 0x15, 0x03, 0x22 };
DeviceAddress outsideThermometer = { 0x28, 0xFF, 0xE4, 0xC9, 0x61, 0x15, 0x03, 0xD8 };
DeviceAddress dogHouseThermometer = { 0x28, 0x59, 0xBE, 0xDF, 0x02, 0x00, 0x00, 0x9F };
void setup(void)
{
// start serial port
Serial.begin(9600);
// Start up the library
sensors.begin();
// set the resolution to 10 bit (good enough?)
sensors.setResolution(insideThermometer, 10);
// sensors.setResolution(outsideThermometer, 10);
// sensors.setResolution(dogHouseThermometer, 10);
}
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
Serial.print("Error getting temperature");
} else {
Serial.print("C: ");
Serial.print(tempC);
Serial.print(" F: ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
}
void loop(void)
{
delay(30000);
Serial.print("Getting temperatures...\n\r");
sensors.requestTemperatures();
Serial.print("Inside temperature is: ");
printTemperature(insideThermometer);
Serial.print("\n\r");
// Serial.print("Outside temperature is: ");
//// printTemperature(outsideThermometer);
// Serial.print("\n\r");
// Serial.print("Dog House temperature is: ");
// printTemperature(dogHouseThermometer);
// Serial.print("\n\r\n\r");
}
wired according this setup:
Was wondering if anyone had already found the problem?
I use this sensor all the time and never noticed any temp reading issue. I wrote my own code though, as I needed it to execute without blocking the main loop too long.
maybe this will help. just call initTemp() in setup() then call updateTemp() in loop(), and you can get temp reading anytime in loop by calling getTemp(). This code is optimized for a single sensor.
#include <OneWire.h>
#define TempPin 17
#define numReadings 8
OneWire ds(TempPin);
volatile uint16_t average;
volatile boolean initialized;
uint16_t sum;
boolean initTemp() {
if (ds.reset()) {
//if we are here, safe to assume temp sensor is present
ds.skip();
ds.write(0x44);
delay(1000);
if (ds.reset()) {
ds.skip();
ds.write(0xBE);
uint8_t data[9];
ds.read_bytes(data,9);
if (ds.crc8(data,8)!=data[8]) {
return false;
}
uint16_t tval = data[1] << 8 | data[0];
if (tval > 0 ) {
sum = tval * numReadings;
average = tval;
initialized=true;
return true;
}
}
}
return false;
}
float getTemp() {
if (!initialized) return 180.0;
static float lasttemp;
static unsigned long lastread;
unsigned long timenow = millis();
if (timenow-lastread>128) {
uint8_t saveSREG = SREG;
cli();
uint16_t t = average;
SREG=saveSREG;
lasttemp = t / 16.0
#ifndef CELSIUS
* 1.8 + 32.0
#endif
;
lastread=timenow;
}
return lasttemp;
}
uint16_t getTempRaw() {
if (!initialized) return 0xFFF;
uint8_t saveSREG = SREG;
cli();
uint16_t t = average;
SREG=saveSREG;
return t;
}
void updateTemp() {
static uint8_t state = 0;
// static uint8_t t = 0;
static uint8_t bytecounter = 0;
switch (state) {
case 0: //convert
if (ds.reset()) { //500us
state=1;
}
break;
case 1:
ds.skip(); //540us
state=2;
break;
case 2:
ds.write(0x44); //550us
state=3;
break;
case 3: //status
if (ds.read()>0) { //528us
state=4;
}
break;
case 4: //read command
if (ds.reset()) { //500us
state=5;
bytecounter=0;
}
else {
// t=0;
state=0;
}
break;
case 5:
ds.skip(); //540us
state=6;
break;
case 6: //read data
ds.write(0xBE); //530us
state=7;
bytecounter=0;
break;
case 7:
static uint8_t data[9];
if (bytecounter<9) {
data[bytecounter++]=ds.read();
return;
}
if (ds.crc8(data,8)==data[8]) {
uint16_t tval = data[1] << 8 | data[0];
if (tval > 256 && tval < 784) {
uint8_t saveSREG=SREG;
cli();
if (!initialized) {
sum = tval * numReadings;
average = tval;
}
else {
sum = (sum - average) + tval;
average = sum / numReadings;
}
SREG=saveSREG;
initialized=true;
}
}
else {
initialized=false;
}
state=0;
break;
}
}
you may need to edit the line
if (tval > 256 && tval < 784) {
as I use that to make sure the temp reading is in a valid range for my application.
I'm with doughboy. I don't don't have a problem, but I also don't use the DallasTemperature library because I don't write code in blocking mode. I also use a wire to each DS18B20 so I don't need to address each one (I have extra pins, so there was no need to use typical onewire mode).
The code is much more straight-forward when doing it this way too. Below is the basic code that I used (but not in blocking mode as this sketch):
#include <OneWire.h>
OneWire temp[2] = {
OneWire(4), // 1-Wire signal pin for lower temp sensor
OneWire(5) // 1-Wire signal pin for upper temp sensor
};
void setup(void) {
// Tell temp sensors to get the temp the first time
int tL = readTemp(0);
int tU = readTemp(1);
}
int readTemp(uint8_t sensor) {
byte data[12];
temp[sensor].reset(); // Reset sensor
temp[sensor].skip(); // Only one sensor so skip the address search
temp[sensor].write(0xBE); // Ask sensor to send latest temp reading
for (int i = 0; i < 9; i++) { // We receive data in this loop
data[i] = temp[sensor].read();
}
temp[sensor].reset(); // Reset sensor
temp[sensor].skip(); // Only one sensor on this pin so skip the address search
temp[sensor].write(0x44); // Tell sensor take another temp reading, will get the result on the next go-around
if (OneWire::crc8(data, 8) != data[8]) {
return -5000; // Error!
}
byte MSB = data[1];
byte LSB = data[0];
int16_t raw = ((MSB << 8) | LSB);
long fahrenheit = ((long)raw * 180 / 16 + 3205) / 10;
return fahrenheit;
}
void loop(void) {
delay(1000); // Do something else (or nothing) while sensor is doing the reading.
int tL = readTemp(0);
int tU = readTemp(1);
}
The tL and tU values are integers (10 times the actual temp in fahrenheit). I do this so I don't need to use floating point variables and math (slow and larger sketches). 70.5 degrees would be returned as 705. Just something else that I always do, along with not writing code in blocking mode.
Anyway, doing things this way, I always get stable results from my sensors. Also, make sure you keep the sensors away from any heat source (including the Arduino). It very well could be 5 degrees warmer next to your Arduino than with some remote calibration sensor.
I think that code still blocks, well all code in arduino blocks It's just a question of how long it blocks. Look at the OneWire library, there are a lot of delays inside due to bit banging.
I need my main loop to run really fast, and the typical gettemp code takes too long for my requirement.
On my code, each call to updateTemp takes no more than 560us, most of the time less. I essentially broke the typical gettemp routine down to its component as a state machine.
first call to updateTemp does ds.reset
second call to updateTemp does ds.skip
third call to updateTemp does ds.write
etc.
I need to do it this way as I want my main loop to complete in the shortest time possible so as not to starve other routines of execution time.
And it has built in running average smoothing of the temp readings.
It is interrupt friendly. I call getTempRaw from a timer interrupt handler and use it to turn a digital output high or low depending on temp value.
I use this code to continuously log temp values to SD card.
I have another version that works on multiple sensor (I tested up to 6 DS18B20) on the same wire. It just adds a couple more states.
Thank you for all replies. Sorry for my late reply. I have tried both the codes from Doughboy and Teckel. And they give me exactly the same output. So therefore I'm starting to believe the sensor, but it is still very strange for me. Because I am measuring room temperature. The 18D20 gives an output of 24 degrees Celsius, but my other two thermometers (analog one and a digital multi meter with temp sensor) give 19-20 degrees. The circa 20 degrees feels to be correct. I cant imagine it being 24 degrees in our living room, then it would feel a lot warmer.
So I am having a headache, I can't deny the value of the 18D20 since I tested 2 pieces on 2 different hardware platforms (ESP01 and Arduino Uno) which gave me (almost) the same reading. But it doesn't rime with the temperature feeling I have in house. I also asked some friends who where over to verified me, but they agreed, they did not believe it to be 24 degrees, it felt more like 20 degrees. Which is also the value of the analog meter(Mercury-in-glass thermometer) and my multi meter. Not sure what I'm going to do, was hoping to implement this in a weather station, to include inside temperature, but I don't like the high numbers...