Wetterstation mit Raspberry Pi Pico und OLED Display

The blogger colleague Andreas Wolter has you in his contribution Given the entry into the Raspberry Pi Pico, as this must be set up for the first time and what it matters. In my today's blog article, I pick up my favorite entry topic weather station. With the Raspberry Pi Pico, just then just called Pico, we want to spend the temperature and later also the humidity and the ambient pressure.

The project is, since the small microcontroller is a product of the Rapsberry Pi Foundation, on the Raspberry Pi 4 with the Thonny Python IDE (ie Micropython) developed. In order for you to get to know the Pico a bit more closely, the project is divided into three parts in this blog:

  1. Temperature output from internally built temperature sensor on console
  2. Temperature output from internally built temperature sensor to i2c-OLED display
  3. Determine environmental conditions with BME / BMP280 and output to I2C OLED display

These are always the first goals for me when I get new microcontrollers.

Required hardware and software

The hardware for this experimental setup is relatively simple, see Table 1.

number Component annotation
1 Raspberry Pi Pico
1 0.96 inch OLED SSD1306 Display I2C
1 Breadboard and Jump Wire
1 GY-BME280 Barometric sensor

Table 1: hardware parts

When software, you use a program with Python3, Thonny Python IDEwhich is already available to the Raspbian Image can be installed for all common operating systems. I recommend at this point, you should e.g. work with Ubuntu to install using the method described in Code 1 Thonny Python IDE.

 sudo PIP3 Install Thonny
sudo usermod -a -G dialout $ User
Code 1: Install Thonny Python IDE VIA PIP3


After that, you can start the Thonny Python IDE "just" about the console, but that's so far justifiable.

Read the temperature from the Pico

In the first part design, the internally built temperature sensor is to be read out from the PICO. You will probably be wondering now because it does not look at the first view that the PICO has a temperature sensor. Therefore, you should first look at the pico's pico, see Figure 1.

Figure 1: Pinout from Raspberry Pi Pico

Figure 1: Pinout from Raspberry Pi Pico, Source: https://datasheets.raspberrypi.com/pico/Pico-R3-A4-Pinout.pdf

Here you can clearly see the connections ADC0 - ADC2, where ADC_VREF can also be viewed here as ADC3, which can be used for analog signals. What you do not see on the Pinout from Figure 1, but in the RP2040 datasheet In chapter 4.9.1 can read, a fifth analog pin (ADC4), which is directly connected to an internally installed temperature sensor, is shown in Figure 2.

Figure 2: ADC connection diagram

Figure 2: ADC connection diagram, Source: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf

From the basic principle, we have already installed the required hardware directly on the Pico to determine the ambient temperature.

Code 2 reads the temperature and outputs them on the console. The program is quite simple, where I would like to explain three places directly.

 // Read Internal Temp Sensor
 // Author: Joern Way
 // License: GNU GPL 3.0
 // Created: 23. Oct 2021
 // Update: 23. Oct 2021
  #First Import Needed Libs
 import machine #Important to get pins and config them
 import uti #For a little timer
 conversion_factor = 3.3 / 65535 # 3.3v Are 16bit (65535)
 whiler True:
     Valuetemp = sensor.Read_u16() * conversion_factor
     Temp = 27 - (Valuetemp - 0.706) / 0.001721 # 5.9.5 of RP2040 datasheet
     print('Temperature Value:'+ "{: .2f}".format(Temp)) # Print in Terminal With Two Decimal
     uti.sleep(2) #Sleep for two seconds

Code 2: Simple program to read internal temperature sensor

First, the line "conversion_factor = 3.3 / 65535", in which a correction factor is defined. We need this because the Pico will later pass us an analog value between 0 and 65535 during the sensor output. The value is interesting insofar as it is the size 2 bytes or 16bit. Since 3.3 volts then corresponds to 65535, we need it to convert the 2 bytes into a voltage.

Then we come to the line "Valuetemp = sensor.read_u16 () * conversion_factor" in which the sensor value is first read out and then multiplied directly with the conversion factor. Interesting is less multiplication, more in this case that READ_U16 ()which is used to get a 16bit value. Different to Read ()Where only a binary value is returned, we have Micropython with READ_U16 () to spend the value in 2 bytes, which makes sense for an analog PIN.

Lastly, the line "TEMP = 27 - (Valuetemp - 0.706) / 0.001721", which is finally used to calculate the temperature of the Pico temperature sensor. I did not come up with this formula, but is so in the datasheet from the Pico under chapter 4.9.5 as well.

