diff --git a/src/main.py b/src/main.py index 4b628c3..b3c8131 100644 --- a/src/main.py +++ b/src/main.py @@ -8,6 +8,8 @@ from patterns import Patterns import gc import utime import machine +import esp32 +import network import time import wifi import json @@ -15,8 +17,21 @@ from p2p import p2p from machine import ADC, Pin, I2C from lsm6ds3 import LSM6DS3, is_lsm6ds3 +# XIAO ESP32-C3: deep-sleep GPIO wake only on GPIO 0-5 (header D0-D3). +SW_PIN = 3 # D1 — switch to GND (short press cycle, long press sleep/wake) +LED_PIN = 8 # D8 — onboard LED (active low) +SLEEP_HOLD_MS = 2000 +SLEEP_RELEASE_WAIT_MS = 500 # wait after release before arming wake + async def main(): + sw = Pin(SW_PIN, Pin.IN, Pin.PULL_UP) + if machine.reset_cause() == machine.DEEPSLEEP_RESET: + print("woke from deep sleep, reason:", esp32.wake_reason()) + while sw.value() == 0: + utime.sleep_ms(50) + settings = Settings() + led = Pin(LED_PIN, Pin.OUT, value=1) patterns = Patterns(settings["led_pin"], settings["num_leds"], selected=settings["pattern"]) if settings["color_order"] == "rbg": color_order = (1, 5, 3) @@ -33,6 +48,14 @@ async def main(): patterns.tick() await asyncio.sleep_ms(0) + async def heartbeat(): + while True: + wdt.feed() + led.value(0) + await asyncio.sleep_ms(80) + led.value(1) + await asyncio.sleep_ms(920) + async def system(): adc = ADC(Pin(0), atten=ADC.ATTN_11DB) while True: @@ -45,30 +68,66 @@ async def main(): print("%.3f V" % voltage) await asyncio.sleep(1) - async def sw(): - sw1 = machine.Pin(8, machine.Pin.IN, machine.Pin.PULL_UP) - sw2 = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP) + def enter_deep_sleep(): + patterns.select("off") + patterns.sync() + utime.sleep_ms(100) + led.value(1) + for iface in (network.STA_IF, network.AP_IF): + wl = network.WLAN(iface) + if wl.active(): + wl.active(False) + if sw.value() == 0: + print("button still pressed, not sleeping") + return + esp32.wake_on_ext1(pins=(sw,), level=esp32.WAKEUP_ANY_LOW) + print("deep sleep — press GPIO %d to wake" % SW_PIN) + machine.deepsleep() + async def prepare_deep_sleep(): + print("release button to sleep") + while sw.value() == 0: + wdt.feed() + await asyncio.sleep_ms(50) + await asyncio.sleep_ms(SLEEP_RELEASE_WAIT_MS) + if sw.value() == 0: + print("button pressed again, sleep cancelled") + return + enter_deep_sleep() + + async def switch_loop(): p = ["on", "rainbow_cycle", "theater_chase", "color_transition", "flicker", "bidirectional_scanner"] - + pattern_index = 0 + press_start = None + sleep_pending = False print(p) - pressed1 = 0 - pressed2 = 0 while True: - if sw1.value() == 0: - patterns.select(p[pattern_index]) - print(p[pattern_index]) - pattern_index = pattern_index + 1 - if pattern_index > len(p)-1: - pattern_index = 0 - print("pressed 1") - if sw2.value() == 0: - patterns.select("off") - await asyncio.sleep_ms(200) + if sleep_pending: + await prepare_deep_sleep() + sleep_pending = False + press_start = None + continue + + if sw.value() == 0: + if press_start is None: + press_start = utime.ticks_ms() + elif utime.ticks_diff(utime.ticks_ms(), press_start) >= SLEEP_HOLD_MS: + sleep_pending = True + press_start = None + else: + if press_start is not None: + held = utime.ticks_diff(utime.ticks_ms(), press_start) + if 50 < held < SLEEP_HOLD_MS: + patterns.select(p[pattern_index]) + print(p[pattern_index]) + pattern_index = (pattern_index + 1) % len(p) + press_start = None + + await asyncio.sleep_ms(50) telemetry = { "voltage": 0.0, @@ -171,18 +230,20 @@ async def main(): print("IMU read error:", e) await asyncio.sleep_ms(200) + wdt = machine.WDT(timeout=10000) + wdt.feed() + w = web(settings, patterns, telemetry) print(settings) # start the server in a bacakground task print("Starting") server = asyncio.create_task(w.start_server(host="0.0.0.0", port=80)) - wdt = machine.WDT(timeout=10000) - wdt.feed() asyncio.create_task(tick()) + asyncio.create_task(heartbeat()) asyncio.create_task(p2p(settings, patterns)) asyncio.create_task(system()) - asyncio.create_task(sw()) + asyncio.create_task(switch_loop()) if imu_sensor is not None: asyncio.create_task(imu_loop()) diff --git a/test/lsm6ds3_test.py b/test/lsm6ds3_test.py index 6cf60e0..16cf6b5 100644 --- a/test/lsm6ds3_test.py +++ b/test/lsm6ds3_test.py @@ -5,7 +5,7 @@ from lsm6ds3 import LSM6DS3, is_lsm6ds3 # XIAO ESP32C3 default I2C pins: SDA=GPIO6 (D4), SCL=GPIO7 (D5) -i2c = I2C(0, scl=Pin(23), sda=Pin(22), freq=400000) +i2c = I2C(0, scl=Pin(20), sda=Pin(21), freq=400000) def scan_i2c():