Maker.io main logo

Adafruit Sparkle Motion

142

2025-05-13 | By Adafruit Industries

License: See Original Project LED Strips Microcontrollers Wifi Addressable LEDs

Courtesy of Adafruit

Guide by Erin St Blaine and 2 other contributors

Overview

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

board_1

We mainly recommend this board for use with WLED and Xlights, ‎but examples are included in this guide for CircuitPython and ‎Arduino.‎

The Adafruit Sparkle Motion is the flagship in our series of "Sparkle ‎Motion" boards, which are our attempt to make the best ‎small WLED-friendly smart LED driving board in the whole world. ‎Our resident mermaid, firepixie makes a lot of projects with WLED ‎and she loves it! So how can we make something that will be ‎powerful enough to drive advanced LED projects with built-in ‎sensors.‎

This version has a built-in antenna so it's ready to go out-of-the-box.‎

This board has everything you could possibly want for big, small, or ‎even massive WLED/xLights projects:‎

  • Power option 1 via USB Type C PD with a slide switch that ‎selects between 5, 12 and 20V (24V pixels can usually run fine at ‎‎20V)‎

  • Power option 2 via 2.1mm DC jack, center positive

  • Low forward-voltage diodes so it’s good for up to 5A from ‎either

  • ‎5 Amp fuse to protect from over-current drive

  • ESP32 mini module with built in antenna port - the classic ‎ESP32 has the best WLED support even if we'd prefer the 'S2 or ‎‎'S3. Comes with 4 MB of flash, dual core 240MHz Tensilica, WiFi, ‎Bluetooth LE, and Bluetooth Classic support

  • USB-serial converter with auto-reset

  • Three output signal terminal block sets with power and ‎ground for each - they'll be level shifted to 5V. Use 26-20AWG ‎stranded or solid core wires, 5A rated

  • ‎6 GPIO breakout pads with a fourth level-shifted output, and 3 ‎more GPIO plus power and ground

  • Built-in I2S microphone for audio-reactive projects with digital ‎quality audio

  • Built-in IR receiver for easy remote-control integration

  • Stemma QT I2C port to connect external sensors/OLED/etc

  • Separate analog/digital input JST port for analog input, ‎potentiometer, microphone, or external IR receiver

  • User button on GPIO 0 plus Reset button

  • Red built-in LED on pin 4‎

  • Small built-in NeoPixel on pin 2‎

  • Compact enough you can use it for wearable projects - ‎‎1.3"x1.75" / 33mm x 45mm size with mounting holes‎

To make it super-fast to get started, terminal blocks are pre-installed: ‎use any 20-26 AWG stranded or solid core wires with a flat-head ‎screwdriver to attach semi-permanently.‎

While we recommend it for use with WLED, it will also work just fine ‎as a compact ESP32 board for use with Arduino, ESP-IDF, ‎MicroPython, CircuitPython or any other ESP32 supported codebase. ‎

scale_2

The Sparkle Motion board has it all. Designed with ease of use for ‎larger scale LED projects using WLED and Xlights, we've packed it ‎with features and components that will enable users to create ‎incredible things.‎

  • Power via USB Type C PD with a slide switch that selects ‎between 5, 12 and 20V (24V pixels can usually run fine at 20V)

OR via 2.1mm DC jack‎

  • Low forward-voltage diodes so it's good for up to 5A from ‎either USB or the DC jack

  • 5 Amp fuse to protect from overcurrent drive

  • ESP32 mini module with built in or optionally wFL antenna port ‎‎(the classic '32 has broad support even if we'd prefer the 'S2 or ‎‎'S3)‎

  • Three output signal terminal block sets with power and ‎ground for each: level shifted to 5V

  • 6 GPIO breakout pads with a fourth level-shifted output, and 3 ‎more GPIO plus power and ground

  • Built-in I2S microphone

  • Built-in IR receiver

  • Stemma QT I2C port to connect external sensors/OLED/etc

  • Separate analog/digital input JST port for analog input, ‎potentiometer, microphone or external IR receiver

  • Compact enough you can use it for wearable projects - ‎‎1.3"x1.75" / 33mm x 45mm size with mounting holes‎

holes_3

Add-ons: yes! OLEDs! Inertial Measurement Units! Sensors a plenty. ‎All plug-and-play thanks to the innovative chainable ‎design: SparkFun Qwiic-compatible STEMMA QT connectors for the ‎I2C bus, so you don't even need to solder! Just plug in a compatible ‎cable and attach it to your MCU of choice, and you’re ready to load ‎up some software and measure some light. Seeed Grove I2C ‎boards will also work with this adapter cable.‎

In addition to the Stemma QT connector, we also added an RGB ‎NeoPixel (with controllable power pin to allow for ultra-low-power ‎usage), a reset button (great for restarting your program or entering ‎the bootloader), and a button on GPIO 0 for entering the ROM ‎bootloader or for user input.‎

Onboard sensors include an IR receiver for easy remote control, and ‎an I2S microphone, so you can quickly and easily add sound ‎reactivity to your project.‎

blocks_4

To make it super-fast to get started, terminal blocks are pre-installed: ‎use any 20-26 AWG stranded or solid core wires with a flat-head ‎screwdriver to attach semi-permanently.‎

attach_5

This board has everything you could possibly want for big, small, or ‎even massive WLED/xLights projects.‎

Pinouts

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

pinouts_6

The Sparkle Motion is a board with a lot of sparkly features. This page ‎covers it all!‎

features_7

Pretty Pins on Github (PDF).‎

Power Pins

power_8

  • USB-C port - This is used for both powering and programming ‎the board. You can power it with any USB C cable that is USB-‎PD rated for the current you'll draw. It is a 5V 5A input - you can ‎use off-the-shelf USB battery packs for portable operation. It is ‎connected to a 5 Amp resetting fuse to protect from ‎overcurrent drive.‎

  • USB-PD slide switch - selects between 5V, 12V, and 20V. ‎Connected to the built-in HUSB238 power delivery chip, which ‎is on the I2C bus with address 0x8 (0x08).‎

  • Barrel Jack - 2.1mm DC jack, center positive. Accepts power up ‎to 24V. It is connected to a 5 Amp resetting fuse to protect from ‎overcurrent drive.‎

  • Power LED - The green LED, located between the USB C port ‎and Barrel jack, indicates when the board is powered up.‎

  • + Terminal Blocks - The 3 VOUT terminal blocks along right ‎side provide 5V-24V power for your pixels. Use 26-20AWG ‎stranded or solid core wires, 5A rated.‎

  • ‎- Terminal Blocks - The 3 GND terminal blocks along the right ‎side are common ground for all power and logic. Use 26-‎‎20AWG stranded or solid core wires, 5A rated.‎

  • ‎3.3V - This pin, located on the top row of the 6 pins broken out ‎in the bottom right corner of the board, is the output from the ‎‎3.3V regulator. It can supply 500mA peak.‎

  • G - This pin, located on the bottom row of the 6 pins broken out ‎in the bottom right corner, is connected to the common ground.‎

ESP32 Module

The processor on the Sparkle Motion is an ESP32 mini module. The ‎classic ESP32 has the best WLED support. Comes with 4 MB of flash, ‎dual core 240MHz Tensilica, WiFi, Bluetooth LE, and Bluetooth ‎Classic support.‎

module_9

NeoPixel Output Signals

neopixel_10

On the right side of the board there are 3 terminal blocks for ‎NeoPixel output signals. All signals are level shifted to 5V. Use 26-‎‎20AWG stranded or solid core wires, 5A rated.‎

  • ‎21 - GPIO21, available as SIG1 in CircuitPython and 21 in Arduino.‎

  • ‎22 - GPIO22, available as SIG2 in CircuitPython and 22 in ‎Arduino.‎

  • 19 - GPIO19, available as SIG3 in CircuitPython and 19 in ‎Arduino.‎

Logic Pins

logic_11

The Sparkle Motion has 4 general purpose "IO" pins broken out near ‎the bottom right corner of the board and 1 additional GPIO available ‎via the 3-pin JST port at the bottom edge of the board.‎

  • ‎10 - GPIO10. This is the UART RX (receive) pin. Connect to the TX ‎pin found on a breakout or device. This is separate than the ‎‎'debug UART' which is connected to the USB-to-Serial ‎converter, so it will not interfere during upload. In Arduino ‎use Serial1. In CircuitPython use board.RX.‎

  • ‎9 - GPIO9. This is the UART TX (transmit) pin. Connect to the RX ‎pin found on a breakout or device. This is separate than the ‎‎'debug UART' which is connected to the USB-to-Serial ‎converter, so it will not interfere during upload. In Arduino, ‎use Serial1. In CircuitPython, use board.TX.‎

  • ‎23 - GPIO23. Available as D23 in CircuitPython and 23 in ‎Arduino. This is a 5V level shifted output only! You can use it as ‎another LED strip pin.

  • 18 - GPIO18. Available as D18 in CircuitPython and 18 in Arduino.‎

  • 27 / JST Port - GPIO27. It uses ADC2. One of the capacitive ‎touch pins. Available as D27 or A0 in CircuitPython and Arduino.‎

Note you cannot read analog inputs on ADC2 once WiFi has started, ‎as it is shared with the WiFi hardware.‎

STEMMA QT

stemma_12

This JST SH 4-pin STEMMA QT connector breaks out I2C (SCL, SDA, ‎‎3.3V, GND). It allows you to connect to various breakouts and sensors ‎with STEMMA QT connectors or to other things using assorted ‎associated accessories. It works great with any STEMMA QT or Qwiic ‎sensor/device. You can also use it with Grove I2C devices thanks ‎to this handy cable.‎

  • SCL - GPIO13‎

  • SDA - GPIO14‎

You can access this I2C port with board.STEMMA_I2C() in ‎CircuitPython and Wire in Arduino.‎

NeoPixel and Red LED

led_13

There are two LEDs you can control in code.‎

  • NeoPixel LED - This addressable RGB NeoPixel LED, ‎labeled Neo on the board, can be controlled with code. It acts ‎as a status LED in CircuitPython and is connected to GPIO2. It is ‎available in CircuitPython as board.NEOPIXEL, and in Arduino ‎as PIN_NEOPIXEL.‎

  • Red LED - This little red LED, labeled LED on the board, is on or ‎blinks during certain operations (such as pulsing when in the ‎bootloader), and is controllable in code. It is available in ‎CircuitPython as board.LED, and in Arduino ‎as LED_BUILTIN or 4.‎

Buttons

buttons_14

There are two buttons on the Sparkle Motion

  • Reset button - This button restarts the board and helps enter ‎the bootloader. You can click it once to reset the board without ‎unplugging the USB cable or battery. ‎

  • Boot button - This button can be read as an input in code. It is ‎connected to pin GPIO0. It is available as board.BUTTON in ‎CircuitPython, and BUTTON in Arduino. Simply set it to be an ‎input with a pullup. This button can also be used to put the ‎board into ROM bootloader mode. To enter ROM bootloader ‎mode, hold down boot button while clicking reset button ‎mentioned above. When in the ROM bootloader, you can ‎upload code and query the chip using esptool.‎

IR Receiver

ir_15

The IR Receiver on the top center of the board makes it easy ‎integrate a remote control into your project.‎

IR - GPIO32. Available as board.IR in CircuitPython, and 32 in Arduino. ‎It is connected to ADC1.‎

I2S Microphone

microphone_16

In the bottom center of the board is an I2S microphone, great for ‎adding audio reactivity to your WLED projects. It uses three data ‎pins:‎

  • DATA - GPIO25‎

  • WS - GPIO33‎

  • BCLK - GPIO26‎

You can use the microphone with WLED and Arduino. There is no I2S ‎input support in CircuitPython at this time.‎

CH343DS1 USB-to-Serial Converter

converter_17

The CH343DS1 USB to serial converter communicates between the ‎ESP32 and your computer over USB. It is a full-speed USB device ‎interface and is USB 2.0 compatible. It has an auto-reset circuit that ‎works perfectly with any ESP32 uploading tool. Sometimes these ‎chips require drivers to be installed on your computer's operating ‎system. We have a Learn Guide detailing how to install these drivers.‎

UART Debug

On the back of the board, the hardware UART debug port has two ‎broken out pads, labeled TX and RX on the board silk. You can ‎connect these to a USB console cable in order to read the debug ‎output from the ESP32 IDF while connected to a USB PD power ‎supply. This is useful if you are writing software and need to see the ‎low-level debug output.‎

uart_18

  • ‎TX - The pad on the top (closest to the Adafruit logo) is the TX ‎pin.‎

  • RX - The pad on the bottom (furthest from the Adafruit logo) is ‎the RX pin.‎

Connecting LEDs

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

Wiring Diagram

wiring_19

There are many different types of pixels available. This is a general ‎reference that shows connection points for most types of strips. Your ‎project may have different requirements, but this is a good starting ‎point.‎

For NeoPixel strips or other strips that have 3 solder pads or wires, ‎connect to the screw terminal at the base of the board. There are ‎markings on the PCB showing which terminal is which. It's set up ‎with three 3-pin strip connections in mind, and each strip has its own ‎power and ground connection. The GPIO pins are labeled: 19, 22, and ‎‎21, and they're in the middle of each block of 3 wires.‎

If you'd like to add a fourth instance/strip, connect the data and ‎ground to the pins next to the screw terminal as shown, and the ‎power wire to one of the +5v screw terminal ports.‎

The two Stemma connector ports can be used to connect sensors or ‎other peripherals.‎

How many LEDs Can I Connect?‎

The Sparkle Motion board has four outputs for LED strips: 3 in the ‎screw terminal and one more using the GPIO pins next to the screw ‎terminal. It has a "Classic" ESP32 chip onboard.‎

Estimating Power Requirements

Each individual NeoPixel draws up to 60 milliamps at maximum ‎brightness white (red + green + blue). In actual use though, it’s rare ‎for all pixels to be turned on that way. When mixing colors and ‎displaying animations, the current draw will be much less. It’s ‎impossible to estimate a single number for all circumstances, but ‎we’ve been using 1/3 this (20 mA per pixel) as a gross rule of thumb ‎with no ill effects. But if you know for a fact that you need every pixel ‎on at maximum brightness, use the full 60 mA figure.

‎To estimate power supply needs, multiply the number of pixels by 20, ‎then divide the result by 1,000 for the “rule of thumb” power supply ‎rating in Amps. Or use 60 (instead of 20) if you want to guarantee an ‎absolute margin of safety for all situations. For example:

‎‎60 NeoPixels × 20 mA ÷ 1,000 = 1.2 Amps minimum

‎60 NeoPixels × 60 mA ÷ 1,000 = 3.6 Amps minimum

‎The choice of “overhead” in your power supply is up to you. ‎Maximum safety and reliability are achieved with a more generously ‎sized power supply, and this is what we recommend. Most power ‎supplies can briefly push a little extra current for short periods. Many ‎contain a thermal fuse and will simply shut down if overworked. So, ‎they may technically work, but this is the electronics equivalent of ‎abusing a rental car.‎

Here is a guide giving more info on what that means in terms of ‎power draw: Powering NeoPixels Guide. The power draw varies ‎greatly depending on the type of pixels and the brightness, as well ‎as the color choice. ‎

Keep in mind, 60 mA is a worst-case estimate! We’ve written a ‎whole separate tutorial on getting things under control: Sipping ‎Power with NeoPixels.

Driving Pixels with WLED

From the WLED Knowlege base:‎

For perfect performance, it is recommended to use 512 LEDs/pin with ‎‎4 outputs for a total of 2048 LEDs.

For very good performance, it is recommended to use 800 LEDs/pin ‎with 4 outputs for a total of 3200 LEDs.

For good performance, you can use 1000 LEDs/pin with 4 outputs for ‎a total of 4000 LEDs.

For okay performance, you can use 1000 LEDs/pin with 5 outputs for ‎a total of 5000 LEDs.

For okay performance, you can use 800 LEDs/pin with 6 outputs for ‎a total of 4800 LEDs.

ESP32 can calculate about 65k-85k LEDs per second (that means ‎‎1000 LEDs @~70fps, 2000 LEDs @~35fps, 4000 LEDs @~18fps)

‎4 outputs seem to be the sweet spot.‎

What Kind of LEDs Can I Use?‎

The Sparkle Motion board and WLED accept a wide variety of pixel ‎types. Anything in the Adafruit store labeled as "NeoPixel" or ‎‎"Dotstar" will work. You can use rings, strips, jewels, pebble pixels, ‎stars, RGBW strips, or just about any RGB addressable pixels you can ‎find in our shop.‎

This setup will NOT work with "dumb" RGB strips or analog strips. It's ‎meant for strips with individually addressable pixels (strips where ‎each pixel can become a different color) rather than the strips that ‎can only show one color at a time.‎

How Do I Power It?‎

The Sparkle Motion board has onboard power management so you ‎can use 5v, 12v, or 24v strips. The board will deliver up to 20v (which ‎is usually sufficient for 24v pixels). Be sure your power supply ‎matches the voltage the LEDs expect. Here are a few good options. ‎Check the shop for more variations including power supplies with ‎inline on/off switches.‎

For wearable or portable projects, you can use a USB battery with 5v ‎pixels, plugged into the onboard USB-C port, or this 8xAA battery ‎pack for 12v pixels. But if you're making a wearable project, you ‎might also want to check out the Sparkle Motion Mini board. It's not ‎quite as powerful and won't drive 12v pixels but can power up to 4A ‎at 5v and that's plenty for most costume pieces.‎

A Word About Connectors

It's possible to direct-wire your LED strips or pixels into the screw ‎terminal, but I find it easier and more convenient to use 3-pin JST ‎connectors that can be permanently affixed to the Sparkle Motion ‎board with strain relief, so they don't pull out. Then I can simply plug ‎in whatever LED strip or strand I want to use.‎

LED strips often come with these connectors already attached, but ‎there seems to be no standard for whether the factories attach the ‎male or the female connector on the "in" end. For my own peace of ‎mind, I try to be consistent and always use the male side of the ‎connectors on the microcontrollers, and the female on the "in" end of ‎my LED strip. Data is flowing "out" from the microcontroller and "in" ‎to the strip, so the male/female metaphor makes good sense in this ‎arrangement. ‎

There is also no standard as to which way the color coding is wired ‎on these connectors. Some have a red wire on the left side, some on ‎the right side. Some have no color coding at all. Hooking your strips ‎up "backwards" (accidentally connecting a red wire to a black wire) ‎can damage your board and your LEDs, so it's important to be really ‎careful when you're setting up your connectors. Be as consistent as ‎possible with color coding and throw away any connectors you've ‎got in the drawer that are wired "backwards" from the rest. ‎

Screw Terminal Connections

Use a tiny precision flat head screwdriver to carefully and gently ‎open the ports on the screw terminal. These are pretty easy to break ‎so be gentle. Look carefully at the openings as you turn the screws. ‎When you see a square opening appear, stop turning.‎

Strip about 1/8" of wire from the 3 connector wires and insert ‎carefully into the screw terminals. Use red for +, the middle wire for ‎data, and the remaining wire for -. Gently tighten the screw until it's ‎snug: about 5 turns -- it shouldn't turn freely, if it does, you've got the ‎wire in the wrong part of the hole so pull it out and try again.‎

connections_20connections_21

The wires should not come out easily when you tug. But, as we know, ‎these controllers get tugged on all the time! After testing to be sure ‎of my connections, I added a zip tie around the back of the controller ‎to create strain relief on the connectors. ‎

wires_22

wires_23

Connect the female side of the JST connector to your LED strip or ‎strand, making sure the wire order matches the male connector in ‎your screw terminal: +5v (red) should match up to +, data IN to GPIO, ‎and G to G. Plug in your strand and power up the board. The board ‎comes pre-loaded with a rainbow animation so your lights should ‎come on if you've got everything hooked up right.‎

strip_24

strip_25

WLED Setup

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

The following pages will walk you through installing WLED and ‎setting up the various features within the software. We will cover ‎getting your lights turned on and responding to sound or IR control. ‎We'll also show you how to connect sensors via the onboard ‎Stemma port and add button control. And we'll show you how to set ‎up multiple strands and multiple controllers and sync them together ‎for larger scale projects.‎

Ready? Set? Let's go.‎

setup_26

WLED Software

Board Choices

WLED runs on several different boards in Adafruit's collection. There ‎are different benefits to each, but the installation process is largely ‎the same. This page contains instructions for multiple boards -- be ‎sure to use the pinouts and installation instructions for the one ‎you're using,‎

Sparkle Motion

This is our flagship ESP32 board, designed with WLED and Xlights in ‎mind. It has 4 outputs and is set up to drive either 5v, 12v or 24v ‎pixels. It's a workhorse of a board and for larger projects it's the clear ‎winner. It has an onboard microphone for instant sound-reactive ‎support, and an IR sensor built in, to make it easy to control your ‎project with an infrared remote. It also has a couple stemma ports so ‎you can add your own sensors or peripherals.‎

Sparkle Motion Mini

The Sparkle Motion Mini is a smaller version of the Sparkle Motion ‎board. It has two LED outputs, a microphone, and two stemma ports ‎that make it easy to add an IR sensor or other peripherals. It's got an ‎onboard NeoPixel and a small footprint, making it perfect for ‎wearables or smaller projects. It will power a whole lot of pixels ‎through the onboard USB port: it's safe to draw up to 4A through this ‎port, giving you plenty of power for most wearable projects.‎

At this time, the Sparkle Motion Mini works best with WLED 0.15.1 ‎‎-- the extra GPIO for the microphone pins are not supported in ‎WLED 0.15.0. This should be fixed with the release of version 16.‎

To get mic support now, the following combined .bin file can be used. ‎Get it by downloading this zip file:‎

esp32_bootloader_v4_WLED_0.16.0-alpha_ESP32.zip

To install, extract the .bin file from the zip and then follow the ‎same ESB Web Flasher process used for installing CircuitPython. ‎At the "Programming the Board" step, choose the .bin file and leave ‎offset as 0x0.‎

QT Py Pico ESP32‎

The QT Py Pico is small and affordable, so usually my go-to for ‎smaller costumes or wearables. It also has a range of BFF add-on ‎boards that add functionality. Here's a guide with more QT Py info. ‎The QT Py will drive up to around 30 pixels through the onboard USB ‎port, so if you have more LEDs than that you may want to consider ‎the Sparkle Motion Mini instead, or you can power the board through ‎the +5v pin.‎

Note: WLED works on the QT Py Pico but NOT on the S2 or S3 ‎versions, at the time of writing.‎

Feather Huzzah ESP32

The Feather Huzzah ESP32 the top of the line. It's a great choice for ‎projects where you want to add sensors, interaction, or drive a whole ‎lot of LEDs. It's the most reliable as well -- I've run these for two ‎months straight with no power cycling and they just keep on truckin. ‎Adafruit has a very wide selection of Feather Wing boards that ‎connect to the Feather microcontroller line. The sky is the limit with ‎these boards.‎

It also comes in a version with a high-powered WiFi range extender! ‎If you're trying to sync multiple instances across distance, check this ‎one out Feather Huzzah ESP32 V2 w.FL Antenna.

Feather Huzzah ESP8266‎

The Feather Huzzah ESP8266 will run WLED as well but won't drive ‎as many pixels: the ESP32 limit on WLED is around 1000 pixels per ‎input, but the ESP8266 tops out at around 500. It's about $5 cheaper ‎though, so for smaller projects it's a great way to save a little money ‎and still have access to all the Featherwing options in the Adafruit ‎store.‎

Driver Update

Some versions of our controllers have a new serial chip which needs ‎a driver installed before we can install WLED. Head over to our How ‎to Install Drivers for WCH USB to Serial Chips tutorial and download ‎and install the new driver.‎

If you have an older QT Py with CP2102 USB-to-Serial bridge, use ‎SiLabs’ driver instead.‎

‎Install WLED

These next steps require a Web Serial-compatible browser. As of ‎this writing, that ‎means Google Chrome, Microsoft Edge or Opera “desktop” ‎browsers. Other browsers (Safari, Firefox, Explorer ‎and anything mobile) won’t work.‎

Visit https://install.wled.me/‎

Plug your microcontroller into your computer with a known good ‎USB cable. Click "Install" and select the port for your board.‎

Depending on the USB-to-serial bridge chip on the board, you might ‎see one or two serial ports. On Mac, for instance, there might be both ‎‎“/dev/cu.usbmodem[number]” and “/dev/cu.wchusbserial[number]”. ‎Use the “wchusbserial” one.‎

browser_26

After successful installation, enter your WiFi network name and ‎password when prompted. This must be a 2.4 GHz WiFi network; ‎ESP32 does not support 5 GHz networks. If it can’t connect, then as a ‎fallback WLED will create its own 2.4 GHz WiFi access point.‎

network_27

Sometimes the "Connect to Wi-Fi" prompt doesn't show up. Don't ‎panic, just see the step below on connecting your computer or ‎mobile device to the WLED-AP access point created on the ‎microcontroller itself!‎

If you don't see the "Connect to Wi-Fi" prompt, you'll need to set up ‎your WiFi network using AP (access point) mode. Open up your WiFi ‎settings and look for a WiFi network called WLED-AP. (Note, this ‎access point can take up to 30 seconds to appear sometimes.) ‎Connect to this network using the default password wled1234. The ‎WLED interface will pop up in its own captive browser window.‎

From here, go into Config/Wifi Settings and enter your WiFi ‎credentials for the access point you normally use near the top.‎

Give your project a name in the mDNS field a little further down the ‎page. Now you can type in "projectname.local" (where "projectname" ‎is your mDNS name) into any web browser on the same wifi network ‎to access your microcontroller.‎

You can also scan the QR code below to open access point mode. ‎

For more help and troubleshooting tips visit the Getting Started ‎page on the WLED knowledge base.‎

dashboard_28

dashboard_29

dashboard_30

qr_31

Setup & Preferences

WiFi Setup

Head to the WiFi Setup screen under Config and create a good URL ‎so you can control your project from any web-enabled device. Call it ‎something you'll remember, that's easy to type into any web ‎browser on your WiFi network in order to connect to your project.‎

In Safari or Chrome on your phone or computer, type in this web ‎address to access the WLED ‎interface: http://projectname.local (where "projectname" is whatever ‎you put into this field).‎

Check out the Additional Settings page for more info on accessing ‎your project. WLED has an "access point mode" that doesn't require ‎a WiFi network for when you're out on the go. It's also helpful to ‎download one of the WLED apps to help manage and organize your ‎projects.‎

create_32

create_33

LED Preferences

Next, head to the LED Preferences tab under the Config menu.‎

Scroll down to Hardware Setup. Put your total number of LEDs into ‎the "Length" field and change GPIO to the pin number associated ‎with the pin you soldered to. Check the pinout diagram for the board ‎you're using (it's the number in yellow).‎

preferences_34

Use It

useit_35

Now you can use any computer or handheld device to control your ‎LEDs. ‎

Make sure your device is on the same WiFi network as your board. ‎Navigate to your custom URL (projectname.local/ ) in a web browser. ‎You'll see a color picker above a whole bunch of color palette choices.‎

Choose a color, choose an effect, and watch your lights animate and ‎glow!‎

Save your favorite combinations as presets, create playlists, control ‎the speed and intensity of the animations, and lots more. This web ‎app is incredibly intuitive and easy to use.‎

Head over to the WLED wiki at https://kno.wled.ge/ to delve into all ‎the particulars.‎

WLED Config

Next, we'll tell WLED about our physical setup. We'll give our project ‎a name and easy-to-remember URL and tell the software how many ‎LEDs we have set up on each pin.‎

WiFi Setup

Head to the WiFi Setup screen under Config. This is where your ‎network credentials live, so you can change them if needed. Scroll ‎down to the mDNS field and create a good URL so you can control ‎your project from any web-enabled device. Call it something you'll ‎remember, that's easy to type into any web browser on your WiFi ‎network in order to connect to your project. ‎

In this example, I'd go to my web browser on my phone, iPad, or ‎computer, and type in "http://projectname.local" to open up the ‎WLED interface on my screen. Your device must be on the same ‎WiFi network as your board.

name_36

name_37

LED Preferences

Next, head to the LED Preferences tab under the Config menu.‎

Scroll down to Hardware Setup. The Sparkle Motion board has 4 ‎spots to attach LED strips: the screw terminal uses GPIO 19, 22, and ‎‎21 and the through-hole solder pads to the left of the screw terminal ‎is GPIO 23.‎

WLED allows up to 4 strips to be connected at once. The strips can ‎be of different types, lengths, and color order. Select your LED type, ‎length, and GPIO pin. If you have multiple strips connected, click the ‎‎+ button and enter the additional strips in the same way. ‎

menu_38

menu_39

Click "save" and if you've done everything correctly, your light ‎strands should come on in a warm, cheerful yellow color. Success! ‎Time to start making pretty light animations. ‎

Troubleshooting

If your lights didn't come on, here are a few things to try:‎

  1. Head back to WLED and check your pinout configuration ‎under LED Preferences. Be sure the pin number is the correct ‎GPIO for the attachment point you used.‎

  2. Check your wiring! Be sure you connected to the IN end of the ‎LED strip. These strips can be inconsistent, so this is a pretty ‎common problem. Use an alligator clip to try connecting the ‎data wire on the other end (the power and ground wires should ‎work from either end).‎

  3. Try re-uploading the WLED software. ‎

  4. If the lights come on but you can't control them: i.e. you type in ‎‎"projectname.local" into your browser and it won't connect, ‎make sure you're on the correct WiFi network. If you're on a ‎different network than the one you set up the software on, you ‎won't see the WLED connection.‎

  5. If your lights came on in blue or green instead of yellow, your ‎color order is wrong. See below to fix.‎

  6. If only half your lights came on, be sure you've got the correct ‎number in the "length" field under LED preferences.‎

  7. If your lights came on in a variety of weird colors and looking ‎like a 1950s diner interior, you may have the wrong LED strip ‎type selected. RGBW strips and RGB strips are not the same, so ‎be sure you've got the correct strip type, or you'll get very odd ‎behavior.‎

  8. If your microcontroller hangs or keeps rebooting, or gets really ‎hot, you may have the power and ground lines switched. ‎Unplug right away and check: this is a fast way to brick your ‎controller.‎

Color Order

If your lights have come on in any color other than a warm yellow, ‎there's one more setting to change. LED strips and pixels are not all ‎standardized, and sometimes the red, green, and blue LEDs inside ‎are connected in a different order. ‎

In the main interface window, choose "solid" as your effect and red ‎as your color from the color picker. ‎

If your lights come on in any color other than red, your color order is ‎set incorrectly. This is an easy fix. Head back to the LED settings tab ‎and find the Hardware Setup section (this is where you set up your ‎pin number earlier). Choose BRG from the dropdown, click save, and ‎see if your pixel colors match your color picker now. If not, try ‎another combo until the lights look correct.‎

color_40

color_41

IR Remote Setup

Adding infrared control to your project is easy. WLED comes ‎preprogrammed to use a variety of common IR remote controls, so ‎you can get instant functionality with just a little bit of setup.‎

The Sparkle Motion board has an onboard IR sensor on pin 32. It's ‎also not too hard to set up your own IR sensor on the stemma port ‎on GPIO 27 in case you want a more accessible sensor if your board ‎is hidden inside an enclosure or inconveniently located. ‎

Click the LED Preferences tab and scroll down to Hardware Setup.‎

Change the IR GPIO pin to 32 and select which remote you're using ‎from the dropdown. I like this 44 key remote since it gives me quick ‎full-strip color control as well as plenty of customizable buttons to ‎use with my different presets.‎

presets_42

Remote Usage: 44 Key Remote

Change the brightness or turn the strip on and off with the buttons ‎on the top row.‎

When you have the "solid" effect selected in WLED, the color buttons ‎near the top of the remote will change the colors, making the pixels ‎act like a "dumb" RGB strip. ‎

On my 44-key remote, there are buttons near the bottom labeled ‎‎"DIY1", "DIY2" etc. WLED will automatically assign your animation ‎presets to these buttons so you can select your favorite presets or ‎playlists. Simply save the presets you want to the first 6 preset slots ‎and the buttons will pull them up. ‎

Head over to the WLED wiki at https://kno.wled.ge/ to delve into all ‎the particulars.‎

Adding a Wired IR Sensor