The output in the console, our program can not currently do not yet, is also quite unspectacular, see Figure 3.

Figure 3: Output of temperature in the console

Figure 3: Output of temperature in the console

In order to succeed in you, a pressure is sufficient F5 or the Greens runButton. But you will quickly find that the internally built temperature sensor is not very precise. But this should not disturb us in this example.

Show the temperature on an I2C-OLED

In the next step, the output of the temperature should no longer take place via the command line, but with regard to use without connection to a PC, via an OLED display. In my case, the 0.96 inch OLED SSD1306 Display I2C with 128x64 pixels. The grand thing is, the connection requires only 4 cables, see Figure 4, a library and a few lines more code.

Figure 4: Wiring Pico with OLED display

Figure 4: Wiring Pico with OLED display

The wiring is already quite fixed, so it should continue directly in Thonny Python IDE with the required library. First open the package management, see Figure 5.

Figure 5: Open package management

Figure 5: Open package management

It opens a new window afterwards by looking for packets, ie libraries for further hardware. In our case we need a micropython library for the SSD1306 controller. Just enter the search window SSD1306 and press Enter or on Search for Pypi and choose the package micropython SSD1306 out, see Figure 6.

Figure 6: Search for Micropython Library for SSD1306

Figure 6: Search for Micropython Library for SSD1306

Right in the next step, press the button To install, where a folder on the Pico lib is created and also the Micropython library for the SSD1306 exactly in this folder lib When copied, see Figure 7.

Figure 7: Installing Micropython Library for SSD1306

Figure 7: Installing Micropython Library for SSD1306

So we have the library first, now the display still needs to be programmed correctly, see code 3.


 // Read Internal Temp Sensor and
 // show on i2c-OLED
 // Author: Joern Way
 // License: GNU GPL 3.0
 // Created: 23. Oct 2021
 // Update: 24. Oct 2021
  #First import needed libs
 from ssd1306 import SSD1306_I2C #Import from Lib the needed subpart
 from machine import Pin, I2C
 import machine  #Important to get Pins and config them
 import utime #For a little timer
 #Definitions for internal temp-sensor
 sensor = machine.ADC(4) # Create object sensor and init as pin ADC(4)
 conversion_factor = 3.3 / 65535 # 3.3V are 16bit (65535)
 #Definitons for i2c-Com
 i2c=I2C(0, sda=sda, scl=scl, freq=400000)
 #Write in cmd found addresses
 i2cScan = i2c.scan()
 counter = 0
 for i in i2cScan:
     print("I2C Address " + str(counter) + "     : "+hex(i).upper())
 #Definitions for OLED-Display
 WIDTH = 128
 HIGHT = 64
 oled = SSD1306_I2C(WIDTH, HIGHT, i2c)
 i = 0
 while True:
     valueTemp = sensor.read_u16() * conversion_factor #
     temp = 27 - (valueTemp - 0.706) / 0.001721 # See 4.9.5 of rp2040 datasheet
     print('Temperatur value: '+ '{:.2f}'.format(temp)) # Print in terminal with two decimal
     print('Counter: ' +str(i))
     #Write data to display
     oled.text('Internal Temp',6,8)
     oled.text('Temp: ',6,22)
     oled.text('Counter: ' + str(i),6,36)
     utime.sleep(2) #Sleep for two seconds


Code 3: Code aus ersten Beispiel um OLED-Display erweitert

In den Kommentaren wird genau erklärt, was ich mache, aber es gibt einige Sektionen, die ich kurz näher erläutern möchte. Angefangen mit „from ssd1306 import SSD1306_I2C“, bei dem wir aus der Bibliothek ssd1306 den Teil SSD1306_I2C laden bzw. bereitstellen. Damit muss nicht die gesamte Bibliothek geladen werden, sondern wir laden genau den Teilbereich, der für uns relevant ist.

Nach dem Kommentar „#Definitons for i2c-Com“ passiert auch erst einmal wenig Spannendes. Zunächst werden die Pins für SDA und SCL deklariert und danach die i2c-Schnittstelle 0 mit den bereits deklarierten Pins und der Frequenz 400kHz erstellt. Im Anschluss, was einfach nur für mich eine Interessante Ausgabe ist, fragt mein Programm alle verfügbaren Hex-Adressen ab, ob ein Teilnehmer vorhanden ist und gibt über die for-Schleife die gefundenen Teilnehmeradressen in der Kommandozeile aus.

Direkt danach, hinter dem Kommentar „#Definitions for OLED-Display“, deklariere ich die Größe des Displays und erzeuge ein Objekt mit allen nötigen Parametern für das Display.

Im Anschluss wurde die while-Schleife so modifiziert, dass sowohl in der Kommandozeile als auch auf dem Display die Temperatur und ein kleiner Counter angezeigt wird, siehe Abbildung 8.

Figure 8: OLED output

Abbildung 8: OLED-Ausgabe

Den Counter habe ich eingefügt, damit ich sehe, dass mein Pico noch arbeitet und nicht unbemerkt hängen geblieben ist.

Die Temperatur von einem GY-BME280 auslesen

Wie Sie wahrscheinlich schon bemerkt oder in der Doku vom Pico gelesen habe, ist die Temperaturangabe des intern verbauten Sensors nicht wirklich genau. An dieser Stelle nutze ich immer gerne den GY-BME280 Barometrischen Sensor für Temperatur, Luftfeuchtigkeit und Luftdruck, da er mir alle relevanten Daten direkt liefert. Schon in früheren Blogbeiträgen ist dieser Sensor von mir genutzt worden. Da der GY-BME280 ebenfalls über i2c kommuniziert, braucht es zunächst auch erst einmal nur vier weitere Drähte, zu den schon genutzten für das OLED-Display, siehe Abbildung 9.

Figure 9: Connect the GY-BME280

Abbildung 9: Das GY-BME280 anschließen

Wenn Sie die Datenblätter des OLED und GY-BME280 durchgelesen haben, sollte Ihnen aufgefallen sein, dass beide Unterschiedliche Adressen nutzen, daher können wir beide Komponenten in Reihe schalten. Wären die Adressen gleich, so müssten wir vom Pico eine weitere i2c-Schnittstelle erzeugen. Suchen Sie nun in der Paketverwaltung nach bme280 und wählen Sie zur Installation die Bibliothek micropython-bme280 Off, even if the specification is mentioned in the description of ESP8266 / ESP32, see Figure 10.

Figure 10: Installing the library for BME280

Figure 10: Installing the library for BME280

This is a library for our sensor now and our sample code can be extended by a few lines, see code 4.


 // Read BME280 and
 // show on i2c-OLED
 // Author: Joern Way
 // License: GNU GPL 3.0
 // Created: 23. Oct 2021
 // Update: 24. Oct 2021
  #First Import Needed Libs
 from SSD1306 import SSD1306_I2C #Import from lib the needed subpart
 from BME280 import BME280 #Import BME280-lib
 from machine import Pin code, I2c
 import machine  #Important to get pins and config them
 import uti #For a little timer
 #Definitions for internal temp sensor
 conversion_factor = 3.3 / 65535 # 3.3v Are 16bit (65535)
 #Definitons for i2c-com
 SDA=Pin code(0)
 SCL=Pin code(1)
 i2c=I2c(0, SDA=SDA, SCL=SCL, freq=400000)
 #Write in CMD Found Addresses
 I2cscan = i2c.scan()
 Counter = 0
 for I in I2cscan:
     print('I2C Address' + string(Counter) + '     : '+hex(I).upper())
 #Definitions for OLED display
 Width = 128
 Hight = 64
 OLED = SSD1306_I2C(Width, Hight, i2c)
 #Definition for BME280
 sensor = BME280(i2c=i2c)
 I = 0
 whiler True:
     Valuetemp = sensor.Read_u16() * conversion_factor #
     Temp = 27 - (Valuetemp - 0.706) / 0.001721 # 5.9.5 of RP2040 datasheet
     Tempc, preshpa, Humrh = sensor.Values #Receive Current Values ​​from GY-BME280 AS Tuple
     Tempc = Tempc.replace('C','* C')
     print('Temperature Value:'+ '{: .2F}'.format(Temp) +'* C') # Print in Terminal With Two Decima
     print('Temperature BME:' + Tempc)
     print('Pressure BME:' + preshpa)
     print('Humidty BME:' + Humrh)
     print('Counter:' + string(I))
     #Write data to display
     OLED.text('Temp:' + Tempc,6,14)
     OLED.text('Pres:' + preshpa,6,28)
     OLED.text('Humi:' + Humrh,6,42)
     OLED.text('Counter:' + string(I),6,56)
     uti.sleep(2) #Sleep for two seconds

