I was travelling when the Raspberry Pi Foundation launched the Pico W, so I had to wait to get back before I could get my hands on one. I have one now, and to try it out, I decided to port my network-oriented PicoWeather app, this time creating a MicroPython version — it was released for CircuitPython.
I wrote PicoWeather almost a year ago as an excuse to use Pimoroni’s PicoWireless ESP32-based WiFi add-on. It was featured in Raspberry Pi’s HackSpace magazine. As one commenter sagely asked at the time, why bother with the Pico part when you could run the whole thing off the ESP32? Well, I wanted to focus on the Pico, and if the WiFi board used an ESP32, what of it? I was interested in the WiFi part, not the Espressif angle.
Pico W, of course, means I don’t need to pose the question at all. MicroPython has WiFi support built in and I’ve used it before for my FeatherClock project. So, having stripped PicoWeather of its Adafruit-sourced ESP32 interface middleware — the reason for coding in CircuitPython — how was the conversion?
Good and, on the whole, straightforward. The are some minor changes to the I²C and GPIO setup flows caused by the differences between CircuitPython and MicroPython. The latter includes this functionality in its
machine module; CircuitPython instead spreads them across its
However, my HTK133 display driver library already works with both — you just pass in an I²C object, however, it’s instantiated — so there were no changes required there. But I did take the opportunity to upgrade both versions to the latest version of HTK133, which I’d recently updated to support Adafruit’s 0.54in four-digit, 14-segment LED backpack at the request of a user.
PicoWeather sets the host’s real time clock, and while CircuitPython uses the
rtc module, MicroPython again organises it under
machine. More logical, yes, but perhaps less Pythonic. However, while the CircuitPython version of PicoWeather can use the ESP32 to set the RTC, the MicroPython version has to do it manually: it makes a call to an NTP time server, decodes the result to a Unix epoch time and sets the RP2040 microcontroller’s RTC with it.
There is a slight difference between the two versions’ WiFi connection flows, but nothing dramatic. My Open Weather integration handles the HTTP request work to get the current weather conditions from the API: I just had to pass MicroPython’s
urequests module into the OpenWeather class constructor in place of Adafruit’s version.
One issue that took some extra time to fix: the original version of the app uses the
monotonic_ns property as the basis for measuring the flow of time and therefore when it’s necessary to request updated weather conditions and when to periodically re-show the current conditions on the LED. This property is absent from MicroPython’s
time module, so I replaced it with
time.tick_us(). I then found that screen refreshes were not happening after a short time.
The fix, found by RTFM-ing MicroPython’s docs, is to use
time.ticks_diff() to calculate time elapsed between
time.tick_us() values. I was just subtracting them, and that’s not the way to do it if you don’t want value overflows to mess up the flow. Making the change makes everything work again.
What particularly pleases me about the Pico W adoption process was that I could make most of the code changes before receiving the Pico W. The Raspberry Pi Foundation has a nice doc on connecting the W to WiFi and making HTTP requests, and that got me most of the way there. The rest was debugging the changes when the W arrived.
Crucially, of course, the arrival of the W at last makes the Pico a viable basis for IoT project. Now I’ve prototyped with MicroPython, I’ll try to remake the PicoWeather app in C.
You can find my updated PicoWeather app in my GitHub repo.
Next time: Back to RP2040 assembly language…