Skip to content

Instantly share code, notes, and snippets.

@minimasoft
Last active November 10, 2025 03:36
Show Gist options
  • Select an option

  • Save minimasoft/3784583858c96600b14894e1bd2dedba to your computer and use it in GitHub Desktop.

Select an option

Save minimasoft/3784583858c96600b14894e1bd2dedba to your computer and use it in GitHub Desktop.
micropython time switch
from time import ticks_ms, ticks_diff, ticks_add
from machine import Pin
class ButtonFilter:
def __init__(self, pin_number, bounce_filter=90):
now = ticks_ms()
self.pin = Pin(pin_number, Pin.IN, Pin.PULL_UP)
self.bounce_filter = bounce_filter
self.state = self.pin.value()
self.next_state = self.state
self.since = now
def value(self):
now = ticks_ms()
reading = self.pin.value()
if reading == self.next_state and self.next_state != self.state:
if ticks_diff(now, self.since) > self.bounce_filter:
self.state = self.next_state
self.since = now
elif reading != self.next_state:
self.next_state = reading
return self.state
class ArgentinianOutput: # Inverted
def __init__(self, pin_number, default=0):
self.pin = Pin(pin_number, Pin.OUT)
self.value(default)
def on(self):
self.pin.off()
def off(self):
self.pin.on()
def value(self, value):
if value:
self.on()
else:
self.off()
def prevent_flip_on_clock_rollover(now, state):
if ticks_diff(state["power"]["until"], now) > 0 and not state["power"]["value"]:
state["power"]["until"] = 0
def long_push_actions(now, state, reading):
LONG_PUSH = 1500
if (state["button"]["value"] == reading) and (reading == 0):
on_time = ticks_diff(now, state["button"]["since"])
if on_time > LONG_PUSH:
if ticks_diff(state["power"]["since"], state["button"]["since"]) >= 0:
state["power"]["until"] = now
state["hodl"] = True
else:
state["power"]["until"] = 0
return True
def push_actions(now, state, reading):
PRESS_POWER_TIME = 5000
if reading != state["button"]["value"]:
state["button"]["value"] = reading
state["button"]["since"] = now
if reading == 0: # pushed
if state["power"]["until"] < now:
state["power"]["until"] = now
state["power"]["until"] = ticks_add(
state["power"]["until"], PRESS_POWER_TIME
)
print(f"power remaining: {ticks_diff(state['power']['until'], now)} ms")
return True
def update_output(now, state, reading):
power_state = ticks_diff(state["power"]["until"], now) >= 0
if power_state != state["power"]["value"]:
print(power_state)
state["power"]["since"] = now
state["power"]["value"] = power_state
state["hodl"] = False
return True
# config
inx = ButtonFilter(14)
out = ArgentinianOutput(15)
# bootstrap the state
state = {
"button": {
"value": inx.value(),
"since": ticks_ms(),
},
"power": {
"value": False,
"until": 0,
"since": ticks_ms(),
},
"hodl": False,
}
while True:
now = ticks_ms()
reading = inx.value()
prevent_flip_on_clock_rollover(now, state)
long_push_actions(now, state, reading)
push_actions(now, state, reading)
if update_output(now, state, reading):
out.value(state["power"]["value"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment