2023-04-27 19:51:44 +00:00
|
|
|
import time
|
2023-05-02 15:19:22 +00:00
|
|
|
from machine import RTC
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
from pimoroni_i2c import PimoroniI2C
|
|
|
|
from breakout_encoder_wheel import BreakoutEncoderWheel, NUM_LEDS
|
|
|
|
|
|
|
|
"""
|
|
|
|
Displays a 12 hour clock on Encoder Wheel's LED ring, getting time from the system.
|
|
|
|
|
|
|
|
Press Ctrl+C to stop the program.
|
|
|
|
"""
|
|
|
|
|
|
|
|
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
|
|
|
|
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
|
|
|
|
|
2023-05-02 15:19:22 +00:00
|
|
|
# Datetime Indices
|
|
|
|
HOUR = 4
|
|
|
|
MINUTE = 5
|
|
|
|
SECOND = 6
|
|
|
|
MICROSECOND = 7
|
|
|
|
|
2023-04-27 19:51:44 +00:00
|
|
|
# Constants
|
|
|
|
BRIGHTNESS = 1.0 # The brightness of the LEDs
|
|
|
|
UPDATES = 50 # How many times the LEDs will be updated per second
|
|
|
|
UPDATE_RATE = 1 / UPDATES
|
|
|
|
|
|
|
|
# Handy values for the number of milliseconds
|
|
|
|
MILLIS_PER_SECOND = 1000
|
|
|
|
MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60
|
|
|
|
MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60
|
|
|
|
MILLIS_PER_HALF_DAY = MILLIS_PER_HOUR * 12
|
|
|
|
|
|
|
|
# Create a new BreakoutEncoderWheel
|
|
|
|
i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
|
|
|
|
wheel = BreakoutEncoderWheel(i2c)
|
2023-05-02 15:19:22 +00:00
|
|
|
rtc = machine.RTC()
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Sleep until a specific time in the future. Use this instead of time.sleep() to correct for
|
|
|
|
# inconsistent timings when dealing with complex operations or external communication
|
|
|
|
def sleep_until(end_time):
|
2023-05-02 15:19:22 +00:00
|
|
|
time_to_sleep = end_time - (time.ticks_ms() / 1000)
|
2023-04-27 19:51:44 +00:00
|
|
|
if time_to_sleep > 0.0:
|
|
|
|
time.sleep(time_to_sleep)
|
|
|
|
|
|
|
|
|
|
|
|
# Simple function to clamp a value between a minimum and maximum
|
|
|
|
def clamp(n, smallest, largest):
|
|
|
|
return max(smallest, min(n, largest))
|
|
|
|
|
|
|
|
|
|
|
|
# Calculates the brightness of an LED based on its index and a position along the LED ring
|
|
|
|
def led_brightness_at(led, position, half_width=1, span=1):
|
|
|
|
brightness = 0.0
|
|
|
|
upper = position + half_width
|
|
|
|
lower = position - half_width
|
|
|
|
if led > position:
|
|
|
|
brightness = clamp((upper - led) / span, 0.0, 1.0)
|
|
|
|
else:
|
|
|
|
brightness = clamp((led - lower) / span, 0.0, 1.0)
|
|
|
|
|
|
|
|
# Handle the LEDs being in a circle
|
|
|
|
if upper >= NUM_LEDS:
|
|
|
|
brightness = clamp(((upper - NUM_LEDS) - led) / span, brightness, 1.0)
|
|
|
|
elif lower < 0.0:
|
|
|
|
brightness = clamp((led - (lower + NUM_LEDS)) / span, brightness, 1.0)
|
|
|
|
|
2023-05-02 15:19:22 +00:00
|
|
|
return int(brightness * BRIGHTNESS * 255)
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Make rainbows
|
|
|
|
while True:
|
|
|
|
|
|
|
|
# Record the start time of this loop
|
2023-05-02 15:19:22 +00:00
|
|
|
start_time = time.ticks_ms() / 1000
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
# Get the current system time
|
2023-05-02 15:19:22 +00:00
|
|
|
now = rtc.datetime()
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
# Convert the seconds, minutes, and hours into milliseconds (this is done to give a smoother animation, particularly for the seconds hand)
|
2023-05-02 15:19:22 +00:00
|
|
|
sec_as_millis = (now[SECOND] * MILLIS_PER_SECOND) + (now[MICROSECOND] // MILLIS_PER_SECOND)
|
|
|
|
min_as_millis = (now[MINUTE] * MILLIS_PER_MINUTE) + sec_as_millis
|
|
|
|
hour_as_millis = ((now[HOUR] % 12) * MILLIS_PER_HOUR) + min_as_millis
|
2023-04-27 19:51:44 +00:00
|
|
|
|
|
|
|
# Calculate the position on the LED ring that the, second, minute, and hour hands should be
|
|
|
|
sec_pos = min(sec_as_millis / MILLIS_PER_MINUTE, 1.0) * NUM_LEDS
|
|
|
|
min_pos = min(min_as_millis / MILLIS_PER_HOUR, 1.0) * NUM_LEDS
|
|
|
|
hour_pos = min(hour_as_millis / MILLIS_PER_HALF_DAY, 1.0) * NUM_LEDS
|
|
|
|
|
|
|
|
for i in range(NUM_LEDS):
|
|
|
|
# Turn on the LEDs close to the position of the current second, minute, and hour
|
|
|
|
r = led_brightness_at(i, sec_pos)
|
|
|
|
g = led_brightness_at(i, min_pos)
|
|
|
|
b = led_brightness_at(i, hour_pos)
|
|
|
|
wheel.set_rgb(i, r, g, b)
|
|
|
|
wheel.show()
|
|
|
|
|
|
|
|
# Sleep until the next update, accounting for how long the above operations took to perform
|
|
|
|
sleep_until(start_time + UPDATE_RATE)
|