Build your own Ambient Color Control Pad and make it easy to set colors on NeoPixel strips. Embed them in a huge, colorful, glowing orb, behind a monitor, or above a cabient. NeoTrellis multicolor controller, say hello to NeoPixels!

Use the NeoTrellis with a Feather M4 Express to select colors that illuminate your world. The control pad sends your color selections to a 2m strip of 120 NeoPixels. Gorgeous diffusion courtesy of an inexpensive white plastic lamp, or pick your own diffuser! All programmed with CircuitPython for your coding pleasure.

This project takes advantage of the Feather M4 Express board's big brains! You may be able to run this on a Feather M0 Express, but you'll need to write to fewer NeoPixels.


1 x Rugged Metal On/Off Switch
19mm 6V RGB On/Off
1 x In-line power switch
for 2.1mm barrel jack
1 x USB cable - A/MicroB
For data and power
1 x USB Cable - Standard A-B
for DIY NeoPixel extension
1 x PLA Filament for 3D Printers
1.75mm Diameter - White - 1KG


To put together this project you'll need a few tools:

  • Soldering iron and solder
  • Wire strippers
  • Diagonal cutters
  • Small flathead screwdriver


You may want to use a lamp shade or other thin plastic material as a diffuser, depending on how you'll be using your Ambient Color Control Pad. You can also use it as underlighting or behind a frame or TV, in which case no need to diffuse.

In this guide I used shade from the IKEA Sjöpenna 17" pendant lamp, round. It comes in a few different sizes. You won't need the mounting hardware, lamp wire, or socket, but you can save those for another project!

3D Print the Enclosure

What If I Don't Have A 3D Printer?

Not to worry! You can use a 3D printing service such as 3DHubs or MakeXYZ to have a local 3D printer operator 3D print and ship you parts to you. This is a great way to get your parts 3D printed by local makers. You could also try checking out your local Library or search for a Maker Space.

3D Printed Parts

The enclosure is comprised of four parts. Each part is listed below with a description. Parts with mounting holes and standoffs can be tapped with an M2.5 size screw tap – This creates precise threads needed for fastening screws. These parts are designed for FDM style 3D printers. 

These files were modified from the original design by the Ruiz Bros. for the NeoTrellis Game enclosure.

Snap Fit Tolerances

The four parts are designed to snap fit together. Chamfered tabs on the inside edges of the frame lock into indentations along the lip of the top and bottom covers. To produce these tolerances, you may need to adjust printer's slice settings.

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
  • 60% infill
  • No support materials required

Build the Controller

Here's how the controller's component work together to provide a beautiful, clear interface for selecting colors:

  • On/off switch turns on and off the Feather M4
  • Feather M4 connected to NeoTrellis for input selections
  • Feather M4 sends color data to NeoPixel strip
  • 5V DC wall supply powers NeoPixel strip (and shares ground with the Feather M4 and NeoTrellis)
  • USB powers Feather M4

The diagram above shows the connections, we'll dive in to further detail as we build it.

NeoTrellis Connector

For lots of details on the NeoTrellis, check out the guide.

First, we will connect the NeoTrellis to the Feather M4 using a four conductor JST-PH cable.

Cut off one end of the cable, and then strip and solder these to the Feather M4 with the following connections from left to right with the "keyed' part of the connector facing up: (the other end will plug into the NeoTrellis)

  • Feather SCL
  • Feater SDA
  • Feather 3V
  • FeatherGND

You can use markings to keep things straight, and follow the images below for guidance.









Button Connections

The button we're using here has a few connections to make, since it contains both a switch and an LED. You can make more connections if you choose to use it in RGB mode, but here we're using only a single color, red, so four wires are needed. Two for the switch and two for the LED.

We will use arcade quick connectors for the wiring, as shown below. The connections to make are:

  • Button R(ed) to Feather GND
  • Button LED cathode to Feather D13
  • Button Common to Feather GND
  • Button Normally Open to Feather En(able) pin
You may need to use a multimeter in continuity mode to determine which of the three center row pins are common, normally open, and normally closed.

Slide the wire terminal connectors onto the button terminals as shown.


Clip the JST connector ends off of the wires.


Strip the wire ends.


Solder the wire ends to the Feather pins as listed above.

Terminal Block