Sometimes you want to place your IR sensor further away from your ‎microcontroller to make an easier line-of-sight for the remote control. ‎Here's how to add a wired IR sensor or IR breakout to the Stemma ‎port on the Sparkle Motion board to make this easy. Use GPIO 27 in ‎config.‎

You'll need an IR sensor and a STEMMA JST 3-pin connector with ‎female sockets. Plug the connector into the smaller of the two ‎Stemma ports. Looking at the sensor with the bump facing you:‎

  • White wire on the left

  • Black wire in the middle

  • Red wire on the right

You can lengthen the wires as needed so your IR sensor ends up ‎right where you want it. ‎

We also have these handy IR breakout boards available.‎

adding_43

WLED Autoreactive Setup

The Sparkle Motion board comes with an onboard PDM microphone, ‎so adding audio reactivity to your project is easy. Here's how to get it ‎set up.‎

Click Config and then select the Usermods tab.

config_42

Scroll down a bit ‎and you'll find the Autoreactive section. ‎

Click the box to enable, then enter the settings and the Digitalmic ‎section as follows:‎

  • Type: Generic I2S

  • Pin I2S SD: 25

  • Pin I2S WS: 33‎

  • Pin I2S SCK: 26‎

The other pins are unused.‎

Reboot your microcontroller for changes to take effect.‎ ‎That means either pressing the reset button or unplugging the board from power completely for a few seconds.

reboot_44

If you want the audio to work well in both loud and quiet settings, you may want to turn on AGC - automatic gain control. Start with Normal and then experiment with other options if you want more or less 'gain speed'.

settings_43

There are a lot of other settings you can adjust in WLED. I found that ‎the default settings for this mic seem to work perfectly, but you can ‎delve into the particulars at https://kno.wled.ge/advanced/audio-‎reactive/‎.

To use audio reactive mode, head back to the main interface and ‎select any effect that has a music note icon next to the name. You can also search for musical-reactive effects that are built in.

Make ‎some noise and see how your lights react.‎ If it doesn't work, check your pins, try turning on AGC, tapping on the mic, and rebooting (removing power completely, waiting a few seconds then turn back on).

noise_45

If you happen to have a 2D matrix as an output, the GEQ effect shows a 'binned' frequency response graph which can be good for debugging!

matrix_46a

matrix_47b

WLED 2d Matrix

If you're using a 2-d matrix such as an LED curtain or net, WLED has ‎a handy 2d-matrix setup feature that will take care of the mapping ‎for you. Head to Config and choose the 2D Configuration tab.‎

Check out these tutorials for more about 2d mapping with WLED:‎

Change the dropdown to read 2d Matrix, and additional options will ‎appear. If you want to sync more than one panel, you can do it here. ‎

Set up your layout numbers to match the number of rows and ‎columns in your project. You can also change orientation here - my ‎pixels start in the lower left corner and finish in the upper right.‎

matrix_45

matrix_46

Matrix Effects

WLED has a hefty number of matrix effects that appear in the list ‎when you've got your 2d matrix set up. Many of them can be ‎customized with speed and intensity sliders, or different color ‎palettes. Go wild! ‎

effects_47

Create Presets

Animation Presets

Once your lights are working, it's time for the fun part: creating light ‎animations using WLED presets. This is easy and intuitive in WLED. ‎Choose a color palette and an effect, then play with the sliders at the ‎bottom of the Effect Mode column to customize the effect.‎

When you find something, you like, click the +Preset button in the ‎Presets tab and give your preset a name, then save it. You can ‎reorder them using the "Save to ID" field. ‎

You can create hundreds of presets using the preprogrammed ‎effects, so take some time to play around and see what looks good ‎on your LED strip.‎

presets_48

Create at least 3 presets and be sure they are saved to ID numbers 1-‎‎3. Our next step will be to set up the switch to toggle between these ‎presets. ‎

Control Presets

The WLED preset interface can also be used to send control ‎commands to the LED strip. Once you've set up a button or switch, it ‎can be used for a wide variety of control functions: change modes, ‎change brightness, toggle the lights on and off, or a whole host of ‎other features. ‎

Each button function in WLED has 3 options: a short press, a long ‎press, or a double press. I want my lights to cycle through presets ‎with a short press, and to turn on or off with a long press. Here's how ‎I set up a control preset for each of these features.‎

Cycle through Presets

Click +Preset and then uncheck the "Use current state" checkbox. ‎This will open up an API command window within the preset ‎module.‎

Call the effect "Next_FX" and type {"ps":"1~3~"} into the API command ‎box. This tells WLED to cycle through presets 1-3. If you'd like to cycle ‎through more presets, change the 3 to the number of presets you ‎have. ‎

Be sure your preset IDs include all the numbers -- skipping a ‎number will break this command.‎

Give your preset an ID number that's above the range of your preset ‎numbers -- I called mine 9. ‎

cycle_49

It's also possible to cycle between playlists. I made a playlist of sound ‎reactive effects and a separate playlist of "standard" effects. I set up a ‎preset that toggles between the two playlists -- effectively turning ‎‎"sound reactive" mode on and off.‎

cycle_50

Toggle On/Off

Create another preset and call it "Toggle". Uncheck the "use current ‎state" checkbox and enter T=2 into the API command box. This will ‎tell the LEDs to toggle between on and off. Save this one to ID 10.‎

create_51

On the next page we'll connect these control presets to our button.‎

Find out more about creating these control presets here: ‎

https://kno.wled.ge/features/presets/‎

You can enter either JSON commands or HTTP commands into this ‎command box, giving you a lot of control over your WLED project. ‎

https://kno.wled.ge/interfaces/json-api/‎

WLED Button Setup

Adding a control button is easy with the Sparkle Motion board. Any ‎momentary switch will work. I'm using this chonky 12mm Tactile ‎Switch Button and a STEMMA JST PH 2mm 3-Pin connector with ‎female sockets.‎

Plug the JST connector into the smaller of the two stemma ports. ‎Straighten out the legs on one side of your button and slip the legs ‎into the female connectors: one leg goes to white (data GPIO 27), the ‎other to black (G). ‎

It's fine to extend these wires so they're longer. For a more solid ‎connection you can cut the connectors off and solder directly to the ‎button legs.‎

legs_52

Open up the LED settings screen in WLED under "Config". Scroll to ‎the button setup section and set button 1 to use pin 27, with the type ‎set as "Pushbutton".‎

Click save. Try pressing your button and see if your effects change. ‎The default behavior for button 1 is to cycle through effects, but we ‎can change this and set up the button for any number of behaviors ‎using the Presets panel.

open_53

I advise against using button 0. WLED's buttons have some default ‎behaviors written in, and one of button 0's default behaviors is that ‎when it's pressed for more than a few seconds, it resets your ‎microcontroller to factory settings. I originally had button 0 selected, ‎and I held the button down a bit too long while I was sewing it onto ‎the hat, and .. POOF. All my settings and presets were wiped out. ‎

Check out the "Backup" section under the Additional Settings page ‎to learn to back up your configuration and presets, in case this kind ‎of thing happens to you.‎

Next, head to the Time & Macros config screen. Scroll down to the ‎Button actions area. ‎

For button 1, enter the number assigned to the two control presets ‎you made on the last page. My Next_FX preset is number 22, so I ‎entered 22 under "short press", and my Toggle preset is number 21, ‎so I've got that set up as a "long press". ‎

I also added my playlist toggle to preset 20, so a double-click of my ‎button will turn sound reactive mode on or off.‎

toggle_54

toggle_55

Troubleshooting

If your button isn't working, here are some things to try:‎

  1. ‎Double check both the LED preferences page and the Time & ‎Macros page to be sure your settings are correct and have ‎saved.‎

  2. Be sure your presets are correctly numbered. WLED gets ‎confused if the presets have non-sequential IDs (so make sure ‎they're numbered 1, 2, 3 rather than 2, 5, 7).‎

  3. Be sure you're connected to the correct legs on your button. ‎You want the legs on the same side (facing the same way), ‎rather than connecting to the two top legs or the two bottom ‎legs. Those pins are connected together inside the button so ‎won't work when the switch is activated.‎

WLED Additional Settings

Brightness Limiter

Find this on the LED Settings screen.‎

WLED automatically limits the brightness of your project, so your ‎power supply doesn't get over-taxed. The default amperage is ‎‎850mA, which is a little low for most power supplies.‎

For some projects, especially battery-powered projects, having the ‎limiter turned on is a good idea. But if you're not getting the ‎brightness you expect, try adjusting this number to match the ‎amperage of your power supply or battery pack.‎

brightness_56

Access Point (AP) Mode

While your home, it's easy to control your project over your local WiFi ‎network. But when you're out at a festival you probably don't have ‎WiFi access. It's still possible to connect to your project and control it ‎using WLED's Access Point Mode.‎

Turn your project on and give it a minute or two to start broadcasting. ‎Look in your WiFi networks and find WLED-AP - this is a mini-WiFi ‎network being broadcast by the Feather. Connect to it - the default ‎password is "wled123". An instance of WLED will automatically pop ‎up and you can control your project from anywhere.‎

If you're putting your lights up in public, it's a good idea to change ‎the AP Mode default password so strangers can't log in and control ‎your lights. This could be a security risk.‎

AP Mode only broadcasts for a few minutes after you boot up the ‎board so if you don't see the WLED-AP network try rebooting.‎

access_57

WLED App

There are a couple different apps available to manage your WLED ‎projects. Name and organize your projects and find them quickly ‎without having to type in a URL. Check the Apple or Android store for ‎downloads. ‎

My favorite is "WLED Native". It allows you to organize multiple ‎instances and easily switch between devices without having to ‎remember any URLs. ‎

native_58

Backup Config & Presets

Under Config / Security & Updates you will find a place to back up ‎your data. It's a good idea to back up your config file as soon as ‎you're happy with the settings. Save it as a .json file on your ‎computer. Now you can prototype and experiment to your heart's ‎content, and if everything breaks, just re-upload this file. Or, if you're ‎doing another build you can use this feature to copy all your settings ‎from one board to another.

backup_59

Install CircuitPython

CircuitPython is a derivative of MicroPython designed to simplify ‎experimentation and education on low-cost microcontrollers. It ‎makes it easier than ever to get prototyping by requiring no upfront ‎desktop software downloads. ESP32 CircuitPython firmware is ‎uploaded to the board via the USB serial port.‎

Follow this step-by-step to get CircuitPython running on your board.‎

Driver Install

If this is your first time using an ESP32 board on Windows or MacOS, ‎you may need to install the USB to serial drivers. There are two ‎options for the USB to serial chipset on your board. If you are unsure ‎which one you have, install both drivers.‎

For instructions and more information regarding the CH9102F chip ‎and driver install, please visit the How to Install Drivers for WCH USB ‎to Serial Chips guide.‎

For driver downloads for the CP2104 and CP2012N, please visit ‎the Silicon Labs Downloads page.‎

For those running Linux, the drivers are already included.‎

CircuitPython Download

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

Download the latest version of CircuitPython for this board via ‎circuitpython.org

Click the link above to download the latest CircuitPython .bin file.‎

Save it wherever is convenient for you.‎

download_60

Connecting to the Web Flasher

To begin, plug your board into your computer via USB, using a ‎known-good data-sync cable, directly, or via an adapter if needed.‎

You will have to use the Chrome or a Chromium-based browser to ‎install CircuitPython. For example, Edge and Opera are Chromium ‎based.‎

Safari and Firefox, etc. are not supported - they have not ‎implemented Web Serial!‎

In the Chrome ‎browser visit https://adafruit.github.io/Adafruit_WebSerial_ESPTool/‎

The main page of the ESP Web Flasher should look something like ‎this.‎

Note: The site now displays an alert that it is no longer maintained ‎and suggests using a different option. The ESP Web Flasher has still ‎proven to be more consistent and easier to use, so it is highly ‎suggested that you continue with this version.‎

flasher_61

You should remove all other USB devices so only the target board ‎is attached. This eliminates confusion over multiple ports!‎

Press the Connect button in the top right of the web browser. You ‎will get a pop up asking you to select the COM or Serial port. Look ‎for USB Single Serial.‎

On some systems, such as MacOS, there may be additional system ‎ports that appear in the list (as shown in the image).‎

connect_62

The JavaScript code will now try to connect to the board. It may ‎timeout for a bit until it succeeds. On success, you will see that it ‎is Connected and will print out a unique MAC address identifying ‎the board along with other information that was detected.‎

core_63

Once you have successfully connected, the command toolbar will ‎appear.‎

toolbar_64

Erasing the Board Contents

If you would like to erase the entire flash area so that you can start ‎with a clean slate, you can use the erase feature. We recommend ‎doing this every time before installing or updating CircuitPython.‎

To erase the contents, click the Erase button. You will be prompted ‎as to whether you want to continue. Click OK to continue. If you do ‎not wish to continue, click Cancel.

erasing_65

You'll see "Erasing flash memory. Please wait..." This will eventually ‎be followed by "Finished." and the amount of time it took to erase.‎

Do not disconnect! Immediately continue on to Programming the ‎Board.‎

disconnect_66

Do not disconnect after erasing! You should immediately continue ‎on to programming your board. If you do not, you may end up with ‎your board in a bad state that makes it more difficult to continue. ‎You can avoid this!‎

Programming the Board

You can click on Choose a file... from any of the available buttons. It ‎will only attempt to program buttons with a file and a unique ‎location. Select the .bin file you downloaded at the beginning of this ‎page from the file chooser dialogue.‎

Verify that the Offset box next to the file location you used is 0x0. ‎The offset defaults to 0x0, so unless you changed it manually, it ‎should be good to go.‎

programming_67

programming_68

Once you choose a file, the button text will change to match your ‎filename. You can then click the Program button to start flashing.

choose_69

A progress bar will appear and after a minute or two, you will have ‎written the firmware.‎

bar_70

You've now successfully programmed CircuitPython onto your board! ‎As suggested in the output, press reset to run the new firmware.

press_71

As the ESP32 does not have native USB, no USB drive will show up ‎on your computer when you reset. With CircuitPython firmware ‎loaded, the REPL can be accessed over a serial/COM port.‎

For more details on installation, how to configure your ESP32, and ‎info on getting started with CircuitPython on your ESP32 using the ‎Web Workflow, check out the CircuitPython on ESP32 Quick Start ‎guide.‎

Connecting to the USB Workflow Code Editor

The USB workflow is a new feature and there may be bugs! If you ‎find a bug, please file an issue on GitHub.‎

To use the Code Editor, you will need an internet browser such as ‎Google Chrome or Microsoft Edge. It's possible that it may work in ‎other browsers as well, but these have been more thoroughly tested.‎

Open your browser and navigate to https://code.circuitpython.org/. ‎Select USB on the dialog prompt that comes up.‎

workflow_72

This will display a page of instructions along with a button to bring ‎up a list of devices to connect to.‎

Click Connect to Device and then select your board in the pop-up ‎window. Click Connect to connect your board to the editor.‎

click_73

click_74

Once you have connected, the Connect button in the upper right-‎hand corner should change to a Disconnect button.‎

disconnect_75

Navigating USB Workflow

Opening and Saving Files

Opening and Saving files is designed to be like to most other ‎applications. Just use the buttons along the top of the editor window.‎

Clicking the Open or Save As buttons along the top will open the ‎File Dialog. Clicking the Save + Run button will save your file and run ‎the code. If your file hasn't been saved yet, this will also bring up the ‎file dialog box.‎

dialog_75

The file dialog that appears is a simplified dialog that displays the ‎current path at the top, allows you to navigate through the file tree ‎to select the file you would like to open, and has buttons on the ‎bottom to open or save the file you would like to use.‎

Canceling will tell the editor that you do not want to continue with ‎the current operation.‎

dialog_76

The X at the top performs the same function as the Cancel button as ‎does clicking outside of the dialog.‎

On the Save As dialog, you can also type in a filename in the field ‎next to the button.‎

function_77

Running Code

As mentioned above, the Save + Run button will first save your file, ‎then run the code. The logic to run the code however is currently ‎very simplistic in that it will try a couple of basic strategies to run ‎your code but doesn't currently do much beyond that.‎

The way it works is if you are working on code.py in the root folder, a ‎soft reset will be performed, which automatically runs code.py. If you ‎were working on some code in another file, the editor will attempt to ‎perform an import on this code, which should run it. When you run ‎your code, it will automatically switch over to the serial terminal.‎

Click the Save + Run button to save and run the code current code.‎

save_78

File Dialog Toolbar

The file Dialog toolbar along the top allows you to perform common ‎operations on files and folders regardless of whether you are saving ‎or opening. Clicking the cancel button at the bottom will not undo ‎any operations that were performed with these buttons.‎

Renaming and Deleting Files and Folders

You can rename or delete both files and folders. An item must be ‎selected first for the buttons to become available.‎

Use the delete and rename buttons here to perform the ‎corresponding operation on the currently selected file or folder.‎

renaming_79

Creating New Folders

This feature allows you to create a new folder to store your work ‎inside of.‎

Clicking the new folder button at the top will prompt you for a folder ‎name. It will inform you of invalid folder names such as the same ‎name as an existing file or folder or a folder that begins with a period.‎

folder_80

folder_81

Uploading and Downloading Files and Folders

This feature allows you to upload or download files as long as they fit ‎in the available space. If you need to add images or sound files for ‎your project, you can use the upload button to add them. If you need ‎to retrieve a file from your device for whatever reason, the download ‎button will give you access to do that.‎

You can also download folders. When you select a folder and click ‎download, the contents of that folder are automatically zipped into a ‎single file. If nothing is selected when you click the download button, ‎the current folder will be used.‎

Use the upload or download buttons to easily add files or retrieve ‎them from your board.‎

downloading_82

Moving Files and Folders

This feature allows you to move files and folders to a different ‎location on the device. When you click the move button, another ‎prompt will appear on top of the dialog that allows you to navigate ‎to where you would like to move the currently selected item. ‎

Use the move button to move files or folders to a new location on ‎the device.‎

The second dialog that appears will show only folders and allow you ‎to navigate to where you would like to move the file.‎

moving_83

moving_84

Using the Serial Terminal

The serial terminal allows you to watch the output of your device as ‎well as type inputs just like you can from a separate application like ‎PuTTY, except there's nothing you need to configure. This allows you ‎to access the REPL or view the output of your currently running code.‎

Use the mode buttons in the bottom left-hand corner to open and ‎close the serial and editor panes.‎

serial_85

More Features to Come

The CircuitPython Code Editor is still under development, so expect ‎more features to be added. If you would like to contribute on GitHub, ‎you can submit any new issues or pull requests for review.‎

Blink

In learning any programming language, you often begin with some ‎sort of Hello, World! program. In CircuitPython, Hello, World! is ‎blinking an LED. Blink is one of the simplest programs in ‎CircuitPython. It involves three built-in modules, two lines of set up, ‎and a short loop. Despite its simplicity, it shows you many of the ‎basic concepts needed for most CircuitPython programs and ‎provides a solid basis for more complex projects. Time to get blinky!‎

LED Location

location_86

Blinking an LED

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/blink/ and then click on the ‎directory that matches the version of CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython Blink Example - the CircuitPython 'Hello, World!'"""
import time
import board
import digitalio

led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT

while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)

View on GitHub

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

editor_87

Navigate to the project bundle that you downloaded and select ‎the code.py file.‎

navigate_88

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.

overwrite_89

You'll see a new code.py file appear in the file browser. Select it and ‎click Open to view it in the code editor.‎

newcode_90

You'll see the LED blink code.py file contents. Click Restart above ‎the Serial monitor to run the LED blink code.‎

run_91

The built-in LED begins blinking!‎

Note that the code is a little less "Pythonic" than it could be. It could ‎also be written as led.value = not led.value with a ‎single time.sleep(0.5). That way is more difficult to understand if ‎you're new to programming, so the example is a bit longer than it ‎needed to be to make it easier to read.‎

It's important to understand what is going on in this program.‎

First you import three modules: time, board, and digitalio. This makes ‎these modules available for use in your code. All three are built-in to ‎CircuitPython, so you don't need to download anything to get started.‎

Next, you set up the LED. To interact with hardware in CircuitPython, ‎your code must let the board know where to look for the hardware ‎and what to do with it. So, you create a digitalio.DigitalInOut() object, ‎provide it the LED pin using the board module, and save it to the ‎variable led. Then, you tell the pin to act as an OUTPUT.‎

Finally, you create a while True: loop. This means all the code inside ‎the loop will repeat indefinitely. Inside the loop, you set led.value = ‎True which powers on the LED. Then, you use time.sleep(0.5) to tell ‎the code to wait half a second before moving on to the next line. The ‎next line sets led.value = False which turns the LED off. Then you use ‎another time.sleep(0.5) to wait half a second before starting the loop ‎over again.‎

With only a small update, you can control the blink speed. The blink ‎speed is controlled by the amount of time you tell the code to wait ‎before moving on using time.sleep(). The example uses 0.5, which is ‎one half of one second. Try increasing or decreasing these values to ‎see how the blinking changes.‎

That's all there is to blinking an LED using CircuitPython!‎

Digital Input

The CircuitPython digitalio module has many applications. The basic ‎Blink program sets up the LED as a digital output. You can just as ‎easily set up a digital input such as a button to control the LED. This ‎example builds on the basic Blink example but now includes setup ‎for a button switch. Instead of using the time module to blink the ‎LED, it uses the status of the button switch to control whether the ‎LED is turned on or off.‎

LED and Button

ledbutton_92

Controlling the LED with a Button

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/digital_input_built_in_button_led/ and then click on the directory that matches the version of ‎CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
CircuitPython Digital Input Example - Blinking an LED using the built-in button.
"""
import board
import digitalio

led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT

button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)

