Compare commits
No commits in common. "d90a17d79ac27a895b7912805f02e9cfa2d44954" and "dcd0246843a2da7bdd6dd6a195e7e55372f7620a" have entirely different histories.
d90a17d79a
...
dcd0246843
|
@ -1,36 +1,6 @@
|
||||||
import time
|
import time
|
||||||
import board
|
import board
|
||||||
import neopixel
|
import neopixel
|
||||||
import adafruit_datetime as datetime
|
|
||||||
from adafruit_seesaw import seesaw, rotaryio, digitalio
|
|
||||||
import busio
|
|
||||||
|
|
||||||
|
|
||||||
####
|
|
||||||
# i2c bus setup
|
|
||||||
|
|
||||||
SDA = board.GP0
|
|
||||||
SCL = board.GP1
|
|
||||||
i2c = busio.I2C(SCL, SDA)
|
|
||||||
|
|
||||||
# END i2c bus setup
|
|
||||||
####
|
|
||||||
|
|
||||||
|
|
||||||
####
|
|
||||||
# Rotary Encoder setup
|
|
||||||
|
|
||||||
seesaw = seesaw.Seesaw(i2c, 0x36)
|
|
||||||
|
|
||||||
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
|
|
||||||
button = digitalio.DigitalIO(seesaw, 24)
|
|
||||||
button_held = False
|
|
||||||
|
|
||||||
encoder = rotaryio.IncrementalEncoder(seesaw)
|
|
||||||
last_position = -1
|
|
||||||
|
|
||||||
# END Rotary Encoder setup
|
|
||||||
####
|
|
||||||
|
|
||||||
|
|
||||||
####
|
####
|
||||||
|
@ -64,13 +34,6 @@ pixels.show()
|
||||||
# END Neopixel setup
|
# END Neopixel setup
|
||||||
####
|
####
|
||||||
|
|
||||||
|
|
||||||
# Use datetime.timedelta to convert an int of seconds to a
|
|
||||||
# string with the format MM:SS
|
|
||||||
def prettytime(seconds):
|
|
||||||
return str(datetime.timedelta(seconds=abs(seconds)))[2:]
|
|
||||||
|
|
||||||
|
|
||||||
# Set the color on a single neopixel based on colormode and
|
# Set the color on a single neopixel based on colormode and
|
||||||
# whether yellowtime or redtime has been reached. Calling
|
# whether yellowtime or redtime has been reached. Calling
|
||||||
# logic should iterate over every neopixel ID that should
|
# logic should iterate over every neopixel ID that should
|
||||||
|
@ -81,8 +44,7 @@ def prettytime(seconds):
|
||||||
# red and yellow are both set to True depends on how the
|
# red and yellow are both set to True depends on how the
|
||||||
# colormode is configured.
|
# colormode is configured.
|
||||||
def colorizer(pxnum, colormode="fill", yellow=False, red=False):
|
def colorizer(pxnum, colormode="fill", yellow=False, red=False):
|
||||||
# Fill every pixel from lowest to currently highest with
|
# Every pixel from lowest to currently highest
|
||||||
# the current color.
|
|
||||||
if colormode == "fill":
|
if colormode == "fill":
|
||||||
if red:
|
if red:
|
||||||
pixels[pxnum] = RED
|
pixels[pxnum] = RED
|
||||||
|
@ -90,8 +52,6 @@ def colorizer(pxnum, colormode="fill", yellow=False, red=False):
|
||||||
pixels[pxnum] = YELLOW
|
pixels[pxnum] = YELLOW
|
||||||
else:
|
else:
|
||||||
pixels[pxnum] = GREEN
|
pixels[pxnum] = GREEN
|
||||||
# Only fill the next pixel with the current color if it's
|
|
||||||
# currently BLANK
|
|
||||||
elif colormode == "candybar":
|
elif colormode == "candybar":
|
||||||
if pixels[pxnum] == BLANK:
|
if pixels[pxnum] == BLANK:
|
||||||
if red:
|
if red:
|
||||||
|
@ -106,7 +66,6 @@ def colorizer(pxnum, colormode="fill", yellow=False, red=False):
|
||||||
# Invalid colormodes end up here
|
# Invalid colormodes end up here
|
||||||
raise Exception("Invalid colormode: " + colormode)
|
raise Exception("Invalid colormode: " + colormode)
|
||||||
|
|
||||||
|
|
||||||
# Count down from the given total seconds, using the chosen
|
# Count down from the given total seconds, using the chosen
|
||||||
# colormode (how the colors are filled into each pixel),
|
# colormode (how the colors are filled into each pixel),
|
||||||
# and the given yellowtime (seconds before timer has elapsed
|
# and the given yellowtime (seconds before timer has elapsed
|
||||||
|
@ -152,11 +111,7 @@ def countdown(
|
||||||
|
|
||||||
# Do update stuff
|
# Do update stuff
|
||||||
|
|
||||||
# Calculate the current position.
|
# Calculate the current position
|
||||||
# Takes the percentage of time elapsed, multiplied with
|
|
||||||
# the total numbers of pixels, and rounded to the nearest
|
|
||||||
# decimal. This results in a number of pixels proportional
|
|
||||||
# to the elapsed time
|
|
||||||
current_position = round(num_pixels * ((seconds - current_time) / seconds))
|
current_position = round(num_pixels * ((seconds - current_time) / seconds))
|
||||||
|
|
||||||
# Catch a couple of special cases
|
# Catch a couple of special cases
|
||||||
|
@ -168,7 +123,7 @@ def countdown(
|
||||||
# If current_position calls for *all*
|
# If current_position calls for *all*
|
||||||
# pixels to be lit, and the timer
|
# pixels to be lit, and the timer
|
||||||
# hasn't expired yet, don't do anything.
|
# hasn't expired yet, don't do anything.
|
||||||
# This will delay the last pixel from
|
# This should delay the last pixel from
|
||||||
# lighting until the timer has fully elapsed
|
# lighting until the timer has fully elapsed
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -176,10 +131,6 @@ def countdown(
|
||||||
# based on the elapsed time
|
# based on the elapsed time
|
||||||
for pixel in range(current_position):
|
for pixel in range(current_position):
|
||||||
# Set pixel color stuff
|
# Set pixel color stuff
|
||||||
|
|
||||||
# If current_time has gone negative, don't
|
|
||||||
# change any pixels, just keep counting for
|
|
||||||
# user feedback
|
|
||||||
if current_time < 0:
|
if current_time < 0:
|
||||||
pass
|
pass
|
||||||
elif current_time <= redtime:
|
elif current_time <= redtime:
|
||||||
|
@ -189,144 +140,20 @@ def countdown(
|
||||||
else:
|
else:
|
||||||
colorizer(pixel, colormode)
|
colorizer(pixel, colormode)
|
||||||
|
|
||||||
# All the pixels have now been set based on the
|
# Display the result IRL
|
||||||
# specified colormode, now display the result IRL.
|
|
||||||
pixels.show()
|
pixels.show()
|
||||||
|
|
||||||
# Increment the elapsed time variable
|
# Increment the elapsed time variable
|
||||||
current_time -= update_interval
|
current_time -= update_interval
|
||||||
|
|
||||||
# Add a negative sign to the output when current_time is negative.
|
# Massage the current_time seconds count into human-readable minutes:seconds
|
||||||
# prettytime() puts the given value through abs() because the way
|
display_time = str(datetime.timedelta(seconds=abs(current_time)))[3:]
|
||||||
# datetime.timedelta() represents negative values is kind of a PITA
|
|
||||||
# to deal with.
|
|
||||||
if current_time < 0:
|
if current_time < 0:
|
||||||
display_time_sign = "-"
|
display_time_sign = "-"
|
||||||
else:
|
else:
|
||||||
display_time_sign = " "
|
display_time_sign = " "
|
||||||
# Give the user feedback
|
print("current time: " + display_time_sign + display_time)
|
||||||
# (this string will eventually go to a ssd1306 OLED display via
|
|
||||||
# displayio, but just put it on the terminal output for now)
|
|
||||||
print("current time: " + display_time_sign + prettytime(current_time))
|
|
||||||
|
|
||||||
# If the button is currently being pressed
|
|
||||||
if not button.value:
|
|
||||||
# We are paused
|
|
||||||
pause = True
|
|
||||||
# There's no long-press option before pausing, so button should
|
|
||||||
# no longer be down.
|
|
||||||
button_held = False
|
|
||||||
print("Timer Paused")
|
|
||||||
# Keep looping here as long as we're paused
|
|
||||||
while pause:
|
|
||||||
# If the button is being pressed
|
|
||||||
if not button.value and not button_held:
|
|
||||||
# The button is being held down
|
|
||||||
button_held = True
|
|
||||||
# Record when the button started being pressed
|
|
||||||
button_held_timer = time.monotonic()
|
|
||||||
# Keep looping while the button is down
|
|
||||||
while not button.value:
|
|
||||||
# Continually check if button_hold_delay has elapsed
|
|
||||||
# while the button is still down
|
|
||||||
if time.monotonic() - button_held_timer > button_hold_delay:
|
|
||||||
# Button should no longer be down
|
|
||||||
button_held = False
|
|
||||||
# Reset the long-press timer as a debounce method
|
|
||||||
button_held_timer = time.monotonic()
|
|
||||||
# No longer in pause mode
|
|
||||||
pause = False
|
|
||||||
# Give the user feedback
|
|
||||||
print("Timer Reset")
|
|
||||||
# Hang around for half a second for debounce
|
|
||||||
time.sleep(0.5)
|
|
||||||
# Return from countdown() back to the main loop
|
|
||||||
return
|
|
||||||
# If the button is not being pressed and button_held is True.
|
|
||||||
# I don't understand why, but it gets hung up here sometimes,
|
|
||||||
# requiring the user to press the button multiple times to
|
|
||||||
# resume the timer again...
|
|
||||||
if button.value and button_held:
|
|
||||||
# Flip it back to False
|
|
||||||
button_held = False
|
|
||||||
# If the button is being short-pressed when it previously wasn't
|
|
||||||
# being pressed, and we are paused.
|
|
||||||
if not button.value and not button_held and pause:
|
|
||||||
# Flip it back to False
|
|
||||||
button_held = False
|
|
||||||
# Exiting pause
|
|
||||||
pause = False
|
|
||||||
# User Feedback
|
|
||||||
print("Timer Resumed")
|
|
||||||
# Hang around for half a second for debounce
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
|
|
||||||
# Hard-coded initial value. (will replace with stored value later)
|
|
||||||
set_time_orig = 120
|
|
||||||
set_time = set_time_orig
|
|
||||||
|
|
||||||
# How many seconds should be added to or subtracted from set_time
|
|
||||||
# for every encoder click
|
|
||||||
set_time_step = 60
|
|
||||||
|
|
||||||
# How long is a long-press in seconds
|
|
||||||
button_hold_delay = 2
|
|
||||||
|
|
||||||
|
|
||||||
# Main loop
|
|
||||||
while True:
|
|
||||||
|
|
||||||
# Negate the position to make clockwise rotation positive
|
|
||||||
position = -encoder.position
|
|
||||||
|
|
||||||
# If the encoder position has changed since last iteration
|
|
||||||
if position != last_position:
|
|
||||||
# If last_position is set to -1, assume it's just been
|
|
||||||
# initialized, so don't adjust anything
|
|
||||||
if last_position == -1:
|
|
||||||
pass
|
|
||||||
# Clockwise turn increases set_time by set_time_step
|
|
||||||
elif position > last_position:
|
|
||||||
set_time += set_time_step
|
|
||||||
# Counter-clockwise turn decreases set_time by set_time_step
|
|
||||||
# only until 0
|
|
||||||
elif set_time > 0:
|
|
||||||
set_time -= set_time_step
|
|
||||||
# Update the position tracker
|
|
||||||
last_position = position
|
|
||||||
# User feedback
|
|
||||||
print("Current set time: " + prettytime(set_time))
|
|
||||||
# If the button is being pressed, and button_held is False
|
|
||||||
if not button.value and not button_held:
|
|
||||||
# Button is being pressed
|
|
||||||
button_held = True
|
|
||||||
# Capture the current monotonic clock time to later detect a long-press
|
|
||||||
button_held_timer = time.monotonic()
|
|
||||||
# Keep looping while the button is down
|
|
||||||
while not button.value:
|
|
||||||
# Continually check if button_hold_delay has elapsed
|
|
||||||
# while the button is still down
|
|
||||||
if time.monotonic() - button_held_timer > button_hold_delay:
|
|
||||||
# Reset the set_time to the value of set_time_orig
|
|
||||||
# (eventually, set_time_orig will be read from persistent config)
|
|
||||||
set_time = set_time_orig
|
|
||||||
# Give the user feedback
|
|
||||||
print("Time reset to: " + prettytime(set_time))
|
|
||||||
# Button should no longer be down
|
|
||||||
button_held = False
|
|
||||||
# Reset the long-press timer as a debounce method
|
|
||||||
button_held_timer = time.monotonic()
|
|
||||||
|
|
||||||
# If the button is not being pressed, and it previously was being pressed
|
|
||||||
if button.value and button_held:
|
|
||||||
# Button is no longer being pressed
|
|
||||||
button_held = False
|
|
||||||
# Start the countdown using the configured set_time
|
|
||||||
countdown(set_time)
|
|
||||||
# Once the timer has been reset, re-init last_position.
|
|
||||||
# In effect, this will display the set_time to the user again
|
|
||||||
last_position = -1
|
|
||||||
# Turn off all pixels
|
|
||||||
pixels.fill(BLANK)
|
|
||||||
pixels.show()
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
# Ref: https://learn.adafruit.com/adafruit-i2c-qt-rotary-encoder/python-circuitpython
|
|
||||||
import board
|
|
||||||
from adafruit_seesaw import seesaw, rotaryio, digitalio
|
|
||||||
import busio
|
|
||||||
|
|
||||||
SDA = board.GP0
|
|
||||||
SCL = board.GP1
|
|
||||||
i2c = busio.I2C(SCL, SDA)
|
|
||||||
seesaw = seesaw.Seesaw(i2c, 0x36)
|
|
||||||
|
|
||||||
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
|
|
||||||
button = digitalio.DigitalIO(seesaw, 24)
|
|
||||||
button_held = False
|
|
||||||
|
|
||||||
encoder = rotaryio.IncrementalEncoder(seesaw)
|
|
||||||
last_position = None
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
# negate the position to make clockwise rotation positive
|
|
||||||
position = -encoder.position
|
|
||||||
|
|
||||||
if position != last_position:
|
|
||||||
last_position = position
|
|
||||||
print("Position: {}".format(position))
|
|
||||||
|
|
||||||
if not button.value and not button_held:
|
|
||||||
button_held = True
|
|
||||||
print("Button pressed")
|
|
||||||
|
|
||||||
if button.value and button_held:
|
|
||||||
button_held = False
|
|
||||||
print("Button released")
|
|
Loading…
Reference in New Issue