NeoPixel LED Holiday Tree

Build an animated LED holiday tree project using Adafruit Feather RP2040 Scorpio and NeoPixel LEDs. Use the NEOPIX8L library for CircuitPython to create advanced animations with buttery smooth frame rates.

3D print and assemble a tree structure that is adorned with NeoPixel LED strips. The Feather RP2040 Scorpio and a Perma-Proto board are housed in snap-fit enclosures. 

Prerequisite Guides

Take a moment to review the following guides.

 

Parts

Angled video of eight LED strips fanned like a curtain emitting red fiery shades.
If there is one thing Adafruit is known for, its mega-blinky-fun-rainbow-LEDs. We just love sticking NeoPixels anywhere and...
$14.50
In Stock
Top view of a small Altoids breath mint case with two Adafruit Perma-Proto Small Mint Tin Size Breadboard PCBs.
Making a project that will fit into an "Altoids Smalls" Mint Tin? Or maybe you just need a small amount of prototyping space and a larger breadboard size is too big? Put down...
$7.95
In Stock
16-pin Ribbon Cable 2x8 IDC Cable
Connect this to that! If you want to bridge those contacts out onto another PCB, you'll want this GPIO Ribbon Cable! Comes in a classic Adafruit Black, has a nice...
$1.95
In Stock
Top view shot of a red and black JST PH 2-Pin Cable to Female Connector - 100mm.
Red and black tinned wires with a 2-pin JST PH connector on the end. 4" / 100mm long. Matches up nicely with our Lipoly chargers!
$0.75
In Stock
Top view shot of JST PH 2-Pin Cable - Male Header - 200mm.
For a really long time we assumed that the JST PH didn't have a free-hanging male header version. But then we found this JST-PH 2-pin Male Cable, and we were...
$0.75
In Stock
Opened box showing many nylon screws
Totaling 420 pieces, this M3 Screw Set is a must-have for your workstation. You'll have enough screws, nuts, and hex standoffs to fuel...
$16.95
In Stock
8 x NeoPixel LED Strip
30x NeoPixel LED Strip with 3-pin JST PH 2mm Connector
8 x 3-Pin JST PH Cable
JST PH 2mm 3-Pin Socket to Color Coded Cable - 200mm
1 x M2.5 Nylon Hardware Kit
Black Nylon Machine Screw and Stand-off Set – M2.5 Thread
1 x USB-C Cable 2 meter long
Pink and Purple Woven USB A to USB C Cable - 2 meters long
1 x 5V 2A USB Power Supply
5V 2A Switching Power Supply w/ USB-A Connector
1 x 5V 10A switching power supply
5V 10A switching power supply
1 x DC Power Jack
Female DC Power adapter - 2.1mm jack to screw terminal block
24 x Nylon Zip Ties
6in white zip ties - 200 Qt pack

The diagram below provides a visual reference for wiring of the components. This diagram was created using the software package Fritzing.

Adafruit Library for Fritzing

Use Adafruit's Fritzing parts library to create circuit diagrams for your projects. Download the library or just grab individual parts. Get the library and parts from GitHub - Adafruit Fritzing Parts.

This circuit diagram shows how to use external power to NeoPixel strips for other projects that may require full brightness and lots of LEDs.

Scorpio Power

See this guide for more about powering Scorpio projects.

Wired Connections

The Feather RP2040 Scorpio is powered by 5V USB power supply. The NeoPixel strips should be powered separately a 5V 10A power supply

3-pin JST socket connectors are wired into a Perma-Proto board to allow the NeoPixel strips to plug into.

A wire is connected from the Feather RP2040 Scorpio ground pin to the ground rails on the Perma-Proto board.

The power and ground rails from the Perma-Proto are connected to a 2.1mm DC power jack.

A 2x8 IDC cable is used to connect the Feather RP2040 Scorpio to the Perma-Proto board.

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. Simply copy and edit files on the CIRCUITPY drive to iterate.

CircuitPython Quickstart

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

Click the link above to download the latest CircuitPython UF2 file.

Save it wherever is convenient for you.

To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in blue above). Continue to hold the BOOT/BOOTSEL button until the RPI-RP2 drive appears!

If the drive does not appear, release all the buttons, and then repeat the process above.

You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.

A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.

You will see a new disk drive appear called RPI-RP2.

 

Drag the adafruit_circuitpython_etc.uf2 file to RPI-RP2.

The RPI-RP2 drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

Safe Mode

You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.

Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.

Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.

Entering Safe Mode

To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)

In Safe Mode

If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.

If you connect to the serial console, you'll find the following message.

