In this project we'll use a Circuit Playground Express to light up a 3D print Christmas tree. The 10x on-board NeoPixels are perfect for lighting up all sorts of decorations and props. Our custom designed geometric Christmas tree is hollow with a thin walled shell. This allows internal light to nicely diffuse the shape. It's also designed to be 3D printed without any support material.

Circuit Python Code

Learn how to use Adafruit's Circuit Python to write code and light up the NeoPixel LEDs using colors and animations. Just download the latest UF2 for your CPX and get the latest library bundle to get started. Our demo code will get you up and running quick and easy!

A special 3D printed mount secures the Adafruit Circuit Playground Express and snap fits under the Christmas Tree. For best lighting effects, use translucent PLA filament to nicely diffuse NeoPixel LEDs.

Prerequisite Guides

There's resources in these guides that go beyond what's covered in this tutorial. The introduction guide is all about setting up your Circuit Playground Express board. The Circuit Python introduction guide walks you through all of the pinouts, sensors and everything you need to know.

USB Power

The Circuit Playground Express can stay connected via USB power from either a wall adapter or computer's hub. This allows the Christmas Tree to stay lit as long as you want (nightlight mode anyone?). The Christmas tree has a cutaway to accommodate for a USB cable. Lipo battery is optional and can be tucked in between the Circuit Playground Express and 3D printed mount.

Snap-On CPX Mount

This 3D printed mount is designed specifically secure the Circuit Playground Express (and Classic) without any hardware screws. Tabs on the sides grasp the edges of the PCB and hold it in place. Built-in standoffs elevate the PCB allowing room for a 500mAh lipo battery. The symmetrical design allows any orientation and provides cut aways for JST and USB connectors. 

3d_printing_cpx-mount-battery.jpg

3d_printing_cpx-mount-side.jpg

3d_printing_cpx-mount-bottom.jpg

3D Modeling CAD

The geometric tree was designed in Autodesk Fusion 360. The source file is available to download and features sketches and parametric timeline so it's free to tweak and modify.

3D Printed Parts

The tree is printed in a translucent filament to better diffuse the LEDs. A special dual color version was designed for dual extrusion setups. The starfruit tree topper requires support material, optionally split in half  print in two pieces and glue together. 

Dual Extrusion

Different colors can be used to create masking effects that reveal light using translucent colors. The black tree is a mix of Fillamentum's Verito Galaxy PLA and Translucent PLA for the rings – This creates a lighting effects that illuminates the rings around the tree. 

Delicious Filaments

For high quality prints we suggest good quality filaments from awesome manufacturers. Here's a list of the various filaments we used in this project.

Slice Settings

Use these settings as reference. Values listed were used in Ultimaker's CURA 3.X slicing software.

  • 0.2mm Layer Height / 0.4mm nozzle
  • 0.38mm Line Width (inner & outer widths)
  • 60mm/s printing speed
  • 20% infill

Multi-Purpose CPX Mount

This mount makes for a quick 3D print and provide decent support for making a simple and portable project. To remove the Circuit Playground from the mount, use fingers to pull apart tabs and push PCB outwards from underneath.

3d_printing_cpx-mount-top.jpg

3d_printing_cpx-mount-solo.jpg

Design Source Files

The tree and CPX mount was designed in Fusion 360. This can be downloaded in different formats like STEP, SAT and more. Electronic components like the board, displays, connectors and more can be downloaded from our Fusion 360 CAD parts github repo.

Setup Adafruit Circuit Playground Express for CircuitPython

We'll need to get our board setup so we can run CircuitPython code. First thing we'll need to do is connect the board to your computer with a microUSB cable. Then double-click on the reset button to put it in "UF2" boot-loader mode. The NeoPixels will turn green. The board will then show up as a USB storage device on your computer named "CPLAYBOOT". 

Follow the guide below to setup the firmware, once complete, come back here and proceed.

Editing Code

You'll want to use the Mu python editor to modify the code. Mu is a simple code editor that works with the Adafruit CircuitPython boards. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in so you get immediate feedback from your board's serial output! See the guide below to for download and setup instructions.

Installing Project Code

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

Thankfully, we can do this in one go. 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 CircuitPlayground_Christmas_Tree/ and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your CIRCUITPY drive.

Your CIRCUITPY drive should now look similar to the following image:

CIRCUITPY
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import board
import neopixel

# On CircuitPlayground Express, and boards with built in status NeoPixel -> board.NEOPIXEL
# Otherwise choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D1
pixel_pin = board.NEOPIXEL

# On a Raspberry pi, use this instead, not all pins are supported
# pixel_pin = board.D18

# The number of NeoPixels
num_pixels = 10

# Increase or decrease between 0 and 1 to increase or decrease the brightness of the LEDs
brightness = 0.6

# The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed!
# For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW.
ORDER = neopixel.GRB

pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=brightness, auto_write=False,
                           pixel_order=ORDER)


def colorwheel(pos):
    # Input a value 0 to 255 to get a color value.
    # The colours are a transition r - g - b - back to r.
    # Works with RGB or RGBW LEDs.
    if pos < 0 or pos > 255:
        r = g = b = 0
    elif pos < 85:
        r = int(pos * 3)
        g = int(255 - pos * 3)
        b = 0
    elif pos < 170:
        pos -= 85
        r = int(255 - pos * 3)
        g = 0
        b = int(pos * 3)
    else:
        pos -= 170
        r = 0
        g = int(pos * 3)
        b = int(255 - pos * 3)
    return (r, g, b) if ORDER in (neopixel.RGB, neopixel.GRB) else (r, g, b, 0)


def rainbow_swirl(wait):
    for j in range(255):
        for i in range(num_pixels):
            pixel_index = (i * 256 // num_pixels) + j
            pixels[i] = colorwheel(pixel_index & 255)
        pixels.show()
        time.sleep(wait)


def rainbow_fill(wait):
    for j in range(255):
        for i in range(num_pixels):
            pixel_index = int(i + j)
            pixels[i] = colorwheel(pixel_index & 255)
        pixels.show()
        time.sleep(wait)


def christmas_flash(duration):
    pixels.fill((255, 0, 0))
    pixels.show()
    time.sleep(duration)
    pixels.fill((255, 255, 255))
    pixels.show()
    time.sleep(duration)


while True:
    for _ in range(5):
        christmas_flash(0.5)

    for _ in range(5):
        christmas_flash(0.1)

    pixels.fill((255, 0, 0))
    pixels.show()
    time.sleep(1)

    rainbow_fill(0.001)  # Increase the number to slow down the rainbow

    pixels.fill((0, 0, 0))
    pixels.show()
    time.sleep(1)
    rainbow_swirl(0.001)  # Increase the number to slow down the rainbow

This guide was first published on Dec 19, 2018. It was last updated on Mar 29, 2024.