Go Down

Topic: DS18B20 reports -196.60°F when temp < 4.1°F w/ DallasTemp library only (Read 8109 times) previous topic - next topic

RichXKU

Running an Uno with Adafruit WiFi shield, 20x4 LCD display (on I2C), a single DHT22 and two DS18B20 probes.

The DHT22 is for room temp/humidity and the two DS18B20 probes go in the refrigerator and freezer respectively.
DHT22 is on pin 2 and the DS18B20s are on pin 7.
Everything works great until the probe in the freezer goes below 4.1°F. At that point that particular probe just returns the value -196.60°F until the temp rises to 4.1 or greater again.
I tried physically swapping the probes to eliminate hardware issues, and no change. Whichever probe is in the freezer gives the -196.60 value below 4.1°F
Both DS18B20 probes are wired together, and I've tried 4.7k and 2.2k pullup resistors (+5VDC to data).
I'm using the DallasTemperature and OneWire libraries for the DS18B20.
The specs of the DS18B20 are -55°C to +125°C (-67°F to +257°F) which is well within the range of a freezer.

I'm hoping this is some strange math issue. Let me know if you have any ideas. My code is below. I've removed unrelated sections because the whole thing wouldn't fit.

Thanks!

Code: [Select]

                   
#include <Adafruit_CC3000.h>    // WiFi stuff
#include <SPI.h>
#include "utility/debug.h"
#include "utility/socket.h"


#include <Wire.h>
#include <LiquidCrystal_I2C.h>  //LCD
#include <OneWire.h>
#include <DallasTemperature.h>  //Temp Probes
#include <DHT.h>                // DHT Temp
#define ONE_WIRE_BUS 7 // Pin for Temp Probes

#define I2C_ADDR    0x27 //Address for LCD
#define BACKLIGHT_PIN     3  //LCD Don't need this but code breaks without it
#define En_pin  2    // LCD
#define Rw_pin  1    // LCD
#define Rs_pin  0    // LCD
#define D4_pin  4    // LCD
#define D5_pin  5    // LCD
#define D6_pin  6    // LCD
#define D7_pin  7    // LCD
#define DHTPIN 2     // DHT Pin
#define DHTTYPE DHT22   // DHT 22  (AM2302)

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.

DHT dht(DHTPIN, DHTTYPE);

 float probeAF;  // floating pt variables for probes in F and C
 float probeAC;
 float probeBF;
 float probeBC;

 float dhtTF;    // DHT Temp in F
 float dhtDP;    // DHT DP in C
 float dhtDPF;   // DHT DP in F
void setup()
{

 sensors.begin();
 dht.begin();
 lcd.begin(20,4);               // initialize the lcd


 lcd.clear();
 lcd.home ();                  
 lcd.print("Room:    |REF: ");    //Line 0 Base Text
 lcd.setCursor (0, 1);
 lcd.print ("T:       |FRZ: ");   //Line 1 Base Text
 lcd.setCursor(0,2);    
 lcd.print("DP:      |");         //Line 2 Base Text
 lcd.setCursor(9,3);
 lcd.print("|");                  //Line 3 Base Text


}


void loop()
{

 sensors.requestTemperatures(); // Send the command to get PROBE temperatures

 float h = dht.readHumidity();
 float t = dht.readTemperature();
delay(1000);
dhtTF = ((t*9)/5)+32;
dhtDP = (dewPointFast(t, h));
dhtDPF= ((dhtDP*9)/5)+32;


 probeAC = (sensors.getTempCByIndex(0)); // Get 1st probe temp
 probeBC = (sensors.getTempCByIndex(1)); // Get 2nd probe temp
 
 probeAF = probeAC * 1.8 + 32.0;
 probeBF = probeBC * 1.8 + 32.0;
 
 lcd.setCursor(15,0);
 lcd.print(probeBF);  // Refrigerator Temp
 lcd.setCursor(19,0);
 lcd.print(char(223));// Degree Symbol
 lcd.setCursor(15,1);
 lcd.print(probeAF);  // Freezer Temp
 lcd.setCursor(19,1);
 lcd.print(char(223));

 lcd.setCursor(3,1);  // Room Temp and DP
 lcd.print(dhtTF);
 lcd.setCursor(8,1);
 lcd.print(char(223));
 lcd.setCursor(3,2);
 lcd.print(dhtDPF);
 lcd.setCursor(8,2);
 lcd.print(char(223));
 

}

double dewPointFast(double celsius, double humidity)
{
double a = 17.271;
double b = 237.7;
double temp = (a * celsius) / (b + celsius) + log(humidity*0.01);
double Td = (b * temp) / (a - temp);
return Td;
}


Nick_Pyner

The environment is probably outside the range for accurate reporting from the DS18B20, but that seems unreasonably inaccurate. It may have something to do with the power supply but you might try testing the probes with standard code that does nothing else first - just temperature to serial monitor.


RichXKU

Thanks Nick, the DS18B20 is spec'd at -55°C to +125°C (-67°F to +257°F) which is well within the range of a freezer.
But I ran the DS18x10_Temperature example from the OneWire library and it shows temps below 4.1 just fine.

So it looks now like the DallasTemp library doesn't work, however reading the DS18B20 with the OneWire library needs a huge amount of supporting code (converting from HEX, etc).