In order to keep things modular, we'll use a three position screw terminal block soldered to the Feather M4's prototyping area for the NeoPixel strip power and data connections.

The DC power from the wall adapter and the NeoPixel USB extension will combine at the terminal block, as well as make the necessary connections to the Feather M4 as listed here:

  • DC adapter GND to NeoPixel strip GND and Feather GND
  • DC adapter +5V to NeoPixel strip +5V
  • NeoPixel Data IN (DIN) to Feather pin D5

Solder the pins of the terminal block to three pads on the Feather's prototyping area.


Use a small jumper or bit of wire to connect the left position of the terminal block as pictured to one of the Feather's GND pads.


Solder another jumper wire from the rightmost terminal to the Feather's D5 pin -- this will be used as the data line to communicate with the NeoPixels!

DC Power Jack

Now, we can prep the panel mount DC power jack. Cut and strip two ~4" / 10 cm lengths of wire -- one red, one black. Solder these to the jack connectors as shown.

It is vital to solder these wires to the proper lugs, or you could fry your project! This type of connector, coupled with our 5V 2A DC power adapter uses a center positive convention. To triple check things, use a multimeter in continuity mode to check that the center post of the jack is connected to the lug to which you are going to solder the red wire.





To be extra sure you've got the correct posts, test the DC voltage on your multimeter. Plug the wall adapter into wall power and the jack (make sure the wires aren't touching!) then test voltage on the wires. You should read about +5V.

USB Terminal Connector to NeoPixel Strip

We want to put a bit of distance between our Ambient Color Control Pad and the NeoPixel strip. To do so we'll repurpose a USB cable. To do so, we need to adapt the input end of the NeoPixel strip to connect to a USB-A cable end. The USB-A female socket to 5-pin terminal block is perfect for this.

Cut and strip the NeoPixel wires as shown. Be sure you have the correct end of the strip! The silkscreen printing on strips can vary, but follow these pictures for guidance, and pay attention to the direction of the data pins. You should see the word 'Din' (data in) printed closest to the left side of an individual NeoPixel and 'Do' (data out) on the right.





Insert the wires to the corresponding positions on the terminal block (the position indicators are molded into the black plastic) Then screw them down tightly.

  • Red to +
  • Data In (usually white or green) to D+
  • Black to -

Bare USB End

Prepare the USB cable by trimming the square USB-B end off and then stripping the wires. Note how this USB-A to B style cable has nice, heavy gauge wires, since USB-A cables are meant to power higher current devices.

Advanced Option: If you want to go the extra mile, you can double up the ground and power lines -- the metal shroud could be paired with the black wire and the white wire could be paired with the red. If you do so, just be sure to make the same connections at the terminal block to the NeoPixel wires.


The first assembly step will be to thread the bare USB cable end into the port on the side of the case frame.

Add DC Panel Mount

Now, add the DC power panel mount, and screw on the nut from the inside as shown.

Screw Terminal Connections

Screw in the data wire from the USB cable to the rightmost position of the screw terminal. This is what connects it to the Feather's D5 pin.

Power Connection

Next, join the two red wires of the DC power jack and the USB cable in the center position of the screw terminal and screw it down snugly.

Ground Connection

Join the two black ground wires coming from the DC power jack and the USB cable, respectively, and screw them into the leftmost position of the screw terminal.

Case Bottom

Use four M2.5 screws to attach the Feather to the case bottom.

Button Connection

Remove the crimp connectors from the button and then thread it into the case.

Slip the nut over the wires, reconnect the crimp connectors (make sure to re-connect to the same terminals!) and screw on the nut.





NeoTrellis Connection

Place the tray insert over the top of the frame, and then plug in the NeoTrellis cable.

NeoTrellis Sandwich

Time to make a delicious PCB/Elastomer/PLA sandwich! Snap fit the NeoTrellis onto the tray, making sure the pad marked "1" on the silkscreen is at the upper left of the case as shown.

Next, layer on the elastomer button pad -- note that there are two pairs of elastomer bumps that are keyed to fit into two pairs of holes in the PCB -- it won't lay flat if you turn it 90 degrees off from this position.

Finally, snap fit on the case top -- again, watch the orientation of this part -- there are two side chamfers that fit the case properly.

Code with CircuitPython

We'll be using CircuitPython for this project. Are you new to using CircuitPython? No worries, there is a full getting started guide here.

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and its installation in this tutorial.

