I was experimenting with some Dallas DS18B20s and happened across this OEM code:
int get_temperature(byte sensor)
{
float temp=(sensors.getTempC(allAddress[sensor]));
if ((temp<125.0) && (temp>-55.0)) return(temp*10);
}
The Arduino DallasTemperature library (i.e. getTempC()) returns:
#define DEVICE_DISCONNECTED_C -127
when it’s having trouble communicating with the sensor. That fails the second comparison above and causes get_temperature() to return without an explicit return value (which C permits but with an undefined return value).
If you work your way through the generated code, the second comparison generates a call to gesf2() to do a soft floating point compare. That function returns -1 (or 255) to indicate that -127.0 is less than -55.0 and then get_temperature() immediately returns with 255 still in r24 which then appears to the caller of get_temperature() as a successful reading of 25.5C.
Just had a quick check on Martin’s PLL code which is what my emonTX code is based and this drops in 300C (BAD_TEMPERATURE) if there is a bad CRC. But Martin manipulates the sensors much more directly than the standard code, i.e. doesn’t use getTempC().
In what conditions would you get a temperature out of range? And what happens in the normal code when there is a CRC error which would be the most likely indication of a comms error I guess.
Simon
int readTemperature()
{
byte buf[9];
int result;
oneWire.reset();
oneWire.write(SKIP_ROM);
oneWire.write(READ_SCRATCHPAD);
for(int i=0; i<9; i++) buf[i]=oneWire.read();
if(oneWire.crc8(buf,8)==buf[8])
{
result=(buf[1]<<8)|buf[0];
// result is temperature x16, multiply by 6.25 to convert to temperature x100
result=(result*6)+(result>>2);
}
else result=BAD_TEMPERATURE;
return result;
}
I provoked it by simply disconnecting the sensor. At the time my ambient was not a million miles from 25.5C so I thought there was some serious magic happening. Closer examination revealed it was jumping from ~24.6C when connected to a rock solid 25.5C when disconnected.
I think a transient CRC error would show up the same way. The DallasTemperature library code is very similar to your snippet above. It reads the entire scratchpad and verifies the CRC. If it’s bad it returns DEVICE_DISCONNECTED. So I think the total failure provoked by my pulling the plug would appear the same as a transient bit corruption.
I suspect it’s just a bug in get_temperature(). It too needs a return(BAD_TEMPERATURE) at the bottom to make sure it never runs off the end and returns the random-ish contents of r25:r24.