Raspberry Pi Temperature Sensor

Reading real-world temperature on a Raspberry Pi means using a digital sensor like the DS18B20, which reports readings over the Pi's built-in 1-Wire interface rather than through a simple analog GPIO reading.

Why Temperature Needs More Than a Digital Pin

GPIO pins only ever tell you high or low - useful for a switch, useless for a continuously varying quantity like temperature. Rather than expecting the Pi to measure a raw analog voltage from a thermistor, the common approach is to use a sensor that does its own analog-to-digital conversion internally and simply reports a finished temperature reading over a digital protocol. The DS18B20 is the most popular example: a small three-pin sensor that communicates using Maxim's 1-Wire protocol, which the Raspberry Pi's Linux kernel already understands natively.

Wiring the DS18B20

  • VDD pin to the Pi's 3.3V rail.
  • GND pin to a Pi GND pin.
  • DATA pin to GPIO4, the pin Raspberry Pi OS's 1-Wire driver expects by default.
  • A 4.7k ohm pull-up resistor between the DATA line and 3.3V - required because 1-Wire is an open-drain bus that needs to be pulled high when idle.

Before the sensor will show up, 1-Wire support has to be turned on: enable it via raspi-config's interface options, or add dtoverlay=w1-gpio to /boot/config.txt and reboot. The kernel then loads the w1-gpio and w1-therm modules and creates a folder such as /sys/bus/w1/devices/28-xxxxxxxxxxxx containing a w1_slave file you can read like a normal text file.

Example

import glob

def read_ds18b20():
    device_file = glob.glob('/sys/bus/w1/devices/28-*/w1_slave')[0]
    with open(device_file, 'r') as f:
        lines = f.readlines()
    # second line holds something like 't=21875' -> 21.875 degrees C
    temp_string = lines[1].split('t=')[1]
    return int(temp_string) / 1000.0

print(f'{read_ds18b20():.1f} C')
Note: gpiozero does not include a DS18B20 class, and that is by design rather than an oversight: gpiozero's device classes drive pins directly through the Pi's own GPIO controller, whereas a 1-Wire sensor is handled entirely by a separate kernel driver and exposed as a file. Reading the sensor is therefore a plain file read rather than a gpiozero device object - but gpiozero is still the natural choice for reacting to the value, as shown below.

Example

from gpiozero import PWMLED
from time import sleep
import glob

warning_led = PWMLED(17)
device_file = glob.glob('/sys/bus/w1/devices/28-*/w1_slave')[0]

def read_ds18b20():
    with open(device_file, 'r') as f:
        lines = f.readlines()
    return int(lines[1].split('t=')[1]) / 1000.0

while True:
    temp_c = read_ds18b20()
    # brighten the LED as the room heats up between 20C and 30C
    warning_led.value = max(0.0, min(1.0, (temp_c - 20) / 10))
    sleep(1)
SensorInterfaceTypical accuracyGood for
DS18B201-Wire (digital, kernel driver)+/-0.5C over -10C to 85CPrecise single-value temperature logging, waterproof probe versions
DHT22Proprietary single-wire timing protocol+/-0.5C, +/-2% humidityCombined temperature and humidity in one sensor
Note: A DS18B20 needs time to complete its internal analog-to-digital conversion - roughly 750 milliseconds for full 12-bit precision. Reading the w1_slave file faster than that just returns the previous stale reading, so pace your polling loop accordingly.
Note: Because 1-Wire is a genuine shared bus, several DS18B20 sensors can sit on the same DATA pin at once. Each one shows up as its own folder under /sys/bus/w1/devices named after its unique factory-programmed serial number, so you distinguish sensors by folder name rather than by which pin they are on.