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')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)