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.
-
Pyboom - A game for the Fruit Jam Py-Boom
Py-Boom is a fast-paced, 8-bit-style arcade game written in CircuitPython for the Adafruit Fruit Jam and other compatible display boards.
This game is a modern take on a classic "catcher" formula, featuring both a single-player mode against an AI and a competitive two-player versus mode.
Game Modes
At the title screen, you can select your game mode:
-
1-Player Mode: You control the Bucket (P1) at the bottom of the screen. An AI-controlled Bomber moves at the top, dropping bombs at an increasing rate. Your goal is to catch as many bombs as possible to survive the level.
-
2-Player Mode: Player 1 controls the Bucket, and Player 2 controls the Bomber. P1's goal is to survive, while P2's goal is to drop bombs strategically to make P1 miss.
How to Play
P1 (Bucket) - The Catcher
-
Goal: Catch every bomb that is dropped. If you miss a bomb, you lose one of your buckets (lives). If you lose all three, the game is over.
-
Winning: If you (P1) successfully catch all bombs in a level (e.g., 10 bombs in Level 1), you win the round and advance to the next, more difficult level.
P2 (Bomber) - The Attacker
-
Goal: Make P1 miss! You have a limited number of bombs per level. Use your movement and timing to drop bombs where P1 isn't.
-
Winning: If you (P2) successfully make P1 lose all three of their buckets, you win the game!
Controls
Action
Player 1 (Bucket)
Player 2 (Bomber)
Move Left
AkeyLeft ArrowkeyMove Right
DkeyRight ArrowkeyDrop Bomb
N/A
Down ArrowkeyStart / Ready
SpacebarEnterkeyOther Controls
-
Select Mode: On the title screen, press the
1or2key. -
Restart Game: On the "Game Over" screen, press the
Rkey to return to the title screen.
Required Files
To run this game, you will need the following files on your CircuitPython device:
-
code.py: The main game code. -
The Fruit Jam OS library package.
-
pyboom.bmp: The title screen logo. -
bomb_icon.bmp: The bomb sprite icon (used in development).
Download at: Pyboom Git Hub
Background
This project was started on Microsoft Make Code for my Pygamer and was called Prison Break. With the introduction of the Fruit Jam I wanted to port this over to Circuit Python. The graphics in Make Code (MC) are saved in a TypeScript file so I had to copy the codes for the sprites over to my Circuit Python. I used the AI tools that are part of Visual Studio Code (VS) the develop functions to map the sprites maps into bitmaps and tile grids. I continued to use the AI tools to help convert the Python code from MC. I mostly used Gemini as I have 3 months of premium from purchasing my phone. Though there were times where Gemini would get stuck on fixing issues it was making so I would switch to the free tokens in VS and use Claude or Chat-GPT. I ran out of free tokens in VS and moved on to Gemini for versions 2 and 3 of the game. I am in the process of uploading my prompts that I still have access to (I lost my VS conversations :( ) and hope to have them done in the next week. I also hope to get controllers setup and maybe make paddle controllers in the future.
I found this a fun project to learn Circuit Python and coding with AI. I'm still learning the concepts of using classes and learned a lot while looking at the errors the AI was coming up with.
-
-
ASTRO - SF Starmaps for the Neotrinkey simple SF starmap creator - github repository here
I wrote this program for the neotrinkey - but will be merging it into "Traveler" a simple SF game for the Fruit Jam based on my earlier neotrinkey progam "Adventure-Engine".
Files:
- astro.py (copy to code.py}
- wise.py
- prt.py (set REPL=True for printing in REPL, False to print via HID)
- ncount.py
When you touch pad #1, produces output like:
Ahghie:3, 1 Mieas:7, 1 Syaei:1, 7 Syuuas:1, 4 Giafnk:5, 4 Zoid:7, 6 .......... ...*...*.. .......... .......... .*...*.... .......... .......*.. .*........ .......... ..........A list of stars and their x,y coordinates in a 10x10 grid, then a map of the stars.
When you touch pad #2, A random star will be picked as your "location" and the list of stars will be displayed AND the distance to each one from your current location:
location = Syuuas Ahghie:3, 1: 3.60555 Mieas:7, 1: 6.7082 Syaei:1, 7: 3.0 Syuuas:1, 4: 0.0 Giafnk:5, 4: 4.0 Zoid:7, 6: 6.32455 location = Zoid Ahghie:3, 1: 6.40312 Mieas:7, 1: 5.0 Syaei:1, 7: 6.08276 Syuuas:1, 4: 6.32455 Giafnk:5, 4: 2.82843 Zoid:7, 6: 0.0 -
Teensy 4.1 Spacemouse to Midi Bridge Here's some Arduino code for the Teensy 4.1 (Adafruit Product ID: 4622) that lets my Spacemouse Wireless from 3Dconnexion appear as a standard USB midi controller to my computer, and presumably any other USB midi hosting device. It provides six high-resolution CC pairs from the knob motion, and two on/off CC's for the two buttons.
The Teensy needs a jumper between the board Vin and the USB Host 5v pins to power the Spacemouse Dongle (unless a powered USB hub is inserted between them).
The teensy, of course, also needs to be fitted with a USB Host socket connected to the USB host pins on the board to to recieve the 3DConnexion dongle or USB wire.
The code was provided by ChatGPT after some relentless back and forth. I'm pretty clueless myself about it. But for a souless device planning to take over the world and annihilate us all, The Chatster has so far proved to be very patient and accomodating. Beyond the obviously tunable lines, the LLM should be able to adapt it more to your liking, even if your skills are as meager as my own.
-
Talking to Aliens with my Fruit Jam I have been writing, and rewriting a very simple "translator" for around 30 years. It started many years ago after getting my first copy of the Klingon Dictionary and I started experimenting with very simple programs. Not true machine translation, I just made what I called a "Universal Translator Assistant" that relexifies a language (like English) into the alien words it has matched to them. Since starting, It has kind of become my personal "hello world" program and I've written versions of this program in C, Perl, Python, BASIC, VisualBasic, CBMBasic, Javascript, Java and Scratch. And now CircuitPython
As noted, it's linguistically more than a little suspect - but it's been a fun project all the same. The languages here are Klingon, Vulcan, Mando'a and Romulan.
The github repository is here
Language sources:
- Mando'a vocab originated in Karen Traviss's Star Wars novels. For more info, see https://mandoa.org/
- tlhIingan (Klingon) vocab is a custom one I created - more official Klingon from: https://kli.org and https://hol.kag.org
- Vulcan vocab from: https://tinyurl.com/VulcanArchive - archive.org of Marketa Zvelbil's original Vulcan work.
- Romulan is from Diane Duane's Rihannsu novels, but I generated more words for use here. See also http://www.rihannsu.org/arch/www.rihan.org/drupal/lessons/introduction.html
The files should be put in apps/UTA, with the .lng files all put in a subdirectory langs.
Enter text and UTA will match English words with the Alien languages. This is not true translation, but provides vocabulary you can use to translate into the target language. It will also match Alien words back to English. Because more than one English word may map to an Alien word, the back translation may look odd.
_ _ _____ _ | | | |_ _|/ \ | | | | | | / _ \ | |_| | | |/ ___ \ \___/ |_/_/ \_\ Universal _... Translator ,' `. Assistant / \ | -._ | \ \ `._ \ \ `... `-..-`. `-._ `. _,-- `. -' '. | '.| ' loading tlhingan text: hello what is your name nuqneH nuq ghaH lIj pong text: *lang vulcan loading vulcan text: live long and prosper tich tor ang tesmur text: *help _ _ _____ _ | | | |_ _|/ \ | | | | | | / _ \ | |_| | | |/ ___ \ \___/ |_/_/ \_\ Universal Translator Assistant Help commands: *help - this file *pItlh - quit program *lang [filename] - loads langs/filename.lng Languages: vulcan, tlhingan, mandoa, romulan text: tich tor ang tesmur live long and prosper text: *lang mandoa loading mandoa text: I love you ni riduurok gar text: ni riduurok gar me love your text:You can create your own language files as NAME.lng in the langs/ directory. The format should be:
"English word", "Alien word" "English word", "Alien word" "English word", "Alien word" "English word", "Alien word" ...You would load that language with the command "*lang NAME"
-
Troubleshooting CircuitPython Programs - Beyond the Print Statement The print() function is your first debugging tool
When creating a CircuitPython program a great way to follow program flow and to examine parameters and values is to use a print() statement sending the information to the REPL. This is simple, tried and true, and you can comment them out when no longer needed to turn them off. Many times this is the way to go.
Sometimes, however, you might have a lot of print statements and multiple function calls and all of the information flowing into the REPL becomes a bit hard to follow.
Making print() output easier to read
At this point one strategy to make the print outputs easier to follow is to add divider lines, line feeds, special characters, etc. For example:
Get creative and use different characters for divider lines (i.e. =, +, *). You can also combine characters such as:
-
Displaying Images on Pico Mac Emulator for Fruit Jam With my recent retro mac classic inspired enclosure project for the Fruit Jam, I got the crazy idea to display my own images on the mac emulator. Sure, you can run MacPaint, but wouldn't it be cool to display custom graphics like the Fruit Jam logo? Well, it turns out there's a bit of a process to get images to display on System 7.5, specifically on 68K architecture (which is what the pico-mac emulator is based on).
Image File Formats
JPEG, PNG and GIF images are the norm with modem day computers. But, in 1984, these image formats were not yet a thing. I thought, surely displaying a bitmap image on Mac OS System 7 shouldn't be too hard, right?
After searching google, easiest approach seemed to be: Use the Graphic Converter mac app to convert a JPEG into a MacPaint document. This however, didn't quite seem to work. When I import the converted macpaint image file into Mini vMac, it wouldn't open in MacPaint. Weird, Ok, lets try a native image file format. Again, that's not really a thing. Enter the world of the .PICT (QuickDraw picture).
-
Using the Fruit Jam Intel 286 Emulator The new 286 PC Emulator for Fruit Jam provides many interesting possibilities and a lot of fun.
This Playground Note will provide information that may not be evident or may otherwise help others.
Initial Impressions
Having wide emulation through the 80286 is helpful, through it wasn't until the '386 that memory handling got better.
I was really excited about all the display modes. But trying to get to them in DOS or QBASIC was impossible. Maybe they'll work in games but I'd like a high resolution DOS screen too.
-
Fun with Fruit Jam Neopixels The adafruit_fruitjam library makes controlling the five neopixels on the board pretty easy...
Start with the basics
We begin by initializing the library and setting things up:
[note these are code snippets only - not a complete project]
From here you can use the standard neopixel "fill" and "show" to control the neopixels altogether. To refer to the neopixel object you reference them by 'jam.neopixels' (note the s on the end) followed by the command. For example, a classic red blink would simply be:
-
TPL5111 - Low Power projects (WipperSnapper, Arduino, CircuitPython, etc) Overview
The TPL5110 (with driven output line) or the TPL5111 (with toggling enable line) allow some really simple low-power projects. Use the zero to sever and supply power, or the one to control enable pins (for LDO/MCU).
Just adjust the potentiometer to tweak the turn-on time, and then with the TPL5111 you send a low high transition to the Done pin to go to sleep. The Enable pin goes low and MCU sleeps until the next cycle.
All of that means you can easily create a no-code low-power project, just by hooking up the TPL5111 to a WipperSnapper compatible board, and combine that with an E-ink display for the ultimate low power setup.
The board wakes up, connects to WiFi and Adafruit IO, get's the latest messages (E-Ink Display) and sends some sensor data. Two small Actions on Adafruit IO switch the Done pin to a high level, and then ten seconds later back to low. A third action updates the screen message with time + weather every 10mins.
Add a third action to update the display or whatever is appropriate (like acting on some sensor data).
Use
\nto force a line break when working with Displays on WipperSnapper
-
Fizzgig I built Fizzgig and would like to share a few notes on my build (made in October 2025). I hope that this is helpful to anyone attempting to build it as well. I had a lot of fun building it!
Speaker
I tried using an external speaker connected with the headphone jack cable. It turned out that this speaker is not deactivated when no sound is played, and it produces very loud white noise (this happens with any speaker connected via this connection). Thankfully, the Adafruit support team reproduced this, and it seems that this behaviour cannot be resolved. So I went along with the oval mini speaker that is connected to the board via PicoBlade. To improve its sound a little, I attached the speaker to a Tic Tac box as a resonator, which worked quite well.
Servo / Jaw
I used lots of hot glue to attach all the hair, so the jaw became rather heavy. I attached some cardboard to the jaw to stabilise it, but this was not enough to support the weight. As a result, the jaw would not close properly. To resolve this, I stabilised the jaw with ice cream sticks. I also extended the servo horn with a piece of carbon tube. I could securely fix this to the servo horn using heat shrink tube with hot glue. My extended servo horn ends in a grommet made out of another piece of carbon tube with a larger diameter that I glued to the jaw. This makes the placement of the servo a lot easier and the connection more stable.
I thought about also adding a spring taken out of a retractable pen to the servo horn extension to help the servo along. In my build, this was not possible to integrate, but there may be setups where adding a spring is possible and makes sense.
Since I could not use a spring, I added a counterweight in the part where the servo horn ends. I glued in a screw and added two nuts for added weight. This helps the servo along.
Code
I used the UF2 file provided in the instruction. I would have liked to change the code to reduce the jaw opening angle (this would have enabled me to use a spring). Adafruit support pointed me to the code, and I was able to identify the place where the servo angles are defined. In my current Arduino IDE, the code would compile successfully, and the IDE even told me that the code had been successfully transferred to the board. However, CIRCUITPY was still visible as a drive after this supposedly successful transfer, and I had to re-upload the original UF2 file to go back to that version. I re-tried with several different methods, but I was not able to make the compiled code transfer to the board successfully. This may be due to my inability, since I am not very experienced using microcontrollers at all. If you are planning to alter the code, do check if it works for you before making your build.
Wig
It makes a lot of sense to buy a wig with really long hair. The instructions advise to cut off the hair along the longest section. I did this, but it would have made more sense to plan ahead to first check where the nose will go. Most hair under the nose will not be needed, as that's where the mouth goes. Depending what your particular wig looks like, it may be better to keep the long hair in the back and trim under the nose.
Also, the hair will be all over the place when you're done.
I styled my Fizzgig's hair with transparent lacquer from a spray can. This was necessary especially around the eyes and the nose.
Frame
I built a wooden frame for my Fizzgig. I had originally used a cardboard box, but for more stability I replaced it with a wooden frame that basically had the same dimensions. My frame is about 31 x 18 x 10 cm. The required dimensions very much depend on the size of the wig and the length of the hair.
-
USB, XT, PS2 keycode cross reference in CSV Recently for the Fruitjam-286 emulator, I needed to create a good mapping from USB HID codes to XT codes.
There are many resources online including Keyboard Scancodes (Andries Brouwer) which is a nice HTML table.
I converted the table into a csv file, and then used a bespoke Python program to convert it to a format for the emulator.
First, my program opens the csv file and checks its structure
-
2025-1017 Speedy-Vi Note I created this Note so I can link a section of CircuitPython Essentials to it. Unfortunately, when I click "Link Note" it still says "You do not have any notes available to link to this guide. To create a new note please visit the Adafruit Playground and create a note." I just created this note so I could link the section of CircuitPython Essentials to it. I must be doing something wrong...
-
CircuitPython Functions to Pretty Up Strings Here's a short one...
Sometimes I find myself wanting to pretty up a string. For example, a value might come in all in lower case letters and I want to capitalize the first letter or maybe go for capitalizing all first letters. Another use case is using variable names (conventionally all lower case) for captions.
- 'this is my string' ===> 'This is my string'
- 'top values' ===> 'Top Values'
Python has title() and capitalize() functions but these are not implemented in CircuitPython.
Also, strings may be in camel case that I want to fix - the Weather Powerup on AdafruitIO sends text data back this way:
- 'mostlyClear' ===> 'Mostly Clear'
When there is a limited set of data I've used if/elif/else statements or used look-up dictionaries, but in some cases the inputs may not be known. Also, who wants to write all of the repetitive code!
Since CircuitPython does include upper() and lower() functions we can build functions to do this. So with the help of CoPilot I drafted and now include these three functions in my code when I am doing anything with strings:
In these sample functions I only apply to strings that are greater than three characters long as generally when I have short strings, I want them to keep the case (such as 'MPH'). But you can change this if you want it to make the change to all input strings. In the camel_to_title() function I also replace underscores with spaces, primarily for when I use variable names as captions.
Hope you find this useful - and be sure to share any custom functions you can't live without.
-
Exploring the Arduino App Lab Binary Overview
To understand what the new Arduino UNO Q is about, I've been looking at the new the Arduino App Lab coding tool. The App Lab download page links to the source code at https://downloads.arduino.cc/app-lab-release/source-app-lab.zip, but the source seems incomplete. Among other differences, there aren't any build instructions or scripts in the source archive. So, I've been poking around trying to understand how the source works and how it differs from the binaries.
Highlights of what I found: You need a UNO Q board to get past the first screen. The app is written with Wails which uses Go for the backend and a web app for the frontend (similar to Electron, but using a native web view rather than embedding a browser). The binaries include embedded markdown for examples that don't appear in the source. The app may be using Hotjar telemetry for analytics.
Download Checksums
When I downloaded the macOS dmg, Linux tar.gz, and source-app-lab.zip files on October 16, 2025, these are the checksums I got:
-
Magnetometer - MMC5603 to measure gas usage inside your home with home assistant I wanted to measure the gas usage inside my home and push the data into Home Assistant.
To collect the data, I wanted to use the MMC5603 magnetometer + ESP32 Feather V2. The MMC5603 had a great price point and the ESP32 Feather V2 was able to connect to my Home Assistant server via WiFi.
Requirements
- ESPHome 2025.8.3
- The Adafruit Products above (MMC5603 + ESP32 Feather V2 or similar board that can connect via WiFi)
- Ethernet Cable (Cat 5 and later is fine)
- USB Power Adapter (e.g. like this one , 5V 1A)
- A short USB-A to USB-C connector (e.g. like this one, data isn't important here - so any cable will do)
- M2.5 screws (lengths and materials will be up to you, I used nylon M2.5 screws to attach the bracket to the gas meter and metal M2.5 screws for the MMC5603 to the bracket).
If you end up using any earlier version of ESPHome and you'll run into issues like I did where the MMC5603 wasn't being registered properly.
I connected everything like this diagram:
I ended up having to create a 3D bracket that could hold the MMC5603 onto the US Gas Meter.
https://www.printables.com/model/1446364-us-gas-meter-brace-for-a-mmc5603-magnetometer