Auto-reload is off.
Running in safe mode! Not running saved code.

CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.

You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.

Flash Resetting UF2

If your board ever gets into a really weird state and doesn't even show up as a disk drive when installing CircuitPython, try loading this 'nuke' UF2 which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.

Once you've finished setting up your Feather RP2040 Scorpio with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

# SPDX-FileCopyrightText: 2023 Jeff Epler for Adafruit Industries
# SPDX-License-Identifier: MIT
import board
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.color import (JADE, RED, WHITE)
from adafruit_led_animation.group import AnimationGroup
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_neopxl8 import NeoPxl8
from adafruit_pixelmap import PixelMap

strand_length = 30
pixel_brightness = 0.8
num_strands = 8

num_pixels = num_strands * strand_length
pixels = NeoPxl8(board.NEOPIXEL0, num_pixels, auto_write=False, brightness=pixel_brightness)

def strand(n):
    return PixelMap(
        pixels,
        tuple(range(n * strand_length, (n + 1) * strand_length)),
        individual_pixels=True,
    )

pixel_strip_A = strand(0)
pixel_strip_B = strand(1)
pixel_strip_C = strand(2)
pixel_strip_D = strand(3)
pixel_strip_E = strand(4)
pixel_strip_F = strand(5)
pixel_strip_G = strand(6)
pixel_strip_H = strand(7)

animations = AnimationSequence(
    AnimationGroup(
        Rainbow(pixel_strip_A, speed=0.01, period=7),
        Rainbow(pixel_strip_B, speed=0.01, period=7),
        Rainbow(pixel_strip_C, speed=0.01, period=7),
        Rainbow(pixel_strip_D, speed=0.01, period=7),
        Rainbow(pixel_strip_E, speed=0.01, period=7),
        Rainbow(pixel_strip_F, speed=0.01, period=7),
        Rainbow(pixel_strip_G, speed=0.01, period=7),
        Rainbow(pixel_strip_H, speed=0.01, period=7),
    ),
    AnimationGroup(
        Chase(pixel_strip_A, speed=0.05, color=WHITE, spacing=5, size=8),
        Chase(pixel_strip_B, speed=0.05, color=RED, spacing=4, size=4),
        Chase(pixel_strip_C, speed=0.05, color=RED, spacing=4, size=8),
        Chase(pixel_strip_D, speed=0.05, color=JADE, spacing=5, size=5),
        Chase(pixel_strip_E, speed=0.05, color=WHITE, spacing=5, size=5),
        Chase(pixel_strip_F, speed=0.05, color=RED, spacing=4, size=5),
        Chase(pixel_strip_G, speed=0.05, color=JADE, spacing=3, size=4),
        Chase(pixel_strip_H, speed=0.05, color=RED, spacing=4, size=8),
        sync=False,
    ),
    AnimationGroup(
        Comet(pixel_strip_A, 0.01, color=WHITE, tail_length=12, bounce=True),
        Comet(pixel_strip_B, 0.01, color=RED, tail_length=12, reverse=True),
        Comet(pixel_strip_C, 0.01, color=RED, tail_length=12, bounce=True),
        Comet(pixel_strip_D, 0.01, color=JADE, tail_length=12, reverse=True),
        Comet(pixel_strip_E, 0.01, color=WHITE, tail_length=12, bounce=True),
        Comet(pixel_strip_F, 0.01, color=RED, tail_length=12, reverse=True),
        Comet(pixel_strip_G, 0.01, color=JADE, tail_length=12, bounce=True),
        Comet(pixel_strip_H, 0.01, color=RED, tail_length=12, reverse=True),
        sync=True,
    ),
    advance_interval=9,
    auto_clear=True,
)

while True:
    animations.animate()

Upload the Code and Libraries to the Feather RP2040 Scorpio

After downloading the Project Bundle, plug your Feather RP2040 Scorpio into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following folder and file to the Feather RP2040 Scorpio's CIRCUITPY drive.

  • /lib
  • code.py

Copy the entire lib folder, including all of its contents.

Your Feather RP2040 Scorpio CIRCUITPY drive should resemble the following after copying the lib folder and the code.py file.

CAD Parts List

STL files for 3D printing are oriented to print "as-is" on FDM style machines. Parts are designed to 3D print without any support material with PLA filament. Original design source may be downloaded using the links below.

File Name List

A list of the parts that need to be 3D printed. Reference the prefix number for the quantity required for the assembly. 

  • 8x Bracket A.stl
  • 1x Bracket B.stl
  • 1x Bracket C.stl
  • 1x Top Bracket.stl
  • 8x Slat A.stl
  • 8x Slat B.stl
  • 8x Slat C.stl
  • scorpio case.stl
  • scorpio top.stl
  • small mint case.stl
  • small mint top cover.stl

