Walkthru module

A project log for NeoTrellis Explorations

Adafruit NeoTrellis is a 4x4 button+Neopixel array that can be chained on i2c bus. I am exploring its programming and uses.

Jerry IsdaleJerry Isdale 07/19/2022 at 08:270 Comments

TThe file (module) encasulates the neopixels in the 4x4 key pad matrix.  Note these are NOT the conventional NeoPixel class.  They are accessed through the Adafruite_seesaw.neopixel version.  At time of project (and this writeup), the release version of adafruit_seesaw package (library) has its own independent NeoPixel class. Of particular annoyance is this class does not derive from Adafruit_CircuitPython_PixelBuf class, which means it cannot be used as a direct replacement for Adafruit_CircuitPython_NeoPixel, especially in the rather nice Adafruit_led_animations package. As mentioned in main project details, Neradoc has a pull request for their version of seesaw that does derive its NeoPixel class from PixelBuf.  The github's lib folder contains a snapshot of that fork of the seesaw package.

The module starts off with the imports and a few module global variables. We pull in all 13 of the current animations.

from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.animation.sparklepulse import SparklePulse
from adafruit_led_animation.animation.comet import Comet
from import Chase
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.rainbowchase import RainbowChase
from adafruit_led_animation.animation.rainbowsparkle import RainbowSparkle
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.colorcycle import ColorCycle
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.customcolorchase import CustomColorChase
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation import helper
import adafruit_led_animation.color as Color

from onboard_neopixel import blinkOnBoardPixel

# a local reference to the neotrellis.pixels PixelBuf derived NeoPixel
__trellis_pixels = None
__allBlack = None
__trellis_pixel_columns = None
__trellis_pixel_rows = None

 Next up we define a list, rainbowPalette, that has 16 somewhat contrasting colors. These will later be available to map to default key colors. Selecting these colors could be a whole huge discussion.

# we have Color.BLACK as well as the other color names (and colorwheel() ) from led_animations
# we need a 16 color palette that does NOT contain black - one for each button in keypad
rainbowPalette = [
    0xa0002, 0x80004, 0x50007, 0x30009,
    0xb, 0x10b, 0x308, 0x606,
    0x804, 0xb01, 0xb00, 0x30900,
    0x50700, 0x70400, 0xa0200, 0xc0000
def print_rainbowPalette():
    print("Rainbow Palette:", rainbowPalette)
    print("Rainbow Palette: ", end=" ")
    for clr in rainbowPalette:
        print(hex(clr), end=", ")

def show_rainbowPalette():
    global __trellis_pixels
    print("RainbowPalete blinking on board pixel")
    for clr in rainbowPalette:
        print("clr ", hex(clr))
        BLINK_COLOR = clr

 Then we define a couple more public module variables. current_animation references the currently active animation. trellisAnimations[] is a list of all the locally created animations. The first 16 entries will be used over in our neotrellis_keypad module.  They are associated by index order with the 16 keys.

# define some module variables
current_animation = None
trellisAnimations = []

the setup_animations(neotrellis):method comes next. It takes a neotrellis object parameter and defines a number  of  animations. The code is almost directly from the Adafruit_led_animations.examples.led_animation_all_animations demonstration program.

setup_animations() is the main entry. It takes a NeoTrellis as a parameter and fills in the globals.  The animations are created as local named objects in setup_animations(), with references hidden away in trellisAnimations[].  We do keep a module reference to the Solid Black animation in __allBlack. There is likely a better organization of references, but that will really depend on how the code gets reused for a real neotreillis product.

# this init function creates a bunch of animations in the trellisAnimations[]
def setup_animations(neotrellis):
    global __allBlack
    global __trellis_pixels
    global __trellis_pixel_columns
    global __trellis_pixel_rows

    __trellis_pixels = neotrellis.pixels
    blink = Blink(__trellis_pixels, speed=0.5, color=Color.JADE)
    color_cycle = ColorCycle(__trellis_pixels, speed=0.4, colors=[Color.MAGENTA, Color.ORANGE])
    comet = Comet(__trellis_pixels, speed=0.1, color=Color.PURPLE, tail_length=4, bounce=True)
    chase = Chase(__trellis_pixels, speed=0.1, size=3, spacing=6, color=Color.WHITE)
    pulse = Pulse(__trellis_pixels, speed=0.1, period=3, color=Color.AMBER)
    sparkle = Sparkle(__trellis_pixels, speed=0.1, color=Color.PURPLE, num_sparkles=6)
    solid = Solid(__trellis_pixels, color=Color.JADE)
    rainbow = Rainbow(__trellis_pixels, speed=0.1, period=2)
    sparkle_pulse = SparklePulse(__trellis_pixels, speed=0.1, period=3, color=Color.JADE)
    rainbow_comet = RainbowComet(__trellis_pixels, speed=0.1, tail_length=16, bounce=True)
    rainbow_chase = RainbowChase(__trellis_pixels, speed=0.1, size=3, spacing=2, step=8)
    rainbow_sparkle = RainbowSparkle(__trellis_pixels, speed=0.1, num_sparkles=4)
    custom_color_chase = CustomColorChase(
        __trellis_pixels, speed=0.1, size=2, spacing=3,
        colors=[Color.ORANGE, Color.WHITE, Color.JADE]

    # thats only 13 built in!  need 16 to have one each key
    allWhite = Solid(__trellis_pixels, color=Color.WHITE)
    allBlack = Solid(__trellis_pixels, color=Color.BLACK)
    __allBlack = allBlack
    allGray = Solid(__trellis_pixels, color=(8,8,2))
    allOrange = Solid(__trellis_pixels, color=Color.ORANGE)
    allRed= Solid(__trellis_pixels, color=Color.RED)
    allBlue = Solid(__trellis_pixels, color=Color.BLUE)
    allGold = Solid(__trellis_pixels, color=Color.GOLD)

Halfway thru setup_animations() we come to the rather nice PixelMaps. From the adafruit learn on led_animations: " The PixelMap helper enables you to treat a strip or strips of LEDs as a grid for animation purposes. It also works great with LED matrices that are actually a strip of LEDs arranged in a matrix, such as the NeoPixel FeatherWing." [and the NeoTrellis]

We create two PixelMaps, one to reference Columns (vertical) keys and one to reference Rows (horizontal) keys. These are then used to create animations that run across/up/down the keypad.

At the end of setup_animiations(), the trellisAnimations[] list is filled and we set the current_animation to be Solid Gray.

    # create some pixelMaps for rows and columns
    __trellis_pixel_columns = helper.PixelMap.vertical_lines(
        __trellis_pixels, 4, 4, helper.horizontal_strip_gridmap(4, alternating=False)
    __trellis_pixel_rows = helper.PixelMap.horizontal_lines(
        __trellis_pixels, 4, 4, helper.horizontal_strip_gridmap(4, alternating=False)

    # and build some animations using PixelMaps (from example, mod for size)
    comet_h = Comet(__trellis_pixel_rows, speed=0.1, color=Color.PURPLE, tail_length=3, bounce=True)
    comet_v = Comet(__trellis_pixel_columns, speed=0.1, color=Color.AMBER, tail_length=6, bounce=True)
    chase_h = Chase(__trellis_pixel_rows, speed=0.1, size=3, spacing=6, color=Color.JADE)
    rainbow_v = Rainbow(__trellis_pixel_columns, speed=0.1, period=2)
    rainbow_chase_v = RainbowChase(__trellis_pixel_columns, speed=0.1, size=3, spacing=2, step=8)
    rainbow_chase_h = RainbowChase(__trellis_pixel_rows, speed=0.1, size=3, spacing=3)
    rainbow_comet_v = RainbowComet(__trellis_pixel_columns, speed=0.1, tail_length=7, bounce=True)

    # build an array of all those animation, first 16 will be tied to keypad actions later
    global trellisAnimations
    trellisAnimations = [
        # first 16 will match to key pad index 0-15
        blink, color_cycle, comet, chase,
        pulse, sparkle, comet_h, rainbow,
        sparkle_pulse, rainbow_comet, rainbow_chase, rainbow_sparkle,
        custom_color_chase, rainbow_chase_v, rainbow_chase_h, rainbow_comet_v,
        # any more are just filler here
        allWhite, allBlack, allRed, allBlue, allGold, allOrange, allGray,
        chase_h, comet_v, rainbow_v,

    # start with simple solid Gray animation
    global current_animation
    current_animation = allGray

    print ("animations setup current_animation: ", current_animation)

Lastly the module defines some functions to act on the current_animation.

def set_all_black_animation():
    global current_animation
    global __allBlack
    current_animation = __allBlack
    current_animation = __allBlack

def set_animation_byIndex(idx):
    global current_animation
    if idx in range(len(trellisAnimations)):
        current_animation = trellisAnimations[idx]

def freeze():
    global current_animation

def resume():
    global current_animation
    print ("resume current_animation: ", current_animation)