• Skip to main content
  • Shop
  • Learn
  • Blog
  • Forums
  • IO
  • LIVE!
  • AdaBox
Adafruit Logo
0
  • Sign In | Create Account
  • Playground
  • Shop
  • Learn
  • Blog
  • Forums
  • IO
  • LIVE!
  • AdaBox
Sign In
0
Adafruit Logo
  • Learn Categories
    • 3D Printing
    • AdaBox
    • Adafruit Products
    • Arduino Compatibles
    • Breakout Boards
    • Circuit Playground
    • CircuitPython
    • CLUE
    • Community Support
    • Components
    • Crickit
    • Customer & Partner Projects
    • Development Boards
    • Educators
    • EL Wire/Tape/Panel
    • Feather
    • Gaming
    • Hacks
    • Internet of Things - IOT
    • LCDs & Displays
    • LEDs
    • Machine Learning
    • MakeCode
    • Maker Business
    • micro:bit
    • Microcontrollers
    • Programming
    • Raspberry Pi
    • Robotics & CNC
    • Sensors
    • STEMMA
    • Tools
    • Trellis
    • Wearables
    Explore, Groups to get your gears turning
    Explore
    Groups to get your gears turning
    Explore Groups
  • New Guides
  • Playground
picofun Notes

picofun

u/picofun
Badges
2

Getting Started

Adafruit Playground is a wonderful and safe place to share your interests with Adafruit's vibrant community of makers and doers. 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.

The goal of Adafruit Playground is to make it as simple as possible to share your work. On the Adafruit Playground users can create Notes. A note is a single-page space where you can document your topic using Adafruit's easy-to-use editor. Notes are like Guides on the Adafruit Learning System but guides are high-fidelity content curated and maintained by Adafuit. Notes are whatever you want them to be. Have fun and be kind.

Click here to learn more about Adafruit Playground and how to get started.

  • By picofun

    Adding WIFI the Easy Way

    Adding WIFI the Easy Way

    If you start from scratch, the best thing is to buy a board with integrated WIFI. But this is not possible in all cases. Many older boards just don't have a suitable chip. This is especially true for boards that are based on the RP2040.

    For example I recently bought the TinyFX from Pimoroni. That is a very small board about the size of a Qt-Py for controlling Lego lighting kits:

    Another example is the Tufty2040, a large sized display with a RP2040 on board:

    But I have also quite a few other boards lying around that would profit from connectivity e.g. the ItsyBitsy M4 Express. And of course I also own some of the shiny new Pico2 boards.

    Airlift

    The standard solution for adding WIFI is Airlift. Airlift is a WIFI-coprocessor running a special firmware on an Espressif ESP32-WROOM-32. Besides the "pure" chip on a breakout, there are also addons for specific form-factors like a FeatherWing or a BitsyWing.

    But Airlift has two major problems. The first is wiring. Airlift is based on SPI and in addition uses a number of control GPIOs. So if you don't use one of the wings (that block all of your pins) you end up with wiring 7-9 jumper-cables. That is not only cumbersome, but the boards above don't even provide that many pins (the TinyFx e.g. just exposes what you see in the image).

    The second problem is software. The Airlift uses a special CircuitPython library that does it's job, but in a slightly different way than the standard WIFI support of CircuitPython does. E.g. instead of connecting with wifi.radio.connect() you use esp.connect_AP() and instead of using wifi.radio.connected you check the connection state with esp.is_connected. There are many other differences in the API. So all the boilerplate code you have or download from the internet has to be adapted for the Airlift. As long as this is your main code.py file, this is no major problem. But once you start using libraries things get complicated. You have to install the source version of the libs and adapt them. Maintaining this is no fun.

    ESP-AT

    An alternative to Airlift is ESP-AT. This is a firmware maintained and provided by Espressif turning many of their chips into WIFI-coprocessors. ESP-AT is highly customizable but in its standard versions it uses plain UART for the communication with the main MCU. So you basically only need four wires: VCC, GND, RX and TX.

    The drawback of ESP-AT is its textual interface: you send so called "AT-commands" to the co-processor and then you have to parse the response to extract the relevant data. Some of these commands are really complicated, e.g. to connect to an AP you would send

    AT+CWJAP="myssid","mypasswd",,0,1,3,1,5,1
    

    Wrapping all the complexity in a library really makes sense. For this reason, Adafruit had created the library CircuitPythonESPAT_Control, but it was abandoned in favor of Airlift and is no longer maintained. That library also suffers from the same drawback as the Airlift library, i.e. it uses a different API than standard CircuitPython.

    CircuitPython-ESP32AT

    For this reason I created a new library called CircuitPython-ESP32AT. This library talks to the ESP-AT on an ESP-coprocessor, but instead of inventing yet another API it uses the standard CircuitPython API for wifi, ssl, socketpool and so on.

    At first, this might seem confusing. On boards with native WIFI these modules don't need to be installed, since the CircuitPython firmware already provides them. For other boards, the ESP32AT project now provides drop-in modules with the same names providing (almost) the same set of functionality.

    One important function the external modules don't provide is the web-workflow which really needs native WIFI. Otherwise, you need to look hard to spot differences.

    You will find installation and setup instructions as well as notes about various hardware alternatives in the repo of the library. Instead of reproducing this information here, I only show some examples I actually use.

    Hardware

    From hardware side, you need a board with a supported ESP-chip. Any ESP32, ESP32-S2 and ESP32-Cx will do. ESP32-S3 and the ESP32-Hx series are not supported. You can even use very old ESP8266 hardware as long as it has 1MB of flash. But this is not really recommended since the ESP8266 only supports operation in TCP/UDP/SSL client mode. In addition, you have to compile the firmware yourself (which in fact is easy and a matter of a quarter of an hour - see the repo for details).

    Wiring is easy: you must connect RX/TX of your host MCU to the AT-UART ports TX/RX of the coprocessor. Besides RX/TX you should also connect GND. Powering the coprocessor directly from the host MCU might or might not work. For example, I had no problems powering the ESP32C3-SuperMini from the 3V3 pin of the Pico/Pico2, but I did not use any other peripherals:

    The connection in this image uses a trick: it redefines the I2C-pins of the PiCowbell adapter from I2C to UART. Of course you loose I2C on these pins, so this is not a solution for all problems but it demonstrates how simple wiring can be compared to the Airlift.

    I am using the same trick for the TinyFX board from above. The board does not have any dedicated UART-pins, but the pins of the Stemma/Qt can also be repurposed to UART instead of I2C. This allows a very simple connection using a Stemma/Qt-DuPont adapter cable for the connection of the TinyFX to again to an ESP32C3:

    Even simpler is the usage together with the Maker Pi Pico Board. This board has a socket designed for the ESP-01S:

    Liligo has created a chip with the same form-factor and basically the same pinout, which is called Lilygo T-01 C3. This board works also in the socket and gives full performance and provides all WIFI-functionality.

    The Swedish company "iLabs" even has a Feather-sized RP2350 board with an integrated ESP32C6:

    Ok, we will see a Pico2-W soon, but until then, this is the best solution for a WIFI-enabled RP2350.

    Performance

    For most use-cases like updating the time, querying an API (e.g. for weather information) or running an AP with a webserver the performance is just on par with native WIFI. There are some special cases though where native WIFI is better: e.g. I have a high-frequency data-sampling application that sends data using UDP to a reciever. Native WIFI can send with a rate of 0.001s per message, using ESP-AT this is much slower (I measured 0.015s per message).

    Also, if you are dealing with large responses the default chunk size of 32 bytes that the adafruit_requests library uses will slow you down, since every chunk is an AT-transaction. Using response.iter_content() directly is a workaround to speed up processing (this also helps native WIFI a bit and Airlift too).

    tinyfx_esp32c3-supermini.jpg
    Save
  • By picofun

    Running Two Programs on a Single CircuitPython Device

    Running Two Programs on a Single CircuitPython Device

    I have a nice e-ink display on my shelf running a CircuitPython program that updates the display every fifteen minutes. Recently I wrote a second program that would also just be ideal for this display.

    Thinking about my options, I could either

    • copy the relevant program to the MCU everytime I want to switch
    • write a wrapper application for both programs

    The first option was not attractive, because I want to switch on a regular basis. The second option also has it's problems. Both existing programs are valid stand-alone and are maintained in their own Github-repositories, so adding a wrapper would make changes to the software much more complicated.

    So I was thinking about a sort of "boot-switcher". Users running Linux on their PCs often have a boot-manager that allows them to switch to more obscure operating systems once in a while, and I wondered if there is a simple way to use this concept also for a CircuitPython device.

    Hardware Setup

    Since a MCU neither has a BIOS that can start a boot-manager before the real OS, nor (usually) a mouse or keyboard attached for the selection of the target program, this solution needs a free GPIO and a slider or button.

    Our "boot-manager" is the code in boot.py. This code reads the state of the GPIO and starts one of the programs depending on the value. Using a slider will result in a "sticky" behavior: unless you flip it again, each reset will start the same program. The button is different, since you have to keep it pressed during power-on/reset to start the second program. So the second program is more of an exception while the first program runs as the default.

    Software Setup

    For the boot-switcher to work, the programs can't be deployed to the top-level directory of the CIRCUITPY-drive. Instead, the layout on the drive is like this:

    So every application moves one level down into its own directory.

    You can find the necessary boot.py in the Github-repo https://github.com/bablokb/cp-bootswitcher. In this file, you have to configure your setup, e.g.

    PIN_SWITCH = board.D1
    APP_NAMES  = ["_app0","_app1"]
    SHARED_FILES = ["boot.py"]+APP_NAMES
    

    The names of the application directories don't matter, but you have to add the names to APP_NAMES. You can also add more files/directories to SHARED_FILES, but all of these entries must be top-level. One use case for this is if your applications share the lib-folder.

    How does it Work?

    The implementation of the boot-switcher turned out to be simple and during power-on or reset you won't notice a delay. The code in boot.py only checks the state of the GPIO and then moves all files from the top-level back to the appropriate application folder and then all files from the other application folder to the toplevel. Moving is a fast operation, since it only changes the entry in the directory-table (FAT), so moving a very large lib-folder won't be slower than moving code.py.

    Other Use-Cases

    There are a number of other use-cases for the boot-switcher, e.g.

    • providing two versions of an application, e.g. a beta version in addition to a productive version
    • providing a special diagnostic application in addition to the normal application
    • running the same application with two different configurations (e.g. within two different WLAN-networks)
    • having two sets of libraries e.g. for CP 8.x and 9.x

    Final Notes

    If you only want to start different top-level programs and otherwise share the rest of your code and all settings, you don't need the boot-switcher. You can do this with a few lines of code, e.g.:

    import supervisor
    ...
    supervisor.set_next_code_file("admin.py",sticky_on_reload=True)
    supervisor.reload()
    

    Code within boot.py can do many things for you. For example, you can make the CIRCUITPY drive writable for your program or hide it for the PC. Of course you can also shoot yourself in the foot, so reading the documentation is recommended.

    Save
  • By picofun

    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).

    Save
  • By picofun

    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.

    Save
Search

Getting Started

Adafruit Playground is a wonderful and safe place to share your interests with Adafruit's vibrant community of makers and doers. 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.

The goal of Adafruit Playground is to make it as simple as possible to share your work. On the Adafruit Playground users can create Notes. A note is a single-page space where you can document your topic using Adafruit's easy-to-use editor. Notes are like Guides on the Adafruit Learning System but guides are high-fidelity content curated and maintained by Adafuit. Notes are whatever you want them to be. Have fun and be kind.

Click here to learn more about Adafruit Playground and how to get started.

    • Contact Us
    • Tech Support Forums
    • FAQs
    • Shipping & Returns
    • Freebies
    • Terms of Service
    • Privacy & Legal
    • Website Accessibility
    • LLMs.txt
    • About Us
    • Press
    • Educators
    • Distributors
    • Jobs
    • Gift Cards
    "Premature optimization is the root of all evil"
    Donald Knuth
    Adafruit Logo
    A Minority and Woman-owned Business Enterprise (M/WBE)