Build Volume

The parts require a 3D printer with a minimum build volume.

  • 195mm (X) x 195mm (Y) x 50mm (Z)

Design Source Files

The project assembly was designed in Fusion 360. This can be downloaded in different formats like STEP, STL and more. Electronic components like Adafruit's boards, displays, connectors and more can be downloaded from the Adafruit CAD parts GitHub Repo.

Large LED Projects

For projects that use more NeoPixels, reference the wiring diagram in the Circuit Diagram page for using external power. 

Small LED Projects

This section shows how to power projects that use a small amount of NeoPixel LEDs with low to medimum brightness settings.

In this project, the Feather RP2040 Scorpio is powered by a 5V 1A USB power supply and uses a total of 240 NeoPixel LEDs. The eight NeoPixel LED strips are powered directly from the Feathers RP2040 Scorpio's USB and ground pins.

Headers & JST Cable for Feather Scorpio

A 2-pin JST plug cable is connected to the Feather RP2040 Scorpio.

A 2x8 right-angled header is soldered to the NeoPixel pins on the Feather RP2040 Scorpio.

Solder Headers & JST Cable

The 2x8 right-angled header is soldered to the top side of the Feather RP2040 Scorpio.

The 2-pin JST plug cable is soldered to the ground and USB pin on the Feather RP2040 Scorpio.

Perma-Proto & Cables

The Perma-Proto board will use several cables to connect to the Feather RP2040 Scorpio and the 8x NeoPixel strips.

  • 8x 3-pin JST socket cables
  • 1x 2-pin JST socket cable
  • 1x 2x8 IDC ribbon cable

2x8 IDC Cable Setup

Divide the 2x8 IDC cable and cut in half using wire cutters.

Separate the individual wires from the IDC cables by peeling them apart.

Locate the notch of the cable to reference the first wire that will be soldered to NeoPixel #0.

Only eight signal wires be used to connect the NeoPixel strips. Locate the wire with the white marking. Cut every other wire after the wire with the white marking.

Wired Perma-Proto

Solder the 3pin JST plug cables to the Perma-Proto board as follows:

The red wires are soldered to the pads on the voltage rail.

The black wires are soldered to the pads on the ground rail.

The white wires are soldered to unique columns on the Perma-Proto.

The wires from the IDC ribbon cable are soldered to pads that are shared with the white wires from the 3-pin JST cables as shown.

Hardware for Bracket Set A

The following hardware is used to assemble the Bracket A set.

  • 8x M3 x 10mm long screws
  • 8x M3 hex nuts

Joining Brackets A

The bracket set A will be joined together using an M3 x 10mm long screw and hex nut.

Start by joining two of the brackets A.

Installing Hex Nuts for Bracket A

Place an M3 hex nut over the tab with the hexagon shaped cavity. Insert an M3 screw through the other side of the tab and begin to fasten the screw. The M3 screw will force the M3 hex nut to be pressed into the cavity.

Remove the M3 screw when the hex nut is fully seated into the cavity.

Joined Bracket A

Insert the M3 screw through the tab on the other bracket and begin to fasten the two brackets together.

Repeat this process to create four sets of bracket A.

Assembled Bracket A Set

Join the four sets of bracket A using the remaining M3 x 10mm long screws.

Slats A & B

Get slats A and B ready to install onto the bracket B.

Joining Slats A & B

Slats A & B feature tabs that will be inserted into the finger joints of bracket B.

The tabs of slats A & B will overlap and press fitted into bracket B's finger joint.

An M3 x 10mm screw will be used to secure the slats to the bracket.

Slats A&B with Bracket B 

Press fit the tabs from slat A & B into one of the finger joints on bracket B.

Adjust the tabs so the mounting holes are all lined up for the M3 x 10mm long screw.

Secure Slats A&B to Bracket B

Insert and fasten an M3 x 10mm long screw through the finger joint of bracket B.

Joined Slats A&B with Bracket B

Take a moment to inspect slats A and B have been properly secured to the finger joint of bracket B.

Assembled Bracket B with Slats A&B

Repeat the assembly process and proceed to secure the remaining slats to bracket B.

Joining Slats A to Bracket A

Bring bracket set A and slats A&B together.

Insert Slats A to Bracket A

Begin inserting the ends of slat A to the square peg holes of  bracket set A.

Press fit slats A into the square holes of bracket A.

Assembled Bracket A with Slats A

