DS18B20 Temperature Sensor with Raspberry Pi Pico using MicroPython

In this user guide, we will learn how to use a DS18B20 temperature sensor with Raspberry Pi Pico in MicroPython. This is a comprehensive article in which we will discuss the sensor and how to access temperature readings through a single sensor. Additionally, we will also display the temperature readings on an SSD1306 OLED display.

DS18B20 Temperature Sensor with Raspberry Pi Pico using MicroPython

Prerequisites

Before we start this lesson make sure you are familiar with and have the latest version Python 3 in your system, have set up MicoPython in Raspberry Pi Pico, and have a running Integrated Development Environment(IDE) in which we will be doing the programming. We will be using the same Thonny IDE as we have done previously when we learned how to blink and chase LEDs in micro-python. If you have not followed our previous tutorial, you check here:

If you are using uPyCraft IDE, you can check this getting started guide:

DS18B20 Introduction

It is a temperature sensor that is single wire programmable in nature. It is widely used to measure the temperature of chemical solutions and substances which are present in a hard environment. One of the advantages of using this sensor is that we only require a single pin of our Raspberry Pi Pico boards to transfer data. Thus, it is extremely convenient to use with the micro-controller as we can measure multiple temperatures by using the least number of pins on our development board.

The table below shows some key characteristics of the ds18b120 sensor.

FeatureValue
Operating Voltage3V-5V
Temperature Range-55°C to +125°C
Accuracy±0.5°C
Output Resolution9bit to 12bit
Key Characteristics of DS18B20

Pinout Diagram

A waterproof version of this sensor is also available in the market. The following figures show the pinout of the DS18B20 sensors.

ds18b20 waterproof pinout diagram
Pin out of waterproof DS18B20

The following diagram shows the pinout of normal DS18B20 temperature sensor.

ds18b20 pinout diagram

The table below lists the pin configurations:

PinDescription
VCCThis is the pin that powers up the sensor. 3.3V for Raspberry Pi Pico boards
DataThis pin gives the temperature value
GroundThis pin is connected with the ground
Pin Configuration details DS18B20

This temperature sensor also comes in a single package module which contains a sensor and a pull-up resistor. If you are using a module, you do not need to connect an external 4.7K ohm resistor. Because the module already has an onboard pull-up resistor.

ds18b20 module
Ds18b20 Module

DS18B20 Parasite vs Normal Mode

The DS18B20 sensor can be powered in two different modes.

Normal Mode: The sensor is powered through an external source through the VDD pin and 4.7K ohm pull-up resistor.

Parasite Mode: The sensor obtains the power from its own data line. Hence, no external power supply is required.

Required Hardware

We will now learn how to connect the temperature sensor with Raspberry Pi Pico. We will need the following components.

Required Components:

  1. Raspberry Pi Pico
  2. DS18B20  sensor
  3. 4.7k ohm resistor
  4. Breadboard
  5. Connecting Wires

Raspberry Pi Pico with DS18B20 Schematic Diagram

As you can see in the schematic diagram below, we have used DS10B20 in normal mode and powered the sensor with its VCC pin from 3.3V pin of Raspberry Pi Pico board.

Connect Raspberry Pi Pico with DS18B20 as shown in the schematic diagram below:

Raspberry Pi Pico with ds18b20 connection diagram
Raspberry Pi Pico with ds18b20 connection diagram

As you can see above, we have powered the sensor using the normal mode. The DS18B20 sensor has three terminals which we saw above in the pinout. The first terminal is grounded with the Raspberry Pi Pico board. The data line of the sensor, which is the middle terminal, is connected through GP2 through a pull-up resistor of 4.7k-ohm. We can choose any other GPIO pin as well. The third terminal is powered by 3.3V from the Raspberry Pi Pico.

You can use any other GPIO pin of Raspberry Pi Pico to connect with the data pin as well. You can refer to this post to know more about Raspberry Pi Pico GPIO pins:

Raspberry Pi Pico with ds18b20

Installing DS18B20 Libraries

For this project we will require two libraries: ds18x20.py and onewire.py. Copy both of these libraries and save them in your Raspberry Pi Pico with the respective file names. Open a new file in Thonny. Copy the libraries given below. Save them to Raspberry Pi Pico with names ds18x20.py and onewire.py under the lib folder.

ds18x20.py

# DS18x20 temperature sensor driver for MicroPython.
# MIT license; Copyright (c) 2016 Damien P. George

from micropython import const

_CONVERT = const(0x44)
_RD_SCRATCH = const(0xBE)
_WR_SCRATCH = const(0x4E)


class DS18X20:
    def __init__(self, onewire):
        self.ow = onewire
        self.buf = bytearray(9)

    def scan(self):
        return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]

    def convert_temp(self):
        self.ow.reset(True)
        self.ow.writebyte(self.ow.SKIP_ROM)
        self.ow.writebyte(_CONVERT)

    def read_scratch(self, rom):
        self.ow.reset(True)
        self.ow.select_rom(rom)
        self.ow.writebyte(_RD_SCRATCH)
        self.ow.readinto(self.buf)
        if self.ow.crc8(self.buf):
            raise Exception("CRC error")
        return self.buf

    def write_scratch(self, rom, buf):
        self.ow.reset(True)
        self.ow.select_rom(rom)
        self.ow.writebyte(_WR_SCRATCH)
        self.ow.write(buf)

    def read_temp(self, rom):
        buf = self.read_scratch(rom)
        if rom[0] == 0x10:
            if buf[1]:
                t = buf[0] >> 1 | 0x80
                t = -((~t + 1) & 0xFF)
            else:
                t = buf[0] >> 1
            return t - 0.25 + (buf[7] - buf[6]) / buf[7]
        else:
            t = buf[1] << 8 | buf[0]
            if t & 0x8000:  # sign bit set
                t = -((t ^ 0xFFFF) + 1)
            return t / 16

onewire.py

# 1-Wire driver for MicroPython
# MIT license; Copyright (c) 2016 Damien P. George

import _onewire as _ow


class OneWireError(Exception):
    pass


class OneWire:
    SEARCH_ROM = 0xF0
    MATCH_ROM = 0x55
    SKIP_ROM = 0xCC

    def __init__(self, pin):
        self.pin = pin
        self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP)

    def reset(self, required=False):
        reset = _ow.reset(self.pin)
        if required and not reset:
            raise OneWireError
        return reset

    def readbit(self):
        return _ow.readbit(self.pin)

    def readbyte(self):
        return _ow.readbyte(self.pin)

    def readinto(self, buf):
        for i in range(len(buf)):
            buf[i] = _ow.readbyte(self.pin)

    def writebit(self, value):
        return _ow.writebit(self.pin, value)

    def writebyte(self, value):
        return _ow.writebyte(self.pin, value)

    def write(self, buf):
        for b in buf:
            _ow.writebyte(self.pin, b)

    def select_rom(self, rom):
        self.reset()
        self.writebyte(self.MATCH_ROM)
        self.write(rom)

    def scan(self):
        devices = []
        diff = 65
        rom = False
        for i in range(0xFF):
            rom, diff = self._search_rom(rom, diff)
            if rom:
                devices += [rom]
            if diff == 0:
                break
        return devices

    def _search_rom(self, l_rom, diff):
        if not self.reset():
            return None, 0
        self.writebyte(self.SEARCH_ROM)
        if not l_rom:
            l_rom = bytearray(8)
        rom = bytearray(8)
        next_diff = 0
        i = 64
        for byte in range(8):
            r_b = 0
            for bit in range(8):
                b = self.readbit()
                if self.readbit():
                    if b:  # there are no devices or there is an error on the bus
                        return None, 0
                else:
                    if not b:  # collision, two devices with different bit meaning
                        if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i):
                            b = 1
                            next_diff = i
                self.writebit(b)
                if b:
                    r_b |= 1 << bit
                i -= 1
            rom[byte] = r_b
        return rom, next_diff

    def crc8(self, data):
        return _ow.crc8(data)

MicroPython Raspberry Pi Pico DS18B20 : Getting Temperature values

After uploading the two libraries mentioned above to our Raspberry Pi Pico, let us program our board with ds18b20 sensor.

Let’s now look at an example to show the working of the sensor. We will connect our ds18b20 sensor with the Raspberry Pi Pico as shown above in the connection diagram. We will see a MicroPython script code and after uploading it to our board, we will see current readings of temperature printed on the MicroPython shell terminal.

DS18B20 MicroPython Code

Now let’s look at the MicroPython script for DS18b20 to get sensor readings. Copy the following code to the main.py file and upload the main.py file to Raspberry Pi Pico.

This MicroPython script reads Temperature values from DS18B20 and prints them on the MicroPython shell console.

import machine, onewire, ds18x20
from time import sleep
 
ds_pin = machine.Pin(2)
 
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
 
roms = ds_sensor.scan()
 
print('Found DS devices')
print('Temperature (°C)')
 
while True:
 
  ds_sensor.convert_temp()
 
  sleep(1)
 
  for rom in roms:
 
    print(ds_sensor.read_temp(rom))
 
  sleep(3)

How the Code Works?

Importing Libraries

Firstly, we will be importing the machine module. We also import the sleep module so that we will be able to add a delay in between our readings. Also, import one wire and ds18x20 libraries that we just uploaded to our board.

import machine, onewire, ds18x20
from time import sleep

Next, we will create an instance of Pin class with an object name of ds_pin and set GP2 as the DS18B20 data line pin. The DS18X20() method

ds_pin = machine.Pin(2)
 
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

The scan() method scans all DS18B20 sensors connected to the ds_sensor pin and saves the 64-bit address of each sensor in a list variable that is “roms”. Later, we will use these addresses to read temperature from the sensor one by one.

roms = ds_sensor.scan()
 
print('Found DS devices')

After that call the object on convert_temp() method before reading the temperature from the sensor using its unique address.

To read the temperature, use read_temp() procedure on ds_sensor object and pass an address which is stored in roms list. The DS18B20 temperature sensor provides data output in float data type. The current temperature readings will be printed in the shell terminal after every 3 seconds.

while True:
 
  ds_sensor.convert_temp()
 
  sleep(1)
 
  for rom in roms:
 
    print(ds_sensor.read_temp(rom))
 
  sleep(3)

Demo

To test the MicroPython script for DS18B20 with Raspberry Pi Pico, upload the main.py file to your board.

You will see the Temperature values on the shell console constantly updating to new values after every 3 seconds.

Raspberry Pi Pico DS18B20 sensor readings on shell

Raspberry Pi Pico Display DS18B20 Sensor values on OLED Display

In this section, we will see how to display DS18B20 Temperature values on a 0.96 SSD1306 OLED display using MicroPython and Raspberry Pi Pico. 

You may also like to read:

SSD1306 OLED Display MicroPython Library

For an OLED display, we will need to upload a library to Raspberry Pi Pico. 

  • To successfully do that, open your Thonny IDE with your Raspberry Pi Pico plugged in your system. Go to Tools > Manage Packages. This will open up the Thonny Package Manager.
Raspberry Pi Pico Installing ssd1306 OLED library MicoPython 1
  • Search for “ssd1306” in the search bar by typing its name and clicking the button ‘Search on PyPI.’
Raspberry Pi Pico Installing ssd1306 OLED library MicoPython 2
  • From the following search results click on the one highlighted below: micropython-ssd1306
Raspberry Pi Pico Installing ssd1306 OLED library MicoPython 3

Install this library.

Raspberry Pi Pico Installing ssd1306 OLED library MicoPython 4

After a few moments this library will get successfully installed. Now we are ready to program our Raspberry Pi Pico with OLED display.

Connecting SSD1306 OLED Display with Raspberry Pi Pico and DS18B20

We will need the following components to connect our Raspberry Pi Pico with the OLED Display and DS18B20.

  1. Raspberry Pi Pico
  2. DS18B20 Sensor
  3. SSD1306 OLED Display
  4. Connecting Wires

The OLED display has 4 terminals which we will connect with the Raspberry Pi Pico. As the OLED display requires an operating voltage in the range of 3.3-5V hence we will connect the VCC terminal with 3.3V which will be in common with the board and the sensor. SCL of the display will be connected with the SCL pin of the module and the SDA of the display will be connected with the SDA of the module. The ground of all three devices will be held common.

Raspberry Pi Pico I2C Pins

