# lissajous clock
# raspberry pi pico
# pico display pack 2.0 - (320 x 240)
# pico omnibus dual expander
# rv3028 rtc
# rgb rotary encoder
import math
import utime
import picodisplay2 as disp
from breakout_rtc import BreakoutRTC
from pimoroni_i2c import PimoroniI2C
from breakout_encoder import BreakoutEncoder
from machine import Pin
# encoder setup
PINS_BREAKOUT_GARDEN = {"sda": 2, "scl": 3}
i2c_0 = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
enc_0 = BreakoutEncoder(i2c_0, 0x0F)
enc_0.set_brightness(1.0)
# enc.set_direction(BreakoutEncoder.DIRECTION_CCW) # Uncomment to flip the direction
steps_per_rev = 61
# display setup
width = disp.get_width()
height = disp.get_height()
disp_buffer = bytearray(width * height * 2)
disp.init(disp_buffer)
disp.set_backlight(0.5) # backlight - 50%
disp.set_pen(0, 255, 0) # pen colour RGB - green
# rtc setup
PINS_BREAKOUT_GARDEN = {"sda": 0, "scl": 1}
i2c_3 = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
rtc = BreakoutRTC(i2c_3)
rtc.set_backup_switchover_mode(3)
rtc.set_24_hour()
rtc.update_time()
switch = Pin(4, Pin.IN, Pin.PULL_DOWN)
button = Pin(5, Pin.IN, Pin.PULL_DOWN)
# global variables
sum_hrs = 0
sum_min = 0
tim = 0
ttim = 0
mim = 0
mtim = 0
rtc_seconds = 0
hours = 0
# functions
def tgraph_hrs():
global tim, ttim
tgraph(ttim, 0.25, 0.25) # tens
tgraph(tim, 0.75, 0.25) # units
return
def tgraph_min():
global mim, mtim
tgraph(mtim, 0.25, 0.75) # tens
tgraph(mim, 0.75, 0.75) # units
return
def tgraph(intime, woff, hoff):
# tgraph: converts a value into a lissajous pattern with complete lobes
# intime - the time value to be converted
# woff - width offset
# hoff - horizontal offset
global width, height
tval = int(intime) % 2
aspect = 4.3
for i in range(722):
sidx = int(math.sin(i) * (width / aspect) + (width * woff))
g = i * int(intime)
hsize = height / aspect
hpos = height * hoff
if tval != 0:
nidx = int(math.cos(g) * hsize + hpos)
else:
nidx = int(math.sin(g) * hsize + hpos)
disp.pixel(sidx, nidx)
return
def hrs_adj():
global tim, ttim, sum_hrs
sum_hrs += 1
if sum_hrs > 24:
sum_hrs = 0
tim, ttim = split_time(sum_hrs)
tgraph_hrs()
utime.sleep(2)
# print (sum_hrs, ttim, tim)
return
def mins_adj():
global mim, mtim, sum_min
sum_min += 1
if sum_min > 59:
sum_min = 0
mim, mtim = split_time(sum_min)
tgraph_min()
utime.sleep(2)
# print (sum_min, mtim, mim)
return
def split_time(value):
if value > 0:
new_value = str(value)
if value < 10:
tens = 0
unit = new_value[0]
else:
tens = new_value[0]
unit = new_value[1]
else:
tens = unit = 0
return unit, tens
def clean_disp():
disp.set_pen(0, 0, 0)
disp.clear()
disp.set_pen(0, 255, 0)
return
def read_rtc():
global tim, ttim, mim, mtim, rtc_seconds
if rtc.read_periodic_update_interrupt_flag():
rtc.clear_periodic_update_interrupt_flag()
if rtc.update_time():
# rtc_date = rtc.string_date()
# rtc_time = rtc.string_time()
rtc_hours = rtc.get_hours()
rtc_minutes = rtc.get_minutes()
rtc_seconds = rtc.get_seconds() # used in cycle_led
# print (rtc_time, rtc_hours, rtc_minutes, rtc_seconds)
tim, ttim = split_time(rtc_hours)
mim, mtim = split_time(rtc_minutes)
return
def set_time():
# seconds, minutes, hours, weekday day, month, year
# rtc.set_time(55,59,22,0,14,2,2022)
global sum_min, sum_hrs
rtc.set_time(0, sum_min, sum_hrs, 0, 1, 1, 2022)
utime.sleep(2)
return
def cycle_led():
# cycle_led: represents 0 to 60 seconds as a varying horizontal line
disp.set_clip(0, 120, 320, 5)
tick = int((rtc_seconds / 60) * 320) # displays horizontal line as a percentage of screen width
disp.pixel_span(0, 120, tick)
disp.update()
disp.remove_clip()
return
def count_changed():
global tim, ttim, mim, mtim, hours, sum_min, sum_hrs
if enc_0.get_interrupt_flag():
count = enc_0.read()
old = count
count = count % 61
enc_0.clear_interrupt_flag()
while count < 0:
count += steps_per_rev
minutes = count
if old < 0:
if count == 60:
hours -= 1
minutes = 0
else:
if count == 60:
hours += 1
minutes = 0
if hours < 0:
hours = 23
minutes = 59
if hours > 23:
hours = 0
minutes = 0
# if count != 60:
# print(count, hours, minutes)
sum_hrs = hours
sum_min = minutes
tim, ttim = split_time(hours)
mim, mtim = split_time(minutes)
return
# initialization
read_rtc()
count_changed()
enc_0.clear_interrupt_flag()
rtc.enable_periodic_update_interrupt(True)
clean_disp()
tgraph_hrs()
tgraph_min()
disp.update()
while True:
if switch.value():
enc_0.set_led(0, 0, 255)
if disp.is_pressed(disp.BUTTON_A): # enter hours
clean_disp()
hrs_adj()
disp.update()
elif disp.is_pressed(disp.BUTTON_X): # enter minutes
clean_disp()
mins_adj()
disp.update()
elif disp.is_pressed(disp.BUTTON_B): # set time
clean_disp()
set_time()
disp.update()
else:
if button.value():
enc_0.set_led(0, 0, 255)
clean_disp()
set_time()
disp.update()
else:
clean_disp()
count_changed()
tgraph_hrs()
tgraph_min()
disp.update()
else:
enc_0.set_led(0, 0, 0)
read_rtc()
clean_disp()
tgraph_hrs()
tgraph_min()
disp.update()
cycle_led()
Comments
Please log in or sign up to comment.