Once you've finished setting up your Feather RP2040 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 to your computer as a zipped folder.

# SPDX-FileCopyrightText: 2017 John Park for Adafruit Industries
# Modified 2023 by Erin St Blaine
#
# SPDX-License-Identifier: MIT


import board
import pulseio
import neopixel
import adafruit_irremote
from rainbowio import colorwheel
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.SparklePulse import SparklePulse
import adafruit_led_animation.color as color

NUMBER_OF_PIXELS = 85
pixels = neopixel.NeoPixel(board.D13, NUMBER_OF_PIXELS)

# Define the brightness levels and their corresponding values
# Start at a non-blinding brightness.
BRIGHTNESS_LEVELS = (0.025, 0.05, 0.1, 0.2, 0.4, 0.6, 0.7, 0.8, 1.0)
brightness_index = 2
pixels.brightness = BRIGHTNESS_LEVELS[brightness_index]

pulsein = pulseio.PulseIn(board.A0, maxlen=120, idle_state=True)
decoder = adafruit_irremote.GenericDecode()

SPEEDS = (0.25, 0.125, 0.1, 0.08, 0.05, 0.02, 0.01)  # Customize speed levels here
speed_index = 4

def setup_animations():
    """Set up all the available animations."""
    # Animation Setup
    rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=2, name="rainbow", step=3)
    sparkle = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.WHITE, name="sparkle")
    solid = Solid(pixels, color=colorwheel(0), name="solid")
    # Make the Solid animation changeable quickly.
    solid.speed = 0.01
    off = Solid(pixels, color=color.BLACK, name="off")
    rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=6, name="rainbow", step=2.4)
    rainbow_carousel = RainbowChase(pixels, speed=SPEEDS[speed_index], size=4, spacing=1, step=20)
    party_chase = RainbowChase(pixels, speed=SPEEDS[speed_index], size=1, spacing=5, step=6)
    rainbow_chase2 = RainbowChase(pixels, speed=SPEEDS[speed_index], size=10, spacing=1, step=18)
    chase = Chase(pixels, speed=SPEEDS[speed_index], color=color.RED, size=1, spacing=6)
    rainbow_comet2 = RainbowComet(
        pixels, speed=0.02, tail_length=104, colorwheel_offset=80, bounce=False)
    rainbow_comet3 = RainbowComet(
        pixels, speed=SPEEDS[speed_index], tail_length=25,
        colorwheel_offset=128, step=4, bounce=False)
    lava = Comet(pixels, speed=SPEEDS[speed_index],
                 color=color.ORANGE, tail_length=40, bounce=False)
    sparkle1 = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.BLUE, num_sparkles=10)
    pulse = Pulse(pixels, speed=0.1, color=color.AMBER, period=3)
    sparkle_pulse = SparklePulse(pixels, speed=0.05, period=2, color=color.JADE, max_intensity=3)

    # Animation Sequence Playlist -- rearrange to change the order of animations
    # advance_interval is None, so the animations change only under user control.
    all_animations = AnimationSequence(
        rainbow,
        rainbow_chase2,
        rainbow_carousel,
        party_chase,
        rainbow_comet2,
        rainbow_comet3,
        sparkle_pulse,
        pulse,
        chase,
        rainbow,
        solid,
        sparkle,
        lava,
        sparkle1,
        off,
        auto_clear=True,
        auto_reset=True,
        advance_interval=None,
    )
    return all_animations

# IR Remote Mapping for the Adafruit mini IR remote
# https://www.adafruit.com/product/389

CMD_1 = 247          #  1: [255, 2, 247, 8]
CMD_2 = 119          #  2: [255, 2, 119, 136]
CMD_3 = 183          #  3: [255, 2, 183, 72]
CMD_4 = 215          #  4: [255, 2, 215, 40]
CMD_5 = 87           #  5: [255, 2, 87, 168]
CMD_6 = 151          #  6: [255, 2, 151, 104]
CMD_7 = 231          #  7: [255, 2, 231, 24]
CMD_8 = 103          #  8: [255, 2, 103, 152]
CMD_9 = 167          #  9: [255, 2, 167, 88]
CMD_0 = 207          #  0: [255, 2, 207, 48]

