Colour-cycling a Christmas Star

A few years ago, at a Christmas market in Germany, I bought myself two pack-flat cardboard stars. They’re meant to use a specific light fitting, but in 2019 I bodged them on top of some simple bedside lamps from Woodies, and in 2020 I hung one using a USB cable that was connected to a Raspberry Pi. Why was the cable connected to a Pi? So that the Pi could run some Python code to talk to the LED light strip that was connected to the APA102 driver. The result is a star that cycles colours nicely.

import bibliopixel as bp
import bibliopixel.colors as colors
import bibliopixel.drivers.channel_order as co
import bibliopixel.drivers.serial as serial
import bibliopixel.layout as layout
from bibliopixel.animation.strip import Strip
from bibliopixel.colors.arithmetic import color_scale

# causes frame timing information to be output
bp.log.setLogLevel(bp.log.DEBUG)


class ColorFade(Strip):
    """Fill the dots progressively along the strip."""

    COLOR_DEFAULTS = (
        (
            "colors",
            [
                colors.Red,
                colors.Orange,
                colors.Yellow,
                colors.Green,
                colors.Blue,
                colors.Indigo,
                colors.Violet,
            ],
        ),
    )

    def wave_range(self, start, peak, step):
        main = [i for i in range(start, peak + 1, step)]
        return main + [i for i in reversed(main[0 : len(main) - 1])]

    def __init__(self, layout, step=1, start=0, end=-1, **kwds):
        super().__init__(layout, start, end, **kwds)
        self._levels = self.wave_range(0, 255, step)
        self._level_count = len(self._levels)

    def pre_run(self):
        self._step = 0

    def step(self, amt=1):
        c_index, l_index = divmod(self._step, self._level_count)
        color = self.palette(c_index)
        color = color_scale(color, self._levels[l_index])
        self.layout.fill(color, self._start, self._end)
        self._step += amt


# set number of pixels & LED type here
driver = serial.Serial(
    num=22,
    ledtype=serial.LEDTYPE.APA102,
    c_order=co.ChannelOrder.BGR,
)
led = layout.Strip(driver)
anim = ColorFade(led)
try:
    # run the animation
    anim.run(fps=30)
except KeyboardInterrupt:
    # Ctrl+C will exit the animation and turn the LEDs offs
    led.all_off()
    led.update()

Tags: