DS18B20 Temperature Sensor return as float function returning null 50% of the time I just got an DS18B20 Temperature sensor and am trying to modify the example code to use a function instead. Below is my getTemp function. It's working but returning results with a 0 value part of the time for example:


  Temperature = 72.39
  Temperature = 0.00


If I add Serial.print(fahrenheit); within the function I am always provided with the correct temperature. I though this may have to do with needing a delay but adding delay(5000); in my loop didn't help. 

I'm assuming it's something simple I'm not understanding about how floats return. 

#include &lt;OneWire.h&gt;

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(2);  // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
}

float getTemp(char tScale) {
  byte i;
  byte present = 0;
  byte type_s = 0;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return false;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i &lt; 9; i++) {           // we need 9 bytes
    data[i] = ds.read();

  }

  // 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 = (data[1] &lt;&lt; 8) | data[0];
  if (type_s) {
    raw = raw &lt;&lt; 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw &amp; 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] &amp; 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw &amp; ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw &amp; ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw &amp; ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  if (tScale == 'C') {
    return celsius;
  }
  else if (tScale == 'F') {
    return fahrenheit;
  }

}
void loop(void) {
    Serial.print("Temperature = ");
    Serial.println( getTemp( 'F' ) );


}


Edit:
Interesting enough, adding an if statement to the loop fixes this, however. I'd still like to understand what is going on:

void loop(void) {
  if ( getTemp( 'F' ) == 0 ){
    Serial.print( "Temperature = " );
    Serial.println( getTemp( 'F' ) );
  }
}
You have intermittent communication problems. 

Your address search occasionally fails and getTemp() returns false. In C++ (and many other languages) false will be implicitly cast to (int) 0, (float) 0.0f, and so on. 

Your getTemp() function  also is difficult to debug because the multiple return statements have different meaning. 

After the delay(250); you do a return false; in order to skip the rest.

In the example at https://www.pjrc.com/teensy/td_libs_OneWire.html the meaning of the return statement(s) is different. There the return happens within the void loop() function, where it simply means to interrupt the current execution (without returning a value) and continue with the next loop.

While it is generally okay to have multiple return, it can sometimes be problematic and I recommend to avoid it. 

If you want to clean this up while still preserving the ability to detect a fault, you have a couple of options (order from most to least recommended):


do the setup/checking in a different function (and only call the second one if the first one succeeded), i.e. if (isReady()) { Serial.println(getTemp()); }
set a separate error variable, i.e. error = true; return 0; (and then check error later)
define a 'default' value that you interpret as an error (and never expect to be a temperature), i.e. return NAN; // not a number