DS18B20 Library ERROR: Bad readings below 0C / 32F

Hi, All,

Looks like I may have uncovered a bug in the DS18B20 library. When reading temps below freezing, the reported temps are in the thousands. :rofl:

The app I’m using is the example ds18b20_singledrop example included with the Particle library. The serial monitor output you see below is the result of the ever-popular upside-down compressed air can test. Temperatures quickly returned to believable levels.

Maybe an unsigned variable hiding somewhere? I had a look at the DS18B20 and OneWire libraries, but nothing of note stood out to my highly untrained eye.

Thanks in advance for any help.

Publishing now.
Publishing now.

I saw this today as well, and I told my wife she should stay indoors.

1 Like

It looks like line 202 in the .cpp in the library should be int16_t instead of uint16_t.

Perhaps @ScruffR has some time to fix and test this?


Hey, bko,

Thank you for the fast response!

I gave it the ol’ college try with a copy-paste of the DS18B20 & OneWire libs; the part of the code you mentioned looks absolutely right for changing, especially given the comments directly above it! Lines 197-203 now look as below.

Sadly, no joy – same behavior as before. Looks like that darn ol’ bug is hiding somewhere else…

 // 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;

I’ve sent him some other data from my log files.

  • Transitions went from 32.00F to 7404.69F, and vice-versa.
  • I switched to Celsius readings for a while … these were pinned at 4095C during my tests.
1 Like

Can you share your code? I’m using the DS18B20 library (0.1.9) and can’t reproduce this. I had not tried any temperatures below freezing until today, but I stuck the probe in my freezer and it worked as expected. It seems that the temperature in my freezer is about 4 degrees Fahrenheit.

My library is a version 0.1.11 (current).

The code I’m using is the example single-drop sensor included as an example in the Particle library.

Temperature readings are good for anything above freezing.

I have only used DS19B20 version 0.1.11, running on a Xenon (on an ethernet featherwing, and without a mesh network). My sensor was connected to the D6 pin.

I can’t share my entire program, but everything that relates to the DS18B20 library is listed in the My code section at the bottom of this reply … but I have a better option for you:

When I saw this problem today, I assumed the problem was in my code, so I began troubleshooting. One of the tests that I ran was to build a fresh copy of the example program ds18b20_SingleDrop.ino. That test captured a transition from erroneous to valid temperatures as you can see below, so it would be ideal code to recreate the problem.

dsTmp 32.22 Faraday 3/29/19 at 10:41:55 am
dsTmp 32.22 Faraday 3/29/19 at 10:41:25 am
dsTmp 32.22 Faraday 3/29/19 at 10:40:54 am
dsTmp 32.22 Faraday 3/29/19 at 10:40:24 am
dsTmp 32.11 Faraday 3/29/19 at 10:39:54 am
dsTmp 32.00 Faraday 3/29/19 at 10:39:23 am
dsTmp 32.00 Faraday 3/29/19 at 10:38:53 am
dsTmp 32.00 Faraday 3/29/19 at 10:38:23 am
dsTmp 32.00 Faraday 3/29/19 at 10:37:51 am
dsTmp 7404.69 Faraday 3/29/19 at 10:37:20 am
dsTmp 7404.69 Faraday 3/29/19 at 10:36:50 am
dsTmp nan Faraday 3/29/19 at 10:36:20 am
dsTmp 7404.58 Faraday 3/29/19 at 10:35:46 am

My code

Global Variable

    const int DALLAS_ONE_WIRE_PIN = D6;
    DS18B20  ds18b20(DALLAS_ONE_WIRE_PIN, true);

This line is in setup()


This function is called from loop()

 void temperatureMonitor() {
	//static uint8_t outdoor_sensor[8] = {0x28, 0xff, 0x7b, 0x67, 0x70, 0x16, 0x04, 0x8b};  // sensor ID
	static const uint16_t READ_INTERLUDE = 30;                      // normal message frequency (in seconds)
	static const uint16_t RETRY_INTERLUDE = 5;                      // interval between retries (in seconds)
	static time_t nextReadTime = Time.now() + (RETRY_INTERLUDE);    // initial setting schedules the first temperature reading
    static char mqttMessage[64]; 
    static bool mqttMessageReadyToSend = false;     // when true, a mqttMessage is ready to publish
    static double lastValidTemperature;

	if (Time.now() >= (nextReadTime)) {
    	double currentReading = ds18b20.getTemperature();
    	if (ds18b20.crcCheck()) { 
    	    // sensor was read successfully ...
            lastValidTemperature = ds18b20.convertToFahrenheit(currentReading);
            // format the temperature message
        	snprintf(mqttMessage, sizeof(mqttMessage),
        	    "{\"time\":%lu, \"fah\":%0.2f}", Time.now(), lastValidTemperature);
            mqttMessageReadyToSend = true;
            // schedule the next reading
        	nextReadTime = (Time.now() + READ_INTERLUDE);       
    	} else {    // CRC error ... invalid data
    	    // schedule the next retry
    	    nextReadTime = (Time.now() + RETRY_INTERLUDE);
    /*  The following code block is designed to run in each loop() cycle. 
        If a message can not be sent immediatly after it is created, this block will
        keep trying to send it until the message is either sent or overwritten
	if (mqttMessageReadyToSend) { 
        if (mqttSessionActive && mqtt->isConnected()) {
	        bool retain = false;
            mqtt->publish("faraday/temp", (const uint8_t*) mqttMessage, strlen(mqttMessage), retain, MQTT::QOS2, NULL);
            mqttMessageReadyToSend = false;

1 Like

I’ll have a look when I find time to.
Maybe my bit shifting skills are a bit rusty :flushed:

0.1.12 should now behave correctly


That did it!

Thanks, @ScruffR, for spending a Spring Saturday morning on this.

Thanks, also, to @bko, who saw the first part of the trail with the uint16_t, where a int16_t should have been. That, and a few other changes, and are we are back to running good code!

Enjoy the weekend, everyone!

1 Like

Yes, it looks good here too.

This mornings readings:

  • 0.1.11 was returning 7394.11F
  • After flashing to 0.1.12 the readings were 21.42 F which is accurate.
1 Like

Was this something that only showed up in 0.1.11? (Just curious. I was not able to see the problem with my existing app using 0.1.9, and when I upgraded to the latest version today (0.1.12) I still don’t see it. But I never actually tried 0.1.11)

Yup, that was only 0.1.11 (and 0.1.10 which had other problems too :blush:).
As I added support for DS2438 I reworked (and bodged) the logic for the other sensor types :flushed:

Thanks for the information. (And thanks for the fix!)

1 Like