Skip to content

Instantly share code, notes, and snippets.

@Tom-Archer
Created June 10, 2023 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tom-Archer/6bfd9f017b28e601e4d484e4b21ceb14 to your computer and use it in GitHub Desktop.
Save Tom-Archer/6bfd9f017b28e601e4d484e4b21ceb14 to your computer and use it in GitHub Desktop.
Battlestar Chronometer Sample Python Code
# Import all board pins and bus interface.
import board
import busio
# Import the HT16K33 LED matrix module.
from adafruit_ht16k33 import matrix
import datetime
import random
import time
# Create the I2C interface.
i2c = busio.I2C(board.SCL, board.SDA)
class LEDBackpack(matrix.HT16K33):
"""LED Backpack interface akin to the C-version"""
def set_pixel(self, x, y, on=1):
"""Convenience function to set a specific pixel."""
self._pixel(x,y,on)
def clear(self):
"""Convenience function to clear the display."""
self.fill(0)
seconds_matrix = LEDBackpack(i2c, address=0x70, auto_write=False)
minutes_matrix = LEDBackpack(i2c, address=0x71, auto_write=False)
hours_matrix = LEDBackpack(i2c, address=0x72, auto_write=False)
def setup():
minutes_matrix.brightness = 1.0 * 12/15
def clear_all():
"""Clear all the displays."""
seconds_matrix.clear()
minutes_matrix.clear()
hours_matrix.clear()
def write_all():
"""Write to all the displays."""
seconds_matrix.show()
minutes_matrix.show()
hours_matrix.show()
def blink_all(b):
"""Blink all the displays (doesn't require a write)."""
seconds_matrix.blink_rate = b
minutes_matrix.blink_rate = b
hours_matrix.blink_rate = b
write_all() # TBD
# The HT16K33 internal memory looks like
# a 8x16 bit matrix (8 rows, 16 columns)
# The HT16K33 has 8 cathodes and 16 anodes
def pixel_test_single_rings(delta, iterations):
""" Turn on each ring individually."""
# Clear all the LEDs for good measure
clear_all()
write_all()
for i in range(0, iterations):
# Seconds
seconds_matrix.clear()
seconds_matrix.show()
for a in range(0, 60):
k = a//8
seconds_matrix.set_pixel(a%8, k)
seconds_matrix.show()
time.sleep(delta/1000)
seconds_matrix.clear()
seconds_matrix.show()
# Minutes
minutes_matrix.clear()
minutes_matrix.show()
for a in range(0, 60):
k = a//8
minutes_matrix.set_pixel(a%8, k)
minutes_matrix.show()
time.sleep(delta/1000)
minutes_matrix.clear()
minutes_matrix.show()
# Hours - LED Pairs
hours_matrix.clear()
hours_matrix.show()
for a in range(0, 12):
k = (a//8)*2
hours_matrix.set_pixel(a%8, k)
hours_matrix.set_pixel(a%8, k+1)
hours_matrix.show()
time.sleep(delta*5/1000)
hours_matrix.clear()
hours_matrix.show()
def pixel_test_all_rings(delta, iterations):
"""Turn on all the rings and then turn off all the rings for the number of iterations."""
# Clear all the LEDs for good measure
clear_all()
write_all()
for i in range(0, iterations*2):
on = (i+1)%2
# Seconds
for a in range(0, 60):
k = a//8
seconds_matrix.set_pixel(a%8, k, on)
seconds_matrix.show()
time.sleep(delta/1000)
# Minutes
for a in range(0, 60):
k = a//8
minutes_matrix.set_pixel(a%8, k, on)
minutes_matrix.show()
time.sleep(delta/1000)
# Hours - Individual LEDs
for j in range(1,-1,-1):
for a in range(0, 12):
k = j + (a//8)*2
hours_matrix.set_pixel(a%8, k, on)
hours_matrix.show()
time.sleep(delta*5/1000)
def pixel_test_spiral(delta, iterations):
"""Illuminate the LEDs in a spiral pattern."""
# Clear all the LEDs for good measure
clear_all()
write_all()
group_size = 6
num_groups = 10
for i in range(0, iterations*2):
on = (i+1)%2
# Seconds
for g in range(0, group_size):
for n in range(0, num_groups):
a = n*group_size + g
k = a//8
seconds_matrix.set_pixel(a%8, k, on)
seconds_matrix.show()
# Delay here means nth LEDs turn on one after another
# and not at the same time.
time.sleep(delta/1000)
# Minutes
for g in range(0, group_size):
for n in range(0, num_groups):
a = n*group_size + g
k = a//8
minutes_matrix.set_pixel(a%8, k, on)
minutes_matrix.show()
# Delay here means nth LEDs turn on one after another
# and not at the same time.
time.sleep(delta/1000)
# Hours - Individual LEDs
for j in range(1,-1,-1):
for g in range(0, 3):
for n in range(0, 4):
a = n*3 + g
k = j + (a//8)*2
hours_matrix.set_pixel(a%8, k, on)
hours_matrix.show()
# Delay here means nth LEDs turn on one after another
# and not at the same time.
time.sleep(delta*5/1000)
def pixel_test_fan(delta, iterations):
"""Rotate a fixed number (6) of LEDs around the display."""
# Clear all the LEDs for good measure
clear_all()
write_all()
# Hours - LED Pairs
# All on, always
hours_matrix.fill(1)
hours_matrix.show()
group_size = 6
num_groups = 5
interval = 60//num_groups
# Make the LEDs appear nicely
for g in range(0, group_size-1):
for n in range(0, num_groups):
a = (n*interval + g)%60
k = a//8
seconds_matrix.set_pixel(a%8, k)
minutes_matrix.set_pixel(a%8, k)
write_all()
time.sleep(delta*2/1000)
# Rotate
for i in range(0, 120*iterations + 1):
seconds_matrix.clear()
minutes_matrix.clear()
for n in range(0, num_groups):
for g in range(0, group_size):
a = (n*interval + g + i)%60
k = a//8
seconds_matrix.set_pixel(a%8, k)
minutes_matrix.set_pixel(a%8, k)
write_all()
time.sleep(delta/1000)
# Make remaining LEDs disappear nicely
for g in range(0, group_size):
for n in range(0, num_groups):
a = (n*interval + g)%60
k = a//8
seconds_matrix.set_pixel(a%8, k, 0)
minutes_matrix.set_pixel(a%8, k, 0)
write_all()
time.sleep(delta*2/1000)
def display_time(the_time):
"""Show a provided time."""
# Clear all the LEDs for good measure
clear_all()
mins = the_time.minute
seconds = the_time.second
hours = the_time.hour % 12
# Make 0 illuminate all LEDs
if seconds == 0:
seconds = 60
if mins == 0:
mins = 60
if hours == 0:
hours = 12
# Set the seconds value
for i in range (0, seconds):
seconds_matrix.set_pixel(i%8, i//8)
# Set the minutes value
for i in range (0, mins):
minutes_matrix.set_pixel(i%8, i//8)
# Set the hours value
for i in range (0, hours):
k = (i//8)*2
hours_matrix.set_pixel(i%8, k)
hours_matrix.set_pixel(i%8, k+1)
# Display
write_all()
print(hours, mins, seconds)
def time_demo(duration):
"""Display the time and count up for the provided number of seconds."""
for i in range (0, duration):
display_time(datetime.datetime.now())
time.sleep(1)
def countdown_demo(h, m, s, delta):
"""Countdown from the provided time (hours, minutes and seconds)."""
# Clear all the LEDs for good measure
clear_all()
# Create the countdown time
now = datetime.datetime.now()
countdown_time = datetime.datetime(now.year, now.month, now.day, h, m, s)
# Display for delta (1 second)
display_time(countdown_time)
time.sleep(delta/1000)
while True:
# Decrement the countdown time by 1 second
countdown_time -= datetime.timedelta(seconds=1)
# Display for delta (1 second)
display_time(countdown_time)
time.sleep(delta/1000)
# Check whether 0h0m0s has been reached
if countdown_time.hour == 0 and countdown_time.minute == 0 and countdown_time.second == 0:
break
# Blink the display
blink_all(2)
time.sleep(5)
clear_all()
write_all()
blink_all(0)
class Snake:
"""Defines a snake"""
def __init__(self, snake_length, matrix_length=60, it_low=30, it_high=50):
"""Constructor."""
self.snake_length = snake_length
self.matrix_length = matrix_length
self.it_low = it_low
self.it_high = it_high
self.start_point = random.randrange(0, matrix_length)
self.direction = random.randrange(0, 2)
if not self.direction:
self.end_point = self.start_point
self.start_point = (self.end_point - self.snake_length)%self.matrix_length
else:
self.end_point = (self.start_point + self.snake_length)%self.matrix_length
# Get a number of iterations
self.iterations = random.randrange(self.it_low, self.it_high+1)
self.iteration = 0
def update(self):
"""Update the position."""
# Move the snake
if not self.direction:
self.start_point = (self.start_point - 1)%self.matrix_length
self.end_point = (self.end_point - 1)%self.matrix_length
else:
self.start_point = (self.start_point + 1)%self.matrix_length
self.end_point = (self.end_point + 1)%self.matrix_length
# Update the iteration
self.iteration += 1
if self.iteration > self.iterations:
self.direction = not self.direction
self.iterations = random.randrange(self.it_low, self.it_high+1)
self.iteration = 0
def write(self, matrix, a):
k = a//8
matrix.set_pixel(a%8, k)
def draw(self, matrix):
if self.start_point < self.end_point:
for a in range (self.start_point, self.end_point):
self.write(matrix, a)
else:
for a in range (self.start_point, self.matrix_length):
self.write(matrix, a)
for a in range (0, self.end_point):
self.write(matrix, a)
class HoursOuterSnake(Snake):
"""Defines a snake on the outer hours LEDs."""
def write(self, matrix, a):
k = (a//8)*2 + 1
matrix.set_pixel(a%8, k)
class HoursInnerSnake(Snake):
"""Defines a snake on the inner hours LEDs."""
def write(self, matrix, a):
k = (a//8)*2
matrix.set_pixel(a%8, k)
def pixel_test_larson(delta):
"""Curved Larson scanners."""
# Clear all the LEDs for good measure
clear_all()
write_all()
# Define the snakes
secondsSnake = Snake(6, 60, 30, 50)
minutesSnake = Snake(8, 60, 30, 50)
hoursOuterSnake = HoursOuterSnake(4, 12, 15, 25)
hoursInnerSnake = HoursInnerSnake(3, 12, 15, 25)
while True:
clear_all()
secondsSnake.draw(seconds_matrix)
minutesSnake.draw(minutes_matrix)
hoursOuterSnake.draw(hours_matrix)
hoursInnerSnake.draw(hours_matrix)
write_all()
secondsSnake.update()
minutesSnake.update()
hoursOuterSnake.update()
hoursInnerSnake.update()
time.sleep(delta/1000)
if __name__ == '__main__':
setup()
while True:
time.sleep(1)
pixel_test_single_rings(20, 3)
pixel_test_all_rings(10, 3)
pixel_test_spiral(10, 3)
pixel_test_fan(10, 3)
pixel_test_larson(100)
#time_demo(10)
#countdown_demo(0, 1, 15, 200)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment