Build a Raspberry Pi Pico WiFi IoT Device

Last Summer, I explored using the Raspberry Pi Pico as the basis of a cellular IoT device. That done, I wanted to try out WiFi connectivity. To do so, I ordered a Pimoroni PicoWireless.

Weather updates, Pico style

This dude is a Pico-sized board that features the near ubiquitous ESP32 WROOM-32E module for 802.11n WiFi. Since the ESP32 and its attached antenna occupy just under half of the board, Pimoroni’s designers decided to fill the remaining space with a MicroSD card slot, a button and an RGB LED. As Barry Norman used to say, “and why not?”

Now, Pimoroni warns that C/C++ support for the MicroSD slot is “quite experimental”, but apparently it’s more solid if you use CircuitPython. Me, I wasn’t interested either way, though I may try it out in due course. One nice touch with the PicoWireless: the MicroSD slot’s two data pins pass through exposed traces on the back, so if you definitely don’t want the card slot and desperately need the Pico’s pins 27 and 2 — GPIO pins 20 and 21 — you can slash the traces to free up those pins for use by your application.

ESP-equipped: Pimoroni’s PicoWireless

You can do that same with ESP32’s IO pins, but would you really spend 12 quid for a WiFi board just to use the MicroSD card?

As I say, the PicoWireless is Pico-sized and comes with female header soldered in place so you can just fit a Pico with suitable male headers attached right onto it. That’s not so useful for other RP2040-based boards, including Pimoroni’s own Tiny 2040, or Picos that are driving other add-ons, such as a display or a sensor. For the Pico, read on for a way around this.

MicroSD, button and LED included

The ESP32 talks to the Pico over an SPI bus, and the C++ code Pimoroni supplies comprises a generic SPI driver, an ESP32 driver which leverages the former, and a subclass of the ESP32 driver which adds methods to drive the board’s RGB LED and to check whether the button is pressed.

The RGB LED, incidentally, is not a WS2812 or similar but a three-colour LED driven by three GPIO pins set as analogue outputs. The pins are 25, 26 and 27, for red, green and blue, respectively. It’s very easy to use. Ditto the button, though the included method doesn’t debounce it to make sure a sensed press or release really is one.

HTTP yes, HTTPS no

I tried out the supplied C++ code first, and it works, but there’s a key failing for anyone hoping to use it for serious data acquisition: it doesn’t support HTTPS. Insecure HTTP is all very well, but every third-party API my applications call all use secure HTTP. So if you hope to use the PicoWireless to pull data from third-party services on the Internet that you trust are not ‘man in the middle’ impersonators, you’re almost certainly going to want HTTPS support.

The ESP32 supports TLS, so it is possible to do HTTPS, but my attempts to make HTTPS connections on port 443 with the ESP32 set to TLS mode (rather than plain TCP) proved unsuccessful: certain responses from the ESP32 don’t match what the driver expects to receive. I plan to do some more work tracking down the error and adding HTTPS support, but in the meantime I switched to Adafruit’s compatible CircuitPython ESP32 driver just to get things going.

This driver does support HTTPS out of the box, and operates securely or insecurely according to whether you prefix the target server’s domain name with https:// or http://. Writing code to send off a request and extract a couple of values from the response JSON was a matter of moments. Ditto coding the PicoWireless RGB LED to display WiFi connection state.

After some basic trials of the HTTPS functionality, I recreated an application I built some time ago for the Electric Imp platform — and continue to use, mounted on a worktop power socket in my kitchen. It’s a connected weather readout: it displays the next hour’s forecast on an 8×8 LED matrix. The forecast is updated every quarter of an hour, scrolling the conditions and an outdoor ‘feels like’ temperature across the matrix. It then shows a conditions icon. So you don’t miss the textual details, they re-scroll every 20 seconds.

Originally, I used the Dark Sky API to retrieve the weather forecast. It’s a great API, but since Dark Sky’s acquisition by Apple a couple of years ago, it’s under threat of extinction — and they’re no longer issuing API keys. So for the Pico version I picked OpenWeather as an alternative, and if you build the weather monitor, you’ll need to register with OpenWeather to get an App ID.

Assemble the Hardware

As I noted earlier, the PicoWireless was designed to clip directly onto a Pico’s male headers. When you fit headers to the Pico, don’t solder Pico pins 5, 6, 7 and 8. Instead carefully push those pins up through the Pico. You’ll end up with underside pins onto which to fit the PicoWireless, and four pins up top with which to connect the 8×8 LED matrix’s I²C backpack. Why those particular pins? They’re not used by the PicoWireless and provide a GND (8), two i2c0 pins (6 and 7), and a plain GPIO pin (5) that you can use to power the matrix — the code sets the pin as a 3V3 output. Just wire the I²C backpack to those four pins.

Pins below for the PicoWireless — and up top for the display

You can find the application’s code in this GitHub repo. Clone it and copy the file and lib folder over to the CIRCUITPY volume that appears when you connect the Pico to your computer. 

If it’s a new Pico, you’ll need to install CircuitPython first. Copy the downloaded file to the RP volume mounted by a raw Pico. If it’s a used Pico, hold down the BOOTSEL button while you connect the Pico to your computer.

The Pico with the 8×8 matrix attached

Finally, you’ll need to create a file called on CIRCUITPY. Add to this nothing more than a Python dictionary declaration:

secrets = { "ssid": "...", "password" = "...", "apikey": "...", "lat": ..., "lon": ..., "tz": ... }

Add your own values in place of the ...: your local WiFi credentials, your OpenWeather App ID (all as strings) and your location’s co-ordinates (as floating point values), and your timezone offset in hours plus or minus GMT. Don’t share this file!

The three key components together

OpenWeather places limits on the number of free API calls you can make in each 24-hour period. Make sure you don’t exceed this during testing. The code calls the API every 15 minutes, so you shouldn’t bust the limit in regular use, but you might if you’re turning the device on and off frequently. 

My Electric Imp version uses the imp MCU’s real-time clock to maintain a daily tally of API calls. On my to-do list is code the CircuitPython version to set the Pico’s RTC from an NTP server — check out my FeatherClock ESP266/32 application code to see how this works — and then use this to make sure daily API accesses stay within the imposed limits.

If you want to change the angle at which the text and icon appear on the display relative to the backpack header pins, look for the line in, matrix.set_angle(x) — change the value of x to 0, 1, 2 or 3 for 0, 90, 180 or 270 degrees.

The values of DISPLAY_PERIOD_NS and FORECAST_PERIOD_NS govern how frequently the display repeats and how often the device pulls down a new forecast from OpenWeather, respectively. The times used are in nanoseconds.

The weather icons are defined in setup_icons(): they are byte arrays comprising eight 8-bit values for the rows of the icon. You can use Ascii to draw alternative icons.

2 thoughts on “Build a Raspberry Pi Pico WiFi IoT Device

  1. captclaude

    It’s a great article by any measure, but I have to admit that I am puzzling over the concept. Why do I need a Pico when I already have the ESP32 processor? That seems like processor overkill somehow. Can you help me (and possibly others) understand?

    1. smittytone Post author

      Of course you can use an ESP32 on its own, and there are plenty of blog posts out there covering this use-case. But I was interested in how I might bring WiFi connectivity to the Pico platform specifically, not in the absolutely most basic way of building a WiFi device. As I write, this exploration was based on an Electric Imp project: the Electric Imp platform’s MCU modules have integrated WiFi — and, I might add, a secure, cloud-accessible microserver component so devices can have their own web presence. And there are many maker-oriented MCU products from Adafruit, SparkFun et al that use the ESP32 as a WiFi module.

Comments are closed.