Looks like I may have uncovered a bug in the DS18B20 library. When reading temps below freezing, the reported temps are in the thousands.
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.
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])
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.
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;
}
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!
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 ).
As I added support for DS2438 I reworked (and bodged) the logic for the other sensor types