Take a moment to review the assembly.

Join Slats B&C to Bracket C

Place bracket c over the mounting tabs of slats B with the mounting tabs fitted into the finger joints.

Grab one slat C and begin inserting the mounting tab into the finger joints of bracket C.

Fasten Slats B&C to Bracket C

Insert and fasten an M3 x 10mm long screw through the finger joint of bracket c to secure slats B and C.

Assembled Bracket C with Slats B&C

Repeat the assembly process and proceed to secure slats B&C to bracket C.

Install Top Bracket to Slats C

Place the top bracket over the tips of slats C. Press fit the tips into the slots of the top bracket. The edges are angled to prevent the tips from separating.

Zip Ties for NeoPixel Strips

Self-locking nylon zip ties will be used to secure the NeoPixel strips to the slats of the tree assembly.

A minimum of three zip ties are used to secure a NeoPixel strip.

Secure NeoPixel Strip to Slats

Place a NeoPixel strip over one of the slats with the JST cable facing towards bracket A.

Use the zip ties to secure the NeoPixel strip to the slats.

Do not over tighten the zip ties. The zip ties should be able to slide along the strip to allow repositioning.

Trim Zip Ties

Remove the access zip ties using flush diagonal cutters.

Installed Zip Ties

Adjust the zip ties so they are not blocking the NeoPixel LEDs.

Proceed to repeat the assembly process and secure the remaining NeoPixel strips to the slats.

Secured NeoPixel Strips

Take a moment to inspect the NeoPixel strips are properly secured to the slats. 

Hardware for Perma-Proto Case

Use the following hardware to secure the Perma-Proto board to the 3D printed case.

  • 4x M3 x 10mm long screws
  • 4x M3 hex nuts

Secure Perma-Proto

Place the Perma-Proto board onto the case with the mounting holes lined up.

Insert the M3 screws through the bottom of the case and secure the board using the hex nuts.

Install Perma-Proto Cover

Insert the various cables from the Perma-Proto through the opening in the center of the top cover.

Press the top cover onto the case to snap fit them together.

Assembled Perma-Proto Case

Take a moment to inspect the Perma-Proto board has been properly secured to the case.

Hardware for Scorpio Case

Use the following hardware to secure the Feather RP2040 Scorpio to the 3D printed case.

  • 2x M2.5 x 10mm long screws
  • 2x M2.5 hex nuts

Install JST cable

Insert the JST plug from the Feather RP2040 Scorpio through the center slot of the 3D printed case.

Install Feather to Case

Place the Feather RP2040 Scorpio into the case with the mounting holes lined up.

Insert 2x M2.5 x 10mm long screws through the holes on the  bottom of the case.

Secure Feather to Case

Use 2x M2.5 hex nuts to secure the Feather RP2040 Scorpio to the case.

Install Feather Scorpio Cover

Get the top cover ready to install onto the 3D printed case for the Feather RP2040 Scorpio board.

Orient the top cover with the Feather RP2040 Scorpio so the slots are lined up correctly with the pins on the board.

Place the top cover over the case and press down to snap fit them together.

Assembled Cases

Get the cases for the Perma-Proto and Feather RP2040 Scorpio and get them ready to connect together.

Connect IDC Cable

Plug the IDC ribbon cable into the 2x8 header of the Feather RP2040 Scorpio with the notch facing up.

The wire with the white marking should be connecting to NeoPixel #0. 

Connect 2-pin JST Cable

Plug in the 2-pin JST cable from the Feather RP2040 to the 2-in JST cable on the Perma-Proto board.

Feather & Perma-Proto Connected

Take a moment to inspect the cables from the Feather RP2040 and Perma-Proto board have been properly connected.

Connect NeoPixels

Get the two cases ready to connect to the NeoPixel strips.

Connect NeoPixel #0

Locate the 3-pin JST cable that is connected to NeoPixel #0 and plug it into one of the NeoPixel strips.

Connected NeoPixels

Proceed to connect the NeoPixel strips to the cables on the Perma-Proto consecutively.

Connected Holiday Tree

Take a moment to inspect the NeoPixel strips have been properly connected to the cables on the Perma-Proto.

USB Power

Plug in a USB-C cable to a 5V 1A power supply to power on the Feather RP2040 Scorpio. The NeoPixel strips should power on and begin animating.

NeoPixel Animations

Take a moment to inspect the NeoPixel strips are animating correctly.

Final Build

Congratulations on building your holiday tree with the Feather RP2040 Scorpio!

This guide was first published on Jan 31, 2023. It was last updated on Mar 28, 2024.