Since the badge has built-in NeoPixels, let's animate them.

Now let's take a look at the code that does the animation.

CircuitPython NeoPixel Code

brightness = 0.2
direction = 1
speed = 1

# Define the NeoPixel
neopixels = neopixel.NeoPixel(
    board.NEOPIXEL,
    NEOPIXEL_COUNT,
    brightness=settings["brightness"],
    auto_write=False,
    pixel_order=neopixel.GRB,
)

# Remap the calculated rotation to 0 - 255
def remap(vector):
    return int(((255 * vector + 85) * 0.75) + 0.5)

# Calculate the Hue rotation starting with Red as 0 degrees
def rotate(degrees):
    cosA = cos(radians(degrees))
    sinA = sin(radians(degrees))
    red = cosA + (1.0 - cosA) / 3.0
    green = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
    blue = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
    return (remap(red), remap(green), remap(blue))

palette = []
pixels = []

# Generate a rainbow palette
for degree in range(0, 360):
    color = rotate(degree)
    palette.append(color[0] << 16 | color[1] << 8 | color[2])

# Create the Pattern
for x in range(0, NEOPIXEL_COUNT):
    pixels.append(x * 360 // NEOPIXEL_COUNT)

while True:
    for color in range(0, 360, speed):
        for index in range(0, NEOPIXEL_COUNT):
            palette_index = pixels[index] + color * direction
            if palette_index >= 360:
                palette_index -= 360
            elif palette_index < 0:
                palette_index += 360
            neopixels[index] = palette[palette_index]
        neopixels.show()
        neopixels.brightness = brightness

This can be broken down. Let's look at each section.

We will begin by including NEOPIXEL_COUNT, which was discussed in the previous section. Next, we set the default brightness, which is a float value between 0.0 and 1.0, the direction which will be either 1 or -1, and the speed which has to be a positive intor integer. Finally, we define the NeoPixel object.

NEOPIXEL_COUNT = 5

brightness = 0.2
direction = 1
speed = 1

# Define the NeoPixel
neopixels = neopixel.NeoPixel(
    board.NEOPIXEL,
    NEOPIXEL_COUNT,
    brightness=settings["brightness"],
    auto_write=False,
    pixel_order=neopixel.GRB,
)

In the next section we define a couple of functions that do the math for generating the rainbow palette. The rotate() function does most of the work and takes in a number between 0 and 360 degrees, with 0 degrees being red, and performs calculations to get the red, blue, and green component values. The values are then remapped with the remap() function to be between 0 and 255.

# Remap the calculated rotation to 0 - 255
def remap(vector):
    return int(((255 * vector + 85) * 0.75) + 0.5)

# Calculate the Hue rotation starting with Red as 0 degrees
def rotate(degrees):
    cosA = cos(radians(degrees))
    sinA = sin(radians(degrees))
    red = cosA + (1.0 - cosA) / 3.0
    green = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
    blue = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
    return (remap(red), remap(green), remap(blue))

In the next section, we pre-calculate the red, blue, and green components of each of the colors so that we don't need to do as much math during the animation sequence and add them into a palette array. For the pattern, we are really just trying to choose some numbers that are distributed evenly.

palette = []
pixels = []

# Generate a rainbow palette
for degree in range(0, 360):
    color = rotate(degree)
    palette.append(color[0] << 16 | color[1] << 8 | color[2])

# Create the Pattern
for x in range(0, NEOPIXEL_COUNT):
    pixels.append(x * 360 // NEOPIXEL_COUNT)

Finally, we get to the main loop and do a simple palette rotation. We do this by going through all of the degrees in the color wheel. Depending on the speed, we may skip a few steps to make it go faster. We simply need to get the index of the color we want in the palette that we had pre-calculated.

We can change the direction by making the index a negative number, which is then adjusted to be within the range of 0-360 and we have our index. We look up the color by providing the index to the palette and then assign the color to the neopixel.

We also set the brightness of the NeoPixels here in case we changed it.

while True:
    for color in range(0, 360, speed):
        for index in range(0, NEOPIXEL_COUNT):
            palette_index = pixels[index] + color * direction
            if palette_index >= 360:
                palette_index -= 360
            elif palette_index < 0:
                palette_index += 360
            neopixels[index] = palette[palette_index]
        neopixels.show()
        neopixels.brightness = brightness

This guide was first published on May 28, 2019. It was last updated on Apr 15, 2024.

This page (Using the NeoPixels) was last updated on Mar 08, 2024.

Text editor powered by tinymce.