Monitor temperature with 1 wire devices

“1-Wire is a device communications bus system designed by Dallas Semiconductor Corp. that provides low-speed data, signaling, and power over a single signal. 1-Wire is similar in concept to I²C, but with lower data rates and longer range. It is typically used to communicate with small inexpensive devices such as digital thermometers and weather instruments. A network of 1-Wire devices with an associated master device is called a MicroLan.”
wikipedia

In this post we will go deeper in how to use 1-wire with Arduino me mesure temperature.

1-wire description

1-wire is a Dallas Semiconductor proprietary adressed serial protocol. This protocol based on a master (in our case the Arduino) communicating with several slave connected to the bus. The same wire is used to power and to communicate with all slaves. Communication operating in parasitic power signal.

1-wire temperature sensors  (named DS1820) are really easy to use, cheap, and pre-calibrated.

1-Wire temperature Devices

Dallas Semiconductor delivers 2 differents 1-wire temperature sensors:

DS18B20

http://www.maximintegrated.com/datasheet/index.mvp/id/2815

This device converts temperature to a 9 bit value.

DS18S20

http://www.maximintegrated.com/datasheet/index.mvp/id/2812

This device is the same than above but you can programmatically choose the resolution of the temperature conversion from 9 bits to 12bits

Packaging

Several packaging are available for both sensor TO92, USOP, SOIC. Here for our exemple, we will use TO92 packages:

ds1820

 

Pull-up resistor

Actually 1-wire devices can be used with 2 modes: parasitic mode with 2 wires (vcc+data and gnd) and classical one with 3 wires (vcc, data and gnd).

With this mode, a 4,7k ohm pull up resistor needs to be connected to the one wire bus. When this line is in hight mode, an internal capacitor is charged to power the device.

Here is an exemple on how to connect a 1wire bus to an Arduino using pin 2. Classical mode

Classic1wire

 

Addressed protocol

1-wire is an addressed protocol so each device has a 64 bits unique identifier

Sans titre

 

family id is a specific id for each family device:

  • DS18S20 family is identified by 0x10
  • DS18B20 family is identified by 0x22

device id is a unique id for each device in a family

CRC is computed with other bits to check the validity

Main command for temperature devices

The communication on the 1-wire bus is initiated by the master (the Arduino, in our case) putting the bus on low state — reset. Each command on the bus should start with a reset.

0xF0: Search Rom: Search for connected devices to the bus

0x55 followed by 64 bit representing slave address: Match Rom: select a slave onto the bus

0x4E : write to RAM: used to configure devices

0xBE: read from RAM: used to get values

0x48: copie RAM to EEPROM: to keep configuration even if powering is off (only bytes 3, 4, 5 are copied for temperature sensors, bytes 1 and 2 contain last temperature measure)

0x44: start a temperature conversion, will be written to bytes 1 and 2

 

DS1820 registry

Capture d’écran 2014-02-23 à 17.54.39

 

Exemple of 1-wire communication

  1. Master send Reset
  2. Master send 0xF0 to search for slaves.
  3. One Slave responds with adress [A]
  4. Master send Rest
  5. Master send 0x55[A] to select device [A]
  6. Master send 0x44 to ask [A] to start a conversion on device [A]
  7. Master send Reset
  8. Master send 0x55[A] to select device [A]
  9. Master send 0xBE to read [A] RAM
  10. Slave send 9 bytes (2 firsts represent the temperature)

Code for the Arduino

A 1wire lib is available for arduino: http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip

Another librairie dedicated to temperature Sensor has been derivated from the previous one: http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library

In this code snippet we will used only the first one

#include 
 
// DS18S20 Temperature chip i/o
OneWire ds(10);  // on pin 10
 
void setup(void) {
  // initialize inputs/outputs
  // start serial port
  Serial.begin(9600);
}
 
void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
 
  //search adresses
  if ( !ds.search(addr)) {
      Serial.print("No more addresses.\n");
      ds.reset_search();
      return;
  }
 
  //get response address
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }
 
  //check CRC
  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }
 
  //read device familly
  if ( addr[0] == 0x10) {
      Serial.print("Device is a DS18S20 family device.\n");
  }
  else if ( addr[0] == 0x28) {
      Serial.print("Device is a DS18B20 family device.\n");
  }
  else {
      Serial.print("Device family is not recognized: 0x");
      Serial.println(addr[0],HEX);
      return;
  }
 
  //start a converion
  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.
 
  //read RAM
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
 
  Serial.print("P=");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  Serial.println();
}

 

Other 1-wire Devices

DS2438: smart battery monitor

Can measure

  • Temperature
  • Voltage
  • Current

http://datasheets.maximintegrated.com/en/ds/DS2438.pdf

 

DS2417: RTC

http://datasheets.maximintegrated.com/en/ds/DS2417.pdf

 

DS2505: 16kbit EEPROM memory

http://datasheets.maximintegrated.com/en/ds/DS2505.pdf

 

DS2450: 4 A/D Converters

http://datasheets.maximintegrated.com/en/ds/DS2450.pdf

 

DS2413: Dual Channel Addressable Switch

http://datasheets.maximintegrated.com/en/ds/DS2413.pdf

6 Comments

  1. Thank you for the short tutorial.

    How do you “address” individual DS18B20 temperature sensors, all on the same wire?

    i.e let’s say there’s 3 temperature sensors connected to the same Arduino D10 pin, how can you tell which is which?
    I want to display the “inside temperature” and “outside temperature” on two separate lines

    Reply
    • Hi Rudi.

      Each 1-wire device is addressed. It means each device has a unique address. So you can map a given location to a given address.

      In the sample code I wrote on this post “addr” is the address of the current device. If several devices are connected, on each loop, you will get data for a different device.

      Hope this help.

      Best,

      Reply

Leave a Comment.