Eventually I got my hands on a Pico with Raspberry Pi’s first microcontroller chip (RP2040). Given that the board was only introduced in January 2021, the amount of documentation, example code and tutorials is truly astonishing.
So with this short blog post I want to see how quickly we can get a basic example running, including some input (ultrasonic distance sensor) and some output (OLED display), since I’ve used both components under Arduino, I had some sort of benchmark. The whole setup measured the distance between sensor and an object and translated this to a a constantly updating curve on the OLED display. There is still room for improvement, e.g.smoothing the data and slowing down the measurement would make the graphical output more attractive. Code for this example can be found here and there is also a version with an LCD display running on 3.3 V, so the wiring is basically the same. Also, as a pattern, as long as we can find the necessary drivers for the sensors we can generate similar setups for temperature and humidity sensors, air quality or light sensors - later we could also store the data on the Pico for further analysis / action ... the sky is the limit. The following video snipet demonstrates only the distance measurement.
This board is particularly interesting for its clock speed and memory (e.g. allowing for embedded machine learning usage), low power consumption (18 mA compared to 53 mA when using an ESP32), USB support for easy handling and all this at a very competitive price (≈4 €), similar to the ESP32. Andreas Spiess offers a comprehensive comparison between the Pico and comparable boards such as ESP32 or STM32 here: https://www.youtube.com/watch?v=cVHCllbN3bQ His final verdict for now is ‘no super obvious advantage’ beside the programable I/O. However, as we know, there is more to a board than mere functionality.
Micropython and Thonny
For this occasion I wasn’t looking for new or unique features. Even though the idea that directly programmable I/O can replace ‘bit banging’ in Python is very tempting, Commonalities with previous experiences are also key when considering this board as a serious contender for upcoming projects.
Getting started with installing the recommended Thonny IDE also delivers Micropython, a resources efficient implementation of Python 3.4, aiming to run under the constraints of microcontrollers. There is a fantastic free ‘Getting started online book’.
I haven’t yet experimented with Circuit Python the Adafruit fork of Micro Python. One of the main benefits is a quicker turnaround when programming going from 'edit-save-compile-upload-reset-run' to 'edit-save-run'. (Note: Using the UF2 bootloader which allows for programming boards over the Mass Storage Class (removable drive).
Electronic components used
To get an input, we use the Ultraschall Sensor HC-SR04 which can measure distances between 2 cm and 4.5 meters. The sensor requires an input of 5V. The reliability of the distance measurement also depends on the surface of the object, i.e. a moving hand works most of the time but can also produce a lot of ‘noise’ in the measurements. Below a relative detailed overview of the signal flow.
The second component used is the OLED Display (64x48 pixels)
/ Driver: SSD1306 (I2C Address: 0x3C or 0x3D). With the following Pins for the I2C protocol:
Wiring of components
The Trigger and Echo Pins of the sensor are connected to the Pico at GPIO3 (Pin 5) and GPIO2 (Pin 4). The OLED component is connected to I2C Pins (Pin 0=SDA, Pin 1=SCL) There is a Pico Pinout at the end of the post!
The Pico can be powered through USB -VBUS at Pin 40 or three AAA Battery – VSYS at Pin 39 (≈ 4.5 V). GP24 can be used to detect whether the Pico runs on battery or not.
Lastly, the fritzing part of the Pico is also an open source contribution.
A first programme
The moving wave form was inspired by an example visualizing sound using a microphone signal.
from machine import Pin, I2C from ssd1306 import SSD1306_I2C import utime from hcsr04 import HCSR04 i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000) oled = SSD1306_I2C(64, 48, i2c) sensor = HCSR04(trigger_pin=3, echo_pin=2) max_dist = 20 #the maximum distance helps scaling the curve on the display while True: oled.fill(0) # clear the display for jj in range(64): # loop through horizontal display resolution dist_pt = sensor.distance_cm() if dist_pt > max_dist: dist_pt =max_dist plot_pt = (1-dist_pt/max_dist+0.0025)*46 # convert to OLED pixels if plot_pt > 47: plot_pt =47 print(int(plot_pt)) oled.text('.',jj,int(plot_pt)) # update x=jj with data point oled.show()
An entire collection of interface examples is provided here.
If we want to run the program without the IDE we need to name the main program ‘main.py’.
>>> import os >>> os.listdir() ['hcsr04.py', 'ssd1306.py', 'ssd1306_test.py'] >>> os.rename('ssd1306_test.py','main.py') >>> os.listdir() ['hcsr04.py', 'main.py', 'ssd1306.py']
Following the maker paradigm of ‘ Low floor, wide walls, high ceiling‘ we could establish the low floor dimension, an afternoon and we could see parallels to the Arduino IDE and the way the board could be used within the ecosystem of existing sensors and drivers.
Similar to the MakeCode environment for Micro:bit or Calliope there is also a block-based programming environment for the Pico (https://make.playpiper.com/), which is entirely web-based, supporting application scenarios in schools. As always, it remains to be seen what blocks exist to program a wide variety of circuits or how easily those blocks can be added. For now, an intriguing idea are the integrated tutorials, leading through some first coding experiences.