Raspberry Pi Pico has two I2C controllers. Both I2C controllers are accessible through GPIO pins of Raspberry Pi Pico. The following table shows the connection of GPIO pins with both I2C controllers. Each connection of the controller can be configured through multiple GPIO pins as shown in the figure. But before using an I2C controller, you should configure in software which GPIO pins you want to use with a specific I2C controller. 

I2C ControllerGPIO Pins
I2C0 – SDAGP0/GP4/GP8/GP12/GP16/GP20
I2C0 – SCLGP1/GP5/GP9/GP13/GP17/GP21
I2C1 – SDAGP2/GP6/GP10/GP14/GP18/GP26
I2C1 – SCLGP3/GP7/GP11/GP15/GP19/GP27

The connections between the three devices which we are using can be seen below.

We have used the same connections as specified in the table above. However you can use other combinations of SDA/SCL pins as well.

SSD1306 OLED DisplayRaspberry Pi Pico
VCC3.3V
SDAGP0 (I2C0 SDA)
SCLGP1 (I2C0 SCL)
GNDGND
DS18B20Raspberry Pi Pico
VCC3.3V
DataGP2
GNDGND

Schematic Raspberry Pi Pico with OLED and DS18B20

Follow the schematic diagram below connect them accordingly.

Raspberry Pi Pico with ds18b20 and oled connection diagram
Raspberry Pi Pico with ds18b20 and OLED connection diagram
Raspberry Pi Pico with ds18b20 and oled

MicroPython Code: Displaying DS18B20 readings on OLED Display

import machine, onewire, ds18x20
from machine import Pin, I2C
from time import sleep
from ssd1306 import SSD1306_I2C

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)

ds_pin = machine.Pin(2)
 
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
 
roms = ds_sensor.scan()
 
print('Found DS devices')
print('Temperature (°C)')
 
while True:
 
  ds_sensor.convert_temp()
 
  sleep(1)
 
  for rom in roms:
 
    print(ds_sensor.read_temp(rom))
    oled.fill(0)
    oled.text("Temperature (C)", 0, 16)
    oled.text(str(ds_sensor.read_temp(rom)), 0, 35)
    oled.show()
 
  sleep(3)

How does the code work?

In the section, we will explain the MicroPython code which is used to display sensor values on OLED.

Import Library

We will import the ssd1306 which is the OLED display library that we installed earlier. This will help us in accessing all the functions defined inside it.

from ssd1306 import SSD1306_I2C

Initialize OLED  

The SCL and SDA pin data gets saved in the object ‘i2c’ which will connect to the I2C bus and help in the communication between the two devices

Now, we will create an object ‘oled’ of SSD1306_I2C which uses the width, height, and the i2c object as parameters.

oled = SSD1306_I2C(128, 64, i2c)

Clears the OLED display with led.fill() routine.

 oled.fill(0)

Take DS18B20 sensor temperature samples and print them in the shell terminal.

ds_sensor.convert_temp()
 
  sleep(1)
 
  for rom in roms:
 
    print(ds_sensor.read_temp(rom))

Finally, display the text along with sensor reading on OLED.

    oled.text("Temperature (C)", 0, 16)
    oled.text(str(ds_sensor.read_temp(rom)), 0, 35)

At the end, call the show() method on oled method for changes to show on OLED. Add a delay of 3 seconds between each reading.

oled.show()
 
  sleep(3) 

Demonstration

Upload the above code as a .py file to Raspberry Pi Pico. Press the run button to upload the code to your Raspberry Pi Pico module. You will see DS18B20 temperature values on the OLED display as follows:

Raspberry Pi Pico with ds18b20 readings on OLED

We have other guides with popular sensors:

Related DS18B20 tutorials and projects:

3 thoughts on “DS18B20 Temperature Sensor with Raspberry Pi Pico using MicroPython”

  1. Hi,

    I followed about 10 different tutorials including yours and I always get the same error:

    >>> %Run -c $EDITOR_CONTENT
    init
    Traceback (most recent call last):
    File “”, line 11, in
    File “ds18x20.py”, line 33, in __init__
    File “onewire.py”, line 30, in __init__
    AttributeError: ‘OneWire’ object has no attribute ‘OPEN_DRAIN’
    >>>

    What could it be?

    Reply

Leave a Comment