while True:
    if not button.value:
        led.value = True
    else:
        led.value = False

View on GitHub

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

editor_93

Navigate to the project bundle that you downloaded and select ‎the code.py file.‎

bundle_94

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

overwrite_95

You'll see a new code.py file appear in the file browser. Select it and ‎click Open to view it in the code editor.‎

new_96

You'll see the digital input code.py file contents. Click Restart above ‎the Serial monitor to run the digital input code.‎

digital_97

Now, press the button. The LED lights up! Let go of the button and ‎the LED turns off.‎

adafruit_products_digitalio_btn_led_v2_scaled

Note that the code is a little less "Pythonic" than it could be. It could ‎also be written as led.value = not button.value. That way is more ‎difficult to understand if you're new to programming, so the example ‎is a bit longer than it needed to be to make it easier to read.‎

First you import two modules: board and digitalio. This makes these ‎modules available for use in your code. Both are built-in to ‎CircuitPython, so you don't need to download anything to get started.‎

Next, you set up the LED. To interact with hardware in CircuitPython, ‎your code must let the board know where to look for the hardware ‎and what to do with it. So, you create a digitalio.DigitalInOut() object, ‎provide it the LED pin using the board module, and save it to the ‎variable led. Then, you tell the pin to act as an OUTPUT.‎

You include setup for the button as well. It is similar to the LED setup, ‎except the button is an INPUT, and requires a pull up.‎

Inside the loop, you check to see if the button is pressed, and if so, ‎turn on the LED. Otherwise, the LED is off.‎

That's all there is to controlling an LED with a button switch!‎

Analog Input

The CircuitPython analogio module has many applications. You can ‎set up an analog input with a potentiometer connected to an analog ‎input pin on your board.‎

Necessary Hardware

You'll need the following additional hardware to complete the ‎examples on this page.‎

Wiring

  • JST-SH signal to potentiometer wiper (white wire)

  • JST-SH 3.3V to potentiometer positive (red wire)‎

  • JST-SH GND to potentiometer ground (black wire)‎

wiring_98

Reading the Potentiometer

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/analog_voltage_values/ and ‎then click on the directory that matches the version of CircuitPython ‎you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython analog voltage value example"""
import time
import board
import analogio

analog_pin = analogio.AnalogIn(board.A0)


def get_voltage(pin):
    return (pin.value * 3.3) / 65535


while True:
    print(get_voltage(analog_pin))
    time.sleep(0.1)

View on GitHub

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

window_99

Navigate to the project bundle that you downloaded and select ‎the code.py file.

bundle_100

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

ok_101

You'll see a new code.py file appear in the file browser. Select it and ‎click Open to view it in the code editor.‎

select_101

You'll see the analog input code.py file contents. Click Restart above ‎the Serial monitor to run the analog input code.‎

analog_102

Now, twist and turn the potentiometer. You'll see the analog voltage ‎values print to the serial console.‎

console_103

Built-In NeoPixel

Your board has a built-in RGB NeoPixel status LED. You can use ‎CircuitPython code to control the color and brightness of this LED. It ‎is also used to indicate the bootloader status and errors in your ‎CircuitPython code.‎

A NeoPixel is what Adafruit calls the WS281x family of addressable ‎RGB LEDs. It contains three LEDs - a red one, a green one and a blue ‎one - alongside a driver chip in a tiny package controlled by a single ‎pin. They can be used individually (as in the built-in LED on your ‎board) or chained together in strips or other creative form factors. ‎NeoPixels do not light up on their own; they require a ‎microcontroller. So, it's super convenient that the NeoPixel is built ‎into your microcontroller board!‎

This page will cover using CircuitPython to control the status RGB ‎NeoPixel built into your microcontroller. You'll learn how to change ‎the color and brightness, and how to make a rainbow. ‎Time to get started!‎

NeoPixel Location

location_104

NeoPixel Color and Brightness

To use with CircuitPython, you need to first install a few libraries, into ‎the lib folder on your board. Then you need to update code.py with ‎the example script.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/status_led_one_neopixel_rgb/ and then click on the directory that matches the version of ‎CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython status NeoPixel red, green, blue example."""
import time
import board
import neopixel

pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)

pixel.brightness = 0.3

while True:
    pixel.fill((255, 0, 0))
    time.sleep(0.5)
    pixel.fill((0, 255, 0))
    time.sleep(0.5)
    pixel.fill((0, 0, 255))
    time.sleep(0.5)

View on GitHub

Update the /lib Folder

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload ‎Folders.‎

view_105

Navigate to the project bundle that you downloaded and select ‎the /lib folder.‎

lib_106

You'll be asked if you want to upload the /lib folder from the Project ‎Bundle. Click Upload.‎

asked_107

After the upload finishes, you can open the lib folder to view the two ‎library files required for the NeoPixel examples.‎

after_108

Update code.py

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

files_109

Navigate to the project bundle that you downloaded and select ‎the code.py file.‎

bundle_110

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

overwrite_111

The built-in NeoPixel begins blinking red, then green, then blue, and ‎repeats!‎

adafruit_products_sparkle_builtin_neopixel_rgb_scaled

First you import two modules, time, and board, and one ‎library, NeoPixel. This makes these modules and libraries available ‎for use in your code. The first two are modules built-in to ‎CircuitPython, so you don't need to download anything to use those. ‎The NeoPixel library is separate, which is why you needed to install it ‎before getting started.‎

Next, you set up the NeoPixel LED. To interact with hardware in ‎CircuitPython, your code must let the board know where to look for ‎the hardware and what to do with it. So, you create ‎a neopixel.NeoPixel() object, provide it the NeoPixel LED pin using ‎the board module, and tell it the number of LEDs. You save this ‎object to the variable pixel.‎

Then, you set the NeoPixel brightness using ‎the brightness attribute. brightness expects float between 0 and 1.0. ‎A float is essentially a number with a decimal in it. The brightness ‎value represents a percentage of maximum brightness; 0 is 0% ‎and 1.0 is 100%. Therefore, setting pixel.brightness = 0.3 sets the ‎brightness to 30%. The default brightness, which is to say the ‎brightness if you don't explicitly set it, is 1.0. The default is really ‎bright! That is why there is an option available to easily change the ‎brightness.‎

Inside the loop, you turn the NeoPixel red for 0.5 seconds, green for ‎‎0.5 seconds, and blue for 0.5 seconds.‎

To turn the NeoPixel red, you "fill" it with an RGB value. Check out ‎the section below for details on RGB colors. The RGB value for red ‎is (255, 0, 0). Note that the RGB value includes the parentheses. ‎The fill() attribute expects the full RGB value including those ‎parentheses. That is why there are two pairs of parentheses in the ‎code.‎

You can change the RGB values to change the colors that the ‎NeoPixel cycles through. Check out the list below for some examples. ‎You can make any color of the rainbow with the right RGB value ‎combination!‎

That's all there is to changing the color and setting the brightness of ‎the built-in NeoPixel LED!‎

RGB LED Colors

RGB LED colors are set using a combination of red, green, and blue, ‎in the form of an (R, G, B) tuple. Each member of the tuple is set to a ‎number between 0 and 255 that determines the amount of each ‎color present. Red, green, and blue in different combinations can ‎create all the colors in the rainbow! So, for example, to set an LED to ‎red, the tuple would be (255, 0, 0), which has the maximum level of ‎red, and no green or blue. Green would be (0, 255, 0), etc. For the ‎colors between, you set a combination, such as cyan which is (0, 255, ‎‎255), with equal amounts of green and blue. If you increase all values ‎to the same level, you get white! If you decrease all the values to 0, ‎you turn the LED off.‎

Common colors include:‎

  • red: (255, 0, 0)

  • green: (0, 255, 0)‎

  • blue: (0, 0, 255)‎

  • cyan: (0, 255, 255)

  • purple: (255, 0, 255)‎

  • yellow: (255, 255, 0)‎

  • white: (255, 255, 255)‎

  • black (off): (0, 0, 0)‎

NeoPixel Rainbow

You should have already installed the library necessary to use the ‎built-in NeoPixel LED. If not, follow the steps at the beginning of the ‎NeoPixel Color and Brightness section to install it.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/status_led_one_neopixel_rainbow/ and then click on the directory that matches the version of ‎CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython status NeoPixel rainbow example."""
import time
import board
from rainbowio import colorwheel
import neopixel

pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
pixel.brightness = 0.3


def rainbow(delay):
    for color_value in range(255):
        pixel[0] = colorwheel(color_value)
        time.sleep(delay)


while True:
    rainbow(0.02)

View on GitHub

Update the code.py file in the USB code editor with the ‎rainbow code.py file. The same libraries from the RGB blinking ‎example are used. The NeoPixel displays a rainbow cycle!

adafruit_products_builtin_neopixel_rainbow_scaled

‎This example builds on the previous example.‎

First, you import the same three modules and libraries. In addition to ‎those, you import colorwheel.‎

The NeoPixel hardware setup and brightness setting are the same.‎

Next, you have the rainbow() helper function. This helper displays the ‎rainbow cycle. It expects a delay in seconds. The higher the number ‎of seconds provided for delay, the slower the rainbow will cycle. The ‎helper cycles through the values of the color wheel to create a ‎rainbow of colors.‎

Inside the loop, you call the rainbow helper with a 0.2 second delay, ‎by including rainbow(0.2).‎

That's all there is to making rainbows using the built-in NeoPixel ‎LED!‎

Sparkle Motion NeoPixel Demo

adafruit_products_sparkle_circuitpython_neopixel_animat

The main use of the Sparkle Motion is lighting up RGB LEDs to ‎dazzle and delight. CircuitPython has ‎the Adafruit_CircuitPython_Neopixel module, which allows you to ‎easily write Python code that lets you control NeoPixels, as well as ‎the Adafruit_CircuitPython_LED_Animation module that provides ‎more advanced control with an assortment of fun and colorful ‎animations. In the example below, you'll run two different LED ‎animations on two strips of NeoPixels at the same time. ‎

Wiring

NeoPixels

  • terminal block - to GND on both NeoPixel strips. (black wire)‎

  • terminal block + to 5V on both NeoPixel strips. (red wire)‎

  • terminal block 21 to DIN on the first NeoPixel strip. (green wire)‎

  • terminal block 22 to DIN on the second NeoPixel strip. (green ‎wire)‎

diagram_112

CircuitPython Usage

To use with CircuitPython, you need to first install a few libraries, into ‎the lib folder on your board. Then you need to update code.py with ‎the example script.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory Sparkle_Motion_Examples/CircuitPython_Sparkle_Motion‎_Neopixel_Animation/ and then click on the directory that matches ‎the version of CircuitPython you're using.‎

Example Code

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Example illustrating two different LED Animations running on
Neopixels connected to 2 of the main outputs of the Sparkle Motion
"""
import board
import neopixel

from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.color import GREEN

strip1_pixel_pin = board.D21
strip2_pixel_pin = board.D22