I guess that is my next project  :~

Thanks again,
Rich

JimboZA

It would be interesting to see what's magic about that temperature. I'm speculating it's when another bit was brought into play in a variable or something like that, overflow kind of thing?
Johannesburg hams call me: ZS6JMB on Highveld rep 145.7875 (-600 & 88.5 tone)
Dr Perry Cox: "Help me to help you, help me to help you...."
Your answer may already be here: https://forum.arduino.cc/index.php?topic=384198.0

RichXKU

I emailed Miles Burton of the Dallas Temp Control library
http://milesburton.com/Dallas_Temperature_Control_Library

And I'll see what he has to say.

robtillaart

The sensor value of  -196.60  equals a Celsius temperature of -127 C.
from the code DallasTemperature.h:

Code: [Select]
// Error Codes
#define DEVICE_DISCONNECTED_C -127
#define DEVICE_DISCONNECTED_F -196.6


So at your sensor gets disconnected because of the cold. You should check your wiring/soldering if it is cold resistant.
The sensor (watretight version) can handle it.

Do you use the watertight version of the DS18B20?
Rob Tillaart

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

RichXKU

Rob, indeed this is the watertight probe.

Per my previous post, this only happens when using the Dallas Temp library. The OneWire test code example for DS18x20 devices returns temps just fine under 4.1 °. I'd rather not using though. because of the excessive amount of code required to convert the info from HEX.

Miles Burton responded and asked me to raise this issue on GitHub but I'm not familiar with using that site aside from reference.

michinyon

If the code thinks it is disconnected,  it doesn't matter which library you use.

RichXKU


If the code thinks it is disconnected,  it doesn't matter which library you use.


Per my previous, previous post, this only happens when using the Dallas Temp library. The OneWire test code example for DS18x20 devices returns temps just fine under 4.1 °. I'd rather not using though. because of the excessive amount of code required to convert the info from HEX.

robtillaart


Rob, indeed this is the watertight probe.

Per my previous post, this only happens when using the Dallas Temp library. The OneWire test code example for DS18x20 devices returns temps just fine under 4.1 °. I'd rather not using though. because of the excessive amount of code required to convert the info from HEX.

Miles Burton responded and asked me to raise this issue on GitHub but I'm not familiar with using that site aside from reference.

I've created an issue for you here - https://github.com/milesburton/Arduino-Temperature-Control-Library/issues/22 -

some note: 
* 4.1F = -15.5 C
* -196.60 = -127 C ==> DEVICE_DISCONNECTED

Rob Tillaart

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

jremington

Quote
I'd rather not using though. because of the excessive amount of code required to convert the info from HEX.
This doesn't make much sense. Hex is just one way of representing of a binary value. To which example are you referring, what do you need to convert and why does it take lots of code?

The code in this tutorial is compact, clearly described and works over the temperature range of the device: http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

RichXKU

Quote
I've created an issue for you here - https://github.com/milesburton/Arduino-Temperature-Control-Library/issues/22 -

Thanks, Rob!

Quote
This doesn't make much sense. Hex is just one way of representing of a binary value. To which example are you referring, what do you need to convert and why does it take lots of code?

The code in this tutorial is compact, clearly described and works over the temperature range of the device: http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

jremington: The hacktronics code uses the Dallas Temp library, which is the cause of the problem.

The DS18x20_Temperature example (below) included with OneWire.h works fine.

Is there a way to modify the code below to remove unnecessary bits and simply store the values of my 2 probes as, say, probeA and probeB?
I don't need to Serial.print anything.

Code: [Select]
#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(7);  // on pin 7 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(57600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

Nick_Pyner


I don't need to Serial.print anything.


So how do you find out if it is working properly? 
It seems that the only thing of value in the code you list is the third line of comment, and about the only constructive thing to come out of all this is that Miles Burton hasn't actually denied there is a problem.  But now, after the masterful comment from Robtillart, who actually took the trouble to convert -196.6 to celcius, you really ought to take clear steps to assure everybody that getting the problem when you use the library is not a coincidence. 

I wouldn't touch that code you are using with a long shovel. You might at least weed out the junk, of which there is quite a lot but, if you really can't get along with the proper stuff, you might try this, which uses no libraries at all.

http://sheepdogguides.com/arduino/ar3ne1tt.htm 

RichXKU

Quote
So how do you find out if it is working properly?

I'm passing the variables to an LCD and webclient.

Quote
But now, after the masterful comment from Robtillart, who actually took the trouble to convert -196.6 to celcius, you really ought to take clear steps to assure everybody that getting the problem when you use the library is not a coincidence.

I really don't see how it's a coincidence. At any temp under exactly 4.1°F the DallasTemp library causes the sensor to report that its disconnected. As soon as the temp rises to exactly 4.1°F again it starts reporting as normal.

Quote
I wouldn't touch that code you are using with a long shovel.

Why? It's the standard example included with the OneWire library. It has no glitches at any temperature, but I just need it to store in variables rather than Serial.print the values.

Quote
you might try this, which uses no libraries at all.
http://sheepdogguides.com/arduino/ar3ne1tt.htm

That's going in the complete opposite direction then. Why abandon the OneWire library if it works?

jremington

The hacktronics code, with its attendant library, works fine for me at temperatures less that 4.1 F. So, why doesn't it work for you?

Go Up