What is 0.00 temperature on DS18B20?

Hi all,

I have a project in which i have 4 1-wire busses with multiple ds18b20 temperature sensors connected that i read once per hour. Here is the complete code: Comments & advices about my code - Programming Questions - Arduino Forum

You can see there that in the setup section i call for the sensors, read the number of devices in each bus, etc... Later, in the loop section, i request for temperatures in each bus in order to save them into an SD card.

I recenty discovered a rare behaviour. One 1-wire bus returned 0.00 values for all the sensors connected to it. I don´t understand what it means (of course, it is not 0ºC, because the other buses returned temperatures in agree with the environmental temperature, of about 11ºC), because if the device is not recognized or there is an error when reading the sensor, it should return -127.00 or 85.00 values.

When i tryed the "testing" example from DallasTemperature library, it required different tests, before to have them ready again.
Now, the device is working well again with my original code, but i am scary about if it happend again, because the device will be stand alone and it will only checked ones per year...

Is any way to detect this kind of behaviour? For example, something like

if (! sensors.requestTemperatures()){

(i know this not works because i tryed).
Something to detect if the the sensors does not reply to that call for temperatures...

Thanks!!

you could detect the zero temperature and do a watchdog reset if multiple sensors return 0 while others don't ...

Build the device to recover from failure (like NASA does)

Thanks robtillaart one more time for you good comments,

Yes, i considered this option but the device will be working in Antarctica, and during some months during the summer the temperatures could reach 0.0ºC (at least for some bus, meanwhile not the others). For that reason, i think that try to detect that the sensors do not reply to the temperature request could be more realistic… at least for my scenario.

My idea is, if i am able to detect this condition, to do a soft reset by this code from this forum:

// Restart the program from beginning
void softReset() {
  asm volatile ("  jmp 0");  
}

Thanks!!

I had a reading of zero from a DS18B20 but it was because my code didn't handle CRC errors properly. I'm not using DallasTemperature library but perhaps you have a similar situation?

Pete

madepablo:
Thanks robtillaart one more time for you good comments,

Yes, i considered this option but the device will be working in Antarctica, and during some months during the summer the temperatures could reach 0.0ºC (at least for some bus, meanwhile not the others). For that reason, i think that try to detect that the sensors do not reply to the temperature request could be more realistic... at least for my scenario.

Another alternative could be using another type of sensor e.g. analog TMP35 or even a ThermoCouple to measure the temperature in 2 different ways. These should not differ more than 2C or so.

Antartica - that sounds like a challenging project - never thought I would contribute to a project so far to the south.
IS there a website of this project?

The Dallas library you use has a function called bool DallasTemperature::isConnected(const uint8_t* deviceAddress)

The code of this function has a flaw if my analysis is correct

// attempt to determine if the device at the given address is connected to the bus
bool DallasTemperature::isConnected(uint8_t* deviceAddress)
{
  ScratchPad scratchPad;
  return isConnected(deviceAddress, scratchPad);
}

// attempt to determine if the device at the given address is connected to the bus
// also allows for updating the read scratchpad
bool DallasTemperature::isConnected(uint8_t* deviceAddress, uint8_t* scratchPad)
{
  readScratchPad(deviceAddress, scratchPad);
  return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
}

If the reading of the scratchpad failes because the one wire bus failes, all values in the scratchpad are zero the CRC will be zero.
Then the function isConnected() will return a false positive.

One way to solve it is to replace the function with a slightly different one and a modified readScratchPad().
WARNING: this is from my experimental version of the lib not much tested or reviewed. (but it seems to solve the issue)
the idea is to have readScratchPad return false if the 1Wire bus could not be reset properly, true otherwise
the CRC test itself remains intact.

bool DallasTemperature::isConnected(const uint8_t* deviceAddress, uint8_t* scratchPad)
{
    bool b1 = readScratchPad(deviceAddress, scratchPad);
    // bool b2 = false;
    // for (int i=0; i<9; i++)
    // {
      // if (scratchPad[i] != 0) b2 = true;
    // }
    return b1 && (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
}

// read device's scratch pad
 // TODO add param for # registers to read. -> mostly only field 0&1 are needed
bool DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad  /* uint8_t regCount */ ) 
{
    // send the command
    _wire->reset();  // TODO CHECK if this one returns wrong value one can already return false -> FAIL FAST?
    _wire->select(deviceAddress);
    _wire->write(READSCRATCH);

    // TODO => collect all comments &  use loop - VERIFY
    // byte 0: temperature LSB
    // byte 1: temperature MSB
    // byte 2: high alarm temp
    // byte 3: low alarm temp
    // byte 4: DS18S20: store for crc
    //         DS18B20 & DS1822: configuration register
    // byte 5: internal use & crc
    // byte 6: DS18S20: COUNT_REMAIN
    //         DS18B20 & DS1822: store for crc
    // byte 7: DS18S20: COUNT_PER_C
    //         DS18B20 & DS1822: store for crc
    // byte 8: SCRATCHPAD_CRC
    //
    // if (regCOunt > 9) regCount = 9;
    // for(int i=0; i<regCount; i++) scratchPad[i] = _wire->read();
    //

    // read the response

    // byte 0: temperature LSB
    scratchPad[TEMP_LSB] = _wire->read();

    // byte 1: temperature MSB
    scratchPad[TEMP_MSB] = _wire->read();

    // byte 2: high alarm temp
    scratchPad[HIGH_ALARM_TEMP] = _wire->read();

    // byte 3: low alarm temp
    scratchPad[LOW_ALARM_TEMP] = _wire->read();

    // byte 4:
    // DS18S20: store for crc
    // DS18B20 & DS1822: configuration register
    scratchPad[CONFIGURATION] = _wire->read();

    // byte 5:
    // internal use & crc
    scratchPad[INTERNAL_BYTE] = _wire->read();

    // byte 6:
    // DS18S20: COUNT_REMAIN
    // DS18B20 & DS1822: store for crc
    scratchPad[COUNT_REMAIN] = _wire->read();

    // byte 7:
    // DS18S20: COUNT_PER_C
    // DS18B20 & DS1822: store for crc
    scratchPad[COUNT_PER_C] = _wire->read();

    // byte 8:
    // SCTRACHPAD_CRC
    scratchPad[SCRATCHPAD_CRC] = _wire->read();

    int b = _wire->reset();
    return (b == 1);
}

I’ll contact the maintainer of the lib to see if it can be included in the official version.
[update] - send mail with proposal to maintainer

I just recalled I filed this fix as an issue 3 months ago at github - where was my mind this morning :wink:

Thanks so much robtillaart and el_supremo,

Yesterday night i was looking for CRC errors, following the @el_supremo comment, to learn about them, and i was exploring also the DallasTemperature library to see if it could something there what could help me.

On one hand i find something like these sentences:

sensors.isValid()
and sensors.reset()

However, the first one was related to a something old version of the library, and it doesn´t appear at present version. I saw the isConnected, but i assumed that when it returned FALSE the resulting temperature is -127 But i see that this is not true, thanls to the explanations of @robtillaart. Thanks so much!

On the other hand, if i do: sensors.reset(), Does it means that it reset all the sensors in the bus? and does it also reset the sensors resolution?

Thanks for thing how to solve this by changing the library. I am sure it will help a lot of people!

On the other hand, you are right, there are other type of sensors what i will use in the future since they are more accurate (0.1ºC or so, such as thermocouple and thermistors). However, for this first prototype, i was looking for something quick to install and to program, because i am worry about the general idea of the device (sensors, power supply, how to install the temperature busses in the field,...). for the next one i will consider real accurate sensors, and also a barebones board to reduce the consume, etc. In any case, the 0.5ºC is no bad at all. In fact, i already have installed in the field about 500 maxim temperature sensors with this resolution, and are quite enough for me purposes.

No, i am sorry. At this stage i didn´t have time to prepare the project webpage, although i have a blog where i write the adventures of your fieldtrips in antarctica. I will send you the link by a PM. In any case, thanks so much for you help to made this project run... We are studing the evolution of the frozen soils in the edge of the antarctic continent (where they are really sensible to small temperature increases), in order to have an "alarm-like" system of global warming and antarctic ice melting... So, your contributions help me to reduce the costs of the monitoring devices, what means more monitoring stations with similar economical costs... So... THANKS!

madepablo:
...
On the other hand, if i do: sensors.reset(), Does it means that it reset all the sensors in the bus? and does it also reset the sensors resolution?

sensors.reset() is not supported in Dallas lib IIRC?
the reset() is an underlying call of the OneWire Lib. It TRIES to reset the bus and its return value tells if it has succeeded or not

In my experience failing DS18B20's were always a problem with wiring. except once when I blew up one.
It created temperature instead of measuring it.

I am glad I can help with such a project. If you need more help let me know.

This maybe be a little outdated for the OP issue, but I ran into the same issue. For someone else that runs into this issue, another solution would be to check the configuration register, byte 4. The configuration register cannot be less than 0b00011111 = 31 per the datasheet page 9.

madepablo:
there is an error when reading the sensor, it should return -127.00 or 85.00 values.

Indeed, but I had a spurious reading 0.00 - once. Nobody could help me and the problem went away, never to be seen again. I assumed that DS18B20 and its library were entirely innocent, and the problem was caused by some other part of the code.