pixel_count = 8

strip1_pixels = neopixel.NeoPixel(
    strip1_pixel_pin, pixel_count, brightness=0.1, auto_write=False
)
strip2_pixels = neopixel.NeoPixel(
    strip2_pixel_pin, pixel_count, brightness=0.1, auto_write=False
)

comet = Comet(strip1_pixels, speed=0.05, color=GREEN, tail_length=3, bounce=True)
rainbow = Rainbow(strip2_pixels, speed=0.05, period=3)

while True:
    comet.animate()
    rainbow.animate()

View on GitHub

Update the /lib Folder

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload ‎Folders.‎

update_113

Navigate to the project bundle that you downloaded and select ‎the /lib folder.‎

select_114

You'll be asked if you want to upload the /lib folder from the Project ‎Bundle. Click Upload.‎

bundle_115

After the upload finishes, you can open the lib folder to view the two ‎library files required for the NeoPixel examples.‎

Your CIRCUITPY/lib folder should contain the following folders:‎

  • adafruit_led_animation/‎

  • adafruit_pixelbuf.mpy

  • neopixel.mpy

library_116

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

editor_117

Navigate to the project bundle that you downloaded and select ‎the code.py file.‎

project_118

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

previous_119

This example utilizes both of the NeoPixel outputs on terminal ‎blocks D21 and D22. It starts by initializing variables for the pixel pins ‎and count of how many NeoPixels are in each strip. Next it creates ‎instances of neopixel.NeoPixel for each strip. Then it creates ‎a Comet animation on one strip, and a Rainbow animation on the ‎other. Inside of the main while True: each animation object has ‎it's animate() function called to advance it by one step.‎

IR Remote

adafruit_products_ir_remote_neopixel_scaled_800

The Adafruit Sparkle Motion has an IR Receiver built-in for all of your ‎remote controlling needs. The Adafruit CircuitPython ‎IRRemote library makes it easy to decode the signals sent to the ‎receiver. This example will get you started by demonstrating how to ‎use one of our mini remote controls to change the color and ‎brightness of a connected strip of NeoPixels.‎

IR Receiver & NeoPixel Output Location

receiver_120

The IR Receiver is connected with the pin alias board.IR. This ‎example assumes the NeoPixel strip will be plugged in to the ‎terminal blocks for pin board.D21.‎

Necessary Hardware

You can use any IR remote with basic NEC codes that are supported ‎by the Adafruit CircuitPython IRRemote library, and any NeoPixel ‎strip that you like. The following items are the ones depicted on this ‎page.‎

Wiring

NeoPixels

  • terminal block - to GND on the NeoPixel strip. (black wire)‎

  • terminal block + to 5V on the NeoPixel strip. (red wire)‎

  • terminal block 21 to DIN on the NeoPixel strip. (green wire)‎

wiring_121

CircuitPython Usage

To use with CircuitPython, you need to first install a few libraries, into ‎the lib folder on your board. Then you need to update code.py with ‎the example script.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory Sparkle_Motion_Examples/CircuitPython_Sparkle_Motion‎_IR_Remote/ and then click on the directory that matches the ‎version of CircuitPython you're using.‎

Example Code

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython Adafruit Sparkle Motion IR remote control NeoPixels example."""
import time

import board
import pulseio
from rainbowio import colorwheel

import neopixel
import adafruit_irremote

pulsein = pulseio.PulseIn(board.IR, maxlen=120, idle_state=True)
decoder = adafruit_irremote.NonblockingGenericDecode(pulsein)

IR_CODE_UP = (0, 253, 160, 95)
IR_CODE_DOWN = (0, 253, 176, 79)

IR_CODE_RIGHT = (0, 253, 80, 175)
IR_CODE_LEFT = (0, 253, 16, 239)

t0 = next_heartbeat = time.monotonic()

pixel = neopixel.NeoPixel(board.D21, 8)

brightness = 1
pixel.brightness = brightness / 10

color_number = 160
pixel.fill(colorwheel(color_number))
while True:
    for message in decoder.read():
        print(f"t={time.monotonic() - t0:.3} New IR Message")
        if isinstance(message, adafruit_irremote.IRMessage):
            if message.code == IR_CODE_UP:
                brightness = min(brightness + 1, 10)
            elif message.code == IR_CODE_DOWN:
                brightness = max(brightness - 1, 0)
            elif message.code == IR_CODE_RIGHT:
                color_number = (color_number + 32) % 256
            elif message.code == IR_CODE_LEFT:
                color_number = (color_number - 32) % 256

            pixel.brightness = brightness / 10
            pixel.fill(colorwheel(color_number))

            print("Decoded:", message.code)
            print("Brightness: ", brightness/10, " Color: ", hex(colorwheel(color_number)))
        elif isinstance(message, adafruit_irremote.NECRepeatIRMessage):
            print("NEC repeat!")
        elif isinstance(message, adafruit_irremote.UnparseableIRMessage):
            print("Failed to decode", message.reason)
        print("----------------------------")

View on GitHub

Update the /lib Folder

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload ‎Folders.‎

browse_122

Navigate to the project bundle that you downloaded and select ‎the /lib folder.‎

downloaded_123

You'll be asked if you want to upload the /lib folder from the Project ‎Bundle. Click Upload.‎

click_124

After the upload finishes, you can open the lib folder to view the two ‎library files required for the NeoPixel examples.‎

Your CIRCUITPY/lib folder should contain the following folders:‎

  • adafruit_irremote.mpy

  • adafruit_pixelbuf.mpy

  • neopixel.mpy

finishes_125

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.

window_126

Navigate to the project bundle that you downloaded and select ‎the code.py file.

open_127

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

new_128

This example utilizes the NeoPixel output terminal blocks for pin D21. ‎It starts by initializing PulseIn and the IR Decoder instance. Then the ‎NeoPixel instance. Inside of the main while True: loop it reads any ‎incoming messages from the decoder. When the up or down ‎commands are received it raises or lowers the brightness of the ‎NeoPixels, when the right or left commands are received it changes ‎the color of the NeoPixels.‎

I2C Scan

scan_129

A QT Py ESP32-S2 connected to an MCP9808 Temperature Sensor ‎for I2C via STEMMA QT.‎

The I2C, or inter-integrated circuit, is a 2-wire protocol for ‎communicating with simple sensors and devices, which means it ‎uses two connections, or wires, for transmitting and receiving data. ‎One connection is a clock, called SCL. The other is the data line, ‎called SDA. Each pair of clock and data pins are referred to as a bus.‎

Typically, there is a device that acts as a controller and sends ‎requests to the target devices on each bus. In this case, your ‎microcontroller board acts as the controller, and the sensor breakout ‎acts as the target. Historically, the controller is referred to as the ‎master, and the target is referred to as the slave, so you may run into ‎that terminology elsewhere. The official terminology is controller and ‎target.‎

Multiple I2C devices can be connected to the same clock and data ‎lines. Each I2C device has an address, and as long as the addresses ‎are different, you can connect them at the same time. This means ‎you can have many different sensors and devices all connected to ‎the same two pins.‎

Both I2C connections require pull-up resistors, and most ‎Adafruit I2C sensors and breakouts have pull-up resistors built in. If ‎you're using one that does not, you'll need to add your own 2.2-10kΩ ‎pull-up resistors from SCL and SDA to 3.3V.‎

I2C and CircuitPython

CircuitPython supports many I2C devices and makes it super simple ‎to interact with them. There are libraries available for many I2C ‎devices in the CircuitPython Library Bundle. (If you don't see the ‎sensor you're looking for, keep checking back, more are being ‎written all the time!)‎

In this section, you'll learn how to scan the I2C bus for all connected ‎devices. Then you'll learn how to interact with an I2C device.‎

Necessary Hardware

You'll need the following additional hardware to complete the ‎examples on this page.‎

While the examples here will be using the Adafruit MCP9808, a high ‎accuracy temperature sensor, the overall process is the same for just ‎about any I2C sensor or device.‎

The first thing you'll want to do is get the sensor connected so your ‎board has I2C to talk to.‎

Wiring the MCP9808‎

The MCP9808 comes with a STEMMA QT connector, which makes ‎wiring it up quite simple and solder-free.‎

Connect the STEMMA QT cable from the STEMMA QT port on your ‎board to the STEMMA QT port on the MCP9808.

cable_130

Find Your Sensor

The first thing you'll want to do after getting the sensor wired up, is ‎make sure it's wired correctly. You're going to do an I2C scan to see if ‎the board is detected, and if it is, print out its I2C address.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file, open the ‎directory CircuitPython_Templates/i2c_scan/ and then click on the ‎directory that matches the version of CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""CircuitPython I2C Device Address Scan"""
import time
import board

i2c = board.I2C()  # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a microcontroller

# To create I2C bus on specific pins
# import busio
# i2c = busio.I2C(board.GP1, board.GP0)    # Pi Pico RP2040

while not i2c.try_lock():
    pass

try:
    while True:
        print(
            "I2C addresses found:",
            [hex(device_address) for device_address in i2c.scan()],
        )
        time.sleep(2)

finally:  # unlock the i2c bus when ctrl-c'ing out of the loop
    i2c.unlock()

View on GitHub

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

upload_131

Navigate to the project bundle that you downloaded and select ‎the code.py file.

file_132

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

new_133

You'll see a new code.py file appear in the file browser. Select it and ‎click Open to view it in the code editor.‎

open_134

Adafruit Sparkle Motion comes with one I2C device built in: HUSB238 ‎power delivery chip. The I2C scan code will show the addresses from ‎the built-in device and the MCP9808.‎

scancode_135

If you run this and it seems to hang, try manually unlocking your I2C ‎bus by running the following two commands from the REPL.‎

Copy Code
import board
board.I2C().unlock()

First you create the i2c object, using board.I2C(). This convenience ‎routine creates and saves a busio.I2C object using the default ‎pins board.SCL and board.SDA. If the object has already been ‎created, then the existing object is returned. No matter how many ‎times you call board.I2C(), it will return the same object. This is called ‎a singleton.‎

To be able to scan it, you need to lock the I2C down so the only thing ‎accessing it is the code. So next you include a loop that waits until ‎I2C is locked and then continues on to the scan function.‎

Last, you have the loop that runs the actual scan, i2c_scan(). Because ‎I2C typically refers to addresses in hex form, the example includes ‎this bit of code that formats the results into hex ‎format: [hex(device_address) for device_address in i2c.scan()].‎

Open the serial console to see the results! The code prints out an ‎array of addresses. You've connected the MCP9808 which has a 7-bit ‎I2C address of 0x18. The result for this sensor is I2C addresses found: ‎‎['0x18']. If no addresses are returned, refer back to the wiring ‎diagrams to make sure you've wired up your sensor correctly.‎

WiFi Test

In this example, you'll test your Sparkle Motion WiFi connection by ‎connecting to your SSID, printing your MAC address and IP address ‎to the REPL and then pinging Google.‎

settings.toml File

If you've worked on WiFi projects with CircuitPython before, you're ‎probably familiar with the secrets.py file. This file is a Python file that ‎is stored on your CIRCUITPY drive that contains all of your secret ‎WiFi information, such as your SSID, SSID password and any API keys ‎for IoT services. ‎

As of CircuitPython 8, there is support for a settings.toml file. Similar ‎to secrets.py, the settings.toml file separates your sensitive ‎information from your main code.py file.‎

Your settings.toml file should be stored in the main directory of your ‎board. It should not be in a folder.‎

settings.toml File Example

Here is an example on how to format your settings.toml file.‎

Download File

Copy Code
# Comments are supported
CIRCUITPY_WIFI_SSID="guest wifi"
CIRCUITPY_WIFI_PASSWORD="guessable"
CIRCUITPY_WEB_API_PORT=80
CIRCUITPY_WEB_API_PASSWORD="passw0rd"
test_variable="this is a test"
thumbs_up="\U0001f44d"

In a settings.toml file, it's important to keep these factors in mind:‎

  • Strings are wrapped in double quotes; ex: "your-string-here"

  • Integers are not quoted and may be written in decimal with ‎optional sign (+1, -1, 1000) or hexadecimal (0xabcd).‎

    • Floats, octal (0o567) and binary (0b11011) are not ‎supported.‎

  • Use \u escapes for weird characters, \x and \ooo escapes are not ‎available in .toml files

    • Example: \U0001f44d for 👍 (thumbs up emoji) ‎and \u20ac for € (EUR sign)‎

  • Unicode emoji, and non-ASCII characters, stand for themselves ‎as long as you're careful to save in "UTF-8 without BOM" format‎

When your settings.toml file is ready, you can save it in your text ‎editor with the .toml extension.‎

ready_136

CircuitPython WiFi Example

In the example below, click the Download Project Bundle button ‎below to download the code.py file in a zip file. Extract the contents ‎of the zip file and then click on the directory that matches the ‎version of CircuitPython you're using.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

from os import getenv
import ipaddress
import wifi
import socketpool

# Get WiFi details, ensure these are setup in settings.toml
ssid = getenv("CIRCUITPY_WIFI_SSID")
password = getenv("CIRCUITPY_WIFI_PASSWORD")

if None in [ssid, password]:
    raise RuntimeError(
        "WiFi settings are kept in settings.toml, "
        "please add them there. The settings file must contain "
        "'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
        "at a minimum."
    )

print()
print("Connecting to WiFi")

#  connect to your SSID
try:
    wifi.radio.connect(ssid, password)
except TypeError:
    print("Could not find WiFi info. Check your settings.toml file!")
    raise

print("Connected to WiFi")

pool = socketpool.SocketPool(wifi.radio)

#  prints MAC address to REPL
print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address])

#  prints IP address to REPL
print(f"My IP address is {wifi.radio.ipv4_address}")

#  pings Google
ipv4 = ipaddress.ip_address("8.8.4.4")
print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000))

View on GitHub

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

editor_137

Navigate to the project bundle that you downloaded and select ‎the code.py file.

select_138

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

bundle_139

Update Your settings.toml File

Remember to add your settings.toml file as described earlier in this ‎page. You'll need to include ‎your CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD in the ‎file. ‎

You can edit the file manually in the USB code editor by ‎clicking Open, selecting settings.toml and clicking Open at the ‎bottom of the dialog box.‎

box_140

With settings.toml open in the editor, you can add your WiFi ‎credentials:‎

CIRCUITPY_WIFI_SSID = "your-ssid-here"

CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here"‎

Once your credentials are entered, click Save above the editor to ‎save your changes to settings.toml.‎

once_141

Once everything is saved to the board, Restart the Serial Console to ‎see the data printed out!‎

saved_142

How the CircuitPython WiFi Example Works

In the basic WiFi test, the board connects to your SSID by importing ‎your SSID and SSID password from the settings.toml file.‎

Download File

Copy Code
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))

Then, your MAC address and IP address are printed to the REPL.‎

Download File

Copy Code
#  prints MAC address to REPL
print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address])

#  prints IP address to REPL
print("My IP address is", wifi.radio.ipv4_address)

‎Finally, google.com is pinged. The amount of time it takes to ping is ‎printed to the REPL and the code stops running.‎

Download File

Copy Code
#  pings Google
ipv4 = ipaddress.ip_address("8.8.4.4")
print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000))

By successfully running this WiFi test code, you can confirm that ‎your board is connecting to WiFi with CircuitPython successfully and ‎you can move on to more advanced projects.‎

Adafruit IO

Adafruit IO gives you the option to disconnect your microcontroller ‎from your computer and run it off of USB power or a battery, and still ‎be able to see the data. It also allows you to send data to your ‎microcontroller, such as NeoPixel colors. This example shows how to ‎both send data to and receive data from Adafruit IO. It pulls from a ‎‎"random" number generator and sends the "random" ‎number to Adafruit IO, while simultaneously listening for NeoPixel ‎color data from Adafruit IO.‎

NeoPixel Location

neopixel_143

Adafruit IO Feeds and Dashboard

The first thing you'll need to do, is head over to Adafruit IO and make ‎sure your account is set up.‎

Then, you need to create two feeds called neopixel and random. ‎These are case sensitive!‎

Next, you'll create a dashboard for the NeoPixel Color Picker. You can ‎name the dashboard whatever you like.‎

Once the dashboard is created, you'll want to add a color picker ‎block. The color picker block is highlighted by a red arrow in the ‎image below.‎

