BME280 with Raspberry Pi Pico using MicroPython

In this user guide, we will take a look at the BME280 sensor which is used to pressure, humidity, and temperature. Firstly, we will learn about BME280 and how to interface with Raspberry Pi Pico. Next, we will work on a simple example to demonstrate its working, and lastly, we will measure Temperature, Humidity, and Pressure with BME280 and display values on an OLED.

BME280 with Raspberry Pi Pico using MicroPython

We have a similar guide with ESP32 and ESP8266 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:

BME280 Introduction

The BME280 sensor is used to measure readings regarding ambient temperature, barometric pressure, and relative humidity. It is mostly used in web and mobile applications where low power consumption is key. This sensor uses I2C or SPI to communicate data with the micro-controllers. Although there are several different versions of BME280 available in the market, the one we will be studying uses I2C communication protocol and SPI.

I2C means Inter-Integrated Circuit and works on the principle of the synchronous, multi-master multi-slave system. With BME280 and the microcontroller, the Raspberry Pi Pico acts as a master, and the BME280 sensor as a slave because it is an external device, acts as a slave. The Raspberry Pi Pico communicates with the BME280 sensor through the I2C protocol to give temperature, barometric pressure, and relative humidity readings.

Pinout Diagram

The figure below shows the BME280 sensor and its pinout.

BME280 Pinout Diagram
BME280 Pinout
  • VCC: connected with 3.3V
  • SCL: used to generate the clock signal
  • SDA: used in sending and receiving data

Raspberry Pi Pico Schematic with BME280

The connection of BME280 with the Raspberry Pi Pico is very simple. We have to connect the VCC terminal with 3.3V, ground with the ground (common ground), SCL of the sensor with SCL of the board, and SDA of the sensor with the SDA pin of the board.

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 two devices which we are using can be seen below.

BME280Raspberry Pi Pico
VCC3.3V
SDAGP0 (I2C0 SDA)
SCLGP1 (I2C0 SCL)
GNDGND

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

Raspberry Pi Pico with BME280 connection diagram
Raspberry Pi Pico with BME280 connection diagram
Raspberry Pi Pico with BME280

BME280 MicroPython Library

We will have to install the BME280 library for MicroPython to continue with our project.

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 “bme280” in the search bar by typing its name and clicking the button ‘Search on PyPI.’ From the following search results click on the one highlighted below: micropython-bme280. Install this library.

Installing BME280 Micropython library Thonny

After a few moments this library will get successfully installed. Now we are ready to program our Raspberry Pi Pico with BME280 sensor in MicroPython.

Measuring Temperature, Pressure & Humidity with BME280

As we have already installed the BME280 library to our Raspberry Pi Pico, now we can use the functions available in the BME280 library to get sensor readings.

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

BME280 MicroPython Code

Now let’s look at the MicroPython script for BME280 to get sensor readings. Copy the following code to the .py file and upload the file to Raspberry Pi Pico. This MicroPython script reads Pressure, Temperature and Humidity values from BME280 over I2C lines and prints them on MicroPython shell console.

from machine import Pin, I2C        #importing relevant modules & classes
from time import sleep
import bme280       #importing BME280 library

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)    #initializing the I2C method 
bme = bme280.BME280(i2c=i2c)          #BME280 object created

while True:
  print(bme.values)
  sleep(10)           #delay of 10s

How the Code Works?

Firstly, we will be importing the Pin class and I2C class from the machine module. This is because we have to specify the pin for I2C communication. We also import the sleep module so that we will be able to add a delay of 10 seconds in between our readings. Also, import the bme280 library which we previously installed.

from machine import Pin, I2C        #importing relevant modules & classes
from time import sleep
import bme280       #importing BME280 library

Defining Raspberry Pi Pico GPIO Pins for BME280

Next, we will initialize the I2C GPIO pins for SCL and SDA respectively. We have used the I2C0 SCL and I2C0 SDA pins.

We have created an I2C() method which takes in four parameters. The first parameter is the I2C channel that we are using. The second parameter specifies the I2C GPIO pin of the board which is connected to the SDA line. The third parameter specifies the I2C GPIO pin of the board which is connected to the SCL line. The last parameter is the frequency connection.

We are setting the SCL on pin 1 and the SDA on pin 0.

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)

Next, we run an infinite loop inside which we create an object of BME280 named bme and access the sensor’s readings through it. We will print the values in the terminal by giving the print command. We also add a delay of 10s after each set of readings are displayed.

while True:
  bme = bme280.BME280(i2c=i2c)          #BME280 object created
  print(bme.values)
  sleep(10)           #delay of 10s

Demo

After you have copied the following code onto the file click on ‘Save’ icon to save your program code on your PC. Save your file by giving it a name ending in .py and save according to your preference by giving the directory.

After you have saved the code press the Run button to upload the code to your Raspberry Pi Pico module. Before uploading code make sure the correct board is selected.

Raspberry Pi Pico with BME280 Thonny

You will see Temperature(°C), Pressure (hPa) and Humidity (%) readings on shell console. Each set of readings will be updated to new ones after every 10 seconds.

Raspberry Pi Pico with BME280 Thonny Shell demo

Raspberry Pi Pico Display BME280 Sensor values on OLED Display

In this section, we will see how to display BME280 Pressure, Temperature, Humidity 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

We have already uploaded the BME280 MicroPython library to Raspberry Pi Pico. For an OLED display, we will also 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 BME280

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

  1. Raspberry Pi Pico
  2. BME280 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.

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

SSD1306 OLED DisplayRaspberry Pi PicoBME280
VCC3.3VVCC
SDAGP0 (I2C0 SDA)SDA
SCLGP1 (I2C0 SCL)SCL
GNDGNDGND

Schematic Raspberry Pi Pico with OLED and BME280

Follow the schematic diagram below connect them accordingly.

Raspberry Pi Pico with BME280 and OLED connection diagram
Raspberry Pi Pico with BME280 and OLED connection diagram
Raspberry Pi Pico with BME280 and OLED

MicroPython Code: Displaying BME280 readings on OLED Display

from machine import Pin, I2C        #importing relevant modules & classes
from time import sleep
import bme280        #importing BME280 library
from ssd1306 import SSD1306_I2C

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)    #initializing the I2C method 
oled = SSD1306_I2C(128, 64, i2c)
bme = bme280.BME280(i2c=i2c)        #BME280 object created

while True:
  oled.fill(0)
  temperature = bme.values[0]         #reading the value of temperature
  pressure = bme.values[1]            #reading the value of pressure
  humidity = bme.values[2]            #reading the value of humidity

  print('Temperature: ', temperature)    #printing BME280 values
  print('Humidity: ', humidity)
  print('Pressure: ', pressure)
  
  oled.text("Temp "+temperature, 0, 0)
  oled.text("PA "+pressure, 0, 20)
  oled.text("Humidity "+humidity, 0,40)
  oled.show()                          #display 
  sleep(10)     #delay of 10s

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 BME280 sensor temperature, humidity, and pressure samples and print them in the shell terminal.

  temperature = bme.values[0]         #reading the value of temperature
  pressure = bme.values[1]                      #reading the value of pressure
  humidity = bme.values[2]                   #reading the value of humidity

  print('Temperature: ', temperature)    #printing BME280 values
  print('Humidity: ', humidity)
  print('Pressure: ', pressure)

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


  oled.text("Temp "+temperature, 0, 0)
  oled.text("PA "+pressure, 0, 20)
  oled.text("Humidity "+humidity, 0,40)

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

oled.show()                      
sleep(10) 

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 BME280 temperature, pressure, and humidity values on the OLED display as follows:

Raspberry Pi Pico with BME280 and OLED demo

Additionally, the shell console also shows the set of BME280 sensor readings:

Raspberry Pi Pico with BME280 Thonny Shell demo 2

We have other guides with popular sensors:

You may also like to read other BME280 related articles:

11 thoughts on “BME280 with Raspberry Pi Pico using MicroPython”

  1. Hi there,
    when I run the above code, I always get the following error:

    Traceback (most recent call last):
    File “”, line 1, in
    File “/lib/bme280.py”, line 75, in __init__
    OSError: [Errno 5] EIO

    Has somebody else encountered this issue and found a solution? I tried it with MicroPython 1.9.1 and 1.8.1

    Reply
  2. HI,
    Looking for help in resolving this error. I see it come up every time I attempt to work with the BME280.

    MPY: soft reboot
    Traceback (most recent call last):
    File “”, line 9, in
    File “bme280.py”, line 74, in __init__
    OSError: [Errno 5] EIO

    9: bme = bme280.BME280(i2c=i2c) #BME280 object created
    73 # load calibration data
    74 dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26)

    Reply
  3. Well on the webpage you create inside the loop the object bme.
    The creation of the object should be outside the loop!
    you need to create the object only once!

    It should be

    bme = bme280.BME280(i2c=i2c) #BME280 object created
    while True:
    print(bme.values)
    sleep(10)

    Even this is strange because you need to read the values somehow
    I’m using this

    t, p, h = bme.read_compensated_data()

    to read temperature,pressure and humidity

    Reply
      • Well re-creating the object all the time start to partialise the stack after a while you could have a problem recreating the object. And why making a new object all the time. You made it once and get around problem with the memory stack.

        Reply

Leave a Comment