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.
-
Option Map: Microcontroller form factors Overview
This page gives an overview of microcontroller form factors typically used by the maker community (at a beginner/intermediate-level). The intention is to assist in finding the right fit for your projects. To achieve this, a high-level introduction of said form factors, and simple feature/property matrices will be presented. Naturally, coverage will be limited by the author's personal knowledge of available options (even if popular in other circles).
The focus is primarily on Adafruit products (tends be available in these popular form factors), but also makes associations to names used by other companies (aliases).
Common form factors (FF)
The following sections present common form factors in decreasing order of size. A few different feature/property matrices will follow (Sorry. Not sure how to link to a lower section).
FF: Mega/Grand Central
Alias: Uno (Arduino), Metro (Adafruit)
A key development board instrumental in popularizing the entire microcontroller-based DIY/maker movement. The UNO significantly reduced the barrier to entry for microcontroller-based prototyping & development.
Note that there are currently 4 revisions of the UNO format (Currently at UNO R4). Arduino describes the differences over time in this article. Another article describing the differences in more detail is linked here (Not verified by the author, but information looks reasonable).
Other useful information:
- Considered relatively large by Today's standards (though realistically still very tiny at ~2.1x2.7").
- Popularized the idea of stacking "shields" on top of the base microcontroller board.
- ...but newer form factors have become so small, that the trend is to stack add-on boards (like FeatherWings) side-by-side using "doubler", "tripler", and "quadrupler" carrier boards.
FF: Feather
-
EPS32 V2 eInk / ePaper Daily Calendar and Clock I oh so wanted to build Liz Clark's QTPy CH32V203 eInk / ePaper Daily Calendar & Clock but I didn't have much luck with booting and programming the CH32V203 board. I am no expert on how to do this. So I reversed engineered the code to Circuit Python and put in on the Huz/zah ESP32 V2 board. I also wanted some color and used the 1.54" 3 color e-ink display. I don't have a 3-D printer so I cut a strip of plexiglass and used a heat gun to put a 45-degree bend so it looks like a paper calendar. Below is my parts list I used to make this calendar.
The code is fairly simple, and I just pieced it together from Adafruit web pages. Granted I could have used WiFi to pull the time down and I may but for now I wanted to get used to playing around with DS3231 board. I used a wire wrap pen which you can get off of Amazon fairly cheap. I've added the code here as well. I am just a NOOB to programming and mostly hack at it to get it working. If you find this helpful, great. It was a fun little project.
- Huz/zah ESP32 V2 Feather ID 5400
- Adafruit EYSSPI Flex Cable 50mm ID 5462
- Adafruit EYESPI Breakout Board 18 Pin Connector ID 5613
- Adafruit 1.54" Tri-Color eInk / ePaper Display 200x200 with EYESPI ID 4868
- Adafruit DS3231 Precision RCT Breakout Board ID 3013
- STEMMA QT / Qwiic JST SH 4 pin Cable 50MM ID 4399
- Rainbow Wire Wrap ID 4730
- Black Nylon Machine Screws and Stand offs M2.5 ID 3299
Wire connection table
EYESPI connector --> ESP32 V2
- VIN ---> 3v
- Gnd ---> Gnd
- SCK ---> SCK
- MOSI ---> MOSI
- MISO ---> MISO
- DC ---> TX
- TCS ---> RX
- SDCS ---> Pin 33 *
- SDCS ---> Pin 27 *
Note: * I will comment, and maybe someone could tell why but Pin 22 and 37 are not in the code but without them the display would not update. So I am guessing the pins are either floating or pulled to ground.
-
Option Map: Powering your circuit Wired solutions: DC adapters & USB PD
High-power: DC adapters
Regulators built into most microcontroller development boards typically cannot supply much current. A common solution is to use an DC power adapter (barrel/terminal blocks):
Some interesting options to take note of:
Regulators tend to come in 3 flavours:
- Linear regulators: Fed from a higher voltage. Typically less efficient than their "switching regulator" counterparts. Typically powered by another (higher voltage) regulator such as a DC power adapter.
- Step-down ("buck"): A switching (voltage) regulator fed from a higher voltage. Typically powered by another (higher voltage) regulator such as a DC power adapter, but can also be driven by a battery.
- Step-up ("boost"): A switching (voltage) regulator fed from a lower voltage. A useful tool to generate higher voltages on devices that aren't normally expected to need them. Commonly used in battery-driven applications where you cannot (don't want?) rely on batteries to generate the high voltages needed.
🧠️Smart load sharing
Some solutions include "smart load sharing". As with everything, not all "load sharing" is created equal, but will tend to implement the following current/power management features:
- Simultaneously power your project while charging.
- Redirect excess current to charge battery when plugged in.
- Avoid unnecessary battery charge/discharge cycles +extending battery life.
- Can be used without a battery being connected.
- Live disconnection of battery or main power source *without losing power.
- *Check product specs to make sure this is actually supported.
- Otherwise: glitches could result in unreliable power or unsafe conditions (damage circuits).
Watch this Adafruit product video (1000C) for further explanation.
Portable solutions: batteries & solar
At the time of writing, there are 4 popular solutions to power portable projects:
- Non-charging: converting battery voltages up ("boost") or down ("buck") to something better suited for your project.
- "Just charger": Separate battery chargers. Won't directly power the project, but used to complement "non-charging" solution.
- USB-fed battery chargers: Not only can your project be powered by a battery, but some options allow that battery to get charged up automatically when connected through a USB port. This is what happens inside most cell modern phones.
- Solar-capable battery chargers: For even more autonomy, some options allow the connection of solar cells. Many solar capable solutions also allow for safe USB battery charging even when connected to a solar cell. Note that not all solar-capable chargers allow safe charging on USB, and so choosing the right might require some additional investigation.
-
Calibrate Your 3D Printer for Dimensional Accuracy If you want to 3D print press-fit or snap-fit project enclosures, there are a few tricks you can use to get better dimensional accuracy. Unless you print in an extremely dry climate, it helps to dry your filament. You can also calibrate your printer's motion system, filament extrusion, and X-Y hole/contour compensation.
Drying Your Filament
FDM 3D printers work by melting plastic filament and carefully extruding it layer by layer to build up the desired shapes. Filament absorbs water from the air, and manufacturing filament involves a water cooling step. Wet filament can break more easily, and it can cause bubbles and stringing. Keeping your filament dry helps to get stronger prints with a smooth surface finish.
How Dry is Dry Enough?
People have lots of opinions about drying (for example, see r/3dprinting on reddit). For me, starting prints with filament stored in a plastic cereal box at 15% relative humidity has been working great. No bubbles. No splattering. Very little stringing.
How To Dry Filament?
For filament that's relatively dry to begin with, you just can put it in an air-tight plastic box with silica gel desiccant packs. In my experience, a plastic cereal box with about 50g of silica gel packets can take a roll of PLA filament from 25% to 15% relative humidity in less than a day. Starting at 15% out of the cereal box, if I print for a few hours in a room that's about 30% to 40% relative humidity, the hygrometer in my dry box usually reads 20% to 30% when I put the roll away. Within a few hours, that goes back down to 15%. But, it's important to note that silica gel can only absorb so much water before it needs replacement or drying, so this approach might not work well in humid conditions.
For new filament, or filament that's been stored in anything other than crispy dry conditions, starting with a filament dryer may be quicker than relying on silica gel alone. Many makes and models of filament dryers are available, with new models introduced fairly often. To see what people currently recommend, you could check r/3dprinting on reddit.
For new filament, I've been using a Sunlu FilaDryer S2 that I bought. The S2 works fine as long as I prop the lid open slightly (5mm to 8mm-ish gap). Typically, in 6 hours or less, the dryer will get a new roll of PLA filament down to about 25% relative humidity, but then it stops getting drier. From there, I put the roll in a cereal box with desiccant, wait a while, and it goes down to 15%.
Upgrading Your Printer's Firmware
Upgrading your printer's firmware to the latest available version may result in improved print quality compared to the factory firmware. How to go about a firmware upgrade will depend on what type of printer you have. For example, the Bambu Lab wiki has a page, Firmware update guide for P1 Series, that explains how to update the Bambu Lab P1S.
Calibrating Tool Head and Print Bed Movement
FDM printers use stepper motors with belts or drive screws to move the tool head and the print bed on 3 axes (X, Y, and Z). The stepper motors are controlled by the printer's firmware, which takes G-code instructions from a slicer (Bambu Studio, Cura, etc.). Calibration can help the motors move accurately, repeatably, and without problematic resonant vibrations.
Typically, printers will provide some way to make sure the bed is level and to calibrate stepper motor motion. Calibrating the motion system can help to avoid problems with waves in the surface of printed parts. Bed leveling helps with good first layer adhesion, avoiding warping, spaghetti prints, and various other problems.
How motion calibration and bed leveling works depends on what kind of printer you have. My printer is a Bambu Lab P1S, which I bought. The P1S uses a Core X-Y design with automatic bed leveling. Since bed leveling is taken care of automatically, I can pretty much ignore that part.
For calibrating the motion system to avoid problems with vibration and belt tension, the P1S has a calibration feature available in the menu system on the printer's LCD control panel. I did that when I first set up the printer. It made a bunch of noise for a while, but was otherwise unremarkable.
Calibrating Filament Extrusion
To extrude the right volume of filament so that each line your printer lays down will merge smoothly into the previous lines, without gaps or bulges, you can calibrate the extrusion of your filament. Extrusion calibration is complicated. Terms people often use to talk about it include over extrusion, under extrusion, K factor, and pressure advance. Options for calibrating different aspects of the extrusion process vary according to the model of your printer and which slicer software you use.
In the Bambu Studio slicer software, the Calibration tab offers two types of extrusion calibration, Flow Dynamics Calibration and Flow Rate Calibration. According to the Bambu Lab wiki, Flow Rate calibration is typically not necessary, so I ignored that one. But, the wiki recommends doing a Flow Dynamics calibration to set the K factor for new filament. I did a Flow Dynamics calibration for the filament I've been using (Bambu PLA Basic), and came up with a K factor of 0.02. I didn't notice much difference compared to the factory settings. The top surfaces of my prints seemed pretty smooth before and after the calibration.
Calibrating X-Y Compensation
In my experience, this is the really useful part for improving dimensional accuracy. Once you know that your filament is dry, your motion system is working well, and your extrusion flow is reasonable, it's time to check your X-Y hole and contour compensation. By printing a test block, measuring it, doing a little math, then setting the X-Y compensation values, I was able to improve my dimensional accuracy from about ± 0.12mm down to about ±0.5mm. That seems to be good enough for making press-fit bearing mounts without too much of wasted test prints.
In Bambu Studio, under Prepare tab > left sidebar > Process heading, you can turn on the Advanced process settings option. When you do that, it enables input fields for "X-Y hole compensation" and "X-Y contour compensation" under Process heading > Quality tab > Precision sub-heading.
To determine X-Y compensation values, you can print a test block, measure it with calipers, then do some simple math. Note that, similar to flow rate K factor calibration, your results here will likely be specific to the particular filament you're using and how dry it is.
-
MyState: Be one with the electronics universe 🧘♀️Ω🧘♂️. Collaborate. Interoperate. Overview
The
MyState
library delivers a framework to simplify configuration and control of appliance-like devices.MyState
makes it quick-and-easy to define device state that is readily controllable from the outside world.Writing code to control state and react to sensor inputs is time consuming. Why not (mostly) solve the problem once, and re-use that infrastructure to build up your next project faster?
Features
- Route raw sensed input signals through custom signal-generating filters, and provide a solid, uniform user-interface experience.
- Load custom device configuration/controlled state on startup by calling
ListenerRoot.script_load()
.- A good way to "recall presets" at the press of a button when manual configuration is a bit of a pain.
- Let anyone control your device using
SigLink
interface (by means of a serial/other IO connection).- Ex: Let a PC control your device using
MyState
"signals" sent across the USB/serial connection. - Configure your device using a custom-built GUI or web interface.
- Ex: Let a PC control your device using
- Applies more formalized (hopefully readable) patterns of "filtering" input/sense signals, and applying a "reactive paradigm" to respond accordingly.
- Aspires to enable a future of composable, modular devices where extension/customization is the norm. Getting our products to cooperate should not be a constant battle requiring mounds of ugly hacks.
✨Highlights
- Call
SigLink.process_signals()
to enable quick-and-easy device control via serial/IO connection.
Details
The framework provides access to device state using something the author calls a "Model-React-Controller" (MRC) -- analogous to a Model-View-Controller.
Code Repository
- Development repository on github: MyState.
- Project examples (self contained): HomeLights_Wired. --- Download:v0.1.
SampleProj: HomeLights_Wired
-
Adafruit I2S MEMS Microphone Breakout: CircuitPython Wiring & Test Working with I2S audio input to your project can be daunting, but the CircuitPython_PIO_I2S library helps with the heavy lifting.
This guide is limited to devices supporting a compatible processor RP2xxx such as the Raspberry Pi Pico and Raspberry Pi Pico 2. Python support via Adafruit_Blinka is not supported at this time.
CircuitPython Microcontroller Wiring
Here is how you'll wire your I2S MEMS Microphone breakout (in this case, SPH0645LM4H) to a Raspberry Pi Pico (RP2040):
-
Science + Fiction = Fun! UPDATE! I discovered the "drake.py" file in my github was NOT the program I describe here. I re-wrote the drake.py program and have replaced it in the archive.
I enjoy the prospect of SETI, the Search for Extraterrestrial Intelligence. So it's only natural that I'd like to do something with the Drake equation "... the probabilistic argument used to estimate the number of active, communicative extraterrestrial civilizations in the Milky Way Galaxy." (https://en.wikipedia.org/wiki/Drake_equation)
Happily I found an example of coding this calculation (https://github.com/DeaconDesperado/pydrake) that I could adapt for this project. I've put the code in a repository "Drake"
Files
- drake.py - calculate the Drake equation- based on https://github.com/DeaconDesperado/pydrake
- sagan - Carl Sagan quotes
- wise.py - selects quotes to display
- ncount.py - used for blinking neopixels
- prt.py - allows prt() to print to REPL or HID keyboard input
Copy the files to your NeoTrinkey running (renaming drake.py to "code.py").
Touch pad#1 for the NeoTrinkey to calculate and print out the estimate - since the factors are coded as ranges, you will get different answers every time. After presenting the calculations, the program will also give a random quote from Carl Sagan - he describes the Drake equation in chapter 12 of his book "Cosmos." This is the "Science" part of my project
For fun, touching pad#2 will give a list of the names of the civilized planets - basically generating a random name for as many as the program calculated (plus Earth). Be aware that the number can be large and this will take a while. And yes, this is the "Fiction" part. :)
Change REPL=False to REPL=True to have output go as if typed via the keyboard.
Output looks like this:
How Many Alien Civilations?
Number of stars in the Milky Way 1e+11
Fraction of stars with planetary systems 0.131585
Number of planets suitable for life 4
Fraction of suitable planets that develop life 0.283515
Fraction of life that becomes sentient and eventually intelligent 0.118758
Fraction of intelligent life that advances to the point of communication 0.0128657
Adjustment for incidence of self-destruction 1.10132e-06
possible number of civilizations 25
Who are we? We find that we live on an insignificant planet of a humdrum star lost in a galaxy tucked away in some forgotten corner of a universe in which there are far more galaxies than people. Carl Sagan
1: Earth
2: Gieuas
3: Zoiah
4: Syoei
5: Mieud
6: Zoafas
7: Syan
8: Theuei
9: Kieei
10: Zoghie
11: Syaie
12: Syafnk
13: Zoyah
14: Paeah
15: Miiah
16: Miuof
17: Reaah
18: Ahghd
19: Aheei
20: Giafn
21: Reud
22: Kiyah
23: Kighn
24: Theie
25: Miud
26: Kieuof
Hope you have fun with this - may it give you something to ponder as you look at the night sky.
The Drake Equation -
Do You Want to Make a Starship? I'm not talking about an ill-named monster rocket booster, but honest-to-goodness STARSHIPS! As Wikipedia puts it:
A starship, starcraft, or interstellar spacecraft is a theoretical spacecraft designed for traveling between planetary systems.[1] The term is mostly found in science fiction.
https://en.wikipedia.org/wiki/Starship
I've certainly not got the resources to make such a vehicle... but what if you could build a really small spacecraft? Say, like this?
This was my inspiration to make a "Starship" on my NeoTrinkey - a simple spaceship program. My "ship on a chip" defines the decks of a ship and a set of potential destinations.
I've included it all in a github repo "Ship on a Chip"
- What IS a "starship?" :https://en.wikipedia.org/wiki/Starship
- Inspired by https://en.wikipedia.org/wiki/Breakthrough_Starshot, https://www.scientificamerican.com/article/inside-the-breakthrough-starshot-mission-to-alpha-centauri/
- trekdecks uses Enterprise deck as found at: https://memory-alpha.fandom.com/wiki/Constitution_class_decks
- Galaxy class decks: https://memory-alpha.fandom.com/wiki/Galaxy_class_decks
- Defiant class decks: https://memory-alpha.fandom.com/wiki/Defiant_class_decks
- Intrepid class decks: https://memory-alpha.fandom.com/wiki/Intrepid_class_decks
- trekdests Destinations used: https://exoplanets.nasa.gov/news/1378/top-10-star-trek-destinations-chosen-by-nasa-scientists/
- exodests from https://en.wikipedia.org/wiki/List_of_nearest_terrestrial_exoplanet_candidates
- sspythondecks created for a simple example
- Copy the files wise.py, prt.py and shipchip.py (as code.py) to neotrinkey.
- Copy a "dests" file (trekdests or exodests) to neotrinkey as "dests" (or create your own set of destinations)
- Copy a "decks" file (trekdecks or sspythondecks) to neotrinkey as "decks" (Or create your own list of decks and dests.)
Change REPL=True to REPL=False if you want output to be "typed" via HID interface.
Change showdecks = False to showdecks = True if you want the decks to be listed on start.
Touch pad #1 to go "up" a deck and pad #2 to go down - holding both jumps to a random deck.
Files:
-
shipchip.py - ship on a chip - copy to code.py
-
prt.py - copy to neotrinkey
-
wise.py - copy to neotrinkey
-
exodests - rename to dests for use
-
sspythondecks - rename to dests for use
-
trekdecks - rename to decks for use
-
trekdests - rename to dests for use
When run, you'll get a message "Welcome aboard" - and you begin on "deck 1" - usually the bridge. A random destination is chosen and after a random number of steps up and down in the turbolift you "arrive" and a new destination is chosen.
Looks like this:
Welcome aboard!
Ship destination is: Remus
You are on deck: 1 Bridge
You are on deck: 2 Science labs
You are on deck: 15 Deuterium fuel storage
You are on deck: 14 Engineering support, water storage
You are on deck: 13 Observation deck, dorsal interconnects
You are on deck: 14 Engineering support, water storage
You are on deck: 1 Bridge
Arrived at Remus
Ship new destination is: Nbiru
You are on deck: 2 Science labs
Make up your own ship with a list of decks in the "decks" file and destinations in the "dests" and you've got your own starship!
How's this for a starship? -
Ringing Tibetan Bowl Timer I replaced the electronics (which had died) in this product from Now and Zen. Original Product
Here is a link to the video where I talk about it. Video
Due to severe RSS, I coded all of this with Talon Voice. There are lots of things I would do to clean up this code (remove globals, clean up use of enums), and given how hard it is to code with my voice, I'm going to leave it as is.
-
Wii Nunchuck USB Adapter I have a confession to make: I don't love playing video games with a keyboard. While the keyboard/mouse combo is the preferred input method for most PC gamers, I find my left hand often gets cramped using WASD-based keyboard input, and wish for a more ergonomic input method sometimes.
I had an idea to make a simple adapter to map Wii Nunchuck input into keyboard events a game would recognize. I figured I could map the Nunchuck's analog stick to keyboard events for movement, and could map the two digital buttons on the Nunchuck to other keys while I was at it.
This setup would allow me to use the Nunchuck to partially or entirely replace input from my keyboard.
Overview
This no-solder adapter is built with either a QT Py RP2040 or a Trinkey QT2040 microcontroller, coupled with a Wii Nunchuck breakout board connected by a Stemma QT cable. The firmware, written in CircuitPython 9, translates Wii Nunchuck analog stick and button events to keyboard events. Thanks to CircuitPython, customization is easy, allowing you to make changes to the generated key events any time. So far, I have used this adapter for games like XCOM-2, FTL: Faster Than Light, and Half-Life 2!
I've included 2 build variants here, one for those with access to a 3D printer, and one for those without. The QT Py build uses a 3D printed case for mounting the QT Py and the Nunchuck breakout board. The Trinkey QT2040 build takes advantage of the identical screw hole placing on the Trinkey and the Nunchuck breakout adapter board, using a handy standoff mounting kit to make a nice tidy little USB-A adapter.
-
ESPTOOL-JS with Partition Table listing + Data saving - Easily backup your device before installing circuitpython/whatever I'm often wanting to list what's on a device in terms of partition table. There's a handy utility included with the ESP-IDF, but it's python only and it only accepts files so you have to first call esptool to save your partition table data. I've had to do it so often that I've saved the two commands in another playground note, but not any longer!
The other thing is I swear that there used to be some online place to download your devices flash for backup using web serial, but try as I might I cant find such a place, and my google-fu is usually on point - ignoring my switch to duckduckgo...I digress, introducing my latest possibly needless project, esptool-js "partition edition":
How to use it?
Well, the image above shows after I've clicked the Read Partition Table button. The default partition offset of 0x8000 should be fine for most boards, otherwise try 0x9000, although custom partition table offsets are supported. You won't even see those options until you've clicked Connect and selected your boards serial port.
Once your partition table has loaded it shows the expected information, the bit most people are usually interested in is the first app partition, or ota_0 in this case, and the user file system (user_fs), which is a FAT partition in this screenshot.
The final column in the table has the download button for each partition, clicking it will start reading from the flash memory of the connected device, and once finished will ask the browser to download it. It will be named according to the chip name, partition type, starting offset, and size in bytes, but all the numbers are in hex not decimal.
-
Tiny Terminal with a Magnetic Connector Those nice magnetic connectors (four pins) were waiting to be used in a project, until now.
I needed a way to peek in on a UART serial stream, but did not want to have a full laptop along for the ride. So I made what is not that different from those old DEC VT-200 terminals.
An RP-2040 to listen to the UART and send the text to the tiny Monochrome 0.96" 128x64 OLED Graphic Display.
The Circuitpython code is simple with a just a bit work to get the all the previous line of the terminal display to move up.
So I use of this for a project that logs data, sent out a UART (as well as to an SD card). Wire the UART to a mag connector, in my case I put Power and Ground on either side while the TX and RX pins are in the middle, but there's not really a standard (until now ;).
Here is code for the monitorand then it pretty easy to add code to any logging project to (also) send Serial Data out on a UART TX pin. I also wired up (optional) 5 volt power and (not optional) ground.
TBD add fritz diagrams, images and more code... -
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 useesp.connect_AP()
and instead of usingwifi.radio.connected
you check the connection state withesp.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 maincode.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. Usingresponse.iter_content()
directly is a workaround to speed up processing (this also helps native WIFI a bit and Airlift too). -
Guide: Zapper Lights/Sound mod If you grew up with a Nintendo Entertainment System, you probably remember playing games like Duck Hunt that used the Nintendo Zapper "light gun". The Zapper used a clever technique that depended on the game being displayed on a Cathode Ray Tube, or CRT television. These days, CRTs are rare, and are often prized collectors items among retro gaming enthusiasts. Since these Zappers don't work on modern TVs, most people don't have much use for them anymore. So, why not convert it into a toy/prop that lights up and plays sounds?
Overview
This project uses a Prop-Maker Feather RP2040 to repurpose the the Zapper's iconic shell and clicky trigger mechanism into a prop/toy that uses a NeoPixel for a "muzzle flash", a speaker to play sound effects, and 3D printed parts to contain the electronics. The code is written in CircuitPython, and sounds can be changed or added by dragging and dropping files with no code changes required!
-
PC media remote Program your device
Installing CircuitPython environment
- Download .uf2 file here:
- Plug in USB cable from PC to RP2040 board while holding the BOOTSEL button.
- A new drive should get mounted on your system.
- Drag/drop downloaded .uf2 file onto newly mounted drive (RPI-RP2).
Installing libraries and project code
From "CircuitPython Library Bundle" (download here):
- Copy from bundle .zip file to the microcontroller [drive:]\lib\ folder:
adafruit_hid
From the PCMediaRemote release page (download here):
- Download and unzip the "Source code (zip)" file from the "Assets" section.
- Copy the "unzipped" custom project code to microcontroller [drive:]:
- [PCMediaRemote folder]\lib_cktpy\* => [drive:]\lib\
- [PCMediaRemote folder]\pkg_install\MediaRemote_RP2040\*.py => [drive:]\
NOTE: Feel free to check for newer versions of PCMediaRemote on the releases page. Code from the main branch might also be functional, but explicit releases are less likely to have issues.
Customizing your solution
You can directly modify the main.py file on the [drive:]\ folder. Every time you save the file, CircuitPython will restart with the updates applied.
Note that if the file gets corrupted for some reason, your changes will be lost. It is recommended to work from a folder on your PC, and manually upload (ex: drag/drop) the changes to the CircuitPython drive.
Overview
A media remote receiver for your PC/MAC/thing supporting keyboard media keys.
- Also works with many smart TVs and phones.
- Flexible CircuitPython-based solution can easily be adapted to other microcontrollers/IR remotes.
- Built-in IR signal decoder utility on serial monitor output.
- An easy, inexpensive, solderless build! (if desired)