create_144

Once you choose the color picker block, you'll need to connect a feed ‎to it. Check the box next to neopixel.‎

check_145

Finally, a Block Settings page will come up. You can add an optional ‎block title here. Then you press Create Block.

block_146

The dashboard should look something like the following.‎

dashboard_147

Now that things are set up on the Adafruit IO end, you can continue ‎on to the code on your microcontroller!‎

Adafruit IO settings.toml

This example requires you to provide your Wi-Fi credentials, and ‎your Adafruit IO username and key. To do this, you'll want to create ‎a settings.toml file on your CIRCUITPY drive.‎

To obtain your Adafruit IO key, follow the initial steps on this page.‎

Your settings.toml file should be structured in a certain way and ‎contain all the necessary information. Follow these instructions ‎to create your settings.toml file.‎

Adafruit IO Example Code

To run this example, you need to first install the NeoPixel, Adafruit IO, ‎and Adafruit MiniMQTT libraries into the lib folder on your board. ‎Then you need to update code.py with the example script.‎

In the example below, click the Download Project Bundle button ‎below to download the necessary libraries and the code.py file in a ‎zip file. Extract the contents of the zip file. You'll see a code.py file ‎and /lib folder.‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Ladyada for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
import time
import ssl
import os
from random import randint
import microcontroller
import socketpool
import wifi
import board
import neopixel
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_io.adafruit_io import IO_MQTT


# WiFi
try:
    print("Connecting to %s" % os.getenv("CIRCUITPY_WIFI_SSID"))
    wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
    print("Connected to %s!" % os.getenv("CIRCUITPY_WIFI_SSID"))
# Wi-Fi connectivity fails with error messages, not specific errors, so this except is broad.
except Exception as e:  # pylint: disable=broad-except
    print("Failed to connect to WiFi. Error:", e, "\nBoard will hard reset in 30 seconds.")
    time.sleep(30)
    microcontroller.reset()

# Initialise NeoPixel
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.3)


# Define callback functions which will be called when certain events happen.
def connected(client):
    print("Connected to Adafruit IO!  Listening for NeoPixel changes...")
    # Subscribe to Adafruit IO feed called "neopixel"
    client.subscribe("neopixel")


def message(client, feed_id, payload):  # pylint: disable=unused-argument
    print("Feed {0} received new value: {1}".format(feed_id, payload))
    if feed_id == "neopixel":
        pixel.fill(int(payload[1:], 16))


# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)

# Initialize a new MQTT Client object
mqtt_client = MQTT.MQTT(
    broker="io.adafruit.com",
    username=os.getenv("ADAFRUIT_AIO_USERNAME"),
    password=os.getenv("ADAFRUIT_AIO_KEY"),
    socket_pool=pool,
    ssl_context=ssl.create_default_context(),
)

# Initialize Adafruit IO MQTT "helper"
io = IO_MQTT(mqtt_client)

# Set up the callback methods above
io.on_connect = connected
io.on_message = message

timestamp = 0
while True:
    try:
        # If Adafruit IO is not connected...
        if not io.is_connected:
            # Connect the client to the MQTT broker.
            print("Connecting to Adafruit IO...")
            io.connect()

        # Explicitly pump the message loop.
        io.loop()
        # Obtain the "random" value, print it and publish it to Adafruit IO every 10 seconds.
        if (time.monotonic() - timestamp) >= 10:
            random_number = "{}".format(randint(0, 255))
            print("Current 'random' number: {}".format(random_number))
            io.publish("random", random_number)
            timestamp = time.monotonic()

    # Adafruit IO fails with internal error types and WiFi fails with specific messages.
    # This except is broad to handle any possible failure.
    except Exception as e:  # pylint: disable=broad-except
        print("Failed to get or send data, or connect. Error:", e,
              "\nBoard will hard reset in 30 seconds.")
        time.sleep(30)
        microcontroller.reset()

View on GitHub

Update the /lib Folder

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload ‎Folders.‎

click_148

Navigate to the project bundle that you downloaded and select ‎the /lib folder.‎

bundle_149

You'll be asked if you want to upload the /lib folder from the Project ‎Bundle. Click Upload.‎

want_150

After the upload finishes, you can open the lib folder to view the ‎library files required for the Adafruit IO example.‎

after_151

Update code.py

In the editor window in your browser, click the Open button to view ‎the file dialog. Then, click the Upload button and select Upload Files.‎

editor_152

Navigate to the project bundle that you downloaded and select ‎the code.py file.‎

editor_153

You'll be asked if you want to overwrite the previous code.py with ‎the new code.py file from the Project Bundle. Click OK.‎

overwrite_154

Update Your settings.toml File

Remember to add your settings.toml file as described earlier in this ‎page. You'll need to include, ‎your ADAFRUIT_AIO_USERNAME, ADAFRUIT_AIO_KEY, CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD in the file.‎

You can edit the file manually in the USB code editor by ‎clicking Open, selecting settings.toml and clicking Open at the ‎bottom of the dialog box.‎

bottom_155

With settings.toml open in the editor, you can add your WiFi and ‎Adafruit IO credentials:‎

CIRCUITPY_WIFI_SSID = "your-ssid-here"

CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here"

ADAFRUIT_AIO_USERNAME = "your-aio-username-here"

ADAFRUIT_AIO_KEY = "your-aio-key-here"

Once your credentials are entered, click Save above the editor to ‎save your changes to settings.toml.‎

Once everything is saved to the board, Restart the Serial Console to ‎run the new code.py. You'll see the connection info and current ‎readings printed out in the console.‎

restart_156

NeoPixel Color Change

To change the color of the NeoPixel, go to the NeoPixel Adafruit IO ‎dashboard you created at the beginning, and click on the colored ‎circle in the ColorPicker block. It will bring up the following.‎

color_157

You can move the dot in the box around, and the slider line across ‎the gradient to choose the perfect color. Choose a new color and ‎click SAVE.‎

The NeoPixel color will update, and you will see the new value ‎printed to the serial console, as shown below.‎

update_158

Code Walkthrough

This example contains three try/except blocks. These are included ‎where the code is likely to fail due to WiFi or Adafruit IO connection ‎failures. WiFi can be finicky, and without these code blocks, if the ‎connection was lost, the code would crash. Instead, it is designed to ‎reset the board and start the code over again to reestablish the ‎connection, regardless of the cause. This ensures your code will ‎continue running. The details of these blocks are explained below.‎

First you import all of the necessary modules and libraries.‎

Download File

Copy Code
import time
import ssl
import os
from random import randint
import socketpool
import wifi
import board
import neopixel
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_io.adafruit_io import IO_MQTT

Note that if a settings.toml file is not present on your CIRCUITPY ‎drive, the code will fail to run, and you will receive an error in the ‎serial console. Add a settings.toml file to your CIRCUITPY drive to ‎resolve this error.‎

The WiFi attempts to connect and prints the status to the serial ‎console. If it connects successfully, the code continues onto the ‎NeoPixel set up.‎

Download File

Copy Code
try:
    print("Connecting to %s" % os.getenv("CIRCUITPY_WIFI_SSID"))
    wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
    print("Connected to %s!" % os.getenv("CIRCUITPY_WIFI_SSID"))

If the WiFi connection is not successful, the error will be printed to ‎the serial console, and the board will hard reset after 30 seconds.‎

Download File

Copy Code
except Exception as e:  # pylint: disable=broad-except
    print("Failed to connect to WiFi. Error:", e, "\nBoard will hard reset in 30 seconds.")
    time.sleep(30)
    microcontroller.reset()

Once the WiFi successfully connects, the NeoPixel object is initiated.‎

Download File

Copy Code
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.3)

Following that are two callback methods. For more details, check ‎out this guide. The connected method subscribes to the NeoPixel ‎feed on Adafruit IO. The message callback checks for updates to the ‎NeoPixel feed and turns the pixel the color from the feed.‎

Download File

Copy Code
def connected(client):
    print("Connected to Adafruit IO!  Listening for NeoPixel changes...")
    # Subscribe to Adafruit IO feed called "neopixel"
    client.subscribe("neopixel")


# pylint: disable=unused-argument
def message(client, feed_id, payload):
    print("Feed {0} received new value: {1}".format(feed_id, payload))
    if feed_id == "neopixel":
        pixel.fill(int(payload[1:], 16))

‎You create a socket pool, use that to initialise the new MQTT Client ‎object, and use that to initialise the Adafruit IO MQTT "helper".‎

Download File

Copy Code
pool = socketpool.SocketPool(wifi.radio)

mqtt_client = MQTT.MQTT(
    broker="io.adafruit.com",
    username=os.getenv("ADAFRUIT_AIO_USERNAME"),
    password=os.getenv("ADAFRUIT_AIO_KEY"),
    socket_pool=pool,
    ssl_context=ssl.create_default_context(),
)

io = IO_MQTT(mqtt_client)

You set up the callback methods mentioned above.‎

Download File

Copy Code
io.on_connect = connected
io.on_message = message

Next, you attempt to connect the client to the MQTT broker. If ‎connection is successful, the code continues on to the timestamp.‎

Download File

Copy Code
try:
    io.connect()

If the MQTT broker connection is not successful, the error is printed ‎to the serial console, and the board will hard reset after 30 seconds.‎

Download File

Copy Code
except Exception as e:
    print("Failed to connect to Adafruit IO. Error:", e, "\nBoard will hard reset in 30 seconds.")
    time.sleep(30)
    microcontroller.reset()

Once the broker is connected, you set ‎the timestamp to 0 immediately before the loop.‎

Download File

Copy Code
timestamp = 0

Inside the loop, you attempt to do two things. You first explicitly poll ‎the message loop. Check out this guide for more details on that.‎

Download File

Copy Code
while True:
    try:
        io.loop()

Second, you have a block of code that runs every 10 seconds. Inside, ‎you obtain a "random" value between 0-255 inclusive, print it to the ‎serial console, and publish it to an Adafruit IO feed. Finally, you reset ‎timestamp, so the block of code knows when another 10 seconds ‎has passed and runs again.‎

Download File

Copy Code
[...]
        if (time.monotonic() - timestamp) >= 10:
            random_number = "{}".format(randint(0, 255))
            print("Current 'random' number: {}".format(random_number))
            io.publish("random", random_number)
            timestamp = time.monotonic()

‎If at any time WiFi or Adafruit IO disconnects, the code will print the ‎error to the serial console, and the board will hard reset after 30 ‎seconds.‎

Download File

Copy Code
[...]
    except Exception as e:
        print("Failed to get or send data, or connect. Error:", e,
              "\nBoard will hard reset in 30 seconds.")
        time.sleep(30)
        microcontroller.reset()

That's all there is to using CircuitPython and Adafruit IO to send data ‎to Adafruit IO and receive data from it!‎

Arduino IDE Setup

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

We primarily recommend using the ESP32 chipsets with Arduino. ‎Don't forget you will also need to install the SiLabs CP2104 Driver if ‎you are using an ESP32 board with USB-to-Serial converter! ‎‎(There's no harm in doing it, so we recommend even if you aren't.)‎

Install Arduino IDE

The first thing you will need to do is to download the latest release of ‎the Arduino IDE. You will need to be using version 1.8 or higher for ‎this guide.‎

Arduino IDE Download

Install CP2104 / CP2102N USB Driver

Many ESP32 boards have a USB-to-Serial converter that talks to the ‎chip itself and will need a driver on your computer's operating ‎system. The driver is available for Mac and Windows. It is already ‎built into Linux.‎

Click here to download the CP2104 USB Driver

Install CH9102 / CH34X USB Driver

Newer ESP32 boards have a different USB-to-serial converter that ‎talks to the chip itself and will need a driver on your computer's ‎operating system. The driver is available for Mac and Windows. It is ‎already built into Linux.‎

If you would like more detail, check out the guide on installing these ‎drivers.‎

Click here to download the Windows driver

Click here to download the Mac driver

Install ESP32 Board Support Package from GitHub

For this board, we recommend you don't use 'release' version of ‎Espressif's board support package because the current release ‎doesn't include board support.‎

Instead, we will install the "very latest" by following these ‎instructions (scroll down for mac and Linux as well.‎

Basically, install by git cloneing the Espressif ESP32 board support to ‎get the very latest version of the code.‎

In the Tools → Board submenu you should see ESP32 Arduino (in ‎sketchbook) and in that dropdown it should contain the ESP32 ‎boards along with all the latest ESP32 boards.‎

tools_159

Look for the board called Adafruit Sparkle Motion (ESP32).‎

look_160

The upload speed can be changed: faster speed makes uploads take ‎less time but sometimes can cause upload issues. 921600 should ‎work fine, but if you're having issues, you can drop down lower.‎

Blink

The first and most basic program you can upload to your Arduino is ‎the classic Blink sketch. This takes something on the board and ‎makes it, well, blink! On and off. It's a great way to make sure ‎everything is working and you're uploading your sketch to the right ‎board and right configuration.‎

When all else fails, you can always come back to Blink!‎

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

adafruit_products_sparkle_blink_scaled

Pre-Flight Check: Get Arduino IDE & Hardware Set Up

This lesson assumes you have Arduino IDE set up. This is a ‎generalized checklist; some elements may not apply to your ‎hardware. If you haven't yet, check the previous steps in the guide to ‎make sure you:‎

  • Install the very latest Arduino IDE for Desktop (not all boards ‎are supported by the Web IDE, so we don't recommend it)‎

  • Install any board support packages (BSP) required for your ‎hardware. Some boards are built in defaults on the IDE, but lots ‎are not! You may need to install plug-in support which is called ‎the BSP.‎

  • Get a Data/Sync USB cable for connecting your ‎hardware. A significant amount of problems folks have stem ‎from not having a USB cable with data pins. Yes, these cursed ‎cables roam the land, making your life hard. If you find a USB ‎cable that doesn't work for data/sync, throw it away ‎immediately! There is no need to keep it around, cables are ‎very inexpensive these days.‎

  • Install any drivers required - If you have a board with a FTDI or ‎CP210x chip, you may need to get separate drivers. If your ‎board has native USB, it probably doesn't need anything. After ‎installing, reboot to make sure the driver sinks in.‎

  • Connect the board to your computer. If your board has a ‎power LED, make sure its lit. Is there a power switch? Make ‎sure it’s turned On!‎

Startup Arduino IDE and Select Board/Port

OK now you are prepared! Open the Arduino IDE on your computer. ‎Now you have to tell the IDE what board you are using, and how you ‎want to connect to it.‎

In the IDE find the Tools menu. You will use this to select the board. ‎If you switch boards, you must switch the selection! So always ‎double-check before you upload code in a new session.‎

startup_161

New Blink Sketch

OK let’s make a new blink sketch! From the File menu, select New.‎

blink_162

Then in the new window, copy and paste this text:‎

Download File

Copy Code
int led = LED_BUILTIN;

void setup() {
  // Some boards work best if we also make a serial connection
  Serial.begin(115200);

  // set LED to be an output pin
  pinMode(led, OUTPUT);
}

void loop() {
  // Say hi!
  Serial.println("Hello!");
  
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);                // wait for a half second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(500);                // wait for a half second
}

Note that in this example, we are not only blinking the LED but also ‎printing to the Serial monitor, think of it as a little bonus to test the ‎serial connection.‎

One note you'll see is that we reference the LED with the ‎constant LED_BUILTIN rather than a number. That's because, ‎historically, the built in LED was on pin 13 for Arduinos. But in the ‎decades since, boards don't always have a pin 13, or maybe it could ‎not be used for an LED. So, the LED could have moved to another ‎pin. It's best to use LED_BUILTIN so you don't get the pin number ‎confused!‎

Verify (Compile) Sketch

OK now you can click the Verify button to convert the sketch into ‎binary data to be uploaded to the board.‎

Note that verifying a sketch is the same as Compiling a sketch - so ‎we will use the words interchangeably.‎

note_163

During verification/compilation, the computer will do a bunch of ‎work to collect all the libraries and code, and the results will appear ‎in the bottom window of the IDE.‎

during_164

If something went wrong with compilation, you would get red ‎warning/error text in the bottom window letting you know what the ‎error was. It will also highlight the line with an error.

For example, here I had the wrong board selected - and the selected ‎board does not have a built in LED!‎

example_165

Here's another common error, in my haste I forgot to add a ; at the ‎end of a line. The compiler warns me that it's looking for one - note ‎that the error is actually a few lines up!‎

common_166

Turning on detailed compilation warnings and output can be very ‎helpful sometimes - It’s in Preferences under "Show Verbose Output During:" and check the Compilation button. If you ever need ‎to get help from others, be sure to do this and then provide all the ‎text that is output. It can assist in nailing down what happened!‎

On success you will see something like this white text output and ‎the message Done compiling. in the message area.‎

success_167

Upload Sketch

Once the code is verified/compiling cleanly you can upload it to your ‎board. Click the Upload button.‎

verified_168

The IDE will try to compile the sketch again for good measure, then ‎it will try to connect to the board and upload the file.‎

This is actually one of the hardest parts for beginners because it's ‎where a lot of things can go wrong.‎

However, let’s start with what it looks like on success! Here's what ‎your board upload process looks like when it goes right:‎

start_169

Often times you will get a warning like this, which is kind of vague:‎

No device found on COM66 (or whatever port is selected)

An error occurred while uploading the sketch

error_170

This could be a few things.‎

First up, check again that you have the correct board ‎selected! Many electronics boards have very similar names or look, ‎and often times folks grab a board different from what they thought.‎

Second, make sure you selected the right port! If you have the ‎wrong port or no port selected, Arduino doesn't know where to look ‎for your board.‎

If both of those are correct, the next step is to enable verbose upload ‎messages.‎

Before continuing we really really suggest turning on Verbose ‎Upload messages, it will help in this process because you will be ‎able to see what the IDE is trying to do. It's a checkbox in ‎the Preferences menu.‎

menu_171

Now you can try uploading again!‎

try_172

This time, you should have success!‎

After uploading this way, be sure to click the reset button - it sort of ‎makes sure that the board got a good reset and will come back to ‎life nicely.‎

Finally, a Blink!‎

OK it was a journey but now we're here and you can enjoy your ‎blinking LED. Next up, try to change the delay between blinks and ‎re-upload. It's a good way to make sure your upload process is ‎smooth and practiced.‎

adafruit_products_sparkle_blink_scaled

Built-In NeoPixel

Your board has a built-in RGB NeoPixel status LED. You can use ‎Arduino code to control the color and brightness of this LED. It is also ‎used to indicate the bootloader status.‎

A NeoPixel is what Adafruit calls the WS281x family of addressable ‎RGB LEDs. It contains three LEDs - a red one, a green one and a blue ‎one - alongside a driver chip in a tiny package controlled by a single ‎pin. They can be used individually (as in the built-in LED on your ‎board) or chained together in strips or other creative form factors. ‎NeoPixels do not light up on their own; they require a ‎microcontroller. So, it's super convenient that the NeoPixel is built ‎into your microcontroller board!‎

This page will cover using Arduino to control the status RGB ‎NeoPixel built into your microcontroller. Time to get started!‎

NeoPixel Location

location_173

Arduino Library Installation

You can install the necessary libraries from the Library Manager. To ‎open, click Sketch > Include Library > Manage Libraries...‎

install_174

Search for NeoPixel and install the Adafruit NeoPixel library.‎

search_175

There are no additional library dependencies for the Adafruit ‎NeoPixel library.‎

Rainbow Swirl Demo

Download File

Copy Code
// SPDX-FileCopyrightText: 2024 ladyada for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <Adafruit_NeoPixel.h>

#define NUMPIXELS 1
Adafruit_NeoPixel pixel(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);

  pixel.begin();
  pixel.setBrightness(25);
  pixel.show();

}