CMD_UP = 95          # ^ : [255, 2, 95, 160]
CMD_DOWN = 79        # v : [255, 2, 79, 176]
CMD_RIGHT = 175      # > : [255, 2, 175, 80]
CMD_LEFT = 239       # < : [255, 2, 239, 16]

CMD_ENTER_SAVE = 111 # Enter/Save: [255, 2, 111, 144]
CMD_SETUP = 223      # Setup: [255, 2, 223, 32]
CMD_STOP_MODE = 159  # Stop/Mode: [255, 2, 159, 96]
CMD_BACK = 143       # Back: [255, 2, 143, 112]

CMD_VOL_DOWN = 255   # Vol - : [255, 2, 255, 0]
CMD_VOL_UP = 191     # Vol + : [255, 2, 191, 64]
CMD_PLAY_PAUSE = 127 # Play/Pause: [255, 2, 127, 128]
CMD_REPEAT = True    # short code: repeat of previous command


def read_command():
    """Try to read an IR command. If none seen or if error, return None."""
    try:
        pulses = decoder.read_pulses(pulsein, blocking=False)
        if pulses:
            code = decoder.decode_bits(pulses)
            if len(code) > 3:
                print("Decoded:", code)
                return code[2]
        # if code is less than or equal to 3 characters long or no pulses received
        return None
    except adafruit_irremote.IRNECRepeatException:  # unusual short code!
        print("NEC repeat!")
        return CMD_REPEAT
    except adafruit_irremote.IRDecodeException as e:  # failed to decode
        print("Failed to decode:", e)
        return None
    except MemoryError as e:
        print("Memory error: ", e)
        return None

SOLID_COLORS = {
    CMD_0 : color.BLACK,
    CMD_1 : color.RED,
    CMD_2 : color.GREEN,
    CMD_3 : color.WHITE,
    CMD_4 : color.BLUE,
    CMD_5 : color.PINK,
    CMD_6 : color.YELLOW,
    CMD_7 : color.PURPLE,
    CMD_8 : color.TEAL,
    CMD_9 : color.ORANGE,
    }

# main program

animations = setup_animations()
last_command = None

while True:
    command = read_command()
    if command is None:
        # Nothing read, just keep animating.
        animations.animate() # Run one animation cycle.
        continue

    if command == CMD_REPEAT:
        command = last_command

    last_command = command
    print("Command", command)


    # See if the command was a number button. Fetch the animation color if it is.
    solid_color = SOLID_COLORS.get(command, None)
    if solid_color:
        # Jump to the "solid" animation. Set its color to
        # the chosen color.
        animations.activate("solid")
        animations.current_animation.color = solid_color
    elif command == CMD_LEFT:
        animations.previous()
    elif command == CMD_RIGHT:
        animations.next()
    elif command == CMD_DOWN:
        # Slow down current animation
        if speed_index > 0:
            speed_index -= 1
            animations.current_animation.speed = SPEEDS[speed_index]
        print("speed of current animation is now:", animations.current_animation.speed)
    elif command == CMD_UP:
        if speed_index < len(SPEEDS) - 1:
            speed_index += 1
            animations.current_animation.speed = SPEEDS[speed_index]
        print("speed of current animation is now:", animations.current_animation.speed)
    elif command == CMD_VOL_DOWN:
        if brightness_index > 0:
            brightness_index -= 1
            pixels.brightness = BRIGHTNESS_LEVELS[brightness_index]
        print("brightness:", pixels.brightness)
    elif command == CMD_VOL_UP:
        if brightness_index < len(BRIGHTNESS_LEVELS) - 1:
            brightness_index += 1
            pixels.brightness = BRIGHTNESS_LEVELS[brightness_index]
            print("brightness:", pixels.brightness)

