• sales

    +86-0755-88291180

RPi Tutorial Series: 1-Wire DS18B20 Sensor User Guide

DS18B20 is a common temperature sensor which communicates over a 1-Wire bus that by definition requires only one data line. Usually, a certain MCU reads data from DS18B20 in strict accordance with Timing, but now we are going to control DS18B20 using a Raspberry and with the Raspbian OS. You will find that everything is file in the Linux.

Enable 1-Wire

Enable 1-Wire interface with the raspi-config tool.

sudo raspi-config

Select Advanced Option -> 1-Wire -> <Yes>

In fact this tool edits the /boot/config.txt and appends this line: dtoverlay=w1-gpio. With this line, a GPIO to drive an external pullup is disabled by default. It's inconvenience in certain condition so we often change "dtoverlay=w1-gpio" to "dtoverlay=w1-gpio-pullup". We also specify GPIO 4 for I/O, so we change the line to "dtoverlay=w1-gpio-pullup,gpiopin=4". Just for instance, because GPIO 4 (BCM numbering, can be checked by this command: gpio readall) is used for I/O by default so "gpiopin=4" is not usually required.

More details about "dtoverlay", please read the manual: /boot/overlays/README.

  • Quote from /boot/overlays/README:
Name:   w1-gpio
Info:   Configures the w1-gpio Onewire interface module.
        Use this overlay if you *don't* need a GPIO to drive an external pullup.
Load:   dtoverlay=w1-gpio,<param>=<val>
Params: gpiopin                 GPIO for I/O (default "4")

        pullup                  Non-zero, "on", or "y" to enable the parasitic
                                power (2-wire, power-on-data) feature


Name:   w1-gpio-pullup
Info:   Configures the w1-gpio Onewire interface module.
        Use this overlay if you *do* need a GPIO to drive an external pullup.
Load:   dtoverlay=w1-gpio-pullup,<param>=<val>
Params: gpiopin                 GPIO for I/O (default "4")

        pullup                  Non-zero, "on", or "y" to enable the parasitic
                                power (2-wire, power-on-data) feature

        extpullup               GPIO for external pullup (default "5")

Finally, we append this line to the config.txt file: "dtoverlay=w1-gpio-pullup,gpiopin=4" (no space in this line).

Check whether the module is started

Connect the Data Pin of DS18B20 to the GPIO 4 of RPi (BCM numbering, corresponds to the physical 7 pin. The same below). The Pins GND/VCC are connected to 3.3V power supply. Reboot the Raspberry Pi to enable the settings. Then list the 1-Wire module with this command:

lsmod | grep w1

You get:


It indicates the module is started. If you didn't find the w1 device, mount it with:

sudo modprobe w1_gpio
sudo modprobe w1_therm

Read temperature

Change the current directory to /sys/bus/w1/devices

cd /sys/bus/w1/devices

List the file and a 28-xxxxxxxxxxxx device directory (e.g. here is 28-00000674869d) will be found. This is the ROM of DS18B20. If more than one DS18B20 are connected, you will find a certain directories more than one.

cd 28-00000674869d

You can read the temperature from the w1_slave file in the directory. This is too good to be true!

cat w1_slave


Read the temperature from the file w1_slave



The YES in the first line indicates CRC check success (Data Valid ). The number following t= is the temperature, 28750 stands for 28.7 (C).

Programming

sysfs

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
 
int main(int argc, char *argv[])
{
    char path[50] = "/sys/bus/w1/devices/";
    char rom[20];
    char buf[100];
    DIR *dirp;
    struct dirent *direntp;
    int fd =-1;
    char *temp;
    float value;
    // These tow lines 
mount the device:
    system("sudo modprobe w1-gpio");
    system("sudo modprobe w1-therm");
    // Check if /sys/bus/w1/devices/ exists.
    if((dirp = opendir(path)) == NULL)
    {
        printf("opendir error\n");
        return 1;
    }
    // Reads the directories or files in the current directory.
    while((direntp = readdir(dirp)) != NULL)
    {
        // If 28-00000 is the substring of d_name,
        // then copy d_name to rom and print rom.  
        if(strstr(direntp->d_name,"28-00000"))
        {
            strcpy(rom,direntp->d_name);
            printf(" rom: %s\n",rom);
        }
    }
    closedir(dirp);
    // Append the String rom and "/w1_slave" to path
    // path becomes to "/sys/bus/w1/devices/28-00000xxxx/w1_slave"
    strcat(path,rom);
    strcat(path,"/w1_slave");
    while(1)
    {
        // Open the file in the path.
        if((fd = open(path,O_RDONLY)) < 0)
        {
            printf("open error\n");
            return 1;
        }
        // Read the file
        if(read(fd,buf,sizeof(buf)) < 0)
        {
            printf("read error\n");
            return 1;
        }
        // Returns the first index of 't'.
        temp = strchr(buf,'t');
        // Read the string following "t=".
        sscanf(temp,"t=%s",temp);
        // atof: changes string to float.
        value = atof(temp)/1000;
        printf(" temp : %3.3f °C\n",value);
 
        sleep(1);
    }
    return 0;
}

Save the file as "ds18b20.c" then compile and run with:

gcc -Wall ds18b20.c -o ds18b20
sudo ./ds18b20

Python

import os
import glob
import time

# These tow lines mount the device:
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
 
base_dir = '/sys/bus/w1/devices/'
# Get all the filenames begin with 28 in the path base_dir.
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_rom():
    name_file=device_folder+'/name'
    f = open(name_file,'r')
    return f.readline()
 
def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
 
def read_temp():
    lines = read_temp_raw()
    # Analyze if the last 3 characters are 'YES'.
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    # Find the index of 't=' in a string.
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        # Read the temperature .
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_c, temp_f
 
print(' rom: '+ read_rom())
while True:
    print(' C=%3.3f  F=%3.3f'% read_temp())
time.sleep(1)

Save the file as "ds18b20.py" then execute with:

sudo python ds18b20.py


expected result

TAG: Raspberry Pi Pico 2 RP2350 1.47 inch LCD B Display Development board RP2350A 1.47inch Screen RGB color Raspberry Pi 6.25 inch DSI Display MIPI LCD Capacitive TouchScreen 720x1560 ESP32 S3 LCD 1.3 inch Holographic Display Screen 1.3inch 3D Transparent Refractive Prism Mini TV For Arduino Raspberry Pi 64MP Camera ESP32 C5 Development Board 1.47 inch LCD Display Screen ST7789 For WiFi6/LVGL/HMI Onborad SD-Port/RGB-LED Pi5 Argon NVIDIA Jetson Orin Nano 4/8GB AI 20/40Tops Lower Power Autonomous Machines Gripper Serial Robotic Arm Gripper Mechanical claw Serial Bus Servo ST3215/CF35-12 Jetson Orin Nano UGV Beast PT ROS2 AI OpenCV Robot Car MediaPipe Raspberry Pi 5 Raspberry Pi Pico 2 RP2350 0.85inch LCD Display Development Board RGB Lighting 128×128 ESP32 S3 4inch LCD Development Board 480x480 TouchScreen Display TVBOX LVGL HMI Sensor CAN RS485 Raspberry Pi 5 PCIe to USB3.2 Gen1 Hub 5Gbps For Raspberry Pi OS Drive free Arduino 0.85inch LCD Raspberry Pi Monitor Official Original DisplayScreen 15.6 inch LCD Full HD 1920x1080 15.6inch ESP32 C3 LCD Development Board 1.3 inch Display Screen ST7789 240x240 3D Transparent Refractive Prism Mini TV For Arduino Raspberry Pi 5 PCIe to M.2 SSD Pi5 Power Gyroscope Sensor