#
# Gundam LED Sequencer
# Robert Pratten
# Open Source Licence: MIT
#
# Uses original "rainbox" code from Pimoroni examples: SPDX-FileCopyrightText: 2021 Sandy Macdonald
# SPDX-License-Identifier: MIT
#
#
import sys
import board
import busio
import time
import analogio
import digitalio
import adafruit_aw9523
import math
from pmk import PMK
from pmk import PMK, number_to_xy, hsv_to_rgb
#from pmk.platform.keybow2040 import Keybow2040 as Hardware # for Keybow 2040
from pmk.platform.rgbkeypadbase import RGBKeypadBase # for Pico RGB Keypad Base
DEBUG = True
#-- active leds are those actually plugged in. Can't set this unless it's hardcoded to the
# gundam model. Hence use 0-15 to allow all. I idea was to make the initial welcome sweep faster
# by stepping over missing LEDs
#
#active_leds = [5,6,7,8]
active_leds = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
#reset all the keys which will hold the gundam led number and brightness value
#99 = not programmed
gundam_leds = [(99, 255) for _ in range(16)]
#sequences correspond to the keypad keys
sequences = ["sweep_up","sweep_down","chase_up","chase_down",
"chase top left to bottom right","chase bottom right to top left","flash all","",
"","","","",
"","","",""]
knob = analogio.AnalogIn(board.GP28)
brightness_range_1 = [0,2,4,8,16,32,128,255]
#Configure the mode LEDs
program_led = digitalio.DigitalInOut(board.GP10)
program_led.direction = digitalio.Direction.OUTPUT
seq_led = digitalio.DigitalInOut(board.GP11)
seq_led.direction = digitalio.Direction.OUTPUT
grid = digitalio.DigitalInOut(board.GP12)
grid.direction = digitalio.Direction.OUTPUT
run_led = digitalio.DigitalInOut(board.GP13)
run_led.direction = digitalio.Direction.OUTPUT
def set_all_LEDS(this_value):
#this_value : Boolean
program_led.value = this_value
seq_led.value = this_value
grid.value = this_value
run_led.value = this_value
return
def flash_all_LEDs():
# quick flash so we know they're working
for i in range(8):
set_all_LEDS(True)
time.sleep(0.3)
set_all_LEDS(False)
time.sleep(0.3)
return
def confirmation():
# quick flash so we know they're working
set_all_LEDS(True)
time.sleep(0.5)
set_all_LEDS(False)
return
def get_knob_value(gundam_led):
raw = knob.value
volts= (raw * 3.3) / 65536
percentage = (raw / 65536) * 100
time.sleep(0.5)
# Determine the band
band = int(percentage / 12.5) # Dividing 100 by 8 gives 12.5
# Ensure band is within range 0-7
band = min(max(band, 0), 7)
brightness = brightness_range_1[band]
print(band, brightness)
gundam.set_constant_current(gundam_led, brightness)
return(brightness)
def set_delay():
raw = knob.value
volts= (raw * 3.3) / 65536
percentage = (raw / 65536) * 100
time.sleep(0.2)
# Define the minimum and maximum delay values
min_delay = 0.01
max_delay = 2
# Calculate the delay based on the percentage
delay = min_delay + (percentage / 100) * (max_delay - min_delay)
print(delay)
return delay
#---- Gundam LED routines
def grow_brightness(brightness,my_led,delay):
for x in brightness:
time.sleep(delay)
gundam.set_constant_current(my_led, x)
return
def dim_brightness(brightness,my_led,delay):
for x in reversed(brightness):
time.sleep(delay)
gundam.set_constant_current(my_led, x)
return
def gundam_all_off():
for my_led in active_leds:
gundam.set_constant_current(my_led, 0)
return
def all_on():
for my_led in active_leds:
gundam.set_constant_current(my_led, 255)
return
def sweep_up(delay):
for my_led in active_leds:
brightness = brightness_range_1
grow_brightness(brightness,my_led,delay)
return
def sweep_down(delay):
for my_led in reversed(active_leds):
brightness = brightness_range_1
dim_brightness(brightness,my_led,delay)
return
#-- end led routines
#--------------------------------------------
# SEQUENCING ROUTINES
#--------------------------------------------
#
def chase_tl2br(gundam_leds,delay): # top-left to bottom right
for led in gundam_leds:
if led[0] != 99: #this led has been programmed
gundam.set_constant_current(led[0], led[1])
time.sleep(delay)
gundam.set_constant_current(led[0], 0) #set brightness to 0
return
def chase_br2tl(gundam_leds,delay): # bottom right to top left
for led in reversed(gundam_leds):
if led[0] != 99: #this led has been programmed
gundam.set_constant_current(led[0], led[1])
time.sleep(delay)
gundam.set_constant_current(led[0], 0) #set brightness to 0
return
def turn_off_row(this_row):
for led in this_row:
if led[0] < 16:
gundam.set_constant_current(led[0], 0)
return
def turn_on_row(this_row):
print(this_row)
for led in this_row:
if led[0] != 99: #this led has been programmed
gundam.set_constant_current(led[0], led[1])
return
def chase_up(gundam_leds,delay): # turn on by rows starting on the bottom row
#turn on bottom row
bottom_row = gundam_leds[8:12]
middle_row = gundam_leds[4:8]
top_row = gundam_leds[0:4]
turn_on_row(bottom_row)
time.sleep(delay)
turn_off_row(bottom_row)
turn_on_row(middle_row)
time.sleep(delay)
turn_off_row(middle_row)
turn_on_row(top_row)
time.sleep(delay)
turn_off_row(top_row)
return
def chase_down(gundam_leds,delay): # turn on by rows starting on the bottom row
bottom_row = gundam_leds[8:12]
middle_row = gundam_leds[4:8]
top_row = gundam_leds[0:4]
turn_on_row(top_row)
time.sleep(delay)
turn_off_row(top_row)
turn_on_row(middle_row)
time.sleep(delay)
turn_off_row(middle_row)
turn_on_row(bottom_row)
time.sleep(delay)
turn_off_row(bottom_row)
return
def the_sweep_up(gundam_leds,delay): # turn on by rows starting on the bottom row
print("sweep-up")
#turn on bottom row
bottom_row = gundam_leds[8:12]
middle_row = gundam_leds[4:8]
top_row = gundam_leds[0:4]
if DEBUG:
print("top row", top_row)
print("middle row", middle_row)
print("bottom row", bottom_row)
turn_on_row(bottom_row)
time.sleep(delay)
turn_on_row(middle_row)
time.sleep(delay)
turn_on_row(top_row)
time.sleep(delay)
turn_off_row(top_row)
turn_off_row(bottom_row)
turn_off_row(middle_row)
return
def the_sweep_down(gundam_leds,delay): # turn on by rows starting on the bottom row
#turn on bottom row
bottom_row = gundam_leds[8:12]
middle_row = gundam_leds[4:8]
top_row = gundam_leds[0:4]
turn_on_row(top_row)
time.sleep(delay)
turn_on_row(middle_row)
time.sleep(delay)
turn_on_row(bottom_row)
time.sleep(delay)
turn_off_row(top_row)
turn_off_row(bottom_row)
turn_off_row(middle_row)
return
def error_condition(error,e):
print(error)
print(e)
flash_all_LEDs()
print("--processing terminated --")
return
#------------------------------------------
# sequences to key assignments
#------------------------------------------
def run_sequence(this_tuple):
seq = this_tuple[0]
delay = this_tuple[1]
if seq == 0:
the_sweep_up(gundam_leds,delay)
elif seq == 1:
the_sweep_down(gundam_leds,delay)
elif seq == 2:
chase_up(gundam_leds,delay)
elif seq == 3:
chase_down(gundam_leds,delay)
elif seq == 4:
chase_tl2br(gundam_leds,delay)
elif seq == 5:
chase_br2tl(gundam_leds,delay)
elif seq == 6:
do_nothing=True
elif seq == 7:
do_nothing=True
elif seq == 8:
do_nothing=True
elif seq == 9:
do_nothing=True
elif seq == 10:
do_nothing=True
elif seq == 11:
do_nothing=True
return
#------------------------------------------
# INITIALISE I2C DEVICES
#------------------------------------------
# I need to get the i2c variable to use in the other chained devices
#
# chatGPT recommended I create a custom class to get the variable that's hidden in the pmk library
class CustomRGBKeypad(RGBKeypadBase):
def __init__(self):
super().__init__()
# Method to expose the I2C instance
def get_i2c(self):
return self._i2c
# Use the custom class instead of the original RGBKeypadBase
keypad = CustomRGBKeypad()
##-- now use standard code to initialise the keypad
keybow = PMK(keypad)
PMK.rotate(keybow,90)
keys = keybow.keys
# Now we can access the I2C instance
i2c = keypad.get_i2c()
# Initialize the AW9523 with the shared I2C instance
try:
gundam = adafruit_aw9523.AW9523(i2c)
gundam.LED_modes = 0xFFFF # constant current mode so I can control the brightness
gundam.directions = 0xFFFF
except Exception as e:
error_condition("no gundam",e)
sys.exit()
#--- END INITIALISATION --------------------------------
#-------------------------------------------------------
# MODE SETUP/CONFIGURATION
#-------------------------------------------------------
modes = ["program","sequence","grid","run"]
mode = 0
set_mode = set([12,13,15])
save_seq = set([12,13,14])
pulse = 0.3 #this is the default delay between gundam LED blinks
def heartbeat(led,delay):
led.value = True
time.sleep(delay)
led.value = False
time.sleep(delay)
return
#define some routines for later
def set_mode_on(led):
if led.value != True:
for _ in range(3):
led.value = True
time.sleep(0.2)
led.value = False
time.sleep(0.2)
return True
#-------------------------------------------------------
#count of gundam_led up to max 15
gundam_led = 0
#time interval between last keypress
k_now = 0
g_now = 0
def next_gundam_led(gundam_led):
gundam_led = (gundam_led+1) % 15
return(gundam_led)
def prev_gundam_led(gundam_led):
gundam_led = (gundam_led-1) % 16
return(gundam_led)
def flash_key(this_key):
pass
#Right now, don't flash the actual key!
#for _ in range(3):
# keys[this_key].set_led(0, 255, 255)
# time.sleep(0.3)
# keys[this_key].set_led(0, 0, 0)
# time.sleep(0.3)
return
def rainbow():
# Increment step to shift animation across keys.
step = 0
for step in range(0,1):
#step += 1
keybow.update()
for i in range(16):
# Convert the key number to an x/y coordinate to calculate the hue
# in a matrix style-y.
x, y = number_to_xy(i)
# Calculate the hue.
hue = (x + y + (step / 20)) / 8
hue = hue - int(hue)
hue = hue - math.floor(hue)
# Convert the hue to RGB values.
r, g, b = hsv_to_rgb(hue, 1, 1)
# Display it on the key!
keys[i].set_led(r, g, b)
time.sleep(0.5)
return
for key in keys:
key.hold_time = 1
rainbow()
# Use cyan as the colour.
rgb = (0, 255, 255)
keybow.set_all(0,0,0)
#-- gundam sweep just to be sure all LEDs are working
for i in range (1):
sweep_up(0.05)
sweep_down(0.05)
gundam_all_off()
#-------
#------------------------------------------------------
# REMEMBERING A SEQUENCE
#------------------------------------------------------
#define the array to hold the button and timing
#99 means empty, 0.3 is the default delay between LEDs lighting up
max_slots = 32
sequence_slots = [(99, 0.3) for _ in range(max_slots)]
#this allows potential for banks of slots - something for the future
def reset_slots(sequence_slots):
sequence_slots = [(99, 0.3) for _ in range(max_slots)]
#reserve the first slot for array index
sequence_slots[0]=(1,0) #(current pointer,unused)
return sequence_slots
def add_seq(sequence_slots,sequence,delay):
#the next available slot is the one being pointed to right now
sequence_slots[sequence_slots[0][0]]=(sequence,delay)
#point to the next slot
sequence_slots[0]=(sequence_slots[0][0]+1,sequence_slots[0][1])
return sequence_slots
def delete_last_seq(sequence_slots):
#the next available slot is the one being pointed to right now
#minus one to back up
sequence_slots[0]=(sequence_slots[0][0]-1,sequence_slots[0][1])
#overwrite
sequence_slots[sequence_slots[0][0]]=(99,0.3)
return sequence_slots
def delete_seq_at(sequence_slots,slot):
#point to the next slot
sequence_slots[slot]=(99,0.3)
return sequence_slots
#------------------------------------------
# FILE OPERATIONS
#------------------------------------------
sequence_slots=reset_slots(sequence_slots)
banks =[]
#banks = [(bank, sequence_slots_1), (bank, sequence_slots_2)]
def save_sequence(banks,filename):
keys[12].set_led(0, 128, 128)
keys[13].set_led(0, 128, 128)
keys[14].set_led(0, 128, 128)
# Open a file in write mode
with open(filename, 'w') as file:
# Write header row. "Bank" allows possibility of multiple banks of sequences
file.write("bank, sequence, delay\n")
# Write data rows
# Write each bank and its corresponding sequence slots
for bank_info in banks:
# Extract bank number and sequence slots
bank_num, sequence_slots = bank_info
# Write each sequence slot along with the bank number
for slot, value in sequence_slots:
file.write(f'{bank_num},{slot},{value}\n')
file.flush()
file.close()
time.sleep(1)
keys[12].set_led(0, 0, 0)
keys[13].set_led(0, 0, 0)
keys[14].set_led(0, 0, 0)
print("file saved")
return
def load_sequence(banks,filename):
# Open the file in read mode
with open('data.csv', 'r') as file:
# Read the lines from the file
lines = file.readlines()
# Initialize variables to store bank number and sequence slots
bank_num = 0
sequence_slots = []
# Iterate over the lines
for line in lines:
# Split the line into fields using the comma as a delimiter
fields = line.strip().split(',')
# If there are 3 fields, it's a line containing bank, slot, and value
if len(fields) == 3:
# Extract bank number, slot, and delay
bank_num, seq, delay = fields
try:
print(bank_num, seq, delay)
seq = int(seq)
delay = float(delay)
# Append the sequence slot to the list
sequence_slots.append((seq, delay))
except:
step_over_the_header_row = True
banks.append((bank_num,sequence_slots))
return banks
def save_leds(gundam_leds,filename):
print("saving leds...")
print(gundam_leds)
with open(filename, 'w') as file:
# Write header row. "Bank" allows possibility of multiple banks of sequences
for item in gundam_leds:
# Write each tuple to the file
file.write(','.join(map(str, item)) + '\n')
file.flush()
file.close()
print("leds saved",filename)
return
def load_leds(filename):
gundam_leds=[]
# Open the file in read mode
with open(filename, 'r') as file:
# Read the lines from the file
lines = file.readlines()
# Iterate over the lines
for line in lines:
# Strip newline characters and split the line into fields using commas as delimiters
fields = line.strip().split(',')
# Convert the fields to appropriate data types (integer and integer atm)
item = (int(fields[0]), int(fields[1]))
gundam_leds.append(item)
return gundam_leds
banks = load_sequence(banks,"data.csv")
gundam_leds = load_leds("leds.csv")
print(banks)
sequence_slots = banks[0][1]
print(sequence_slots)
mode = 3 #run mode!
#------------------------------------------------------
# MAIN LOOP READING THE KEYPAD
#------------------------------------------------------
gundam_led=0
current_gundam_led_brightness = get_knob_value(gundam_led)
last_blink_time = -1
cntr_led =0
last_blink_time = time.monotonic() - pulse
blink = False
try:
while True:
#indicate the right mode. subroutine flashes LED
if modes[mode] == "program":
run_led.value = False
seq_led.value= False
grid.value= False
program_led.value = set_mode_on(program_led)
elif modes[mode] == "run":
seq_led.value= False
grid.value= False
program_led.value= False
run_led.value = set_mode_on(run_led)
elif modes[mode] == "grid":
run_led.value = False
seq_led.value= False
program_led.value= False
grid.value= set_mode_on(grid)
elif modes[mode] == "sequence":
program_led.value = False
seq_led.value = True
run_led.value= False
grid.value= False
if cntr_led ==0:
program_led.value = True
elif cntr_led ==1:
seq_led.value= True
elif cntr_led ==2:
grid.value = True
elif cntr_led ==3:
run_led.value = True
#this_led.value == False
#run_led.value = set_mode_on(run_led)
#pulse the run LED
now = time.monotonic()
if (now >= (last_blink_time + pulse)):
blink = not blink
last_blink_time = now
# If we just turned the LED off, increment cntr_led
if not blink:
if cntr_led ==0:
program_led.value = False
elif cntr_led ==1:
seq_led.value= False
elif cntr_led ==2:
grid.value = False
elif cntr_led ==3:
run_led.value = False
cntr_led = (cntr_led + 1) % 4
#heartbeat(run_led,pulse)
# Always remember to call keybow.update() on every iteration of your loop!
keybow.update()
keystate = keybow.get_states()
keypresses = keybow.get_pressed()
key_set = set(keypresses)
#print(keypresses)
#print(leds)
#########################################################
#-- PROGRAMMING MODE ---
if mode == 0:
if 15 in keypresses: #set the other buttons
#illuminate the button
keys[15].set_led(0, 128, 128)
for key in keypresses:
if key <12:
keys[key].set_led(12, 0, 0)
print(keypresses)
print(gundam_leds)
current_gundam_led_brightness = get_knob_value(gundam_led)
#save into the key the gundam LED and the current brightness setting
gundam_leds[key] = (gundam_led, current_gundam_led_brightness)
print(gundam_leds)
if 14 in keypresses: #set the other buttons
#illuminate the button
keys[14].set_led(0, 128, 128)
for key in keypresses:
if key <12:
keys[key].set_led(0, 0, 0)
#reset key with no gundam LED and no brightness
gundam_leds[key] = (99, 0)
print(keypresses)
keys[15].set_led(0, 0, 0)
keys[14].set_led(0, 0, 0)
#cycle through the Gundam LEDs...
if (mode == 0):
if 12 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
gundam_led = next_gundam_led(gundam_led)
print(gundam_led)
#try to turn on the gundam LED in this position
gundam_all_off()
gundam.set_constant_current(gundam_led, current_gundam_led_brightness)
if 13 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
gundam_led = prev_gundam_led(gundam_led)
print("LED = "+ str(gundam_led)+" at glow "+str(current_gundam_led_brightness))
gundam_all_off()
gundam.set_constant_current(gundam_led, current_gundam_led_brightness)
#########################################################
elif mode == 1: #sequencing mode
print(keypresses)
if 15 in keypresses: # change the pulse/delay
if 4 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[4], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,4,pulse)
print(sequence_slots)
if 0 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[0], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,0,pulse)
print(sequence_slots)
if 1 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[1], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,1,pulse)
print(sequence_slots)
if 2 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[2], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,2,pulse)
print(sequence_slots)
if 3 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[3], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,3,pulse)
print(sequence_slots)
if 5 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[5], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,5,pulse)
print(sequence_slots)
if 6 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[6], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,6,pulse)
print(sequence_slots)
if 7 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[7], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,7,pulse)
print(sequence_slots)
if 8 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[8], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,8,pulse)
print(sequence_slots)
if 9 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[9], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,9,pulse)
print(sequence_slots)
if 10 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[10], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,10,pulse)
print(sequence_slots)
if 11 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
print(sequences[11], pulse)
confirmation()
sequence_slots=add_seq(sequence_slots,11,pulse)
print(sequence_slots)
else:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
pulse = set_delay()
if 4 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
chase_tl2br(gundam_leds,pulse)
if 5 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
chase_br2tl(gundam_leds,pulse)
if 0 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
the_sweep_up(gundam_leds,pulse)
if 1 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
the_sweep_down(gundam_leds,pulse)
if 2 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
chase_up(gundam_leds,pulse)
if 3 in keypresses:
g_gap = keybow.time_of_last_press - g_now
g_now = keybow.time_of_last_press
if g_gap>0.0266016:
chase_down(gundam_leds,pulse)
#########################################################
# RUN MODE
elif mode == 3: #run through the sequence_slots!
start_slot = 1
while sequence_slots[start_slot][0]<99:
run_sequence(sequence_slots[start_slot])
start_slot=start_slot+1
print(start_slot)
#check for mode change just in case!
if set_mode.issubset(key_set):
k_gap = keybow.time_of_last_press - k_now
k_now = keybow.time_of_last_press
#print(k_now)
#print(k_gap)
if k_gap>0.0266016:
mode = (mode+1) % len(modes)
print(modes[mode])
flash_key(mode)
#print(key_set)
#--------------------------------
# CHANGE MODE
#--------------------------------
# if the "set_mode" key set is a subset of those being pressed... then change the mode
if set_mode.issubset(key_set):
k_gap = keybow.time_of_last_press - k_now
k_now = keybow.time_of_last_press
#print(k_now)
#print(k_gap)
if k_gap>0.0266016:
mode = (mode+1) % len(modes)
print(modes[mode])
flash_key(mode)
#--------------------------------
# SAVE SEQUENCE
#--------------------------------
# if the "save sequence" key set is a subset of those being pressed... then change the mode
if save_seq.issubset(key_set):
k_gap = keybow.time_of_last_press - k_now
k_now = keybow.time_of_last_press
#print(k_now)
#print(k_gap)
if k_gap>0.0266016:
banks =[(0,sequence_slots)]#assumes there could be several banks of sequences
save_leds(gundam_leds,'leds.csv') #
save_sequence(banks,"data.csv")
except KeyboardInterrupt:
print("show's over")
keybow.set_all(0,0,0)
gundam_all_off()
Comments