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.
-
Fruit Jam Two Gamepad Demo This is my third iteration of a CircuitPython USB host gamepad tester, now with support for two controllers. The main loop in code.py uses asyncio to improve code readability. There's a new boot keyboard to gamepad mapper. For hot-swapping controllers, I devised an unplug detection heuristic to work around limitations in the current CircuitPython USB host implementation. Player numbers get assigned according to Fruit Jam top plate silkscreen port numbers. Player 1 gets USB 1, and Player 2 gets USB 2.
This demo project is meant to help folks who want to make Fruit Jam libraries for writing games. I don't plan to make a library on my own, but I wrote this code with library-making in mind in case somebody else wants to. Note that some of the performance and stability workarounds included here may become unnecessary once USB host implementation bugs get fixed.
The code here was written and tested with CircuitPython 10.0.0-beta.2 on a rev D Fruit Jam that I bought from the first production batch that went up in the shop.
Related work:
- Fruit Jam Gamepad Tester guide (my previous gamepad tester)
- Fruit Jam Fruitris (Tetris) game guide by @relic-se
- Feather TFT Gamepad Tester with Sprites guide (my original gamepad tester)
Overview
-
Fruit Jam Fruitris (Tetris) Parts
I am using a production revision D Fruit Jam board. Most additional components can likely be found around the house such as HDMI cable & display, headphones, power supply, etc. The controller system is designed to be as compatible as possible. So, most USB controller devices should work or even a USB keyboard.
It is possible to use a Metro RP2350 which is discussed in learn guides such as Larsio Paint Music., but this guide will not discuss that procedure nor has the software been tested within that environment.
From the Adafruit Shop
Controls
Action Keyboard Gamepad Buttons Move Left Left Arrow Left Move Right Right Arrow Right Rotate Clockwise Up Arrow or X Up or A Button #2 Drop: Soft Down Arrow Down Button #1 Drop: Hard Z B Quit (reload) Enter Start Button #3 -
TactileAudio Project: Four-Channel Touch-Sensitive Audio Player Audio Adaptor Board
Order 1 (required)
Teensy 4.1 Board
Order 1 (required)
-
Build a Brain in your NeoTrinkey! BuildABrain
Simple expert system for NeoTrinkey - yes/no questions, inspired by https://en.wikipedia.org/wiki/20Q
This project lets you put a simple expert system into your neotrinkey! The "brain" will ask yes/no question - touch pad #1 for "Yes" and pad #2 for "No"
Github archive *here*
Uncomment the dataset you want - this is shipped with a Star Wars set and Star Trek.
#from SWBrain import * #for Star Wars dataset from STBrain import * #for Star Trek dataset
Here's how the Star Trek set was designed:
Basically, sketch out the decision tree, then number each node. Create a "yes" and "no" array that links each node to the next node (if any).
#Data in nodes for Star Trek info Words = ["Think of someone from Kirk's Enterprise.","Gold uniform", "Captain", "Blue Uniform", "Kirk", "Russian", "Vulcan", "Male", "Chekov", "Sulu", "Spock", "Scotty", "Uhura", "Male", "Are they dead","McCoy", "Chapel"] Yes = [0, 2, 4, 6, 0, 8, 10, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0 ] #node for yes answers No = [0, 3, 5, 7, 0, 9, 13, 12, 0, 0, 0, 14, 0, 16, 0, 0, 0 ] #node for no answers
note: the zeroth node should be the introduction, for Star Trek it's "Think of someone from Kirk's Enterprise."
Files:
-
BuildABrain.py - copy to code.py on NeoTrinkey
-
STBrain.py - Star Trek data
-
SWBrain.py - Star Wars data
-
prt.py - lets you redirect output via HID output, just set REPL=False
Note: if REPL=False the program will blink Neopixels until you touch one of the pads.
Here's how it looks in action:
Think of someone from Kirk's Enterprise. Gold uniform? No Blue Uniform? Yes Vulcan? Yes Spock? Yes I was right! let's try again Think of someone from Kirk's Enterprise. Gold uniform? No Blue Uniform? No Male? Yes Scotty? No Are they dead? No Maybe you should talk to my programmer!
Give it a try - see if you can build a brain for you NeoTrinkey!
-
-
Watch Tower - Radio controlled watch transmitter There are some beautiful radio-controlled watches available these days from Citizen, Seiko, Junghans, and even Casio. These timepieces don’t need fiddling every other month, which is great if you have more than one or two and can never remember what comes after “thirty days hath September…”
In the US, these watches work by receiving a 60-bit 1-Hz signal on a 60-kHz carrier wave broadcast from Fort Collins, Colorado called WWVB. The broadcast is quite strong and generally covers the entire continental US, but some areas of the country can have unreliable reception. I live in the SF Bay Area in an area with high RF noise and my reception can be spotty. My watches sync often enough that it’s not an issue 363 days out of the year, but sometimes they can miss DST shifts for a day or two. The east coast is known to be even more challenging.
Wouldn’t it be great if anyone could set up a little repeater to transmit the time so their watches were always in sync?
WWVB has been around awhile and there have been various other projects (1,2) that have demonstrated the feasibility of making your own WWVB transmitter. But these all had very limited range. I wanted to build something that could cover my whole watch stand and be based on a more familiar toolset for the typical hobbyist, namely USB-based 32-bit microcontroller development boards, WiFi, and Arduino. My goal was to make something approachable, reliable, and attractive enough it could sit with my watch collection.
Is this legal?
The FCC requires a license to transmit, but has an exemption for 60 kHz transmitters as long as the field strength is under 40 μV/m40 μV/m at 300 meters. You will definitely not exceed this limit 💪🏼
-
USB Cipher Machine Historically it's been common for militaries to use purpose built mechanical cipher machines like the well known Enigma Machine, or the more mundanely named M-209. Ever since I learned about these devices they fascinated me. This project is a small toy cipher device inspired by them albeit made with a microcontroller instead of mechanical parts and pieces.
I showed this project on Show & Tell, the video is embedded below.
Hardware
-
Fruit Jam Portable MIDI Synth This is a minimalist polyphonic square wave synth for Fruit Jam that's intended for portable use with a USB power bank. The only output is audio to the board's headphone jack. The only input is from a USB MIDI controller connected to the board's USB host port. To set the volume, you can edit the code.
The main interesting thing about this project is that it demonstrates how to make a CircuitPython synth with MIDI events coming from the USB host interface rather than a USB device interface or UART MIDI. Also, this works as a good stress test of the CircuitPython USB host stack in combination with audio output using I2S and synthio.
This code was developed and tested on CircuitPython 10.0.0-beta.0 with a pre-release rev B Fruit Jam prototype which uses a different I2S pinout from the current rev D boards. Keep in mind that what's written here may be out of date by the time CircuitPython 10.0.0 is released and the production revision of the Fruit Jam board becomes available in the shop.
Related guides: Fruit Jam USB Host MIDI Tester, Fruit Jam Gamepad Tester
Transparency note: Adafruit provided the Fruit Jam rev B prototype board I used for this guide (Thanks Adafruit!).
Overview
-
Reviving My Netduino 2 (without the .Net MF) Some History
I've had two Netduino 2's sitting in my electronics box for years, more years than I'm willing to admit. During that time, I'd done very little with them. When I originally bought them, Visual Studio was my daily development environment, and I knew my way around it quite well. I'd tinkered for a bit with an Arduino, but I was eager to use .Net and Visual Studio on this new device. I did build a few things with them, but frankly they didn't grab my interest and at the time, the much more powerful Raspberry Pi was drawing my attention away. So, these boards were relegated to the back of my toolbox. They seemed to be pretty content there, and I kept them cool and dry, so we were all happy for the time being.
A Spark of Blue
Fast forward to 2025 and as I was organizing my development boards into a new case, the Netduino's resurfaced, and my curiosity was rekindled. Did one of those blue LEDs just blink at me? Could these devices still work? Part of me always thought I should do more with them, maybe now is the time. Is the .Net Micro Framework still available? Could these boards be brought back, or would they remain dormant and only come out during my nostalgic times of remembering and reminiscing? Time to start searching and see what I can find.
Surprisingly, a lot of the original content is still available. Unfortunately, the firmware and Visual Studio add-in haven't been maintained in a long time. The last published versions were targeting Visual Studio 2015 and possibly worked with VS2017. Microsoft's download center doesn't even have VS2015 or even VS2017 and the .Net Micro Framework has been archived. But I wasn't going to give up. I found an old copy of VS2015, downloaded the additional tools required for Netduino development and got them installed. However, I wasn't able to connect the boards to the Visual Studio or deploy any code. I couldn't even get the Netduino Updater to flash the latest firmware. Sigh! It was looking like these devices were obsolete or at least too complicated to get any custom program running.
-
Displays and Clocks with Adafruit IO - Back to the Future with timezones Testing the display support recently added to Adafruit IO's no-code Arduino firmware, WipperSnapper, I've come unstuck with my automations a few times due to living over the other side of the pond (🫖) from Adafruit HQ...
"Why?", you ask? Time-zones!
In case you were unaware, Adafruit HQ runs on New York time, also known as EST (Eastern Standard Time), which is currently 4hours behind UTC (daylight savings can alter this 4hr offset).
Now to make life easier, the schedule block uses a timezone location set in the User account page, meaning my schedules run as expected, yay! The tricky bit comes when you want to start comparing time or timestamp values.
Most things live in server time, which is set to New York, but many other bits and bobs are presented in UTC.
For our purposes we want things in our local time, advancing time back to the future, with a no-code clock!Setup DST Change-over Actions
- Create a new feed to store the timezone offset inside if you haven't already got one. Do it on the /feeds page, and then on the new feed page add data manually for the current time-zone offset.
- Create a new Action on the /Actions page, called "Start of DST", with a description of when it should run.
- Add a schedule trigger block to the diagram. Use the cogs to alter the schedule block for your DST changeover. In my case we don't support "last X in Month" yet so I'm using "Every Sunday in March", followed by a check of a liquid template function if it's the last sunday in the month.
- If needed for complex schedules then add a Set Variable block (variable named timezone_offset_hours) with the value set to the timezone offset feed (Get feed block). Otherwise jump to step 7.
- Add a set variable block for a new variable called is_last_sunday, then add a template block as the value.
For the template body, use the following (which adds 7days then compares the month to current)
Template:{%- assign now_s = "now" | date: "%Y-%m-%dT%H:%M:%S" | date: "%s" %}
{%- assign now_z_s = "now" | date: "%Y-%m-%dT%H:%M:%SZ%z" | date: "%s" -%}
{%- assign server_utc_diff = now_z_s | minus: now_s -%}
{%- assign thing = 3600 | times: vars["timezone_offset_hours"] | minus: server_utc_diff -%}
{%- assign bst_time_s = now_s | plus: thing -%}
{%- assign current_month = bst_time_s | date: "%m" -%}
{%- assign next_week_month = bst_time_s | plus: 604800 | date: "%m" -%}
{%- if current_month != next_week_month -%}1{%- else -%}0{%- endif -%}
- Add a logic IF condition block, then place a number comparison block from the maths category (=)
Inside the number comparison block, add a Get Variable block for is_last_sunday, and compare to 1.
- Add a Set Feed block to the Actions: section of the diagram, and select the timezone offset feed in the dropdown. For the value enter the local UTC offset in hours during the next daylight savings time period.
- Save and run the action, enabling if asked.
- Create a second action for the end of Daylight savings time, with the appropriate local UTC offset in hours for that next period. Save it and run it, enabling if asked.
Your actions should look similar to this:
- Create a new feed to store the timezone offset inside if you haven't already got one. Do it on the /feeds page, and then on the new feed page add data manually for the current time-zone offset.
-
Using the Terminal and displayio for DVI in CircuitPython See the new guide Using DVI Video in CircuitPython which supersedes this Playground Note. Same author, greatly expanded content.
-
Fruit Jam USB Host MIDI Tester This is a CircuitPython-in-the-middle MIDI filter and visualizer project for Fruit Jam. When you plug a USB MIDI controller into the Fruit Jam, MIDI input events will be shown on the DVI visualizer display and echoed on the usb_midi output port to the Fruit Jam's host computer. You could use this as the starting point for a USB MIDI filtering project.
The note visualizer has a grid of channels and notes to cover the range of a full size piano (midi notes 21 to 108). Dots indicate a note that hasn't played yet. Note-On messages turn the dot into a white rectangle. Note-Off messages turn the rectangle black. It works like a 1-bit heat map showing which notes and channels are active. Pitch bend, CC, aftertouch, etc. get shown as text in the bottom left of the visualizer and echoed to the serial console. USB host port connection status gets shown in the bottom right of the visualizer.
This code was developed and tested on CircuitPython 10.0.0-beta.0 with a pre-release revision B Fruit Jam prototype. Keep in mind that things may change by the time CircuitPython 10.0.0 is released.
Related guide: Fruit Jam Gamepad Tester
Transparency note: Adafruit provided the Fruit Jam rev B prototype board I used for this guide (Thanks Adafruit!).
Overview
-
GPS Tracker Coding in CircuitPython - Going Down the AI Rabbit Hole The Idea
I've lately been dabbling with AI coding assistance and have been impressed with what it can do. So, I thought I'd do a whole project from scratch using several boards I have been meaning to do something with. I thought I'd also take you all on the journey and maybe you will find this useful. I will use this Playground article to document the process. I will go through the components and assembly, list the prompts I used with the AI tool to build the code, and share what value this new tool gives me.
The Build
The project is a GPS tracker. In a nutshell a GPS module, an OLED display and an AdaLogger board. Here are the components I used:
Design Choices
I chose these components for simplicity. Choosing an AdaLogger for the microprocessor gives me an SD card to log the output and gives me one Neopixel, a separate LED I can use as an indicator and an extra input button with board.BUTTON. The OLED display, although small (128x32), can convey a lot of information if done well, plus it gives me three input buttons for controls. The GPS board just works well with little effort.
Assembly
Since the Feather ecosystem is perfectly modular, assembly was simple:
- Solder headers on to the microprocessor, GPS FeatherWing and the OLED FeatherWing
- Solder the sockets on to the Feather Tripler
- Prepare the AdaLogger by inserting a formatted SD card and attach the LiPo battery to the connector.
- Insert a coin cell into the GPS module
- Plug the three boards into the Tripler - I used a couple of rubber bands and a small piece of foam on the bottom to hold it all together
That's all there is to it! With that - we are (almost) ready to code.
-
Omron D6T thermal sensor with WipperSnapper (Arduino / ESP32-S3) https://github.com/tyeth/omron-devhub_d6t-arduino
Brent nerd sniped me this week with his talk of a non-contact thermal sensor for Leaf VPD measurement on WipperSnapper, as I've been wanting VPD measurements of my Banana plant for a very long time.
Limor then came in with some suitable new sensor alternatives (the TMP007 being obsolete), and my mind wandered through the digikey site briefly, stumbling upon the D6T thermal sensor series from Omron.
Conveniently it uses a very similar cable to my favourite sensors, the JST-GH locking cable, but a 4pin variant. No Problem! Cut the 6pin version right through pin 5 (then removing the 5th wire and contact), and a final extra trim of the locking tab, and hey presto an instant fit!
Easy pinout, as it's I2C, but wants 5volt power/logic. The handy StemmaQT 3v to 5v logic level converter (PID 5649) quickly gets you to stemma and voltage compatibility. Then for software Omron have a library on Github.
Sadly it looks unmaintained, or at least incompatible with ESP32. So a quick fix or two (merge some old community PRs -❤️open-source), rebase it, swap the Wire (I2C) to be a passed argument, and now it's hopefully suitable for all!
This is the connector / pinout details:
-
AIO-Connected Workshop Thermal Camera Project Objective
To observe thermal conditions out in my remote laboratory (i.e., the workshop bench in the detached garage), I previously installed an Adafruit IO (AIO) connected corrosion monitoring system that watches conditions inside and outside of the garage. The CircuitPython-based corrosion monitor consists of an interior temperature/humidity sensor and, thanks to AIO Plus, correlates with exterior weather conditions. However, from the temperature/humidity sensor's perspective, if a door or window is left open it takes far too long to detect the issue. It would be ideal to be able to "see" if a relatively small area inside the workshop has experienced a temperature change relative to the bulk of the air in the space. An added benefit would be to detect human motion in the workshop area or to discover if the soldering iron was accidentally left on.
Requirements
- Periodically capture and upload a thermal image of a critical portion of the workshop.
- Monitor for temperature extremes and upload an image when exceeded.
- Detect human motion and upload an image.
- Provide a local color display with automatic brightness control.
- Continuously update the local display image at least twice a second to quickly detect motion and respond to thermal events.
- Upload the captured thermal image on a remotely accessible AIO dashboard page via the local WiFi network.
- Upload bitmap image payload to AIO in less than 10 seconds.
- Power from a USB 5-volt wall wart.
Future and Nice-to-Have
- Blank the screen when motion has not been detected for a preset amount of time (screen saver).
- SD Card storage of images and temperature statistics with historical view UI.
- Trigger AIO notification events related to motion or alarm settings.
- Upload minimum, average, maximum temperature values with image; display on dashboard.
- Interface to Apple HomeKit.
- Capture local audio.
- Live MEMENTO photo overlay.
To speed up prototyping and algorithm development, CircuitPython was the choice for the software side of things. Besides, the code needed for creating images with a thermal camera and for reliable communication with AIO already exists in other projects that I've recently developed.
System Components
The thermal camera components consist of:
- ESP32-S3 4Mb/2Mb Feather.
- 2.4" TFT FeatherWing (optionally wired for display brightness control and an ambient light sensor).
- AMG8833 Thermal Camera Breakout, connected to the ESP32 Feather with a 100mm STEMMA-QT cable.
- An optional ALS-PT19 Analog Light Sensor Breakout connected to the TFT FeatherWing's +3V, GND, and A3 pads. The light sensor is used to automatically control display brightness in proportion to the ambient light level.
If display brightness control is needed, the TFT FeatherWing will require a short jumper wire soldered to connect the
TX
pin andLITE
pads to allow PWM control of the display backlight brightness. See photo.For automatic display brightness control, connect the ALS-PT19 light sensor output to the
A3
GPIO pin pad. Also connect the sensor's power and ground to the FeatherWing's3V
andGND
pads. For the prototype, three Dupont Cable 20cm Soft Silicon wires were cut in half and with the wire end soldered to the sensor breakout and the Dupont pin end inserted into the outer row of the Feather socket as shown in the wiring photos. -
Fruit Jam Lines Screensaver This is a twisty-lines CircuitPython graphics toy inspired by screensavers from the 1990's (Macintosh After Dark 2 NightLines, Windows 95 Mystify, etc). To make the trail of lines, the code keeps track of two bouncing-ball style points and draws a line between them. Each new line gets added to a list, and the oldest line gets dropped off the end. The line colors cycle through a color swirl palette generated from a gradient using the LCh color space. This is meant for picodvi video output on RP2350 boards including Metro RP2350 and Fruit Jam.
To learn more about how I generated the rainbow swirl color palette, check out my Fruit Jam Color Gradient Generator Playground guide from last week.
This code was developed and tested on CircuitPython 10.0.0-alpha.7 with a Metro RP2350 (no PSRAM version) and a pre-release revision B Fruit Jam prototype. Keep in mind that things may change by the time CircuitPython 10.0.0 is released.
Transparency note: Adafruit provided the Fruit Jam rev B prototype board I used for this guide (Thanks Adafruit!).
Video Demo