When you need reliable, high-accuracy thermal logging on a single-board computer, the DS18B20 is the definitive raspberry pi temp sensor. Unlike analog thermistors that require ADC scaling or I2C sensors that suffer from address conflicts, the DS18B20 uses the 1-Wire protocol. It outputs a calibrated digital signal directly to a GPIO pin, supports multi-drop bus wiring, and comes in waterproof stainless-steel probe variants for harsh environments.
This guide targets the Raspberry Pi 4 Model B (4GB/8GB) and the Raspberry Pi 5, running Raspberry Pi OS (Bookworm or later) with Python 3.9+. We will cover the physical wiring, kernel overlay configuration, and a robust native Python script that handles the most common 1-Wire bus errors without requiring third-party pip packages.
Sensor Selection: Why DS18B20 Wins for the Pi
Before wiring, it is worth understanding why the DS18B20 outperforms other common modules for dedicated temperature logging. The table below compares real-world bench specifications for the most popular Pi-compatible environmental sensors.
| Sensor Model | Protocol | Accuracy (Typical) | Operating Voltage | Best Use Case |
|---|---|---|---|---|
| DS18B20 | 1-Wire (Digital) | ±0.5°C (-10 to +85°C) | 3.0V - 5.5V | Liquids, outdoor, multi-node bus |
| DHT22 / AM2302 | Custom Single-Bus | ±0.5°C (Temp), ±2% (RH) | 3.3V - 5.5V | Indoor ambient air + humidity |
| TMP102 | I2C | ±0.5°C (-25 to +85°C) | 1.4V - 3.6V | PCB board-level thermal monitoring |
| BME280 | I2C / SPI | ±0.5°C (Temp), ±3% (RH) | 1.71V - 3.6V | Weather stations (Pressure/Temp/Humidity) |
The DS18B20's primary advantage is its unique 64-bit serial code embedded in every chip. This allows you to wire dozens of sensors to a single GPIO pin (a multi-drop bus) and read them individually by their hardware ID. Furthermore, its 3.0V minimum operating voltage makes it natively compatible with the Pi's 3.3V logic level, avoiding the logic-level shifting required by some 5V-only sensors.
Parts List & GPIO Pin Mapping
For this build, we are using the external power mode (VDD connected to 3.3V) rather than parasitic power mode, as it provides faster conversion times and higher stability on the Pi's GPIO bus.
Required Components
- Microcontroller: Raspberry Pi 4 Model B or Raspberry Pi 5
- Sensor: DS18B20 (Maxim/Analog Devices). Either the TO-92 through-hole package or the waterproof stainless-steel probe.
- Resistor: 4.7kΩ 1/4W metal film resistor (crucial for the 1-Wire pull-up).
- Wiring: Male-to-female jumper wires or 22 AWG solid core wire.
- Prototyping: Half-size solderless breadboard.
Pin Mapping Table
The 1-Wire interface on the Raspberry Pi defaults to GPIO 4. Do not connect the data line to any other pin unless you are modifying the kernel device tree overlay.
| DS18B20 Pin (TO-92) | Waterproof Probe Wire | Raspberry Pi GPIO | Physical Pin # | Notes |
|---|---|---|---|---|
| Pin 1 (GND) | Black | GND | Pin 6 | Common ground reference |
| Pin 2 (DQ / Data) | Yellow or White | GPIO 4 | Pin 7 | Requires 4.7kΩ pull-up to 3.3V |
| Pin 3 (VDD) | Red | 3V3 Power | Pin 1 | Do not use 5V on Pi 4/5 GPIO |
Physical Wiring & Enabling the 1-Wire Bus
The Raspberry Pi does not have a hardware 1-Wire controller. It bit-bangs the protocol via the GPIO pin using a kernel overlay. You must enable this overlay before the OS will create the virtual device files in the /sys/ directory.
- Wire the Sensor: Connect VCC to Pin 1 (3.3V), GND to Pin 6, and Data to Pin 7 (GPIO 4).
- Install the Pull-Up Resistor: Insert the 4.7kΩ resistor between the 3.3V line (Pin 1) and the Data line (Pin 7). Without this resistor, the data line will float, and the Pi will read garbage or fail to detect the sensor entirely.
- Enable 1-Wire via raspi-config:
- Open a terminal and run:
sudo raspi-config - Navigate to Interface Options > 1-Wire and select Enable.
- Reboot the Pi:
sudo reboot
- Open a terminal and run:
- Verify the Kernel Overlay: After rebooting, check the boot config by running
cat /boot/firmware/config.txt | grep w1(or/boot/config.txton older OS versions). You should seedtoverlay=w1-gpio.
Complete Python Read Script with Error Handling
While you can install third-party libraries like w1thermsensor via pip, the native Linux sysfs interface is bulletproof, requires zero dependencies, and is ideal for headless cron jobs. The script below targets Python 3.9+ and includes explicit error handling for the two most common 1-Wire failure modes: missing device files and the 85°C power-on reset ghost reading.
import os
import glob
import time
# Base directory for 1-Wire devices injected by the kernel
BASE_DIR = '/sys/bus/w1/devices/'
def get_sensor_paths():
"""Finds all connected 1-Wire temperature sensors (family code 28)."""
device_folders = glob.glob(BASE_DIR + '28*')
if not device_folders:
return []
return [os.path.join(folder, 'w1_slave') for folder in device_folders]
def read_temp_raw(sensor_file):
"""Reads the raw hex dump from the 1-Wire sysfs file."""
try:
with open(sensor_file, 'r') as f:
lines = f.readlines()
return lines
except FileNotFoundError:
print(f'Error: {sensor_file} not found. Is the sensor disconnected?')
return None
def parse_temperature(sensor_file):
"""Parses the raw data, checks the CRC, and returns Celsius."""
lines = read_temp_raw(sensor_file)
if lines is None:
return None
# Wait for the sensor to finish conversion if CRC fails on first read
retries = 0
while lines[0].strip()[-3:] != 'YES' and retries < 5:
time.sleep(0.2)
lines = read_temp_raw(sensor_file)
if lines is None:
return None
retries += 1
if retries == 5:
print('Error: CRC check failed after 5 retries. Check pull-up resistor.')
return None
# Extract the temperature value from the second line
try:
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
# Handle the 85.0 power-on reset error
if temp_c == 85.0:
print('Warning: Read 85.0C. This is the power-on default. Sensor may lack sufficient power.')
return None
return temp_c
except IndexError:
print('Error: Malformed data returned from sensor.')
return None
if __name__ == '__main__':
print('Scanning for DS18B20 sensors...')
sensors = get_sensor_paths()
if not sensors:
print('No sensors found. Verify dtoverlay=w1-gpio is in config.txt and wiring is correct.')
else:
print(f'Found {len(sensors)} sensor(s). Starting continuous read...')
try:
while True:
for i, sensor in enumerate(sensors):
temp = parse_temperature(sensor)
if temp is not None:
print(f'Sensor {i+1} [{sensor.split("/")[-2]}]: {temp:.2f} C | {(temp * 9/5) + 32:.2f} F')
time.sleep(2)
except KeyboardInterrupt:
print('\nLogging stopped.')
Debugging: Exact Errors and the First Three Checks
The 1-Wire protocol is unforgiving of marginal connections. If your script fails, do not immediately rewrite your code. Perform these first three hardware checks, which resolve 95% of Pi temp sensor issues.
The First Three Things to Check
- Verify the 4.7kΩ Pull-Up Resistor: The 1-Wire bus is an open-drain protocol. The Pi can pull the line LOW, but it relies on the external pull-up resistor to bring it HIGH. If the resistor is missing, or if you used a 10kΩ+ resistor by mistake, the signal edges will be too slow, and the CRC check will fail.
- Confirm the Kernel Overlay is Active: Run
ls /sys/bus/w1/devices/. If you only seew1_bus_master1and no folder starting with28-, the Pi is not detecting the sensor's ROM. This means either the overlay is disabled, or the data wire is broken. - Check for Parasitic Power Wiring Mistakes: If you wired VDD to GND (intending to use parasitic power mode) but didn't configure the Pi for it, the sensor will not power up. For beginners, always wire VDD to 3.3V (External Power Mode).
Common Error Strings and Ranked Causes
FileNotFoundError: [Errno 2] No such file or directory: '/sys/bus/w1/devices/28-00000xxxxxx/w1_slave'
- Cause 1 (Most Likely): The sensor disconnected or the wire broke while the script was running. The kernel dynamically removes the directory when the ROM is no longer detected on the bus.
- Cause 2: You hardcoded the sensor ID in an older script, but you swapped the physical sensor. Use the
glob.glob('28*')method shown in our code to dynamically find the ID.
85.000 C continuously.
- Cause 1 (Most Likely): Insufficient current on the 3.3V rail, or the wire run is too long (>3 meters) causing voltage drop. 85°C is the DS18B20's hardware power-on reset value. If the sensor fails to complete the ADC conversion before the Pi reads the scratchpad, it returns this default.
- Cause 2: You are reading the sensor too fast. The DS18B20 requires up to 750ms for a 12-bit conversion. Ensure your loop has a
time.sleep()delay.
Extending and Simplifying the Build
Once you have a single sensor logging reliably, you will likely want to scale the system or adapt it for a different deployment environment.
How to Extend: Multi-Drop Bus Wiring
The 1-Wire protocol allows you to wire up to 20+ DS18B20 sensors in parallel on the exact same GPIO 4 pin. To extend the build: Simply wire the VCC, GND, and Data pins of additional sensors in parallel with the first one. Crucially, you only need one 4.7kΩ pull-up resistor for the entire bus. If your cable runs exceed 5 meters, drop the pull-up resistor value to 2.2kΩ or 1.5kΩ to compensate for the increased capacitance of the long wires, which otherwise rounds off the digital square waves.
The Python script provided above already handles this: the get_sensor_paths() function uses a glob wildcard (28*) to automatically discover and iterate over every sensor connected to the bus, printing their unique 64-bit ROM IDs so you can map them to physical locations.
How to Simplify: Switching to I2C
If you find the 1-Wire kernel overlay frustrating, or if you are building a quick prototype and don't want to deal with pull-up resistors and bit-banging timing issues, simplify the build by switching to an I2C TMP102 or BME280 sensor.
- Why it's simpler: I2C has dedicated hardware controllers on the Pi (SDA on GPIO 2, SCL on GPIO 3). The OS handles the clock stretching and timing automatically.
- The trade-off: You lose the ability to easily run 50-foot waterproof probes. I2C is strictly for PCB-level or short-distance breadboard communication (usually under 1 meter without specialized bus buffers).
- Implementation: Enable I2C via
raspi-config, wire SDA/SCL, and use thesmbus2oradafruit-circuitpython-bme280library to read registers directly.
For a deeper dive into the electrical characteristics and timing diagrams of the 1-Wire protocol, refer to the official Analog Devices DS18B20 datasheet. For broader Raspberry Pi hardware configuration details, consult the Raspberry Pi Foundation configuration documentation. If you are adapting this for weatherproof outdoor enclosures, Adafruit's DS18B20 guide offers excellent supplementary mechanical mounting advice.






