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.
-
Get Radio I've been spending a bunch of time testing code across different MCUs and networking chips. It started with my work with Connection Manager. Then I was digging into Requests and MiniMQTT . Which of course lead me to places like NTP, AzureIoT and AWS_IOT.
As I jumped around, I needed a way to always get the right radio. Sometimes it's native WiFi, which is easy:
wifi.raidio
, but other times, it's some SPI based FeatherWing or maybe a M4 with and AirLift (talking to youPyPortal
andMatrixPortal M4
)...Introducing:
get_radio
It's not perfect, and I'm guessing there are things I haven't thought of, but it works for me so far.
The only thing a normal developer, with the right libraries installed and only one radio needs to do is:
The nice thing is it will connect for you and everything! Store your creds as
WIFI_SSID
? Got you covered. What aboutCIRCUITPY_WIFI_SSID
? Got you covered there too. What about insecrets.py
? Sadly not there,settings.toml
is the way to go.Now let's say you aren't using a FeatherWing, or you are connecting things to different pins? Well your set there too!
-
Mandelbrot on a Neotrinkey? ... It's Complicated. It's no secret that I keep trying to think of new things to do with the NeoTrinkey. One day, for some reason*, I wondered if it would be possible to render the Mandelbrot set in ascii... with a NeoTrinkey.
Since the NeoTrinkey runs CircuitPython and since many, many projects are shared online in Python... it seemed reasonable to assume I could find code that would help me do this. And I did - I found a github project by "LadyClaire" : https://github.com/claiire/python-mandelbrot - this seemed exactly like what I wanted.
Except... well, I said it was "complicated." The math to render the Mandelbrot set involves manipulating points on the complex number plane and Python easily does such math, CircuitPython doesn't.
Which meant I couldn't just run LadyClaire's code - I needed to write my own complex.py module that let me do the work. Import complex.py and you get:
- absC - returns absolute value of a complex number
- plsC - adds two complex numbers
- sqrC - squares two complex numbers
- mltC - multiplies a complex number by a number
- mltCC - multiplies two complex numbers.
- mltI - multiplies a complex number by i
With those functions, I could tweak the code into mandelbrotx.py - adding in some blinking lights (you need ncount.py). The mandelbrotx.py module (which you'll rename code.py) has a variable REPL - REPL=True directs the output to the REPL, REPL=False sends it out as keystrokes.
When you run the program you need to touch pad #2 to start the rendering - you'll see lights blink as each row is calculated. When it's done you'll see the image at the top - generated not by some supercomputer... but your friendly, NeoTrinkey!
*Note: I know the reason, it's because I follow a Mastodon account, [email protected], which posts random images from the Mandelbrot set.
-
Look Ma, No Microcontroller! (Night Light Edition) Inspiration
This is a piece of "found art"; a multi-colored circuit board hiding inside some old discarded electronics. It just needed a backlight and a frame to highlight its beauty. From the beginning, I knew this would become a nightlight and held onto the board until I had acquired the perfect combination of discarded LEDs and a few other components needed to make it shine.
Case Design
My 3D printed case had 3 chambers. One for the electronics, one for the LEDs, and a thin slot a the front to hold the circuit board and clear plastic cover. The reason for the separation was to make sure the LEDs were the right distance to illuminate the board and to minimize the light that leaked out that back of the frame while still allowing hot air to escape. The design was almost perfect, but I ended up having to cut a large slot in the back so I could replace the back wall with a slotted version for better ventilation (not pictured).
Before closing up the case, test that it can be dimmed appropriately.
-
Web API's & You Below is a test of the Playground Note code embed directly from Github (must be .md or .py file). If you see the full code below it is working as intended. If the example in the library gets updated this Playground Note might not be kept up to date with future changes. The code below will always be the most up to date as it is pulled directly from the adafruit_requests examples library.
Full Example Code
- An uncomprehensive & comprehensible guide to using Adafruit Requests with web API's.
The amount of online API examples for the Adafruit_Requests library is growing. If you're interested in using an API but an example does not exist and you're unsure how to start I will help walk you through the process.
I wrote the majority of the web API examples currently in the examples directory. I'm a pretty good source on how to approach a new unknown web API and wrangle out some basic data.
JSON
Data is malleable, it can be shaped and formed in a variety of ways. The most common format currently used with REST API's is JSON. The Adafruit_Requests library is particularly good with JSON data. If you don't know how to read or write in JSON don't worry, you won't need to. The library handles all the format conversions for you. All you need to know is how to get at the data you want and I will walk you through how to do that.
Before we begin there are some glossary terms that you'll need to know in order to make sense of JSON for the web.
REST
Representational State Transfer (REST) is a software architecture that imposes conditions on how an API should work. Most web API's use the REST architecture. All a beginner needs to know about REST is it's the way a website allows you to retrieve data from an API.
Endpoint
An endpoint refers to the data to retrieve from an API. This can be part of the JSON heirarchy path or a key:value pair. For web API's typically this refers to the JSON Key:Value pair.
Key:Value
- Key:Value (always a pair separated by a colon)
A key is a unique identifier associated with data and the value is the actual data. An example would be if you're working with a weather API and might want to return current:temperature for a geographic area to display freedom units on a TFT. It would return as `current:70.0` (in Fahrenheit) or if you're living in a sensible country using the metric system it would return `current:21.1` (in Celsius).
Key Error
It's useful to know the above terms because an error that a website or Circuit Python might return is `invalid key:value pair` or simply `key error`. That error means you requested a key:value that does not exist, you spelled it incorrectly, or the request was otherwise incorrectly formatted.
-
Babel - Let's make some Alien words!! Here's another silly NeoTrinkey project - let's make some alien words!
babel.py - generates "alien" words using a set of rules for Wookie, Klingon, Vulcan, Mando'a and Romulan.
ncount.py - blinks numbers
Touching pad #1 toggles between the five languages, and blinks the number (1..5) for the language choice. Each language defines a set of consonants, vowels and an array of word patterns (V for vowel, C for consonant, v 50% chance for a vowel, c 50% chance for consonant). When you touch pad #2, a list of words (random quantity, 1 to 10) is created following the rule sets. The rule sets were created using known words from those languages.
Change the variable REPL to direct the output: True means the program prints to the repl, False sends the output to the keyboard.
Example output:
Wookie: OUWA ROR HOH AROOAUW HOUW WOH ORAUW ORUUUUR WOR OWOUOOR
Klingon: laq noegh tSyIm DIyS mI Ho jaab
Vulcan: su tuai tiustoa het' tiy k' t
Mando'a: ary reara 'hr syc tmn cor khc
Romulan: ihf ki'vh ies lu'm m'ih ih eenh hieh uek
Note: These are generated words, and only by coincidence match vocabulary in any real lexicons.
For fun you can replace my rule sets for any other alien or fantasy language you wish to create.
There's a hoopy frood who really knows where his towel is. -
Stuff My Dog Said (via AdafruitIO) Inspiration
This project is an extension of the original doggy buttons project where I'll be showing how to make a public dashboard that publishes everything my dog says. This project is just one example of how to extend the features of my doggy buttons and perhaps one of the silliest IOT devices ever made. If you want to know about the buttons themselves, see the original project writeup.
With a project like this, it's also important to think about privacy. I don't want my dog making it possible to tell when we're away from home, so I'll also show how to add a delay so that activity is only published once it's sufficiently stale.Setup Challenges
User Space vs Admin Space
The first version of my program was kicked off by
/etc/rc.local
on boot, but this had the side effect of running the program asroot
. That was fine for my original project, but I had followed best practice and not usedsudo
whenpip3 install
ing the Python libraries needed for loading data to AdafruitIO. If I logged in to run the program as my user, it would end when I logged off butroot
no longer had all the Python libraries needed to run.Lennart (Binary Labs) suggested the simple and elegant solution of adding
sudo -u MY_PI_USERNAME
before the command that would launch my code in/etc/rc.local
. This allows the program to be run as my user without having to login and was much simpler and cleaner than the other solutions I was considering.Concurrency
The first version of my code simply added a call to
aio.send_data(...)
in the same loop that processed button presses, but I quickly discovered that the upload process could take 3 - 4 seconds leading to very delayed sounds when more then one button was pressed. Things like "water outside walk later" became "water ... outside ... walk ... later". This was starting to confuse my dog because the sounds weren't immediately connected with the button presses and would sometimes sound when she had gone to push something else entirely because the button "wasn't working".To fix this it was going to be necessary to introduce separate queues, one for playing sounds that could respond quickly, and one for uploading button presses that could slowly upload data to AdafruitIO in the background.
-
Getting QWIIC thru window, door, etc. A few hours ago, I saw an announcement of a new Adafruit product #5961, connecting Stemma QT/Qwiic connector to a breadboard.
I quickly realized that by having two of these, with headers soldered on (consider using right-angle headers for this), one can use "Flat Flexible Cable" ("FFC") AF04-5-ND from Digi-Key, along with Digi-Key crimp-on connectors 609-3512-ND, to connect something like a sensor on one side of a door/operating window/etc to a microcontroller on the other side.
The FFC is MUCH thinner than a normal Stemma QT/Qwiic cable, or indeed any sort of "ribbon" cable I've seen in my nearly 60 years of "doing" electronics, so the FFC is MUCH better at getting through doors/windows/etc. You may be familiar with FFC in a custom form (often called Flexible Printed Circuits) for connectors on various small displays.
I should mention that those "crimp on" connectors can be a tad bit ornery to get on. I usually find that a largish pair of "pump" pliers to do the ''crimping' and another pair of pliers to "convince" the side pieces to close will do the trick. Also, if you have a sensor exposed to the weather, you might want to consider adding some conformal coating (though the device and connections before applying the coating, and if your sensor includes humidity and/or barometric pressure, be sure to protect the "sensor hole" from the coating.
One instance of this that I've used the FFC for is a sensor outside a window while keeping an ESP-8266 safely on the window sill. I also have sensors inside both the fridge section and freezer section of my side-by-side with an ESP-8266 on top of the unit. (A fridge would make a pretty good Faraday Cage, so WiFi inside the fridge probably wouldn't work.)
-
NeoPixel Stick and Pi Pico Need to add a simple diagnostic display to a Pico project? Or perhaps you want a quick and easy NeoPixel light show? Let's see what we can do!
Equipment
-
Reading Pixels from the RA8875 Driver Board Intro to the RA8875 Driver Board for Circuit Python
The Adafruit RA8875 driver in Circuit Python does not currently support displayio. You must use read/write registers with a barebones ra8875 graphics library. The current feature set and how it is used is only for very advanced users.
You can draw a bmp image and overlay text but you'll quickly find that's about all you can do with it. There are only 2 examples provided and the driver board is unlike any other display device for Circuit Python. Any knowledge you have of displayio does not transfer over to this board; the RA8875 is unique.
The interest of using an 800x480 bare display with Circuit Python is typically due to the sheer size of it but it should come with fair warning: You must be capable of programming with circuit python from scratch without displayio.
The bits and bytes of binary color
Since the RA8875 can only display a maximum of 16-bit color; the 24-bit image must be converted to 16-bit (color565).
The RA8875 stores color information in its memory with 2 bytes (2 pairs of 8 bits). Here is a binary representation of how it stores the color. 11111111 00000000 There are 8 bits in 1 byte.
However the RA8875 actually stores them in what is known as swapped color565. Each first byte must be swapped with the 2nd. This is not some type of color conversion error. These are the direct reads from the memory addresses for the stored colors.
-
Using GPIO on Arduino. Hi. today i`m going to show you how to use the GPIO or pins on Arduino it doesn't matter witch one as long as it has GPIO.
First jumper weirs:
-
About I've been doing the hobbies of coding and circuit boards for three years now, I use Adafruit a lot and would love to help other people with the same hobbies on here with fun projects and useful info. I will be doing small and large guide projects. I will make sure to add all of the crucial info and extra detail to make it easier. thanks.
needed components during my tutorials:
led`s and resistors, transistors, capacitors
3d printed software or cnc soft-where.
basic circuit boards and device to code them with Arduino ide or mu editor.
That`s all! thank you for your time.
-
The Necrochasm: Pushing the Prop-Maker RP2040 to its limit! This is a project that was years in the making, I went through many iterations that failed one way or the other. However, the final project was only started about a few months ago. It's great to see this project realized at last! The trigger really works, it has the appropriate sound effects, it has two firing speeds, and a "virtual ammo" system that you replenish by physically removing and reinserting the cartridge. So, where did it all begin?
The initial step of the process was to design the 3D printable case, which I did in blender. I found someone who extracted a model of the Necrochasm from the game itself and went to work sculpting out the finer details, hollowing out the interior, and adding LED areas. I also took this time to log into Destiny, and use my in-game Necrochasm to record the proper sound effects.
I exported the resulting pieces from blender to fusion 360 where I added the hardware mounting features. My vision for this prop was to have one area where most of the electronics were stored. This trapezoidal area at the bottom-front of the prop looked like it had the most storage capacity.
-
CG-35: A Retro RPN Calculator The CG-35 is a CircuitPython emulation of the Hewlett Packard HP-35 Scientific Reverse-Polish Notation (RPN) calculator designed for the Adafruit ESP32-S3 Feather and 3.5-inch TFT FeatherWing capacitive touch display. The calculator consists of a 10-digit LED-like display backed-up with 20-digit internal calculation precision.
This emulation reproduces the HP-35 calculator's v2.0 firmware where the change sign (CHS) key is active only after digit entry has begun. And because of the
udecimal
andutrig
classes, calculation accuracy of monadic, dyadic, and trigonometric functions was improved. As an added bonus not present on the original calculator, a status message will appear just below the primary display when a calculation error is encountered.The calculator's graphical layout was designed to mimic the aspect ratio of the original calculator -- that's why the left and right sides of the display screen were left empty. However, to provide a more reliable touch screen experience, the keys are somewhat proportionally larger than the original.
This project was inspired by Jeff Epler's DIY Desktop Calculator with CircuitPython project and Jeff's work to create CircuitPython versions of
udecimal
andutrig
. Thank you Jeff!GitHub Repository: https://github.com/CedarGroveStudios/CG-35_Calculator
Primary Code Module
The primary code module
cg_35_calculator.py
, imported bycode.py
, instantiates the display, plots the calculator case and buttons, and implements all calculator operational processes. This module uses a state machine design with the following named states:- IDLE -- Display results or wait for input
-
C_ENTRY -- Coefficient entry (keys:
0
-9
,.
,CHS
,EEX
) -
E_ENTRY -- Exponent entry (keys:
0
-9
,.
,CHS
) -
STACK -- Stack management (keys:
ENTER
,CLR
,CLX
,STO
,RCL
,R
,x<>y
,π
) -
MONADIC -- Monadic calculator functions (keys:
LOG
,LN,
e^x
,√x
,ARC
,SIN
,COS
,TAN
,1/x
) -
DYADIC -- Dyadic calculator functions (keys:
x^y
,-
,+
,*
,÷
) - ERROR -- Calculation error
The calculator's display precision and internal calculation precision are specified using the variables
DISPLAY_PRECISION
andINTERNAL_PRECISION
. Although the internal precision exceeds that of the original HP-35 calculator, it is recommended to keep the existing default settings of 10 digits and 20 digits, respectively, to avoid rounding errors.The variable
DEBUG
can be use to provide additional internal register status via the REPL. This boolean variable defaults toFalse
(no additional register status). -
Using Multiple WiFi Access Points with CircuitPython Introduction:
If you have the need your WiFi project to operate at various locations with different WiFi SSID/PASSWORD settings at each location, read on. If you are using an MCU with built-in WiFi that CircuitPython 9.0.0 or later supports, there may be a solution to your issue.
Overview of the project:
This article will provide you with two tools to get you started.
- A code.py defined function (def) that will cycle through the WiFi networks defined in settings.toml. It will also show a sorted list of available WiFi access points found locally.
- A sample settings.toml to get you started.
- There are additional functions and features that will be covered as we go along.
- There will be a description of how each function works and interacts.
Why would you need multiple WiFi SSIDs in IoT projects?:
Let’s say you have a project that you must develop at home, show friends how it works at your bridge club, test it under various situations, and demonstrate its features to a customer. Having all the SSIDs and PASSWORDs predefined and having your project cycle through them without your intervention, except the first time you add them, would speed things up.
Prerequisites:
The system requirements are simple. An MCU with built-in WiFi that is supported by Circuit Python 9.0.0 or newer. My tests were run on a Raspberry Pi Pico W. All the libraries are built into CP 9.x.x that the sample code.py needs. They are: import os, wifi, random, binascii. The additional libraries used by the diagnostic code are import time, board, digitalio, ipaddress, supervisor, microcontroller and are also built-in.
If your MCU is listed at the web site below, your board is probably supported.
https://docs.circuitpython.org/en/latest/shared-bindings/wifi/index.html
Click on Available on these boards for a full listing. Considering the length of the boards listed, I have not tested, nor can I guarantee this code will work with any or all of them.
Upload the code and configuration:
To test if this program will work on your MCU (listed above), load CircuitPython 9.0.0 or newer, copy the code.py and settings.toml files to your board. Then startup REPL and see what is happening. It should cycle through the 10 SSID/PASSWORD pairs preloaded into settings.toml and fail at each one and move on to the next.
If you get wifi not found/defined, this program will not work because CP 9.x.x does not support your board. The AdaFruit Forum experts will have to address this.
Replace one of the test sites listed in settings.toml with your local WiFi SSID and PASSWORD then watch what happens. The program should pick a random site and cycle through to your site and connect. It will wait 10 seconds then reboot and pick a random site and cycle again. Then change the IP address in line 116 and verify that your MCU can ping a known good local site.
This should work out-of-the-box. If yours doesn’t, contact me on the AdaFruit Forum, @blakebr.
Conclusion:
I hope this utility helps you in making your programs more bulletproof while connecting to WiFi. I am looking forward to your real-life testing and improving this utility with your input.
I suggest you place the code snippet below someplace in your program to periodically test that the WiFi connection is still good.
-
Touchscreen TFT & SDCard with the Raspberry Pi Pico W The goal for this project is to get the display, touch screen, and sd card working on the Pi Pico by calibrating the touchscreen and printing the contents of the sdcard to serial console.
Learning how to share multiple SPI peripherals reduces the amount of pins you need which can increase the amount of available pins for other uses. A SPI bus is very similar to an I2C bus except the SPI peripheral has a unique chip select pin assigned to it. I find it easier to think of the chip select pin as a SPI address pin. You can only have 1 address per device with I2C and the same holds true with SPI devices except the address is a physical pin.
Because SPI peripherals require a physical pin you will be limited to how many you can have based on how many free pins your microcontroller has. What SPI lacks in chain ability it makes up for with speed.
- I2C devices are half-duplex
- SPI devices are full duplex
Because SPI communication is twice as fast as I2C it makes far more sense to use SPI for displays and sd cards! Don't get me wrong, I2C definitely has its place for uses such as:
- temp sensors
- optical sensors
- 7-Segment displays
- 14-Segment displays
- small 16x9 matrix LED modules
- Neopixel strips
- and chaining a ton of devices on 1 bus without the limitation of physical pins per device.
When it comes to needing faster communication for a display that has 480x320 (153,600 total) pixels or sd card reading & writing for a single device that's where the SPI protocol outperforms I2C.
I recently worked on a project with a Raspberry Pi Pico that needed to have a Touchscreen TFT & SD Card. That's actually 3 peripherals because the touchscreen controller chip requires pins too. In the majority of scenarios when you have a SPI touchscreen you actually have 2 SPI devices, the display and the touchscreen.
In the Raspberry Pi Pico pinout diagram there are 2 separate SPI buses. SPI0 and SPI1. SPI0 peripherals cannot communicate with peripherals on the SPI1 bus and vice versa. A peripheral would be anything on the SPI protocol such as a display, sdcard, temp sensor, etc... They are highlighted below with magenta labels. Please notice that each SPI bus is prepended with SPI0 or SPI1.
Here is the wiring setup using an Adafruit Proto Picow Doubler. The doubler offers a maximum of 3 input headers per physical pin. That means you can share up to 3 SPI devices per pin with their doubler. This is a very handy feature as I didn't have to use a breadboard to prototype this project, very cool. The reset button also came in handy during prototyping. If you have a Pi Pico I highly recommend getting one of these. They're like Feather doublers but for the Pico.