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.
-
Serial Programmer for ESP32 If you've ever worked with the ESP32, you'll know that it does not have native USB. Most ESP32 development boards will include a USB to serial converter chip, like the CP2102N that you'll see on the Feather ESP32 V2. If you're working with a bare ESP32 though, or maybe doing some reverse engineering, what do you do?
Parts
I was in this position for a project I'm currently working on. I'm doing some reverse engineering on the Yoto Mini player, which uses an ESP32. I needed to access the chip over serial for programming and it would need to be repeatable. I wanted it to be non-destructive to the board yet stable and to use parts that I already had in my parts bin.
I decided to solder up the programming circuit to a 1/4 size perma proto that I could plug in a USB serial/FTDI cable. You don't need an FTDI cable here, you could just use a USB to TTL Serial Cable, but I always keep the FTDI cable in my desk drawer.
-
A mini-IBM PC Using an Adafruit Fruit Jam My affinity for IBM PCs, starting with the first IBM PC 5150 is fairly well known in Maker circles. I have had several PCs now over the last few years but had pared back to one PC 5150, one XT 5160 and one AT 5170. Now that has changed, as I have a new PC, which I built. This one is considerably smaller than the others, and so much lighter in weight (it is definitely not a boat anchor).
I present my mini-IBM PC. It bears a striking resemblance to its big sister (background, to the right below), thanks to 3D printing. And the code emulates a PC up to a 386 class machine. I'll show you the details in this guide.
This build has some modular features, so you do not have to build all of the pieces shown. Possible builds:
- With all the features shown including the base system and monitor.
- Just the base system, use your own monitor.
- Optional parts of the base system include the LEDs on the front, the IBM joystick adapter and even the on/off button on the side if you wish.
- Use any USB keyboard you like.
You can start with the base system and build it up how you wish.
The project is open source under an MIT License.
Parts
-
Home Hub - Door and Window Sensors Introduction
I got burned buying into the Google security ecosystem a while back and promised myself to never do it again. Plus now I know exactly what all the pieces of our home monitoring system are doing and where they're communicating. Easy upgrading too!
All other sensors will use the same code base and construction.
Design
The sensor is coded in CircuitPython
The current case is the snap fit case provided by team Adafruit. There will be a smaller case for the sensors mounted on doors and windows.
You will need an MQTT broker for all of this to work together. You can use Adafruit IO.
In my implementation I set up a Mosquitto MQTT broker on a RaspberryPi 4 Model B running Debian Bookworm and Mosquitto v2.022.
The first sensor built and put into use is for the garage door
Our house has a detached garage. The opening for the garage is perpendicular to the house which is good for esthetics and access, bad for knowing if the door is open.
Parts
Code
Sensor
The code for this project can be found on Github.
It is one part of the larger home monitoring project.
The following libraries are required:
- os
- time
- board
- digitalio
- wifi
- adafruit debouncer
- adafruit minimqtt
- adafruit minimqtt
- adafruit connection_manager
- adafruit logging
Feature Highlights
- When the door is open the sensor publishes a 1 to monitoring.garage-sensor
Node-Red subscribes and will
- Change the indicator on the sensor page; red - open, green - closed
- Change the indicator on the home page; red - open, green - closed. Since we often reference if the door is open or closed, having an indicator on the home page saves having to switch tabs every time we want to know the state of the door
Node-Red
I have a flow dedicated to handling sensor data.
Configuration
Add an MQTT in node and configure it to subscribe to the topic for the sensor. For me it's monitoring.garage-sensor.
After that you'll need to connect it to a UI LED node that will take action based on the message payload.
I have three functions in my flow, two are disabled and will be used when traveling. The active function will generate an email when it's past a certain hour and the garage door is still open.
To build the function nodes, you will need some familiarity with Javascript. Word of caution, there are some differences between Javascript and Javascript within Node-Red. I had to narrow a few searches to get some of the answers I initially needed.
The code in the function for sending a notification looks like this:
context.data = context.data || {}; switch (msg.topic) { case "monitoring.garage-sensor": context.data.garage = msg.payload; msg = null; break; case "home.hour": context.data.hour = msg.payload; msg = null; break; default: msg = null; break; } if (context.data.garage != null && context.data.hour != null) { if (context.data.hour >= 20 && context.data.garage == 1) { var newMsg = { "topic": "Your Attention Needed" ,"payload": "Garage door is open" } } } return newMsgTo receive email, you'll need to have an MTA. I have a secondary Gmail account that I'm using to send mail.
Project Construction
Circuit Board
- Solder breadboard jumper wires to the earth and data pins.
- Connect one side of contact switch to the jumper wires
- Using the snap fit case, secure the QT PY, ensure the jumper wires are hanging outside the case, and close the case
Installation in the Garage
I used Uglu Dashes to secure the magnets to the side of the garage door and to the frame. It's been there now for over 6 months without issue. I did clean both areas with rubbing alcohol before applying the Uglu.
-
Home Hub - Motion Detector Introduction
The motion detector will be deployed alongside the driveway camera.
It can be used anywhere you'd like to track and report on motion.
Design
Code is written in CircuitPython.
Your infrastructor will need to include:
- MQTT - you can use AdafruitIO or build your own. In my implementation I set up a broker on a RaspberryPi 4 Model B running Debian Bookworm and Mosquitto.
- Node-Red - my Node-Red journey is chronicled here.
All MQTT information, including feed names, are stored in the settings.toml file.
Parts
Code
Motion Detector
Home hub projects are all in this parent project.
Here you'll find the motion detector code.
Libraries Required
import os import time import board import digitalio import wifi import adafruit_minimqtt.adafruit_minimqtt from adafruit_minimqtt.adafruit_minimqtt import MMQTTException import adafruit_connection_manager import adafruit_logging
Featured Highlights and One Lowlight
- Loads all configurations from settings.toml
- Notifies devices on network when motion is detected
- Suspends sending motion events when recording is in progress
- Does not utilize secure connection for MQTT broker, I have been unable to successfully connect using certificates. Even followed the solution that worked on an ESP32 a last year with no success. Instead uses a special MQTT user that has access restricted by ACL until I can get encryption working.
The TL;DR Nuts and Bolts
The sensor will subscribe to:
- monitoring.recording
The sensor will publish to:
- monitoring.motion-detect
When the sensor detects motion it will publish to monitoring.motion-detect which will trigger the camera to start working
When sensor receives a message on monitoring.recording that recording has begun, it will enable recording mode and will not send any motion detection events
When the sensor receives a message on monitoring.recording that recording is complete, it will disable recording mode and will begin sending new motion detection events
You will need a local MQTT server or Adafruit IO in order to record and display sensor data.
Currently implemented actions based on motion detection
- Driveway camera: when motion is detected will take a snapshot and record a 30 second clip
- Entryway or trellis lights: when motion is detected will stop the current running animation and set the lights to solid white
Case
I used OpenSCAD and the YAPP Box (Yet Another Parametric Project Box Generator) library from mrWheel. This library is well documented and has a lot of features.
Node-Red
All sensors share the same flow in Node-Red
Node-Red subscribes to the monitoring.motion-detect feed. When a message is received it will update the UI LED node to be either red (motion detected) or green (all clear).
-
Home Hub Project with Node-Red-Dashboard Introduction
When we moved into our new home I started planning how I wanted to handle sensors and LED lighting projects. I needed a place where I could manage motion, window and door sensors, Raspberry Pi cameras and doorbells, and LED lighting projects.
Design
First step, identify a way to see all the data once I started collecting it. I began by using Adafruit IO. However, as I thought more about what data I was going to be sending and how I wanted to access to that information and dashboard for others, I didn't want it to be public in any way. So I chose, instead, to built a Raspberry Pi 4 based Mosquito MQTT server.
Beside sensor and camera data, I wanted a way to control any LED projects, and I wanted a hub feel where data including date, time, shared calendar events, and weather data can be easily viewed.
After fumbling around a few different options for viewing MQTT data; I landed on Node-Red.
Here's a screenshot of what it looks like.
What is Node-Red
From their website, Node-Red is:
Low-code programming for event-driven applications
I'm definitely not a Node-Red expert, however, what I've learned and implemented so far has yielded results more than I expected. I quickly found modules for communicating with my MQTT server and my WLED LED nets/Sparkle Motion board.
I have Node-Red running on the same Raspberry Pi as the Mosquito MQTT server. Set up was well documented and went smoothly. Right now the service is not exposed outside of my home network so I haven't implemented HTTPS and other security features. It's on the to-do list.
I'm not going to get into the how-to portion of Node-Red, but I will be showing some of the flows I have and providing detail on how I implemented things. Where I provide more detail I will try to include examples from the configuration of buttons, button groups, and functions. In my search for information as I learn, I'm finding a lot of pictures of flows without understanding what's actually happening under the hood.
Once configured, Node-Red runs a webserver and any device can connect from their browser of choice. Node-Red also handles different display sizes so it works on your phone or tablet out of the box.
Things to know before reviewing associated projects that display in Node-Red
@flowfuse Node-Red-Dashboard-2 provides the UI elements needed to monitor and interact with devices in your IOT set up.
While Node-Red-Dashboard-2 provides most of the UI elements you will need, for an LED indicator I chose to install the node-red-dashboard-2-ui-led node.
The flow also needs MQTT communications. These are in the node-red package and do not need to be installed separately.
Because I wanted email notifications, in the event the garage door is still up under certain circumstances, I had to install the node-red-node-email node.
Projects
All projects fall under one of three categories at this point:
- Sensors
- Cameras
- LEDs
In Progress
- LEDs: Trellis/Entryway net project
- Cameras: Driveway
- Sensors: Motion detector
Complete
- Home hub
- Sensors: Garage door sensor
- LEDs: Christmas tree and star lights
-
Christmas Tree & Star Lights with Node-Red Introduction
We have a 1960's era aluminum Christmas tree. For the time that we've had it we've relied on newer and slightly less dangerous color wheels, then stage lighting. When we moved we didn't bring any of the lighting with us.
I decided to string the poles of the tree with LEDs.
The prior year I made a star topper which used a Bluefruit for lighting. This year I added 24 LEDs for the star that plug into the highest string on the poles.
Design
The current design is written in CircuitPython. For communication it relies on MQTT and Node-Red.
Everything worked great, however, after I worked on a different LED project that used WLED, I think I'll convert this project to WLED. I'm not going to delete this code base, I think it has some interesting implementation features and is worth preserving.
Infrastructure-wise with either implmentation you will need:
- MQTT - you can use AdafruitIO or build your own. In my implementation I set up a broker on a RaspberryPi 4 Model B running Debian Bookworm and Mosquitto.
- Node-Red - my Node-Red journey is chronicled here.
Parts
Code
Tree & Star
The code can be found on Github
As I was coding this project, I found myself thinking I was going to be reusing a lot of it. So I repurposed an old project and replaced what was there with new helper classes.
I did run into an issue where I could not get the LED Animation library to play nicely with MQTT. I tried a few things, including asyncio, and ended up posting on the forums. mikeysklar came to the rescue and you'll see his contribution in the code.
The tree has 196 LEDs and the star has 24.
data = { 'tree_animations': ['multi_chase'] ,'star_animations': ['rainbow_sparkle'] ,'num_pixels' : 220 ,'tree_pixel_subset': [0, 195] ,'star_pixel_subset': [196, 24] ... }Libraries Needed
import json import board import time import os import neopixel import adafruit_logging import wifi import supervisor import adafruit_connection_manager import adafruit_minimqtt.adafruit_minimqtt from adafruit_led_animation.group import AnimationGroup from adafruit_minimqtt.adafruit_minimqtt import MMQTTException from adafruit_led_animation.sequence import AnimationSequence from adafruit_led_animation.helper import PixelSubset from circuitpy_helpers.led_animations import animationBuilder from circuitpy_helpers.led_animations import controlLights from circuitpy_helpers.led_animations import updateAnimationData from circuitpy_helpers.file_helpers import updateFiles from circuitpy_helpers.calendar_time_helpers import timeHelper from circuitpy_helpers.network_helpers import wanChecker
Featured Highlights
The tree subscribes to the following MQTT feeds:
- tree.lights - listens for events from Node-Red to update animation, start time, stop time
- home.time - listens for events from home hub in order to know when to stop or start the lights
- home.sunset - listens for events from home hub in order to know current sunset, uses this for start time
In order to take events from tree.lights and actually change the running animation and colors, I needed to be able to do a couple of things:
- Have a list of supported animations - this is done via the animations.json file
- Be able to override the default values for animations
- Be able to on-the-fly update the data file to implement the new animation/colors choice
When the code first starts it will check if there are overrides for the chosen animation and do an in-line replacement of those values. It will then check to see what the color selection is. Color choice is specified in the animations.json file and can be:
- random - a random color will be selected
- data - in the data file, for each animation is an entry for color. A string representation of the color can be provided or a the name of a color_palette.
Once up and running, about every 30 seconds, the animations will pause long enough for the code to query MQTT for any updates. If a new message arrives the code will update the data file with the appropriate information and perform a
supervisor.reload().You can also change the start and stop times or disable them so that the lights will run continually.
When using start and stop times; when the criteria is met to do either, the code will light sleep until the alarm is met.
Case
I used OpenSCAD and the YAPP Box (Yet Another Parametric Project Box Generator) library from mrWheel for the Feather case. This library is well documented and has a lot of features.
I found a star on Thingiverse years ago and downloaded the SCAD file. I re-mixed it for my own needs. Unfortunatly now I cannot find the Thing anymore. If you recognize the code as yours please let me know so I can give you proper credit.
-
Show And Tell: A self contained Circuitpython WiFi enabled Ultrasonic Water Flow Sensor! Post I was recently able to get this project working with a UFM01 ultrasonic water flow sensor from ScioSense https://www.sciosense.com/ufm-01-ultras ... ng-module/ (available from Digikey and Mouser for about $37) and an old Metro ESP32-S2 I had laying around. There is a recent Arduino library for the sensor, but I wanted to try it with Circuitpython. The ultrasonic sensor was a huge improvement over the Hall Effect pulse counter sensors I had been using, as they would frequently clog, and Circuitpython isn't as good with interrupts as Arduino.
The sensor itself communicates over UART to a hardware Serial port of the ESP32 (I chose IO5 and 6, as it lined up with my existing Arduino R4 shield). It sends out a BCD hex string with the serial number, flow volume, rate, and -bonus- water temperature, which can be parsed out and displayed on the serial REPL.
Once that was working, it was on to a WiFi enabled interface. The sensors are located away from any wireless networks, so the ESP is set to Access Point (AP) mode, and the user can connect to it as one would any other wireless network (192.168.4.1 and password). Security was not a major factor, so the password was kept simple. The measured parameters are displayed on a web page to either a laptop or cell phone, as well as the max flow rate (the water is pumped through the sensor, so I use it to gauge the pump health). It took a bit to get a reset button working, but the button now resets the accumulated flow logged in the sensor. (the total flow volume remains stored in the sensor's memory after removing power).
I know the styling of the code does not use the standard settings.toml file, but can be modified if needed. The attached code.py and ufm01-circuitpython.py files are all that are needed beyond the stated includes from the adafruit bundle. It is currently working on the ESP32-S2 Metro board; you can try other WiFi enabled boards and tell me how that works.
This is a project ported from the Arduino platform, and has the advantages of much faster changes than re-compiling and downloading, especially if you just need to make minor changes. The Arduino project had the code derive a unique SSID based on the ESP32's MAC address, but I kept it simple here. Most of the code length is for the web page display and controls.Technical notes: The nature of the ultrasonic sensor is that the elements need to be immersed in water. The sensor will throw an error code if no water is present. Be sure to place is in a way that it stays full of water when any is present, like a P-trap or similar. I have mine placed above a pump's check valve.
ScioSense has a good writeup in their data sheet online. I was very happy to see an affordable and easy to implement ultrasonic flow sensor, as the turbine types I had been using would clog constantly due to small debris in the pump discharge.
The only issues I have had with these sensors are: 1: There is no reverse voltage protection diode, so either add one or be very careful when hooking it up. 2: The point where the wires enter the potting compound on the sensor is weather proof but not water proof. If the sensor is immersed in more than about a foot of water, water will eventually seep in and render the sensor inoperable.
There is also a 1-wire version of the library that uses the brown wire (seen unused in the picture). When I was working with the factory tech support (before the Arduino library came out), it was not yet supported. It now seems to work, with Arduino support for ESP32 and Mega 2560 platforms. I am testing it with the Arduino R4 Wifi, and have had some issues, which is why I gave the Circuitpython a try.The first python code is a driver that parses the hex BCD output from the sensor. It is called ufm01_circuitpython. The second code has the webserver, etc. This is my first attempt at posting on adafruit-playground.com, so bear with me, and moderators/admin- please feel free to edit this for style and content.
-
Fruit Jam Code Practice Oscillator This is a Morse code practice oscillator for Fruit Jam with super clean sine wave tones and a 3d-printable straight key. The key uses a Kailh Cherry MX compatible keyswitch for reliable switching and flexures to make a precision hinge that works well when printed in PLA. Set screw adjustment lets you shorten the keyswitch travel. The audio output chain uses an
audiofilter.Filterto bandpass filter the output of asynthio.Synthesizerfor smooth note attacks and releases without keyclick.[Update: You can now use Button #3 to generate tones if you'd rather not build the 3d printed mx straight key (2026-01-07)]
Overview
-
Moon Miner Arcade Game for the Adafruit Fruit Jam Moon Miner is a retro-styled arcade game reminiscent of the Lunar Lander arcade game from the 1980s. Your mission is to retrieve minerals from various moons around the solar system. It is a physics-based game, where you must navigate your rocket ship based on gravity and thrust to make a safe landing for retrieving minerals. Achieve a successful landing by reducing speed to near zero and keeping the lander upright on designated flat areas. It is available to play on the Adafruit Fruit Jam.
Features
- The game employs physics to maneuver based on gravity. The game takes into account each moon has different gravitational properties.
- A heads-up display shows mission flight data in real-time.
- Complete the mission of collecting gems and your best time to complete the mission is saved. Play again to beat your best time.
- There are several ways you can die. Make sure you land on a horizontal surface at a safe velocity (and watch out for volcanos).
- Use fuel locations when running low on fuel. Some locations can be revisited again for additional fuel.
- Four missions are included.
- Written entirely in CircuitPython for the Adafruit Fruit Jam.
The full learn guide, including download and installation instructions can be found at the author's web site at https://danthegeek.com/2025/12/28/moon-miner-learn-guide/
-
Newxie Digital to Analog Thermometer A Newxie display is a modern take on the classic Nixie tube aesthetic. It is a 135 wide x 240 tall TFT display with double pins on the bottom for mechanical stability - see the product page link below.
What's a good use for a Newxie display? How about an analog thermometer - you know, the old-school type with a glass tube with red alcohol inside that rises as the temperature rises. Let's build it!
Original Idea
I've been working of building a weather information center using a Fruit Jam and the AdafruitIO Weather Power-up. AdafruitIO provides over 300 hyper local weather data elements updated every 20 minutes. Using it is like drinking from a fire hose, and most boards can only handle a few data points due to memory constraints. The Fruit Jam changed all that - with a 640x480 display and tons of memory, I can now display pages and pages of weather data.
Once I had the horsepower to show more than just text, I started thinking about more expressive ways to visualize the data. I thought that a classic thermometer would be an ideal way to display temperature data. As an added bonus, by adding a narrow stripe inside the main body, I can show a second temperature, such as the "feels like" temperature. Here is how it came out:
On page 1 of the Fruit Jam Weather Center (I'm up to 10 pages so far) it shows current weather data. The thermometer sits vertically along the right edge, with bold tick marks and a clean red column that rises with the temperature. It shows degrees Fahrenheit for the left scale, degrees Celsius on the right side, and freezing is marked in red.
The graphic was built using rounded rectangles from the adafruit_display_shapes library for the outlines and indicators, lines from display_shapes for the tic marks, and bitmap_fonts for the numbers. When all was said and done, there ended up being a lot of display elements to create this seemingly simple graphic.
After all that work let's make it reusable...
With a little effort I converted the text into a separate helper library. The first hurdle was that not all displays are as large as the Fruit Jam. The original was 440 px high but to be reusable it needs to be scalable. Likewise if it isn't going to be as tall I'd also want to be able to customize the min/max values. Ultimately the goal was to make most of the elements customizable. After several iterations I with AI's help, got it working well enough to try it on a different display.
I had a "multi-board" where I have a Feather RP2350 connected to a 240x320 display, an RTC module, a TLV320 DAC, etc., that I've been using to try things out. So, I added an SPA06-003 temperature breakout and added the thermometer graphic:
-
Polyglot - more alien language fun! Rewrite quotes in "alien" dialects using an Adafruit NeoTrinkey! Github repository here
This project is spun off of an earlier one, "Babel" that generates alien language words based on a rule set. The words resemble Wookie, Klingon, Vulcan, Romulan and Mando'a language vocabulary from Star Wars and Star Trek. The words created might actually be words in those languages - but for this program they are created randomly.
A Carl Sagan quote (from the "sagan" file) is selected and printed, and each unique word is assigned one of the generated words, then the quote is displayed "translated" into the alien dialect. NOTE: this absolutely not a real translation, just a fun exercise in generating alien text.
FILES:
- polyglot.py - rename to code.py on the NeoTrinkey Set REPL=True for the output to go to the repl in Mu or Thonny. set to False and the output will be printed as if keyed in on the device the Neotrinkey is plugged into.
- prt.py - helper file to define prt().
- sagan - set of Carl Sagan quotes. Feel free to replace quotes with any words of wisdom you choose.
Touch pad #1 to select and translate the quote
Touch pad #2 to click through the language choices
OUTPUT:
Wookie Klingon Vulcan We are the representatives of the cosmos; we are an example of what hydrogen atoms can do, given 15 billion years of cosmic evolution. Carl Sagan h hi k t'ity kl k rak h hi nii taai kl lta ht kt te niuhl' naito r'k toat kl taahi w'itka niu kot Mando'a If you wish to make an apple pie from scratch, you must first invent the universe. Carl Sagan te 'aa s olj 'eusa eela res oone crl 'e 'aa 'a' yirtt e'' stna elrh arss nthe Romulan Imagination will often carry us to worlds that never were. But without it we go nowherw. Carl Sagan ihmu eif vuu'i efn leelu ei'h na'dh 'isn uhn uuld ane hemf' enk' feiaf levk' hd viefe muehn -
Noisy GIF Player: a tiny portable GIF player with sounds I wanted to make a gift for a family member that should show them animated GIFs, including sounds, of some family moments as a keepsake. I have a ton of family photos and videos and I wanted to allow the recipient to take some of the more memorable ones on-the-go in a little portable battery-powered device that's easy to use.
After a a lot of back-and-forth help on the Adafruit forums, I was finally able to settle on the final design which I then released to GitHub. It uses the following main components:
All the parts are shoved quite densely into a tiny 3D printed enclosure. It's easy to use: press the button to reset the device and a random GIF and WAV start playing. When the GIF is done, the board enters deep sleep, and wakes up again once you reset it.
To load up the GIFs and WAVs in a compatible format, I included a wrapper script for FFmpeg. That guarantees that you can load up media that's compatible. And lastly, I added the ability to hold down one of the buttons to enter a USB mode to transfer GIFs without the need to remove the microSD card.
I learned a few important lessons on the way:
- Rendering GIFs takes a lot more bandwidth and processing power than you might first think. I had to set the SPI bus speed for the LCD to its highest possible setting, way above the default value. Even a little 240x135 screen would show tearing without this.
- IO speed was actually a limiting factor, not the CPU for a while. I initially tried to use an SPI-based SD card reader, but ultimately had to go with one that supported SDIO to get the transfer speeds I needed.
- A design goal was to show the GIF as quickly as possible after pressing the button. I wanted to use CircuitPython, but it turned out to be just too slow at booting up.
- I wanted to cleverly package the components in a way that took up the least amount of space. Fortunately, all the pins on the SDIO breakout would align perfectly to power, ground, and usable GPIO pins. I could do the same with the data pins on the I2S amplifier, although I needed to solder in extra wires to get power. It got complicated because I repurposed the SPI bus's MISO pin as a normal GPIO pin for the I2S amplifier, but that required initializing SPI without MISO, which isn't how CircuitPython worked by default. That led me down a rabbit hole that ultimately added so much complexity to getting it working in CircuitPython that Arduino ended up being easier.
I built a prototype on a breadboard first by soldering on the full headers to all the boards, which turned out to be a good idea when I needed to make updates to the wiring and components to make it work. Once I had it working properly on the breadboard, I then built the real thing using a separate set of components I ordered.
-
Wizard Crystal Scepter / Staff INTRODUCTION
Hey all!
I wanted to share my wizard crystal scepter / staff build, aimed towards renaissance fairs or Halloween costumes.
The majority of this prop is built using 1" PVC Pipe, found at any big box hardware store such as Lowes or Home Depot. There are a few 3D printed components.
Some experience with coding is recommended.
REQUIRED COMPONENTS
1x SPDT Slide Switch https://www.adafruit.com/product/805
1x Button Switch https://www.adafruit.com/product/367
1x RP2040 PropMaker board https://www.adafruit.com/product/5768
1x Lithium Ion 3.7v battery https://www.adafruit.com/product/1781
3 conductor wire (at least 6-7 feet in length)
https://www.amazon.com/dp/B0DMK8HK6R?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1 (or similar)
1x 5ft 1" PVC Pipe https://www.lowes.com/pd/Charlotte-Pipe-1-in-dia-x-5-ft-L-450-PSI-PVC-Pipe/3133093 (Or similar)
1x 1" PVC Pipe Cap https://www.homedepot.com/p/Charlotte-Pipe-1-in-PVC-Socket-Schedule-40-Pressure-Cap-PVC021161000HD/203818100?source=shoppingads&locale=en-US&fp=ggl (or similar)
EVA Foam. I used 5mm thickness.
https://www.amazon.com/dp/B08YXXCG6J?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
EVA Clay foam (Optional but recommended)
https://www.michaels.com/product/modeling-foam-by-make-market-10625195
Rubber Cement https://www.walmart.com/ip/Gorilla-4-Ounce-Crystal-Clear-Rubber-Cement-Bottle-with-Brush-Applicator-Model-105779-1-Pack/105406946?wl13=1885&selectedSellerId=0&wmlspartner=wlpa (or similar)
1x Can of Plastidip https://www.lowes.com/pd/Plasti-Dip-11-fl-oz-Gray-Aerosol-Spray-Rubberized-Coating/50107784
-
Rust on Adafruit RP2040 Feather ThinkInk (JD79661 E-Paper) I wanted to share my experience experimenting with Rust on the Adafruit RP2040 Feather ThinkInk board, specifically using a bare E-Paper display.
Hardware:
- Adafruit RP2040 Feather ThinkInk (https://www.adafruit.com/product/5727)
- Bare EPD display (JD79661 chipset): {https://www.adafruit.com/product/6373)
Background
I went through all the official tutorials for the ThinkInk Feather: https://learn.adafruit.com/adafruit-rp2040-feather-thinkink
The provided examples are excellent, but they currently focus on CircuitPython and Arduino. Adafruit already provides solid drivers for the JD79661 chipset, and the display is also well supported in the Arduino ecosystem via the GxEPD2 library: https://github.com/ZinggJM/GxEPD2
This made me curious: can I do the same thing in Rust?
Rust on RP2040
The RP2040 has very good Rust support thanks to the rp-rs ecosystem. A great starting point is the RP2040 project template: https://github.com/rp-rs/rp2040-project-template
There is also an existing HAL board definition for the Adafruit Feather RP2040 here: https://github.com/rp-rs/rp-hal-boards/tree/main/boards/adafruit-feather-rp2040
While it’s not an exact match for the ThinkInk Feather, it’s close enough to serve as a solid base, with only minor adjustments needed.
Driver work
At the moment, there is no native Rust driver for the JD79661 E-Paper controller. To move forward, I implemented a custom Rust driver, based directly on the source code from Adafruit’s CircuitPython and Arduino implementations.
Once the low-level driver was in place, everything integrated nicely with the Embedded Graphics framework. Rendering text and images worked as expected.
As a proof of concept, I was able to:
- Convert a JPG image to BMP
- Render and display it correctly on the E-Paper display
Results & Code
All of my experiments and findings are documented here: https://github.com/melastmohican/adafruit-feather-thinkink-discovery
The repository includes:
- Project setup for Rust on the ThinkInk Feather
- A custom JD79661 driver
- Examples using Embedded Graphics
- Notes on differences between the standard Feather RP2040 and the ThinkInk variant
Closing thoughts
Overall, Rust works very well on the RP2040, and bringing up an E-Paper display was quite feasible even without an existing driver. Hopefully this helps others who want to explore Rust + E-Paper + Adafruit hardware.
-
PyBadge Timer Box PyBadge as a CircuitPython Learning Platform
The PyBadge is one of the most feature‑packed ways to experiment and learn CircuitPython. With an integrated TFT display, eight buttons, five NeoPixels, a light and an acceleration sensor, audio with an on-board speaker and amplifier for an external speaker, LiPo charging, and multiple expansion ports including a FeatherWing socket, it’s practically a handheld programming lab.
Then last week JP had Adalogger FeatherWing with its built‑in RTC on as his product pick of the week the idea clicked: let’s turn the PyBadge into a portable, multi‑function timing tool!
Components
Assemble the parts
Putting it all together is quite simple. The only soldering needed is attaching header pins to the AdaLogger.
- Solder header pins to the FeatherWing. Install the headers on the bottom of the board facing downward.
- Insert the coin cell into the FeatherWing.
- Attach the FeatherWing to the socket on the back of the PyBadge.
- Plug in the speaker
- Plug in the battery
- Connect to USB and you are ready to roll!
Install CircuitPython
Now install CircuitPython on your PyBadge - follow the instructions in the Learn Guide: