Arduino and the DS18B20 temperature sensor

So, this is the reason I started with an Arduino in the first place. In summer 2010 I ordered an Arduino and a DS18B20 temperature sensor because I wanted to monitor the water temperature in my aquarium in the summer and have the Arduino start fans if needed. My flat is directly below the roof and gets quite hot.

But I never figured out how to read the temperature from the sensor, every tutorial I followed, every code snippet I found showed either nothing at all or ridiculously wrong temperatures. Nevertheless, I just decided to try it again, wired it up and the third code snippet I tried worked. Of course, it’s the sample code right on the Arduino Playground

A DS18B20 temperature sensor wired up to an Arduino Duemilanove

It’s not perfect, it shows a little higher temperature than my regular room thermometer (20.6°C vs 23.5°C) and on random occasions it reads 85°C, but that should be easy to normalize.

So, here is the code, straight from the Arduino playground:

#include <OneWire.h>
 
OneWire ds(3); // on pin 3
void setup(void) {
  Serial.begin(9600);
}
 
void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  if ( !ds.search(addr)) {
      ds.reset_search();
      return;
  }
  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 < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }
 
  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  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("\n");
}

I removed some debug output so it shows only the temperature, and beware, this code only seems to work with the DS18B20, not with the DS18S20 and other variants of this sensor.

This is a schematic of the wiring:

The three pins on the bottom are, in order, Ground, +5V, and a digital input pin (in my case pin3)

Published by

Gerald

Diplom-Informatiker (DH) in Darmstadt. Ich blogge über Entwicklung, Internet, mobile Geräte und Virtualisierung. Meine Beiträge gibt es auch bei Google+ und Facebook.

One thought on “Arduino and the DS18B20 temperature sensor”

  1. >It’s not perfect, it shows a little higher temperature than my regular room thermometer (20.6°C vs 23.5°C) and on random occasions it reads 85°C, but that should be easy to normalize.

    The DS18B20 is very accurate but you have to connect Vdd to ground if you use the parasite power mode. Otherwise you will get wrong temperatures and/or errors on the 1-wire bus (85°C).

Leave a Reply

Your email address will not be published. Required fields are marked *