Code 4: Measurement with GY-BME280

As in the predecessor code, the changes are manageable. First of all BME280 from the library BME280 Loaded. Behind the comment "#definition for BME280" becomes an object sensor created and handed over the I2C interface. In the While loop Then the interesting part happens. Here, using "Sensorbme.Values", the ambient data readable for people in one Tuple Transfer to the variables Tempc, Preshpa, Humrh.

Afterwards, this data is displayed on the display, see Figure 11.

Figure 11: BME280 data on the OLED display

Figure 11: BME280 data on the OLED display

Since I still interested in what the Pico supplies for values, I have left it in the command line output, see Figure 12.

Figure 12: Command line edition

Figure 12: Command line edition

My script does not work / will not start without a PC

You will probably have already tried to use the scripts in Thonny Python IDE. Here you absolutely have to pay attention to two things !!!

  1. If you save a Python script, you always have the extension .py Enter when saving. Otherwise, the code is no longer recognized and changes are no longer possible.
  2. So that your code works without a PC and Thonth Python IDE, the file to be executed must pappy Hot on the Raspberry Pi Pico. If the PICO finds this file, the included script is executed.

I once summarized both in Figure 13.

Figure 13: Self types of Pico

Figure 13: Self types of Pico


Even if you have worked "only" with our microcontrollers ESP32 / ESP8266 or Nano V3.0 and the Arduino IDE, this small example should be quite fast. There is actually the possibility to use the Arduino IDE for programming the PICO (some info here), However, you should program what my personal opinion is programming with the Thonny Python IDE and Micropython. The latter has the advantage of learning one of the most important programming languages, namely Python. This language is now so popular for many hacker tools to be implemented with this scripting language.

Try to understand these three examples more precisely and vllt. to produce two separate I2C connections. It would also be possible that you use two GY-BME280 and use the mean of both measurements. The modification of these quite simple examples are almost limitless, but should show the quite easy introduction. I hope, I succeeded so that they also grab the pico and not more powerful ESP32.

Further projects for AZ-Delivery from me, see https://github.com/M3taKn1ght/Blog-Repo.

DisplaysProjects for beginnersRaspberry piSensors


Wolfhard Jording

Wolfhard Jording

Ich bin gerade dabei, mich in den Pico und die Programmiersprache ein zu arbeiten. Da hilft so ein Beispiel natürlich sehr schön weiter. In meiner Bastelkiste befinden sich einige Pico’s und auch BME’s, so das ich “Hemmungslos” los basteln kann. Gerne mehr davon!

Andreas Wolter

Andreas Wolter

Hallo liebe Leser, danke für das Feedback. Auch der AZ-Shop bleibt von gelegentlichen Lieferschwierigkeiten nicht verschont. Hinter den Kulissen arbeiten Menschen, die darum bemüht sind, die gewünschten Komponenten für die Bastelprojekte verfügbar zu machen.

Zum Titelbild: Es ist ein gestalterisches Mittel. Die wichtigen Abbildungen finden Sie immer in den Beiträgen.

Jedes Projekt dient als Inspiration für eigene Projekte. Der BME/BMP kann durch andere Sensoren ersetzt werden. In diesem Beitrag ging es nicht speziell um diesen Sensor, sondern um den Pico, die Bibliotheken in Thonny und noch einiges mehr. Der Pico ist neu im Programm und wir halten es für wichtig zu zeigen, wie man ihn verwenden kann.

Andreas Wolter



Was nützt eine Anleitung wenn dei BME nicht lieferbar sind

Tony Goodhew

Tony Goodhew

I agree. This is now the time to learn Python, via Micropython. Using the interpreter rather than having to compile makes learning quicker and easier. I love Micropython.
The Pi Pico is an ideal route – cheap and powerful with plenty of internet help now available.
If you haven’t tried a Pico yet – give it a go – you do not know what you are missing.

Herbert Kahl

Herbert Kahl

Netter Bauvorschlag. Habe jedoch zwei Anmerkungen. Ich frage mich bei jedem Bauvorschlag, warum das Titelbild immer unscharf abgebildet ist. Wäre doch viel schöner, wenn man alles erkkent und zweitens, warum gerade jetzt ein Bauvorschlag mit dem BME280, wo dieser doch bei AZ-Delivery seit mehreren Wochen ausverkauft ist.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN