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.

68.90
69.01
69.01
69.01
69.01
Publishing now.
69.12
62.38
7356.54
7347.99
7358.00
7372.17
7381.74
7389.61
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?

2 Likes

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;
  switch(addr[0])

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()

    ds18b20.setResolution(9);

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;
        }
	}
	return;
}

1 Like

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


Update:
0.1.12 should now behave correctly

3 Likes

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