As part of my personal interest in different areas of technology, I have decided to go a bit deeper in the low power consumption microcontroller boards world that will (hopefully) leads me to a better understanding of practical implementation of Internet-of-Things (IoT) concept.
In this article I tried to document my beginner’s journey to learn how the new Raspberry Pi Pico board works and interacts with other devices. Most articles and guides I have seen assume that you know things that (I believe) a beginner usually don’t know (at least, I didn’t), so I will try to explain a few things that helped me to better understand what I was doing and fill some gaps between hardware configuration and programming languages (MicroPython in this case).
These are the required items to complete this guide.
- Pi Pico – preferably a pre-soldered version, otherwise (like myself) you will need to solder the pins yourself.
- MicroUSB cable – make sure it’s a proper cable for data transfer, otherwise your computer will not communicate with Pi Pico board.
- Breadboard – a half sized breadboard (400 points) is what I’ve used here.
- Cables/Wire Jumpers – cables are a good start, but wire jumpers keep your breadboard tidy.
- OLED Display – I’ve used a 0.91 cm (0.56 ft) 128×32 SDD1306 model. Make sure that yours is at least SDD1306. Same as Pi Pico board, pre-soldered pins will help here.
- Thonny installed on your computer (https://thonny.org/). Version 3.3.3 or later is required to support Pi Pico.
Note: If you don’t want to test an OLED display, only the two first items are required to install MicroPython and complete the internal LED quick test.
If you are wondering how much you are going to spend with this exercise, I paid €23.05 for all the items on a Spanish online store. I will put the links here if you are interested.
- Pi Pico Start Kit – tinyurl.com/y6edmoba
- Wire jumper pack – tinyurl.com/y6sel84j
- OLED Display – tinyurl.com/yykx2l2m
Please note that neither the Pi Pico and OLED display in the list above come pre-soldered.
The first thing we have to do is install MicroPython onto Pi Pico. Before plugging the USB cable, hold the BOOTSEL button located on the top of you Pi Pico and then connect the USB cable. After about 3 seconds, release the BOOTSEL button. The picture below shows where the BOOTSEL button is located.
You should see your Pi Pico as a removable USB storage in your computer. As I’m using a Mac, I can see it in Finder.
Now start Thonny app, and it will automatically ask you to install MycroPython firmware on Pi Pico. Just go ahead and finish the installation.
After finishing the firmware installation, you should see a MicroPython REPL prompt in the shell box.
Quick Internal LED Test
If you want to run a quick test and check if the communication with the board is working properly, copy and paste the following lines into the shell box.
import machine led = machine.Pin(25, machine.Pin.OUT) led.value(1)
If the green led on top of your Pi Pico board is on, then the test works.
Before we start our wiring task, it would be good to have a quick overview of the pins we are going to use from Pi Pico. The board contains 40 pins and the picture below shows which ones we are going to use for this guide.
Here is a brief explanation for each selected pin:
- Pin 40 (VBUS) – this is the the pin that takes power directly from the micro USB port and it runs at 5v. Pin 36 could also be used as the OLED display we are using also works with 3.3v.
- Pin 3 (GND) – the ground connection to complete the circuit connected to the power source (any other GND pin could also be used)
- Pin 11 (I2C0 SDA / GP8) – this is the channel to send and receive data.
- Pin 12 (I2C0 SDL / GP9) – the clock signal.
With Pin 11 and 12 we can notice that I2C (Inter-Itegrated Circuit) is the standard used here to communicate with the OLED display. Pi Pico has 2 I2C buses, that is why we can see both I2C0 and I2C1 notations in the diagram above.
The GPxx notation is for General-purpose input/output (GPIO) along with the respective pin number (xx) which should not be confused with the physical pin numbers mentioned above. We will see later in the coding section that our code will refer to pins by function. E.g. Pin(9) is actually pin GP9 (Pin 11), not the physical Pin 9.
The wiring diagram below shows how we connect the OLED display to Pi Pico.
After finishing the wiring exercise, your prototype should look something like this.
The Indoor Thermometer program
As this is a quickstart guide, I’m not going into the details of the code. I believe there are enough comments in the code to explain what it is doing. I just would like to mention a few things:
- The code imports the SS1306 driver, so it will not work if your OLED display uses a different driver.
- In line 10 we are specifying the GPIO pins for SDA (data) and SCL (clock), as mentioned in the Wiring Information section above.
- As commented in the code, we are using an internal sensor to measure the temperature.
Open Thonny then copy and pate the code below.
# Thermometer with Oled Display SSD1306 from machine import Pin, I2C, ADC from ssd1306 import SSD1306_I2C import framebuf import utime WIDTH = 128 # oled display width HEIGHT = 32 # oled display height i2c = I2C(0, scl=Pin(9), sda=Pin(8)) # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8) print("I2C Address : "+hex(i2c.scan()).upper()) # Display device address print("I2C Configuration: "+str(i2c)) # Display I2C config oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display # Thermometer logo as 32x32 bytearray buffer = bytearray(b"\x00\x03\xc0\x00\x00\x07\xe0\x00\x00\x0e\x70\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0c\x30\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x0d\xb0\x00\x00\x1d\xb8\x00\x00\x1b\xd8\x00\x00\x37\xec\x00\x00\x37\xec\x00\x00\x37\xec\x00\x00\x33\xcc\x00\x00\x19\x98\x00\x00\x1c\x38\x00\x00\x0f\xf0\x00\x00\x03\xc0\x00") # Load the thermometer logo into the framebuffer (the image is 32x32) fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB) # Init internal temperature sensor sensor_temp = ADC(4) # Define the conversion factor conversion_factor = 3.3 / (65535) while True: # Read temperature from sensor reading = sensor_temp.read_u16() * conversion_factor temperature = 27 - (reading - 0.706) / 0.001721 # Clear the oled display in case it has junk on it. oled.fill(0) # Blit the image from the framebuffer to the oled display oled.blit(fb, 96, 0) # Add text with temperature oled.text(" This Room",5,2) oled.text("Temperature",5,13) oled.text(" is " + str(int(temperature)) + " C",5,25) # Update the oled display so the image & text is displayed oled.show() # Sleep 2 seconds before measure again utime.sleep(2)
When you click save for the first time, Thonny will ask where you want to save it. Just choose ‘Raspberry Pi Pico’, name the file ‘main.py’ and save it. Now try to run it and see if it works by pressing F5 or clicking on the green play button.
You may be a bit disappointed that it didn’t work, and you got the following message:
Well, it is because we haven’t included the SS1306 driver library (and most of the guides I’ve seen don’t include this part). Luckily this if very simple with Thonny (I didn’t have the same experience with VSCode and PyCharm). On the menu, click on ‘Tools’ and select ‘Manage Packages…’.
Search for ‘SSD1306’ and a few results should come back from PyPI.
Select ‘micropython-ssd1306’ and then click on ‘Install’ button. Once finished, you will see the ssd1306 package on the left side. Click on it and see the driver added to the /lib folder.
Close the package management window and run it again. Now you should see a successful execution informing the IC2 Address and Configuration.
This is because Thonny automatically downloaded the package and added it to our codebase. Now we can finally see the working prototype!