Adafruit Playground is a wonderful place to share what you find interesting. Have a cool project you are working on? Have a bit of code that you think others will find useful? Want to show off your electronics workbench? You have come to the right place.
Adafruit Playground is a safe place to share with the wonderful Adafruit community of makers and doers.
-
Running Pi-HATs with a Raspberry Pi Pico
Running Pi-HATs with a Raspberry Pi Pico
Being a Pi-user since the very first Pi1, I own many different Pi-HATs. Some of them are in daily use, but many of them are sitting in the shelf. So I wondered if I could give them a second chance in combination with a Pico. And one of my major use-cases are e-ink displays for the Pi. These e-inks don't really match with the Pi, since they are optimized for low-power scenarios. But even the Pi-Zero drains batteries too fast to be a suitable partner for these kind of displays.
Although equipped with a full 2x20 pin socket, most HATs only use a few pins like power, ground, I2C or SPI. So using a bunch of jumper cables should already be sufficient. Although that is true and fine for initial tests, a good and solid connection is always the better alternative.
So I did some research and discovered a few adapter-boards on the market that might be suitable. But on closer inspection it turned out that most of them missed one important point: just mapping some arbitrary pins is not enough. So I decided to create my own adapter boards.
Hardware
One board uses the Pi form-factor, the second uses the Pi-Zero form-factor:
They fit into standard enclosures, but since the USB-connection is on the side they need an additional cutout. Changing available 3D-models should be a simple task. And the bigger adapter PCB has a footprint for a standard JST-2 battery connector exactly where the USB-power cutout is. Anyhow, this was not the major challenge when designing these boards.
The biggest challenge was the correct pin-mapping. The Pi has I2C, UART, two SPI and I2S. I did not take the last one into account so I ended up with two revisions. I2S needs two consecutive pins. On the Pi, that is GPIO18 and GPIO19, but they are not next to each other on the pin-header.
Another contraint was space. I did not want to route traces below the WLAN-chip and antenna of the Pico-W. In the end I had to make a compromise for the Pi-Zero adapter: the first revision maps both SPIs but not I2S, the second revision maps SPI0 and I2S but not SPI1. Which is not a big deal since I haven't found a HAT yet that actually uses SPI1.
I also don't map the ID-pins of the Pi. These are used to automatically configure the correct driver on the Pi. On the Pico, you don't run a generic OS but a specific program, so you have to take care about correct drivers already before when you put them on the CIRCUITPY-drive.
The Pi-adapter has more space. I added a SD-card reader and I broke out a number of pins. One of the drawbacks of many HATs is that they block the complete pin-header although they only use a few pins. Breaking out the pins is not strictly necessary since you can access all pins from the back anyhow.
Software
The second part of the project was porting the HAT-drivers to the Pico. For Adafruit HATs, that was fairly simple. Adafruit has CircuitPython support for almost everything they sell. And since Blinka brings CircuitPython to the Pi-SBCs, "porting" the drivers is a matter of using the correct pins.
On example: the speaker-bonnet. The learning guide (https://learn.adafruit.com/adafruit-speaker-bonnet-for-raspberry-pi) tells you it is using the I2S pins GPIO18, GPIO19 and GPIO21 on the Pi. After looking up the mapping for the adapters, you just plug in those pins into a small example program provided by a second guide: (https://learn.adafruit.com/mp3-playback-rp2040/pico-i2s-mp3) and off you go playing MP3 on the speaker-bonnet. This is actually much simpler on the Pico compared to the Pi, because you don't have to go through all the steps to install the relevant drivers.
For other HATs, you will usually find CircuitPython example code for the Pi using Blinka in the learning guide for the HAT. In this case, you can take the code as is and only replace the pin-numbers.
I also own a number of HATs from Pimoroni. They don't provide CircuitPython drivers, but at least for some of the HATs there are ready to use drivers for the builtin driver-IC. In only a few cases I had some real porting work to do. But once I found out how to translate CPython I2C/SPI-calls to CircuitPython, the porting was straightforward.
Project-Repository
You can find the project repository here: https://github.com/bablokb/pcb-pico-pi-base. The repo has KiCad design files as well as ready to use production files for my preferred PCB manufacturer.
Also in the repo are CircuitPython libraries and example code for all the HATs I tested or ported.
Next Steps
What I might do in the future is to create a similar adapter PCB for the Feather form-factor. While in my current designs the Pico sits inbetween the PCB and the HAT, with the Feather I would probably make the Feather plug in from behind.
The second thing I am working on is to support the new Waveshare ESP32-S3-Pico. This is an ESP32-S3 in the Pico form-factor with identical physical dimensions and identical pin-layout. This breakout is interesting since it gives me a device with far more memory than the Pico provides. And I don't have to create new adapter boards. First results look promising.
CircuitPython Board Definition Files
Since I have two form-factors and two revisions each with their own pin-mapping, looking up the mapping is cumbersome. So I also created my own CircuitPython versions that do the mapping for me. So
board.GPIO18
will always map to the correct pin on the Pico, regardless which PCB I use.With two form-factors, two revisions and now three devices (Pico, Pico-W, EPS32-S3-Pico) I have a total of 16 combinations, thus potentially 16 CircuitPython versions. A lot to maintain, but not all combinations are actually in use (yet).
-
Using Github Codespaces for CircuitPython Development
Using Github Codespaces for CircuitPython Development
Introduction
If you wan't to contribute to CircuitPython, one of the hurdles you need to take is the installation of the development environment.
There is a nice guide from Dan Halbert https://learn.adafruit.com/building-circuitpython which walks you through all the necessary steps.
There are a few problems though:
- you will need to download and install a lot of software-packages. Some of them might even need other versions than those that the packet-manager of your distribution provides. Or they conflict with other projects you are working on.
- If you use a different flavor of Linux, you cannot just copy and paste the commands from the guide but also have to change commands and package-names.
- Your software-environment is bloated. Disks are very large these days, so this is not the main problem, but backups take definitely longer (I assume that you do backup your computer).
You could use a dedicated development machine or a virtual machine, but setting this up is again additional work.
Github Codespaces are a solution for all of these problems. A Codespace is a sort of virtual Linux-system. Technology wise it is a Linux container running within docker in the cloud. If you have a Github account, you can create such a system within seconds. You just head to https://github.com/codespaces and create a codespace from one of the templates (the "Blank" template is just fine).
The interface to the codespace is the web-version of "Visual Studio Code" (VSC), so you have a state-of-the-art editor, terminals, git and so on - all from within your browser. As an alternative, you can install VSC on your local machine, add the codespace-extensions from the VSC-marketplace and connect from your local VSC to you codespace. This is higly recommended, since the browser version is sometimes sluggish.
Since codespaces use ressources in the cloud, Github charges for using them. The good news is that the free plan of every account has 120 CPU-hours and 15GB storage per month included. The minimal machine has 2 CPUs, so this boils down to 60 hours per month. This should be enough unless you are a professional developer.
Automatic Setup for CircuitPython
At this point, you could just create an empty codespace from the template and follow the guide from Dan. I actually recommend that you do that once, since you will learn about the different tools you need to install.
For regular use, it is much simpler to let Github do all this work. For this reason the CircuitPython repository has predefined codespace configurations for most of the ports.
So the normal workflow would look like this:
- create a fork of https://github.com/adafruit/circuitpython
- create a new development branch within your fork
- clone this branch into a codespace
- go for a coffee-break: the initial setup will take about 10 minutes
- edit and build your own version of CircuitPython
- add, commit and push any changes back to your branch
- create a pull-request for upstream
You can find detailed instructions for the third step in the Readme: https://github.com/adafruit/circuitpython/blob/main/.devcontainer/Readme.md
Daily Use
Once you have created your codespace, you can keep it and use it whenever you want. Codespaces have two states: "active", i.e. running or "stopped". In the latter state you are only charged for the storage, so don't forget to stop your codespace after you finished your work. Github will automatically stop your codespace after 30 minutes of inactivity. In your accout settings you can change this value to something shorter. Also, Github will delete unused codespaces after 30 days of inactivity. But you will be prompted before this happens.
Storage size is a minor problem, since Github does not charge for the storage that the standard Linux image uses. A fully operational codespace for the espressif-port e.g. has about 2.4GB, so the 15GB limit will be enough for a number of codespaces.
Further Reading
Codespaces are a powerful tool with many features not covered here. To find out more, read the documentation: https://docs.github.com/en/codespaces.
Final Note
The scripts for the automatic setup of codespaces are not maintained by the core CircuitPython developers. As CircuitPython evolves the buildsystem will change and the scripts might stop working. In this case, it is best to create an issue.