uint16_t firstPixelHue = 0;

void loop() {  
  firstPixelHue += 256;
  for(int i=0; i<pixel.numPixels(); i++) {
      int pixelHue = firstPixelHue + (i * 65536L / pixel.numPixels());
      pixel.setPixelColor(i, pixel.gamma32(pixel.ColorHSV(pixelHue)));
    }
  pixel.show();
  
  delay(10);

}

Upload the sketch to your board. You'll see the onboard NeoPixel run ‎through a looping rainbow animation.‎

Arduino Sparkle Motion Demo

adafruit_products_sparkle_neopixel_anim_scaled

The main use of the Sparkle Motion is lighting up RGB LEDs to ‎dazzle and delight. Using the Sparkle Motion with Arduino involves ‎installing the Adafruit_NeoPixel library and running the provided ‎example code. In the example below, you'll attach two NeoPixel ‎strips to the Sparkle Motion Mini and see how you can write code to ‎run two different LED animations on two strips of NeoPixels at the ‎same time.‎

Wiring

NeoPixels

  • terminal block - to GND on both NeoPixel strips. (black wire)‎

  • terminal block + to 5V on both NeoPixel strips. (red wire)‎

  • terminal block 21 to DIN on the first NeoPixel strip. (green wire)‎

  • terminal block 22 to DIN on the second NeoPixel strip. (green ‎wire)‎

wiring_176

Library Installation

You can install the Adafruit NeoPixel library for Arduino using the ‎Library Manager in the Arduino IDE.‎

manager_177

Click the Manage Libraries ... menu item, search for Adafruit ‎NeoPixel and select the Adafruit NeoPixel library:‎

item_178

No additional dependencies are required for the NeoPixel library.‎

Example Code

Download File

Copy Code
// SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <Adafruit_NeoPixel.h>

#define BLOCK_1 21
#define BLOCK_2 22
#define NUM_PIXELS 8

Adafruit_NeoPixel STRIP_1(NUM_PIXELS, BLOCK_1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel STRIP_2(NUM_PIXELS, BLOCK_2, NEO_GRB + NEO_KHZ800);

void setup() {
  STRIP_1.begin();
  STRIP_2.begin();
  STRIP_1.setBrightness(25);
  STRIP_2.setBrightness(50);
}

uint16_t pixelHue_1 = 0;
uint16_t pixelHue_2 = 256;

void loop() {  
  pixelHue_1 += 256;
  for(int i=0; i<STRIP_1.numPixels(); i++) {
      int hue_1 = pixelHue_1 + (i * 65536L / STRIP_1.numPixels());
      STRIP_1.setPixelColor(i, STRIP_1.gamma32(STRIP_1.ColorHSV(hue_1)));
    }
  STRIP_1.show();

  pixelHue_2 -= 256;
  for(int i=STRIP_2.numPixels(); i>-1; i--) {
      int hue_2 = pixelHue_2 + (i * 65536L / STRIP_2.numPixels());
      STRIP_2.setPixelColor(i, STRIP_2.gamma32(STRIP_2.ColorHSV(hue_2)));
    }
  STRIP_2.show();
  
  delay(10);

}

View on GitHub

Upload the example code to the Sparkle Motion. You'll see both ‎strips cycle through the rainbow swirl, but in a different order on ‎each strip.‎

adafruit_products_sparkle_circuitpython_neopixel_animat

Arduino IR Remote

adafruit_products_sparkle_ir_remote_scaled

The Adafruit Sparkle Motion has an IR Receiver built-in for all of your ‎remote controlling needs. The IRremote library makes it easy to ‎decode the signals sent to the receiver. This example will get you ‎started by demonstrating how to use one of our mini remote ‎controls to change the color and brightness of a connected strip of ‎NeoPixels.‎

IR Receiver & NeoPixel Output Location

ir_179

The IR Receiver is connected to pin 32. This example assumes the ‎NeoPixel strip will be plugged in to the terminal blocks for pin 21.‎

Necessary Hardware

You'll need an IR remote that uses one of the protocols supported by ‎the IRremote library, and any strip of NeoPixels. The following items ‎are the ones depicted on this page.‎

Wiring

NeoPixels

  • terminal block - to GND on the NeoPixel strip. (black wire)‎

  • terminal block + to 5V on the NeoPixel strip. (red wire)‎

  • terminal block 21 to DIN on the NeoPixel strip. (green wire)‎

wiring_180

Library Installation

You can install the Adafruit NeoPixel, and IRremote libraries for ‎Arduino using the Library Manager in the Arduino IDE.‎

ide_181

Click the Manage Libraries ... menu item, search for Adafruit ‎NeoPixel and click the Install button on the Adafruit NeoPixel result:‎

click_182

Next, search for IRremote and click the install button on ‎the IRremote result:‎

next_183

No additional dependencies are required for the NeoPixel or ‎IRremote libraries.‎

Example Code

Download File

Copy Code
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
// SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
//
// SPDX-License-Identifier: MIT

/*
 * Based on the SimpleReceiver.cpp and SimpleSender.cpp from the
 * Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 * by Armin Joachimsmeyer
 ************************************************************************************
 * MIT License
 *
 * Copyright (c) 2020-2023 Armin Joachimsmeyer
 *
 */

#include <Arduino.h>

#include <IRremote.hpp> // include the library
#include <Adafruit_NeoPixel.h>

#define NEOPIXEL_STRIP_PIN 21
#define NUM_PIXELS 8

#define IR_RECEIVE_PIN   32

Adafruit_NeoPixel NEOPIXEL_STRIP(NUM_PIXELS, NEOPIXEL_STRIP_PIN, NEO_GRB + NEO_KHZ800);

uint8_t upCmd = 0x5;
uint8_t downCmd = 0xD;
uint8_t rightCmd = 0xA;
uint8_t leftCmd = 0x8;

uint16_t pixelHue = 0;
uint8_t brightness = 25;

void setup() {
    Serial.begin(115200);
    while (!Serial)
        ;
    Serial.println("Adafruit Sparkle Motion IR Remote Control NeoPixels Demo");
    IrReceiver.begin(IR_RECEIVE_PIN);
    Serial.print("IRin on pin ");
    Serial.print(IR_RECEIVE_PIN);
    NEOPIXEL_STRIP.begin();
    NEOPIXEL_STRIP.setBrightness(25);
}

void loop() {
    /*
     * Check if received data is available and if yes, try to decode it.
     * When left or right buttons are pressed, change the pixelHue.
     * When up or down buttons are pressed, change the brightness.
     */
    if (IrReceiver.decode()) {
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println("unknown");
            IrReceiver.printIRResultRawFormatted(&Serial, true);
            IrReceiver.resume();
        } else {
            IrReceiver.resume();
            //IrReceiver.printIRResultShort(&Serial);

            // Ignore repeat codes from holding down the button
            if (IrReceiver.decodedIRData.flags == 0){
              //Serial.printf("Command: %d\n",IrReceiver.decodedIRData.command);
              if (IrReceiver.decodedIRData.command == upCmd){
                Serial.println("UP btn");
                brightness = min(brightness + 25, 255);
              }else if (IrReceiver.decodedIRData.command == downCmd){
                Serial.println("DOWN btn");
                brightness = max(brightness - 25, 0);
              }else if (IrReceiver.decodedIRData.command == leftCmd){
                Serial.println("LEFT btn");
                pixelHue = (pixelHue - 8192) % 65536;
              }else if (IrReceiver.decodedIRData.command == rightCmd){
                Serial.println("RIGHT btn");
                pixelHue = (pixelHue + 8192) % 65536;
              }

              NEOPIXEL_STRIP.setBrightness(brightness);
              NEOPIXEL_STRIP.fill(NEOPIXEL_STRIP.gamma32(NEOPIXEL_STRIP.ColorHSV(pixelHue)));
              NEOPIXEL_STRIP.show();
              delay(100);
            }
        }
        Serial.println();
    }
}

View on GitHub

Once the code is running, press the up and down arrow keys on the ‎remote to increase and decrease the brightness. Press the left and ‎right arrow keys to cycle through the available colors forward or ‎backward.‎

adafruit_products_sparkle_ir_remote_scaled

I2C

A lot of sensors, displays, and devices can connect over I2C. I2C is a 2-‎wire 'bus' that allows multiple devices to all connect on one set of ‎pins so it's very convenient for wiring!‎

When using your board, you'll probably want to connect up I2C ‎devices, and it can be a little tricky the first time. The best way to ‎debug I2C is go through a checklist and then perform an I2C scan.

Common I2C Connectivity Issues

  • Have you connected four wires (at a minimum) for each I2C ‎device? Power the device with whatever is the logic level of ‎your microcontroller board (probably 3.3V), then a ground wire, ‎and a SCL clock wire, and a SDA data wire.‎

  • If you're using a STEMMA QT board - check if the power LED ‎is lit. It's usually a green LED to the left side of the board.‎

  • Does the STEMMA QT/I2C port have switchable power or ‎pullups? To reduce power, some boards have the ability to cut ‎power to I2C devices or the pullup resistors. Check the ‎documentation if you have to do something special to turn on ‎the power or pullups.‎

  • If you are using a DIY I2C device, do you have pullup ‎resistors? Many boards do not have pullup resistors built in ‎and they are required! We suggest any common 2.2K to 10K ‎resistors. You'll need two: one each connects from SDA to ‎positive power, and SCL to positive power. Again, positive ‎power (a.k.a VCC, VDD or V+) is often 3.3V.

  • Do you have an address collision? You can only ‎have one board per address. So, you cannot, say, connect two ‎AHT20's to one I2C port because they have the same address ‎and will interfere. Check the sensor or documentation for the ‎address. Sometimes there are ways to adjust the address.‎

  • Does your board have multiple I2C ports? Historically, boards ‎only came with one. But nowadays you can have two or even ‎three! This can help solve the "hey, but what if I want two ‎devices with the same address" problem: just put one on each ‎bus.‎

  • Are you hot-plugging devices? I2C does not support dynamic ‎re-connection, you cannot connect and disconnect sensors as ‎you please. They should all be connected on boot and not ‎change. (Only exception is if you're using a hot-plug assistant ‎but that'll cost you).‎

  • Are you keeping the total bus length reasonable? I2C was ‎designed for maybe 6" max length. We like to push that with ‎plug-n-play cables, but really please keep them as short as ‎possible! (Only exception is if you're using an active bus ‎extender).‎

Built-in I2C Device

The Adafruit Sparkle Motion has one built-in device connected to the ‎I2C bus, a HUSB238 power delivery chip using address 0x8.‎

Perform an I2C scan!‎

Install TestBed Library

To scan I2C, the Adafruit TestBed library is used. This library and ‎example just make the scan a little easier to run because it takes ‎care of some of the basics. You will need to add support by installing ‎the library. Good news: it is very easy to do it. Go to the Arduino ‎Library Manager.‎

perform_184

Search for TestBed and install the Adafruit TestBed library.‎

testbed_185

Now open up the I2C Scan example

scan_186

Download File

Copy Code
// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// --------------------------------------

#include <Wire.h>

// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

void setup() {
  WIRE.begin();

  Serial.begin(9600);
  while (!Serial)
     delay(10);
  Serial.println("\nI2C Scanner");
}


void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    WIRE.beginTransmission(address);
    error = WIRE.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

View on GitHub

Wire up I2C device

While the examples here will be using the Adafruit MCP9808, a high ‎accuracy temperature sensor, the overall process is the same for just ‎about any I2C sensor or device.‎

The first thing you'll want to do is get the sensor connected so your ‎board has I2C to talk to.‎

Wiring the MCP9808‎

The MCP9808 comes with a STEMMA QT connector, which makes ‎wiring it up quite simple and solder-free.‎

Connect the STEMMA QT cable from the STEMMA QT port on the ‎Sparkle Motion to the STEMMA QT port on the MCP9808.‎

wiring_187

Now upload the scanning sketch to your microcontroller and open ‎the serial port to see the output. You should see something like this:‎

sketch_188

I2S Mic

mic_189

You can use the onboard I2S microphone with the built-in I2S library ‎in the espressif board support package. The I2S microphone is ‎connected to the following pins on the Sparkle Motion:‎

  • BCLK: 26‎

  • WS: 33‎

  • DATA_IN: 25‎

The example below will plot samples from the mic to the plotter ‎inside the Arduino IDE.‎

No additional libraries need to be installed for this example - the I2S ‎library is included in the Espressif board support package.‎

Example Code

Download File

Copy Code
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT

#include <Arduino.h>
#include "ESP_I2S.h"

// I2S pin definitions for Sparklemotion
const uint8_t I2S_SCK = 26;  // BCLK
const uint8_t I2S_WS = 33;   // LRCLK
const uint8_t I2S_DIN = 25;  // DATA_IN

// Create I2S instance
I2SClass i2s;