Follow this guide for instructions on installing the latest release version of CircuitPython for the Feather M4 Express.


You'll also need to add the following libraries for this project. Follow this guide on adding libraries. The ones you'll need are:

  • adafruit_neotrellis
  • adafruit_bus_device
  • adafruit_seesaw
  • neopixel

Download the latest adafruit-circuitpython-bundle .zip file as linked in the guide. Then,  unzip the file and drag those libraries to the lib folder on you Feather M4.


Here is the code we'll use. Copy it and then paste in Mu. Save it to your Feather M4 as code.py

# Ambient Color Control Pad
# NeoTrellis to select colors of NeoPixel strip
# NeoTrellis connected to Feather M4 (need the extra memory vs. M0) SCL, SDA
# NeoPixel 120 strip connected to pin D5
# NeoPixel strip powered over 5V 2A DC wall power supply
# On/off button RGB connects En to GND, LED to D13

import time
import board
from board import SCL, SDA
import busio
import neopixel
from adafruit_neotrellis.neotrellis import NeoTrellis
from digitalio import DigitalInOut, Direction

button_LED = DigitalInOut(board.D13)
button_LED.direction = Direction.OUTPUT
button_LED.value = True

pixel_pin = board.D5
num_pixels = 120

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

# create the i2c object for the trellis
i2c_bus = busio.I2C(SCL, SDA)

# create the trellis object
trellis = NeoTrellis(i2c_bus)

# color definitions
OFF = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
YELLOW_GREEN = (127, 255, 0)
CYAN = (0, 255, 255)
LIGHT_BLUE = (0, 127, 255)
BLUE = (0, 0, 255)
PURPLE = (127, 0, 255)
ORANGE = (255, 80, 0)
PINK = (255, 0, 255)
ROUGE = (255, 0, 127)
WHITE = (100, 100, 100)
WHITE_WARM = (120, 100, 80)
WHITE_COOL = (80, 100, 120)
WHITE_GREEN = (80, 120, 100)

COLORS = [  # pixel colors

pixels.fill(COLORS[1])  # turn on the strip

def dimmed_colors(color_values):
    (red_value, green_value, blue_value) = color_values
    return (red_value // 10, green_value // 10, blue_value // 10)

# this will be called when button events are received
def blink(event):
    # turn the trellis LED on when a rising edge is detected
    # do the chase for the NeoPixel strip
    if event.edge == NeoTrellis.EDGE_RISING:
        trellis.pixels[event.number] = dimmed_colors(COLORS[event.number])
        for chase_off in range(num_pixels):  # chase LEDs off
            pixels[chase_off] = (OFF)

        for chase_on in range(num_pixels - 1, -1, -1):  # chase LEDs on
            pixels[chase_on] = (COLORS[event.number])

    # turn the trellis LED back to full color when a rising edge is detected
    elif event.edge == NeoTrellis.EDGE_FALLING:
        trellis.pixels[event.number] = COLORS[event.number]

# boot up animation on trellis
trellis.pixels.brightness = 0.2
for i in range(16):
    # activate rising edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_RISING)
    # activate falling edge events on all keys
    trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
    # set all keys to trigger the blink callback
    trellis.callbacks[i] = blink

    # light the trellis LEDs on startup
    trellis.pixels[i] = COLORS[i]

print("  Ambient Color Control Pad")
print("    ---press a button to change the ambient color---")

while True:

    # call the sync function call any triggered callbacks
    # the trellis can only be read every 17 milliseconds or so

Control Color

It is time to power up your Ambient Color Control Pad and connect it to the NeoPixel strip!

Plug in DC power, USB power, and the NeoPixel strip's USB adapter.

Next, press the on/off button to fire it up!

We have color! Now, you can try out the different color buttons and enjoy the light show.


The true beauty of the ambient color comes from having a large diffusion object to fill with color. Here, I've put together the shade from a lamp and then filled it with the NeoPixel strand, draped inside of it, near the center.

Going Beyond the Guide

Now that you have your Ambient Color Control Pad providing easy control of simple color changes, you can get fancy! How about different animation modes? Or color interpolations? It's all up to you!

Enjoy your super saturated ambient environment!

This guide was first published on Oct 27, 2018. It was last updated on Oct 27, 2018.