Adafruit Sparkle Motion
2025-05-13 | By Adafruit Industries
License: See Original Project Addressable LEDs LED Strips Microcontrollers Wifi
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.ā
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. ā
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ā
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.ā
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.ā
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.ā
The Sparkle Motion is a board with a lot of sparkly features. This page ācovers it all!ā
Pretty Pins on Github (PDF).ā
Power Pins
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.ā
NeoPixel Output Signals
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
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
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
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
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
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
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
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.ā
ā ā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
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.ā
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. ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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).ā
Use It
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.
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. ā
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:ā
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.ā
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).ā
Try re-uploading the WLED software. ā
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.ā
If your lights came on in blue or green instead of yellow, your ācolor order is wrong. See below to fix.ā
If only half your lights came on, be sure you've got the correct ānumber in the "length" field under LED preferences.ā
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.ā
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.ā
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.ā
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.ā
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.
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.
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'.
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).
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!
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 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! ā
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.ā
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. ā
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.ā
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.ā
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.ā
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.
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.ā
Troubleshooting
If your button isn't working, here are some things to try:ā
āDouble check both the LED preferences page and the Time & āMacros page to be sure your settings are correct and have āsaved.ā
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).ā
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.ā
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.ā
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. ā
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.
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.ā
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.ā
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).ā
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.ā
Once you have successfully connected, the command toolbar will āappear.ā
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.
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.ā
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.ā
Once you choose a file, the button text will change to match your āfilename. You can then click the Program button to start flashing.
A progress bar will appear and after a minute or two, you will have āwritten the firmware.ā
You've now successfully programmed CircuitPython onto your board! āAs suggested in the output, press reset to run the new firmware.
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.ā
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.ā
Once you have connected, the Connect button in the upper right-āhand corner should change to a Disconnect button.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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
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.ā
# 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)
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.ā
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.ā
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.ā
You'll see the LED blink code.py file contents. Click Restart above āthe Serial monitor to run the LED blink code.ā
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
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.ā
# 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
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.ā
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.ā
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.ā
You'll see the digital input code.py file contents. Click Restart above āthe Serial monitor to run the digital input code.ā
Now, press the button. The LED lights up! Let go of the button and āthe LED turns off.ā
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.ā
Potentiometer with Built In Knob - 10K ohmā
JST SH Compatible 1mm Pitch 3 Pin to Premium Male Headers āCable
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)ā
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.ā
# 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)
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.
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.ā
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.ā
You'll see the analog input code.py file contents. Click Restart above āthe Serial monitor to run the analog input code.ā
Now, twist and turn the potentiometer. You'll see the analog voltage āvalues print to the serial console.ā
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
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.ā
# 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)
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.ā
Navigate to the project bundle that you downloaded and select āthe /lib folder.ā
You'll be asked if you want to upload the /lib folder from the Project āBundle. Click Upload.ā
After the upload finishes, you can open the lib folder to view the two ālibrary files required for the NeoPixel examples.ā
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.ā
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.ā
The built-in NeoPixel begins blinking red, then green, then blue, and ārepeats!ā
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.ā
# 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)
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!
ā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
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)ā
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
# 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()
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.ā
Navigate to the project bundle that you downloaded and select āthe /lib folder.ā
You'll be asked if you want to upload the /lib folder from the Project āBundle. Click Upload.ā
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
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.ā
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.ā
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
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
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)ā
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
# 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("----------------------------")
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.ā
Navigate to the project bundle that you downloaded and select āthe /lib folder.ā
You'll be asked if you want to upload the /lib folder from the Project āBundle. Click Upload.ā
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
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.
ā
Navigate to the project bundle that you downloaded and select āthe code.py file.
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.ā
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
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.ā
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.ā
# 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()
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.
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.ā
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.ā
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.ā
If you run this and it seems to hang, try manually unlocking your I2C ābus by running the following two commands from the REPL.ā
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.ā
# 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.ā
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.ā
# 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))
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.
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.ā
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.ā
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 everything is saved to the board, Restart the Serial Console to āsee the data printed out!ā
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.ā
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.ā
# 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.ā
# 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
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.ā
Once you choose the color picker block, you'll need to connect a feed āto it. Check the box next to neopixel.ā
Finally, a Block Settings page will come up. You can add an optional āblock title here. Then you press Create Block.
The dashboard should look something like the following.ā
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.ā
# 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()
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.ā
Navigate to the project bundle that you downloaded and select āthe /lib folder.ā
You'll be asked if you want to upload the /lib folder from the Project āBundle. Click Upload.ā
After the upload finishes, you can open the lib folder to view the ālibrary files required for the Adafruit IO example.ā
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.ā
Navigate to the project bundle that you downloaded and select āthe code.py file.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
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".ā
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.ā
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.ā
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.ā
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.ā
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.ā
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.ā
[...]
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.ā
[...]
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.ā
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.ā
Look for the board called Adafruit Sparkle Motion (ESP32).ā
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.ā
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.ā
New Blink Sketch
OK letās make a new blink sketch! From the File menu, select New.ā
Then in the new window, copy and paste this text:ā
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.ā
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.ā
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!ā
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!ā
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.ā
Upload Sketch
Once the code is verified/compiling cleanly you can upload it to your āboard. Click the Upload button.ā
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:ā
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
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.ā
Now you can try uploading again!ā
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.ā
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
Arduino Library Installation
You can install the necessary libraries from the Library Manager. To āopen, click Sketch > Include Library > Manage Libraries...ā
Search for NeoPixel and install the Adafruit NeoPixel library.ā
There are no additional library dependencies for the Adafruit āNeoPixel library.ā
Rainbow Swirl Demo
// 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
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)ā
Library Installation
You can install the Adafruit NeoPixel library for Arduino using the āLibrary Manager in the Arduino IDE.ā
Click the Manage Libraries ... menu item, search for Adafruit āNeoPixel and select the Adafruit NeoPixel library:ā
No additional dependencies are required for the NeoPixel library.ā
Example 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);
}
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.ā
Arduino IR Remote
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
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)ā
Library Installation
You can install the Adafruit NeoPixel, and IRremote libraries for āArduino using the Library Manager in the Arduino IDE.ā
Click the Manage Libraries ... menu item, search for Adafruit āNeoPixel and click the Install button on the Adafruit NeoPixel result:ā
Next, search for IRremote and click the install button on āthe IRremote result:ā
No additional dependencies are required for the NeoPixel or āIRremote libraries.ā
Example 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();
}
}
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.ā
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.ā
Search for TestBed and install the Adafruit TestBed library.ā
Now open up the I2C Scan example
// 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
}
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.ā
Now upload the scanning sketch to your microcontroller and open āthe serial port to see the output. You should see something like this:ā
I2S Mic
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
// 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();
}
}
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.ā
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.)ā
Let's start by scanning the local networks.ā
Load up the WiFiScan example under Examples->Examples for āYOUR BOARDNAME->WiFi->WiFiScanā.
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.ā
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:ā
// 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");
}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.ā
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
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.ā
// 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);
}
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.
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.ā
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.ā
ā ā
āāOnce you have successfully connected, the command toolbar will āappear.ā
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.ā
āā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.ā
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.ā
Once you choose a file, the button text will change to match your āfilename. You can then select the Program button to begin flashing.ā
A progress bar will appear and after a minute or two, you will have āwritten the firmware.ā
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:ā
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.ā
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:ā
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.ā
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
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
dimensions are in inches
ā3D Modelā