Upload the Code and Libraries to the Feather RP2040

After downloading the Project Bundle, plug your Feather RP2040 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 items to the Feather RP2040's CIRCUITPY drive. 

  • lib folder
  • code.py

Your Feather RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

CIRCUITPY

How the CircuitPython Code Works

First, we import all the necessary libraries and animations we'll be using.

Check out the CircuitPython LED Animations Library guide for more info on adding your own animations.

import board
import pulseio
import neopixel
import adafruit_irremote
from rainbowio import colorwheel
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.chase import Chase
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.SparklePulse import SparklePulse
import adafruit_led_animation.color as color

NeoPixel Setup

Set your total number of pixels here. If you soldered to a different pin than 13, you can change the pin number here as well.

NUMBER_OF_PIXELS = 85 
pixels = neopixel.NeoPixel(board.D13, NUMBER_OF_PIXELS)

Speed & Brightness Control

This code includes 8 brightness levels and 7 speed levels, which can be selected with buttons on the IR remote. You can edit them, add or subtract here.

# Define the brightness levels and their corresponding values
# Start at a non-blinding brightness.
BRIGHTNESS_LEVELS = (0.025, 0.05, 0.1, 0.2, 0.4, 0.6, 0.7, 0.8, 1.0)
brightness_index = 2
pixels.brightness = BRIGHTNESS_LEVELS[brightness_index]

pulsein = pulseio.PulseIn(board.A0, maxlen=120, idle_state=True)
decoder = adafruit_irremote.GenericDecode()

SPEEDS = (0.25, 0.125, 0.1, 0.08, 0.05, 0.02, 0.01)  # Customize speed levels here
speed_index = 4

Animations

Here is where you set up and define your animations. You can edit colors, spacing, and lots of other variables until the animations do exactly what you want.

Pressing the left and right arrow keys will cycle through the animations in this list. You can add, subtract, or reorder them so the animations appear in the order you want.

def setup_animations():
    """Set up all the available animations."""
    # Animation Setup
    rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=2, name="rainbow", step=3)
    sparkle = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.WHITE, name="sparkle")
    solid = Solid(pixels, color=colorwheel(0), name="solid")
    # Make the Solid animation changeable quickly.
    solid.speed = 0.01
    off = Solid(pixels, color=color.BLACK, name="off")
    rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=6, name="rainbow", step=2.4)
    rainbow_carousel = RainbowChase(pixels, speed=SPEEDS[speed_index], size=4, spacing=1, step=20)
    party_chase = RainbowChase(pixels, speed=SPEEDS[speed_index], size=1, spacing=5, step=6)
    rainbow_chase2 = RainbowChase(pixels, speed=SPEEDS[speed_index], size=10, spacing=1, step=18)
    chase = Chase(pixels, speed=SPEEDS[speed_index], color=color.RED, size=1, spacing=6)
    rainbow_comet2 = RainbowComet(
        pixels, speed=0.02, tail_length=104, colorwheel_offset=80, bounce=False)
    rainbow_comet3 = RainbowComet(
        pixels, speed=SPEEDS[speed_index], tail_length=25, 
        colorwheel_offset=128, step=4, bounce=False)
    lava = Comet(pixels, speed=SPEEDS[speed_index], 
                 color=color.ORANGE, tail_length=40, bounce=False)
    sparkle1 = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.BLUE, num_sparkles=10)
    pulse = Pulse(pixels, speed=0.1, color=color.AMBER, period=3)
    sparkle_pulse = SparklePulse(pixels, speed=0.05, period=2, color=color.JADE, max_intensity=3)

    # Animation Sequence Playlist -- rearrange to change the order of animations
    # advance_interval is None, so the animations change only under user control.
    all_animations = AnimationSequence(
        rainbow,
        rainbow_chase2,
        rainbow_carousel,
        party_chase,
        rainbow_comet2,
        rainbow_comet3,
        sparkle_pulse,
        pulse,
        chase,
        rainbow,
        solid,
        sparkle,
        lava,
        sparkle1,
        off,
        auto_clear=True,
        auto_reset=True,
        advance_interval=None,
    )
    return all_animations

IR Mapping

The next section deals with mapping the button keys using the Adafruit IR remote. If you want to use a different remote, change the codes to match your remote here.

CMD_1 = 247          #  1: [255, 2, 247, 8]
CMD_2 = 119          #  2: [255, 2, 119, 136]
CMD_3 = 183          #  3: [255, 2, 183, 72]
CMD_4 = 215          #  4: [255, 2, 215, 40]
CMD_5 = 87           #  5: [255, 2, 87, 168]
CMD_6 = 151          #  6: [255, 2, 151, 104]
CMD_7 = 231          #  7: [255, 2, 231, 24]
CMD_8 = 103          #  8: [255, 2, 103, 152]
CMD_9 = 167          #  9: [255, 2, 167, 88]
CMD_0 = 207          #  0: [255, 2, 207, 48]

CMD_UP = 95          # ^ : [255, 2, 95, 160]
CMD_DOWN = 79        # v : [255, 2, 79, 176]
CMD_RIGHT = 175      # > : [255, 2, 175, 80]
CMD_LEFT = 239       # < : [255, 2, 239, 16]

CMD_ENTER_SAVE = 111 # Enter/Save: [255, 2, 111, 144]
CMD_SETUP = 223      # Setup: [255, 2, 223, 32]
CMD_STOP_MODE = 159  # Stop/Mode: [255, 2, 159, 96]
CMD_BACK = 143       # Back: [255, 2, 143, 112]

CMD_VOL_DOWN = 255   # Vol - : [255, 2, 255, 0]
CMD_VOL_UP = 191     # Vol + : [255, 2, 191, 64]
CMD_PLAY_PAUSE = 127 # Play/Pause: [255, 2, 127, 128]
CMD_REPEAT = True    # short code: repeat of previous command

Solid Color Keys

The 0-9 buttons will select solid colors from the rainbow, with 0 as "black", which will turn the LEDs off. You can edit the colors, or assign different animations to the buttons by editing this code. 

SOLID_COLORS = {
    CMD_0 : color.BLACK,
    CMD_1 : color.RED,
    CMD_2 : color.GREEN,
    CMD_3 : color.WHITE,
    CMD_4 : color.BLUE,
    CMD_5 : color.PINK,
    CMD_6 : color.YELLOW,
    CMD_7 : color.PURPLE,
    CMD_8 : color.TEAL,
    CMD_9 : color.ORANGE,
    }

Main Loop

The main loop starts with the while True: line. First, the code checks to see if a button has been pressed. If you open the serial monitor and press some buttons on the remote, you'll see a readout of which code is being transmitted. 

Finally, the code tells the NeoPixels how to behave when a button is pressed. This is the part you'll edit if you want to customize your button layout.

# if control mode is 0..
    # control the volume of the white noise
    if ctrl_mode == 0:
        # encoder neopixel is blue
        pixel0.fill(BLUE)
        # if the encoder moves..
        if pos0 != last_pos0:
            # if you increase the encoder
            # increase value by 0.1
            # maxed out at 1
            if pos0 > last_pos0:
                volume = volume + 0.1
                if volume > 1:
                    volume = 1
            # if you decrease
            # decrease value by 0.1
            # minimum value of 0
            if pos0 < last_pos0:
                volume = volume - 0.1
                if volume < 0:
                    volume = 0
            print(volume)
            # reset the position
            last_pos0 = pos0

This guide was first published on Mar 07, 2023. It was last updated on Jul 20, 2024.

This page (Software) was last updated on Jul 20, 2024.

Text editor powered by tinymce.