I'm having trouble getting light sleep working with PinAlarms on my MagTag. Any ideas or workarounds for using light sleep and getting the button state when not plugged into a PC?
Steps to reproduce:
- Copy code.py onto the MagTag (CircuitPython)
- Unplug the MagTag from the PC
- Re-boot the Magtag
- Press either of the two middle buttons (B or C) to exit deep sleep and enter the light sleep function
- Press any button (A, B, C, D) to wake up from the light sleep
- Observe that the
alarm.wake_alarm is being set to None
While that's probably sufficient for telling that a button was pressed, I'm not sure how to figure out which button was pressed.
What does work:
- Skip step 2 above, leaving the MagTag connected to the PC
- Using a busy waiting strategy instead. Replace the
light_sleep_wait() call with busy_button_wait(magtag, active_mode_s) and move the button deinit() calls to just before the deep sleep call
Example code.py to reproduce the issue:
import alarm
import board
import time
from adafruit_magtag.magtag import MagTag
# This works when plugged in or not plugged in
# I'd prefer the light sleep way, however, instead of writing a busy loop.
def busy_button_wait(magtag, active_mode_s):
start_time = time.monotonic()
while time.monotonic() < (start_time + active_mode_s):
# Refresh the timer at the start of each loop
if magtag.peripherals.any_button_pressed:
start_time = time.monotonic()
if magtag.peripherals.button_a_pressed:
button_name = "A"
if magtag.peripherals.button_b_pressed:
button_name = "B"
if magtag.peripherals.button_c_pressed:
button_name = "C"
if magtag.peripherals.button_d_pressed:
button_name = "D"
magtag.set_text(f"button_name: {button_name}")
time.sleep(.1)
# This only works when plugged into a PC
def light_sleep_wait(magtag, active_mode_s, pin_alarms):
while True:
light_timer_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + active_mode_s)
# Exit the program, and then deep sleep until the alarm wakes us,
# either from a button press or a timer.
triggered_alarm = alarm.light_sleep_until_alarms(
pin_alarms[0],
pin_alarms[1],
pin_alarms[2],
pin_alarms[3],
light_timer_alarm
)
if type(triggered_alarm) is alarm.time.TimeAlarm:
# Leave interactive state because active_mode_s time has lapsed
return
elif (type(triggered_alarm) is alarm.pin.PinAlarm) or (triggered_alarm == None):
# Inspect what triggered it:
# magtag.set_text(triggered_alarm)
# time.sleep(5)
# When connected to PC and a button is pressed, light_sleep_until_alarms gives us back the PinAlarm
button_name = ""
if type(triggered_alarm) is alarm.pin.PinAlarm:
if triggered_alarm.pin == board.BUTTON_A:
button_name += "A"
if triggered_alarm.pin == board.BUTTON_B:
button_name += "B"
if triggered_alarm.pin == board.BUTTON_C:
button_name += "C"
if triggered_alarm.pin == board.BUTTON_D:
button_name += "D"
# But when disconnected from a PC and a button is pressed, light_sleep_until_alarms gives us back None
else:
magtag.set_text(triggered_alarm)
time.sleep(5)
# My poor attempt at getting the button state anyways
# magtag.peripherals.button_x_pressed can't be used because we deinitialized them earlier so this code crashes.
if magtag.peripherals.button_a_pressed:
button_name += "A"
if magtag.peripherals.button_b_pressed:
button_name += "B"
if magtag.peripherals.button_c_pressed:
button_name += "C"
if magtag.peripherals.button_d_pressed:
button_name += "D"
magtag.set_text(f"button_name: {button_name}")
def wakeup_into_active(active_mode_s=15, deep_mode_s=30):
# On a button press, we wakeup from deep sleep and go into an active waiting state for 15 seconds
magtag = MagTag()
magtag.add_text( text_scale=.1, text_wrap=50, text_maxlen=300, text_position=(10, 10), text_anchor_point=(0, 0))
is_deep_button_wake = type(alarm.wake_alarm) is alarm.pin.PinAlarm
is_deep_timer_wake = type(alarm.wake_alarm) is alarm.time.TimeAlarm
magtag.peripherals.buttons[0].deinit()
magtag.peripherals.buttons[1].deinit()
magtag.peripherals.buttons[2].deinit()
magtag.peripherals.buttons[3].deinit()
pin_alarm_A = alarm.pin.PinAlarm(pin=board.BUTTON_A, value=False, pull=True)
pin_alarm_B = alarm.pin.PinAlarm(pin=board.BUTTON_B, value=False, pull=True)
pin_alarm_C = alarm.pin.PinAlarm(pin=board.BUTTON_C, value=False, pull=True)
pin_alarm_D = alarm.pin.PinAlarm(pin=board.BUTTON_D, value=False, pull=True)
# If button, go into interactive state
# Else if timer, do any non-interactive updates
if is_deep_button_wake:
magtag.set_text(f"Entering interactive mode for {active_mode_s} seconds")
# busy_button_wait(magtag, active_mode_s) # Works
light_sleep_wait(magtag, active_mode_s, [pin_alarm_A, pin_alarm_B, pin_alarm_C, pin_alarm_D]) # Only works when plugged into a PC
elif is_deep_timer_wake:
magtag.set_text(f"Performing non-interactive updates")
else:
magtag.set_text(f"First time around")
deep_timer_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + deep_mode_s)
# Only two PinAlarms can be used for deep sleep at a time
alarm.exit_and_deep_sleep_until_alarms(
pin_alarm_B,
pin_alarm_C,
deep_timer_alarm
)
# Main
wakeup_into_active()
I'm having trouble getting light sleep working with PinAlarms on my MagTag. Any ideas or workarounds for using light sleep and getting the button state when not plugged into a PC?
Steps to reproduce:
alarm.wake_alarmis being set toNoneWhile that's probably sufficient for telling that a button was pressed, I'm not sure how to figure out which button was pressed.
What does work:
light_sleep_wait()call withbusy_button_wait(magtag, active_mode_s)and move the button deinit() calls to just before the deep sleep callExample code.py to reproduce the issue: