Pages: [1]   Go Down
Author Topic: Maxim DS18B20 Temperature Sensor Giving Bad Readings  (Read 2136 times)
0 Members and 1 Guest are viewing this topic.
Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the Dallas/Maxim DS18B20 to measure temperature. Every few minutes it gives a bad reading. I sample temperature several times a second. The device is powered on the Vdd pin rather than using parasitic power. After giving a start conversion command, I check for an end of conversion by issuing a read slot and waiting for a high. I have tried to implement the timing requirements specified in the data sheet (480us min write slots and 60us min read slots).
Has anyone else had a similar problem? The only thing I can think of are that there may be spikes on the 5v from the USB cable, so I'll add a capacitor for filtering. Possibly the timing is borderline and delays could be increased. Implementing CRC checking would probably sort out all these problems.

This is the code which is quite long. Maybe some experts would spot something!

Code:
boolean DS18B20Initialize(int pin)
{
unsigned long start_time;
boolean low_detected=false;
int state;
char string[17];

digitalWrite(pin,HIGH); // make sure pin is high before enabling output
pinMode(pin,OUTPUT);
digitalWrite(pin,LOW);
delayMicroseconds(480);
pinMode(pin,INPUT);

start_time = micros();

while(!digitalRead); // wait for line to be pulled high

while((micros()-start_time)<480L)
{
if(!digitalRead(pin))
 low_detected=true; // a device  responded
}

//delayMicroseconds(5); // delay before next command
if (low_detected)
return(true);
else
return(false);
}

void DS18B20Write(int pin,byte data)
{
 byte n;

 for(n=0; n<8; n++)
 {
 if ((data & 0x01) == 1)  // test least significant bit
 {
 digitalWrite(pin, LOW);
 pinMode(pin, OUTPUT);
 delayMicroseconds(5); // > a low of >1us needed for a  "high" . delayMicroseconds accurate for delay > 3us so use 5us
 pinMode(pin, INPUT);
 delayMicroseconds(60); // sensor reads during a 60us max window
 }
 else
 {
 digitalWrite(pin, LOW);
 pinMode(pin, OUTPUT);
 delayMicroseconds(60); // minimum of 60us required for a low
 pinMode(pin, INPUT);   // release bus and let the resistor pull the input high
 delayMicroseconds(5);  // 1us required between write slots
 }

 data=data>>1; // now the next bit is in the least significant bit position.
 }

}

byte DS18B20Read(int pin)
{
 int n;
 int state;
 byte data=0;


 for (n=0; n<8; n++)
  {
   digitalWrite(pin,LOW);
   pinMode(pin,OUTPUT);
   delayMicroseconds(5); // a low of >1us needed at beginning of read slot delayMicroseconds accurate for delay > 3us so use 5us
   pinMode(pin,INPUT);   // release bus and let the resistor pull the input high
   delayMicroseconds(5); // wait another 5us and then read state of line within the 15us deadline required
   state=digitalRead(pin);
   delayMicroseconds(60); // complete the 60us read slot + add 5 us at the end
   data = (data >> 1) | (state<<7);
  }
   return(data);
}

boolean DS18B20ReadROMCode(int pin, byte *array)
{
 int i;
 
if(!DS18B20Initialize(tempsensor_pin))
 return(false);
DS18B20Write(tempsensor_pin,0x33); // Read the sensor's ROM code

for(i=0;i<8;i++)
 {
  *array = DS18B20Read(tempsensor_pin);
   array++;
 }
}

void DS18B20WMatchROMCode(int pin, byte array[])
{
 int i;

 DS18B20Write(tempsensor_pin,0x55); // Match the sensor's ROM code

 for(i=0;i<8;i++)
 {
  DS18B20Write(tempsensor_pin,array[i]);
 }
 
}

float ReadTemperature(int pin)
{
 int LoByte,HiByte,TReading,SignBit, Tc_100, Whole, Fract;
 int state;
 float temperature;
 static int errors=0;


// Initialize temperature sensor

if(DS18B20Initialize(tempsensor_pin))
{
//DS18B20Write(tempsensor_pin,0xCC); // skip rom
DS18B20WMatchROMCode(tempsensor_pin,TempSensorROMCode);
DS18B20Write(tempsensor_pin,0x44); // start conversion
}
else
{
 Message("Cant Init Sensor");
 return(1111);
}



// check to see if conversion is complete by issuing read slots and waiting for a "1"
do
{
 digitalWrite(pin,LOW);
 pinMode(pin,OUTPUT);
 delayMicroseconds(5); // a low of >1us needed at beginning of read slot delay. delayMicroseconds accurate for delay > 3us so use 5us
 pinMode(pin,INPUT);   // release bus and let the resistor pull the input high
 delayMicroseconds(5); // wait another 5us and then read state of line within the 15us deadline required
 state=digitalRead(pin);
 delayMicroseconds(60); // complete the 60us read slot + add 5 us at the end
} while (state==LOW);



if(DS18B20Initialize(tempsensor_pin))
{
//DS18B20Write(tempsensor_pin,0xCC); // skip rom
DS18B20WMatchROMCode(tempsensor_pin,TempSensorROMCode);
DS18B20Write(tempsensor_pin,0xBE); // read scratchpad
LoByte=DS18B20Read(tempsensor_pin);
HiByte=DS18B20Read(tempsensor_pin);
}
else
{
 Message("Cant Init Sensor");
 return(1111);
}

TReading = (HiByte << 8) + LoByte;

SignBit = TReading & 0x8000;  // test most significant bit

if (SignBit) // negative
{
 TReading = (TReading ^ 0xffff) + 1; // 2's comp
}


// Work out the whole and decimal parts
Whole = TReading >> 4;  
if(Whole > 30 || Whole < 0)
{
digitalWrite(onboard_led,HIGH);
errors++;
printNumber(errors);
}


//Fract = (TReading & 0x000F) * 6 + (TReading & 0x000F) / 4; // Convert two decimal places to an integer
 


temperature = TReading * 0.0625;  
if(SignBit)
 temperature = temperature * (-1);

return(temperature);
}
« Last Edit: June 23, 2013, 06:23:56 pm by Eugbug » Logged

Visit my blog at  http://eugbugino.blogspot.com and DIY, gardening and tool articles at http://eugbug.hubpages.com

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if you use the - http://milesburton.com/Dallas_Temperature_Control_Library - ?

does it block then?

BTW there is an error in this line, can you spot it?

Code:
while(!digitalRead); // wait for line to be pulled high
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Code:
while(!digitalRead); // wait for line to be pulled high

digitalRead without specifying a pin.... Yes, very dumb!
Logged

Visit my blog at  http://eugbugino.blogspot.com and DIY, gardening and tool articles at http://eugbug.hubpages.com

Dee Why NSW
Offline Offline
Edison Member
*
Karma: 47
Posts: 2202
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Every few minutes it gives a bad reading.
 I sample temperature several times a second.

That (without bothering to look at any code) may be the problem. I understand  the DS18B20 takes a while to do its stuff and once per second is about as fast as you should go.
Logged

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Every few minutes it gives a bad reading.
 I sample temperature several times a second.

That (without bothering to look at any code) may be the problem. I understand  the DS18B20 takes a while to do its stuff and once per second is about as fast as you should go.

Yes, I had considered that. The max conversion time at 12 bit resolution is quoted as 750 ms. I actually check in code for a "high" indicating an end of conversion. Values are still being output on the port several times per second. So either my code check for valid data isn't working or the sensor is converting in record time. I'll add a delay between conversions and eliminate the code check and see if it eliminates the problem.
Logged

Visit my blog at  http://eugbugino.blogspot.com and DIY, gardening and tool articles at http://eugbug.hubpages.com

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Update --

I added a 2 second delay between issuing the start conversion command and reading the two lower bytes in the scratchpad. This didn't make any difference.
Logged

Visit my blog at  http://eugbugino.blogspot.com and DIY, gardening and tool articles at http://eugbug.hubpages.com

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what is the length of the wires?
if it is long yo might use a smaller pull up resistor 2.2K iso 4.7K  (eh, do you use a pull up resistor?)
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

what is the length of the wires?
if it is long yo might use a smaller pull up resistor 2.2K iso 4.7K  (eh, do you use a pull up resistor?)


The leads are only about 15 cm long and I'm using a 4k7 resistor. I was considering using a decoupling capacitor on 5v power line from the Arduino board to filter transients but this could possibly damage the circuitry when the USB cable is disconnected.
Logged

Visit my blog at  http://eugbugino.blogspot.com and DIY, gardening and tool articles at http://eugbug.hubpages.com

Dee Why NSW
Offline Offline
Edison Member
*
Karma: 47
Posts: 2202
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, I recognise that there can't be much wrong with the code but I have now had a look and it is incomprehensible. You might try alternative code from Hacktronics or, if you are just using one or two sensors, the Sheepdog guides.

While the 4k7 pullup is surely OK, the 15cm suggests cable you have cobbled yourself. If this is just wires, or cheapo cable, you might try using decent shielded cable. All my sensors come with 3m shielded cables. I had strife with just a short extension of cheap cable.
« Last Edit: June 25, 2013, 06:45:25 pm by Nick_Pyner » Logged

Hamburg, Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Eugbug,
I used this sensor in a project a while back. In order to learn how to use it, I wrote a library that wrapped the one-wire library. I won't claim this to be the greatest code but it worked well for me in a Sous Vide cooker project. Maybe you can get some ideas from it. It even has documentation!

* DS1820.zip (142.25 KB - downloaded 35 times.)
Logged

Pages: [1]   Go Up
Jump to: