Wednesday, March 3, 2021

Reading the temperature from DS18B20 one-wire digital thermometer

Overview Of DS18B20

DS18B20 is a digital interface temperature sensor from Maxim Integrated. It has only one wire digital data input output, with two additional supply voltage pins. The temperature conversion from this device ranges from -55 degree Celsius to +125 degree Celsius. 
 
Digital temperature resolution is select-able between 9 to 12-bit. Within these 12-bit digital data, it consists of signed value, decimal temperature value and a 4-bit fraction numbers.

Reading the temperature from DS18B20 one-wire digital thermometer
A temperature reading from DS18B20 strobe-type.

 
Using only one wire digital data line, we can use multiple devices on this single wire. Each device is identified by its serial number and family code.

The conventional package and pin diagram of DS18B20

Within three pins of this device, the data DQ pin is open-drain. Hence it needed to pull up high via a resistor about 4.7 kOhm of resistance.

Typical connection to MCU

In some case, it doesn't require VDD.

Arduino Interfaces To DS18B20 With OneWire Library

Using the OneWire library developed by an author on Github, reading the device ID and temperature from this device family save a lot of time.
 
Installed library for OneWire
 
This library allow us to search for ROM. ROM identifies the devices connect on one wire bus. So we can use as much as one wire devices on a single line.

There are many function that I don't list them here. The example programs come this device could explain a lot about the overall processes.

In this example, I modified the device search and temperature reading to display their information on a SPI character LCD I made.

Reading the temperature from DS18B20 one-wire digital thermometer
Schematic Diagram For This Example

Arduino code lists below.

#include <OneWire.h>
#include <ShiftedLCD.h>
#include <SPI.h>

//OneWire Object Connect To Pin 2
OneWire  ds(2);

//Select pin 8 for Enable pin
LiquidCrystal lcd(8);

String dsString="";

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

  lcd.begin(16,4);
  lcd.clear();
 
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }
 
  if (OneWire::crc8(addr, 7) != addr[7]) {
      return;
  }
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
     
      type_s = 1;
      dsString="DS18S20";
      break;
    case 0x28:
     
      dsString="DS18B20";
      type_s = 0;
      break;
    case 0x22:
     
      dsString="DS1820";
      type_s = 0;
      break;
    default:
     
      dsString="N/A";
      return;
  }

  lcd.setCursor(0,0);
  lcd.print("Sensor: "+dsString);
 
  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

 
 
 

  // 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] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~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;
 
  lcd.setCursor(0,1);
  lcd.print("Temperature:");
  lcd.setCursor(-4,2);
  //lcd.print(String(celsius)+char(223)+"C" +" " + String(fahrenheit)+char(223)+"C");
  lcd.print(String(celsius)+char(223)+"C");
  lcd.setCursor(-4,3);
  lcd.print(String(fahrenheit)+char(223)+"F");
  delay(1000);
}


Arduino sketch could download here.

No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)