void setup() {
  // Fast serial for plotting
  Serial.begin(500000);
  
  // Initialize I2S
  i2s.setPins(I2S_SCK, I2S_WS, -1, I2S_DIN);
  if (!i2s.begin(I2S_MODE_STD, 44100, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT)) {
    Serial.println("Failed to initialize I2S bus!");
    return;
  }

  Serial.println("I2S Mic Plotter Ready");
}

void loop() {
  static uint32_t lastPlot = 0;
  
  // Get a sample
  int32_t sample = i2s.read();
  
  // Only plot every 1ms (1000 samples/sec is plenty for visualization)
  if (millis() - lastPlot >= 1) {
    if (sample >= 0) {  // Valid sample
      // Plot both raw and absolute values
      Serial.printf("%d,%d\n", (int16_t)sample, abs((int16_t)sample));
    }
    lastPlot = millis();
  }
}

View on GitHub

Upload the sketch to your board and open up the Serial Plotter ‎‎(Tools -> Serial Plotter) at 500000 baud. You'll see the raw samples ‎and average samples from the I2S microphone plotted over time.‎

upload_190

WiFi Test

Thankfully if you have ESP32 sketches, they'll 'just work' with ‎variations of ESP32. You can find a wide range of examples in ‎the File->Examples->Examples for Adafruit Metro ESP32-‎S2 subheading (the name of the board may vary so it could ‎be "Examples for Adafruit Feather ESP32 V2" etc.)‎

test_191

Let's start by scanning the local networks.‎

Load up the WiFiScan example under Examples->Examples for ‎YOUR BOARDNAME->WiFi->WiFiScan‎.

load_192

And upload this example to your board. The ESP32 should scan and ‎find WiFi networks around you.‎

For ESP32, open the serial monitor, to see the scan begin.‎

For ESP32-S2, -S3 and -C3, don't forget you have to click Reset after ‎uploading through the ROM bootloader. Then select the new USB ‎Serial port created by the ESP32. It will take a few seconds for the ‎board to complete the scan.‎

serial_193

If you cannot scan any networks, check your power supply. You need ‎a solid power supply in order for the ESP32 to not brown out. A ‎skinny USB cable or drained battery can cause issues.‎

WiFi Connection Test

Now that you can scan networks around you, it’s time to connect to ‎the Internet!‎

Copy the example below and paste it into the Arduino IDE:‎

Download File

Copy Code
// SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
//
// SPDX-License-Identifier: MIT


/*
  Web client

 This sketch connects to a website (wifitest.adafruit.com/testwifi/index.html)
 using the WiFi module.

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the Wifi.begin() call accordingly.

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the Wifi.begin() call accordingly.

 created 13 July 2010
 by dlf (Metodo2 srl)
 modified 31 May 2012
 by Tom Igoe
 */

#include <WiFi.h>

// Enter your WiFi SSID and password
char ssid[] = "YOUR_SSID";             // your network SSID (name)
char pass[] = "YOUR_SSID_PASSWORD";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;                      // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)

char server[] = "wifitest.adafruit.com";    // name address for adafruit test
char path[]   = "/testwifi/index.html";

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to SSID: ");
  Serial.println(ssid);

  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }

  Serial.println("");
  Serial.println("Connected to WiFi");
  printWifiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("GET "); client.print(path); client.println(" HTTP/1.1");
    client.print("Host: "); client.println(server);
    client.println("Connection: close");
    client.println();
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true) {
      delay(100);
    }
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

View on GitHub

NOTE: You must change the SECRET_SSID and SECRET_PASS in ‎the example code to your WiFi SSID and password before ‎uploading this to your board.‎

note_195

After you've set it correctly, upload and check the serial monitor. You ‎should see the following. If not, go back, check wiring, power, and ‎your SSID/password

password_196

If you have issues establishing a connection, try power cycling the ‎board by unplugging and replugging the USB cable.‎

Factory Reset

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

Your microcontroller ships running a factory demo. It's lovely, but you ‎probably had other plans for the board. As you start working with ‎your board, you may want to return to the original code to begin ‎again, or you may find your board gets into a bad state. ‎Either way, this page has you covered.‎

Factory Reset Example Code

If you're still able to load Arduino sketches, you can load the ‎following sketch onto your board to return it to its original state.‎

Download File

Copy Code
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <Arduino.h>
#include "WiFi.h"
#include <Adafruit_TestBed.h>
#include "ESP_I2S.h"
extern Adafruit_TestBed TB;

// I2S pin definitions
const uint8_t I2S_SCK = 26;  // BCLK
const uint8_t I2S_WS = 33;   // LRCLK
const uint8_t I2S_DIN = 25;  // DATA_IN
I2SClass i2s;

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  i2s.setPins(I2S_SCK, I2S_WS, -1, I2S_DIN);
  if (!i2s.begin(I2S_MODE_STD, 44100, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT)) {
    Serial.println("Failed to initialize I2S bus!");
    return;
  }
  // TestBed will handle the neopixel swirl for us
  TB.neopixelPin = PIN_NEOPIXEL;
  TB.neopixelNum = 1;
  TB.begin();

  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
}

// the loop routine runs over and over again forever:
uint8_t wheelColor=0;
void loop() {
  if (wheelColor == 0) {
    // Test I2C!
    Serial.print("I2C port ");
    TB.theWire = &Wire;
    TB.printI2CBusScan();

    // Test WiFi Scan!
    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.print("WiFi AP scan done...");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.print(i + 1);
            Serial.print(": ");
            Serial.print(WiFi.SSID(i));
            Serial.print(" (");
            Serial.print(WiFi.RSSI(i));
            Serial.print(")");
            Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
            delay(10);
        }
    }
    Serial.println("");
    for (int i=0; i < 5; i++) {
      int32_t sample = i2s.read();
      if (sample >= 0){
        Serial.print("Amplitude: ");
        Serial.println(sample);
    
        // Delay to avoid printing too quickly
        delay(200);
        }
      }
  }

  TB.setColor(TB.Wheel(wheelColor++)); // swirl NeoPixel
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

  delay(5);
}

View on GitHub

Your board is now back to its factory-shipped state! You can now ‎begin again with your plans for your board.‎

Factory Reset .bin

If your board is in a state where Arduino isn't working, you may need ‎to use these tools to flash a .bin file directly onto your board.‎

There are two ways to do a factory reset. The first is using WebSerial ‎through a Chromium-based browser, and the second is ‎using esptool via command line. We highly recommend using ‎WebSerial through Chrome/Chromium.‎

First, you'll need to download the factory-reset.bin file. Save the ‎following file wherever is convenient for you. You'll need access to it ‎for both tools.‎

Click to download the Sparkle Motion Factory Reset .BIN

Now that you've downloaded the .bin file, you're ready to continue ‎with the factory reset process. The next two sections walk you ‎through using WebSerial and esptool.‎

The WebSerial ESPTool Method

We highly recommend using WebSerial ESPTool method to perform ‎a factory reset and bootloader repair. However, if you'd rather use ‎esptool via command line, you can skip this section.‎

This method uses the WebSerial ESPTool through Chrome or a ‎Chromium-based browser. The WebSerial ESPTool was designed to ‎be a web-capable option for programming ESP32 boards. It allows ‎you to erase the contents of the microcontroller and program up to ‎four files at different offsets.‎

You will have to use a Chromium browser (like Chrome, Opera, ‎Edge...) for this to work, Safari and Firefox, etc. are not supported ‎because we need Web Serial and only Chromium is supporting it to ‎the level needed.‎

Follow the steps to complete the factory reset.‎

If you're using Chrome 88 or older, see the Older Versions of Chrome section at the end of this page for instructions on enabling ‎Web Serial.‎

Connect

You should have plugged in only the ESP32 that you intend to flash. ‎That way there's no confusion in picking the proper port when it's ‎time!

In the Chrome ‎browser visit https://adafruit.github.io/Adafruit_WebSerial_ESPTool/. ‎You should see something like the image shown.

visit_197

Press the Connect button in the top right of the web browser. You ‎will get a pop up asking you to select the COM or Serial port.‎

Remember, you should remove all other USB devices so only the ‎ESP32 board is attached, that way there's no confusion over ‎multiple ports!‎

On some systems, such as MacOS, there may be additional system ‎ports that appear in the list.‎

systems_198

The JavaScript code will now try to connect to the ROM bootloader. It ‎may timeout for a bit until it succeeds. On success, you will see that ‎it is Connected and will print out a unique MAC address identifying ‎the board along with other information that was detected.‎

javascript_199‎ ‎

‎‎Once you have successfully connected, the command toolbar will ‎appear.‎

command_200

Erase the Contents

To erase the contents, click the Erase button. You will be prompted ‎whether you want to continue. Click OK to continue or if you ‎changed your mind, just click cancel.‎

erase_201

‎‎You'll see "Erasing flash memory. Please wait..." This will eventually ‎be followed by "Finished." and the amount of time it took to erase.‎

Do not disconnect! Immediately continue on to programming the ‎ESP32.‎

disconnect_202

Do not disconnect after erasing! Immediately continue on to the ‎next step!‎

Program the ESP32‎

Programming the microcontroller can be done with up to four files ‎at different locations, but with the board-specific factory-‎reset.bin file, which you should have downloaded earlier, you only ‎need to use one file.‎

Click on the first Choose a file.... (The tool will only attempt to ‎program buttons with a file and a unique location.) Then, select the ‎‎*-factory-reset.bin file you downloaded in Step 1 that matches your ‎board.‎

Verify that the Offset box next to the file location you used is (0x) 0.‎

offset_203

Once you choose a file, the button text will change to match your ‎filename. You can then select the Program button to begin flashing.‎

flashing_204

A progress bar will appear and after a minute or two, you will have ‎written the firmware.‎

bar_205

Once completed, you can skip down to the section titled Reset the ‎Board.‎

The esptool Method (for advanced users)‎

If you used WebSerial ESPTool, you do not need to complete the ‎steps in this section!‎

Alternatively, you can use Espressif's esptool program to ‎communicate with the chip! esptool is the 'official' programming tool ‎and is the most common/complete way to program an ESP chip.‎

Install ESPTool.py

You will need to use the command line / Terminal to install and ‎run esptool.‎

You will also need to have pip and Python installed (any version!).‎

Install the latest version using pip (you may be able to ‎run pip without the 3 depending on your setup):‎

pip3 install --upgrade esptool

Then, you can run:‎

esptool.py

Test the Installation

Run esptool.py in a new terminal/command line and verify you get ‎something like the below:‎

run_206

Connect

Run the following command, replacing the COM88 identifier after --‎port with the COMxx, /dev/cu.usbmodemxx or /dev/ttySxx you found ‎above.‎

esptool.py --port COM88 chip_id

You should get a notice that it connected over that port and found ‎an ESP32.‎

notice_207

Installing the Factory Test file

Run this command and replace the serial port name, COM88, with ‎your matching port and *-factory-reset.bin with file you just ‎downloaded

esptool.py --port COM88 write_flash 0x0 *-factory-reset.bin

Don't forget to change the --port name to match.‎

There might be a bit of a 'wait' when programming, where it doesn't ‎seem like it's working. Give it a minute, it has to erase the old flash ‎code which can cause it to seem like it's not running.‎

You'll finally get an output like this:‎

output_208

Once completed, you can continue to the next section.‎

Reset the board

Now that you've reprogrammed the board, you need to reset it to ‎continue. Click the reset button to launch the new firmware.‎

In the event that pressing the reset button does not restart the board, ‎unplug the board from USB and plug it back in to get the new ‎firmware to start up.‎

The NeoPixel LED on the Sparkle Motion will perform one rainbow ‎cycle. In the serial monitor, you'll see the results of a WiFi scan, I2C ‎scan and readings from the onboard I2S microphone.‎

You've successfully returned your board to a factory reset state!‎

Older Versions of Chrome

As of chrome 89, Web Serial is already enabled, so this step is only ‎necessary on older browsers.‎

We suggest updating to Chrome 89 or newer, as Web Serial is ‎enabled by default.‎

If you must continue using an older version of Chrome, follow these ‎steps to enable Web Serial.‎

If you receive an error like the one shown when you visit the ‎WebSerial ESPTool site, you're likely running an older version of ‎Chrome.‎

You must be using Chrome 78 or later to use Web Serial.‎

chrome_209

To enable Web Serial in Chrome versions 78 through 88:‎

  • Visit chrome://flags from within Chrome.‎

  • Find and enable the Experimental Web Platform features

  • Restart Chrome

restart_210

Downloads

On macOS, you need to use this board with a hub and USB A to USB ‎C cable to upload any software. If you plug the board directly into a ‎USB C port on your Mac, it will assume it needs power delivery (PD) ‎and the USB to Serial port will not work.‎

Files

Schematic and Fab Print

schematic_211

schematic_212

dimensions are in inches

‎3D Model‎

model_213

Mfr Part # 6100
ADAFRUIT SPARKLE MOTION - ALL-IN
Adafruit Industries LLC
$204.86
View More Details
Mfr Part # 1219
HDWR T-PLATE 20X20 ALUM EXTRUSN
Adafruit Industries LLC
ADAFRUIT NEOPIXEL PEBBLE / SEED
Mfr Part # 6023
ADAFRUIT NEOPIXEL PEBBLE / SEED
Adafruit Industries LLC
$328.03
View More Details
USB TO 2.1MM MALE BARREL JACK CA
Mfr Part # 2697
USB TO 2.1MM MALE BARREL JACK CA
Adafruit Industries LLC
Mfr Part # 4397
STEMMA QT QWIIC JST SH CABLE 150
Adafruit Industries LLC
Mfr Part # 352
AC/DC DESKTOP ADAPTER 12V 60W
Adafruit Industries LLC
$204.86
View More Details
Mfr Part # 5130
AC/DC DESKTOP ADAPTER 3-24V
Adafruit Industries LLC
$143.69
View More Details
Mfr Part # 875
BATTERY HOLDER AA 8 CELL LEADS
Adafruit Industries LLC
Mfr Part # 4528
4-PIN STEMMA/GROVE - QT/QWIIC 4"
Adafruit Industries LLC
Mfr Part # 6160
MINI SPARKLE MOTION - WLED-FRIEN
Adafruit Industries LLC
$155.60
View More Details
Mfr Part # 5395
ADAFRUIT QT PY ESP32 PICO - WIFI
Adafruit Industries LLC
$122.75
View More Details
Mfr Part # 3405
HUZZAH32 ESP32 FEATHER LOOSE HDR
Adafruit Industries LLC
$163.81
View More Details
Mfr Part # 5438
ESP32 FEATHER V2 STEMMA QT
Adafruit Industries LLC
$163.81
View More Details
Mfr Part # 2821
ESP8266 FEATHER HUZZAH LOOSE HDR
Adafruit Industries LLC
$122.75
View More Details
PANEL MOUNT 1K POTENTIOMETER (BR
Mfr Part # 1789
PANEL MOUNT 1K POTENTIOMETER (BR
Adafruit Industries LLC
Mfr Part # 157
IR (INFRARED) RECEIVER SENSOR -
Adafruit Industries LLC
Mfr Part # 5939
ADAFRUIT INFRARED IR REMOTE RECE
Adafruit Industries LLC
Mfr Part # 954
CABLE USB TO TTL SERIAL DEBUG
Adafruit Industries LLC
IC SOCKET - FOR 20-PIN 0.3 CHIPS
Mfr Part # 2204
IC SOCKET - FOR 20-PIN 0.3 CHIPS
Adafruit Industries LLC
Mfr Part # 5755
JST SH COMPATIBLE 1MM PITCH 3 PI
Adafruit Industries LLC
Mfr Part # 2540
ADDRESS LED STRIP SERIAL RGB 2M
Adafruit Industries LLC
$409.73
View More Details
Mfr Part # 1426
ADDRESS LED MODULE SERIAL RGB
Adafruit Industries LLC
Mfr Part # 5027
STEMMA QT MCP9808 TEMP SENSOR
Adafruit Industries LLC
Mfr Part # 4399
STEMMA QWIIC JST SH CABLE 50MM
Adafruit Industries LLC
Mfr Part # 5159
STEMMA QT HOT-SWAP I2C BUFFER
Adafruit Industries LLC
Mfr Part # 4756
STEMMA QT I2C EXTENDER LTC4311
Adafruit Industries LLC
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.