Ver Fonte

light sleep (breaks alarm)

Fabian Peter Hammerle há 2 anos atrás
pai
commit
986b9e651a
1 ficheiros alterados com 44 adições e 6 exclusões
  1. 44 6
      vibrating_alarm_m5stickc.py

+ 44 - 6
vibrating_alarm_m5stickc.py

@@ -2,19 +2,31 @@
 tested on uiflow for stickc v1.8.1
 """
 
-# pylint: disable=import-error
 import json
 
+# pylint: disable=import-error
+import esp32
 import m5ui
 import machine
 import micropython
 import utils
+import utime
 from m5stack import axp, btnA, btnB, lcd, rtc
 
 _FONT = lcd.FONT_DejaVu40
 _DEFAULT_FONT_COLOR = lcd.WHITE
 _ALARM_TIME_PATH = "alarm.json"
 _SCREEN_WIDTH, _SCREEN_HEIGHT = lcd.winsize()
+_AWAKE_SECONDS = 8
+
+
+def _handle_pending_events():
+    # > [...] a millisecond sleep larger than 10ms will check for pending (soft)
+    # > interrupts during the sleep. [...] The reason for the 10ms value is
+    # > because the FreeRTOS tick is 10ms, [...]
+    # https://github.com/micropython/micropython/issues/3493#issuecomment-352617624
+    # https://github.com/micropython/micropython/commit/4ed586528047d3eced28a9f4af11dbbe64fa99bb
+    utime.sleep_ms(11)
 
 
 class App:
@@ -22,6 +34,8 @@ class App:
     def __init__(self) -> None:
         self._clock_text_box = None
         self._menu_position = 0
+        self._wait_for_sleep_start_time_update = False
+        self._sleep_start_time_seconds = 0.0
         self._alarm_hour = None
         self._alarm_minute = None
         self._alarm_hour_text_box = None
@@ -53,6 +67,14 @@ class App:
                 alarm_time_file,
             )
 
+    def _reschedule_sleep(self, interrupt: bool) -> None:
+        if interrupt:
+            self._wait_for_sleep_start_time_update = True
+            micropython.schedule(self._reschedule_sleep, False)
+        else:
+            self._sleep_start_time_seconds = utime.time() + _AWAKE_SECONDS
+            self._wait_for_sleep_start_time_update = False
+
     def _update_menu(self, event_arg: None) -> None:
         # pylint: disable=unused-argument; callback
         self._alarm_hour_text_box.setColor(  # type: ignore
@@ -67,6 +89,7 @@ class App:
         )
 
     def _button_a_pressed(self) -> None:
+        self._reschedule_sleep(interrupt=True)
         self._menu_position = (self._menu_position + 1) % 5
         # https://docs.micropython.org/en/latest/library/micropython.html#micropython.schedule
         micropython.schedule(self._update_menu, None)
@@ -85,6 +108,7 @@ class App:
             24 * 60 * 60
         ) + 1
         print("alarm in ", seconds_until_alarm / 60, " min")
+        # TODO configure wake from sleep
         self._alarm_timer.init(  # type: ignore
             period=seconds_until_alarm * 1000,  # ms
             mode=machine.Timer.ONE_SHOT,
@@ -103,6 +127,7 @@ class App:
         self._configure_alarm_timer()
 
     def _button_b_pressed(self) -> None:
+        self._reschedule_sleep(interrupt=True)
         if self._menu_position == 1:
             self._alarm_hour += 1  # type: ignore
         elif self._menu_position == 2:
@@ -115,7 +140,8 @@ class App:
         self._alarm_minute %= 60  # type: ignore
         micropython.schedule(self._update_alarm_time, None)
 
-    def _format_time(self) -> str:
+    @staticmethod
+    def _format_time() -> str:
         return "{:02d}:{:02d}".format(*rtc.now()[3:5])
 
     def _setup_clock(self) -> None:
@@ -129,7 +155,7 @@ class App:
             rotate=90,
         )
         machine.Timer(0).init(
-            period=10000,  # ms
+            period=4000,  # ms
             mode=machine.Timer.PERIODIC,
             callback=lambda t: self._clock_text_box.setText(self._format_time()),  # type: ignore
         )
@@ -170,9 +196,21 @@ class App:
         self._setup_alarm()
         btnA.wasPressed(self._button_a_pressed)
         btnB.wasPressed(self._button_b_pressed)
+        # not sure whether ext0 would be better
+        esp32.wake_on_ext1([btnA.pin], esp32.WAKEUP_ALL_LOW)
+        self._reschedule_sleep(interrupt=False)
+        while True:
+            while utime.time() < self._sleep_start_time_seconds:
+                utime.sleep(1)  # seconds
+            # TODO turn off display
+            axp.setLcdBrightness(30)
+            machine.lightsleep()
+            # TODO turn on display
+            axp.setLcdBrightness(100)
+            print("wake reason:", machine.wake_reason())
+            _handle_pending_events()
+            while self._wait_for_sleep_start_time_update:
+                _handle_pending_events()
 
 
 App().run()
-
-# TODO https://docs.micropython.org/en/latest/library/machine.WDT.html#machine-wdt
-# TODO https://docs.micropython.org/en/latest/esp8266/tutorial/powerctrl.html#deep-sleep-mode