DS18B20 Not returning anything "CRC is not valid"

I have two DS18B20’s, one of which I know is faulty (as it got very hot when I put it in the wrong way round) but the other one I think is ok.
I have pin 1 connected to ground, pin 2 connected to pin 13 of the arduino through a 4k4 pull up resistor and pin 3 connected to ground (as I thought was necessary for parasite power mode). I have a sample sketch which is supposed to output the temperature to the serial port. All it does though is print “CRC is not valid” to the serial window in the IDE.
Also, if I try to power the DS18B20 from 5V (which the datasheet says is possible through pin 3) the arduino freezes and serial output stops. I also can’t upload a sketch while the DS18B20 is connected.
Any ideas?

/* ds18B20_test

  Test utility to configure resolution and read temp from the Dallas Semi 18B20 
  one-wire digital temp sensor.
  
  datasheet: http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf

  Derived from sample code at http://www.arduino.cc/playground/Learning/OneWire

*/

#include <OneWire.h>

#define BAUDRATE 9600
#define TEMPSENSOR 13  // arduino i/o port connected to the ds18B20
#define DEBUG         // uncomment for verbose output

/* some defines to make more legible checks into data read from the device 
 *   (see the DS18B20 datasheet for more detail)
 */ 
#define TEMP_LSB 0
#define TEMP_MSB 1
#define TH_REG 2
#define USERBYTE_1 2
#define TL_REG 3
#define USERBYTE_2 3
#define CONFIG_REG 4
#define CRC 8

OneWire ds(TEMPSENSOR); 

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

/* convert celsius to fahrenheit
 *
 *   takes: float
 * returns: float
 */
float c2f(float cel) {
  return (cel * (9.0/5.0)) + (float)32;
}

/* read temp from DS18B20 sensor using one-wire protocol */
void loop() {

  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  int temp_c_int;
  float temp_c_frac;
  float temp_c;
  float temp_f;
  int test_bit;
  int set_bit;
  int resolution_floor;
  float expon;
  
  if ( !ds.search(addr)) {
      ds.reset_search();
      return;
  }

  /* print the address - might be useful for non-debug mode if you have
   *   >1 devices on the bus
   */
#ifdef DEBUG
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }
#endif

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }

  if ( addr[0] != 0x28) {
      Serial.print("Device is not a DS18B20 family device.\n");
      return;
  }

  /* modify scratchpad register to set temp sampling resolution */
  ds.reset();
  ds.select(addr);    
  ds.write(0x4E);          // write scratchpad (starts at byte 2)
  // note:  set high/low temp alarms by changing the next two values 
  ds.write(0x4B);    // default value of TH reg (user byte 1)
  ds.write(0x46);    // default value of TL reg (user byte 2)
  // uncomment one of the following
  ds.write(0x7F);    // 12-bit sampling resolution (default)
  //ds.write(0x5F);    // 11-bit
  //ds.write(0x3F);    // 10-bit
  //ds.write(0x1F);    // 9-bit

  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

  if (!present) {
    Serial.print("ERROR: selected device not present\n");
    return;
  }
  
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
#ifdef DEBUG
    Serial.print(data[i], HEX);
    Serial.print(" ");
#endif
  }

  if (data[8] != OneWire::crc8(data,8)) {
    Serial.print("ERROR: CRC didn't match\n");
    return;
  }
  
  /* print raw bytes from which we'll extract temp data */
#ifdef DEBUG 
  Serial.print("[MSB:");  Serial.print(data[TEMP_MSB],BIN);
  Serial.print(" LSB:");
  Serial.print(data[TEMP_LSB],BIN);
  Serial.print("] ");
#endif
  
  /* compute the degrees in celcius / integer part */
  temp_c_int = 0;
  
  /* The measured temp is spread across two bytes of the returned data.
   *  The integer part of the temp value is spread across the least 3 significant
   *  bits of the most significant byte (MSB) and the most significant 4 of 
   *  the LSB.  Here we shift those 7 bits into their proper place in our
   *  result byte. 
   *
   * note: could do this with 2 bit-shift / mask operations, alternatively
   */
  set_bit = 6;
  for (test_bit = 2; test_bit >= 0; test_bit--) {
    temp_c_int |= ( ((data[TEMP_MSB] & (1 << test_bit)) >> test_bit) << set_bit );
    set_bit--;
  }
  for (test_bit = 7; test_bit >= 4; test_bit--) {
    temp_c_int |= ( ((data[TEMP_LSB] & (1 << test_bit)) >> test_bit) << set_bit );
    set_bit--;
  }

#ifdef DEBUG
  Serial.print(temp_c_int,DEC);
#endif

  /* compute the fractional part */

  /*  first figure out what resolution we're measuring in - varies between 1 and 4 bits
   *    after the decimal (based on the contents of the CONFIG_REG byte):
   *        bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)
   *        bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)
   *        bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)
   *        bit 6 == 1 && bit 5 == 1 --> 12-bit resolution   
   */
  if ((data[CONFIG_REG] & (1 << 5)) > 0) {        
    if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 and 5 are set
      resolution_floor = 3;
    } el

This code worked for me:
http://www.nuelectronics.com/download/projects/ds18b20.pde

Add a 700 msec delay after the first command if you are using parasitic power mode.

However if your arduino stops working just after you connect the DS to Vcc then I am afraid your “good” sensor is damaged too.

Ok, thought so. Guess its back to nuelectronics for another sensor and an LCD maybe. Thanks for the info :)

ok i copy and pasted the code from here. http://www.nuelectronics.com/download/projects/ds18b20.pde

But all i get is that the temp reading is 0.00

I do have mine setup to run off of parasite power. And i did add the delay here (assuming this is where you were talking about.

void loop() { int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

OneWireReset(TEMP_PIN); delayMicroseconds(700); OneWireOutByte(TEMP_PIN, 0xcc);

ok i copy and pasted the code from here. http://www.nuelectronics.com/download/projects/ds18b20.pde

But all i get is that the temp reading is 0.00

I do have mine setup to run off of parasite power. And i did add the delay here (assuming this is where you were talking about.

void loop() { int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

OneWireReset(TEMP_PIN); delayMicroseconds(700); OneWireOutByte(TEMP_PIN, 0xcc);

I get more or less the same result as you:

When running the DS18B20 in normal power mode, with the code from Nuelectronics, I get the reading 0.00 all the time. When running in parasite power mode I get the reading 85.0 all the time.

This is how I connect the sensor: - In normal power mode: GND to GND on Arduino, DQ to Pin 3 on Arduino and Vdd to +5V on Arduino. - In parasite mode: GND to GND on Arduino, DQ to Pin 3 + DQ to +5V on Arduino, through a 4K4 resistor.

Anyone here with an idea about what is wrong?

When getting started, I found it easier to not use parasite power mode.

You don’t mention having a pull up resistor on the data line. I too got all “0” until I realized I left it out. I forget the value, look in the data sheet. 330-450 ohms?

Arduino gnd → DS gnd
Arduino 5V → DS Vdd
Arduino pin 3 → DS Dout
4700 ohms from DS Vdd to DS Dout

use this code:

#define TEMP_PIN  3

void OneWireReset(int Pin);
void OneWireOutByte(int Pin, byte d);
byte OneWireInByte(int Pin);

void setup()
{
    Serial.begin(9600);
    Serial.print("temperature measurement setup in progress\n");

    pinMode(TEMP_PIN, INPUT);      // sets the digital pin as input (logic 1)
    digitalWrite(TEMP_PIN, LOW);
    delay(100);
}

void loop()
{
  int HighByte, LowByte, TReading, SignBit, Tc_100, Tf_100, Whole, Fract;

  OneWireReset(TEMP_PIN);       // reset
  OneWireOutByte(TEMP_PIN, 0xcc); // skip ROM code
  OneWireOutByte(TEMP_PIN, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(TEMP_PIN);         // reset
  OneWireOutByte(TEMP_PIN, 0xcc); // skip ROM code
  OneWireOutByte(TEMP_PIN, 0xbe); // Read scratchpad code (temperature in this case)

  LowByte = OneWireInByte(TEMP_PIN);
  //Serial.print("Low byte = ");
  //Serial.print( LowByte );
  //Serial.println();
  
  HighByte = OneWireInByte(TEMP_PIN);
  //Serial.print("High byte = ");
  //Serial.print( HighByte );
  //Serial.println();

  TReading = (HighByte << 8) + LowByte;
  //Serial.print("Raw temp = ");
  //Serial.print( TReading );
  //Serial.println();

  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's complement the answer
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;

  
  if (SignBit) // If its negative
  {
     Serial.print("-");
  }
  
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
  {
     Serial.print("0");
  }
  Serial.print(Fract);
  Serial.print("C\n");

  Tf_100 = ((Tc_100 * 9) / 5) + 3200;
  Whole = Tf_100 / 100;  // separate off the whole and fractional portions
  Fract = Tf_100 % 100;

  
  if (SignBit) // If its negative
  {
     Serial.print("-");
  }
  
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
  {
     Serial.print("0");
  }
  Serial.print(Fract);
  Serial.print("F\n");

  Serial.print("\n");

  delay(2000);      // 2 second delay.  Adjust as necessary
}

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
}

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n = 8; n != 0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {  // if it is "1", pull low for just 5uS
         //digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         
         // then wait (external resistor pulls line back high)
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
      }
      else
      {  //lsb is "0", so pull low for 60uS
         //digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         
         // release, allowing external resistor to pull high
         pinMode(Pin, INPUT);
      }

      d = d >> 1; // now the next bit is in the least sig bit position.
   }
   
}

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for ( n = 0; n < 8; n++ )
    {
        // digitalWrite(Pin, LOW);
        // pull pin low for 5uS
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        
        // release pin, allowing external resistor to pull line back high for 5uS
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        
        // DS18B20 either pulls line low, or leaves it high
        // find out which...
        b = digitalRead(Pin);
        
        // wait bit time
        delayMicroseconds(50);
        
        // assemble our collected bits
        d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}

If you're interested, have a look at the code I posted here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1217214709. Hopefully you'll find it useful. Also, I use a 4.7k resistor for the pull up, and it seems to work fine for me.

Also, I use a 4.7k resistor for the pull up, and it seems to work fine for me

Indeed, that is what the data sheet says, and what I used. (changed in connection list to be correct.)

Don't know why I thought it was a few hundred rather than a few thousand...Gettin old, I guess.

Thanks hj43us,

I got it working right away after spending a great deal of time working on it other ways.

http://steliosm.net/projects/picaxetwitter/image_2.jpg is a good photo showing how it should be connected.

The DS18B20 code at the nuelectronics site appears a pirated version of my code which appears at http://www.phanderson.com/arduino/ with no credit given to me.

However, it is not correct. The correct code which includes the strong pullup is at http://www.phanderson.com/arduino/

Peter H Anderson