Bug: Deep Sleep Wake-up Issue on ESP32-C3
Port, board and/or hardware
ESP32 PORT, ESP32-C3 Super Mini
MicroPython version
Micropython 1.24.1
Reproduction
Title: Bug: Deep Sleep Wake-up Issue on ESP32-C3
Description:
I am experiencing an issue with the deep sleep wake-up functionality on the ESP32-C3 using MicroPython. The device does not wake up as expected when a GPIO pin changes from low to high.
Steps to Reproduce:
- Flash the latest version of MicroPython on an ESP32-C3.
- Use the following code to enter deep sleep and wake up on a GPIO pin change:
import machine import esp32 import time WAKEUP_GPIO_PIN = 0 LED_GPIO_PIN = 8 pin = machine.Pin(WAKEUP_GPIO_PIN, machine.Pin.IN, machine.Pin.PULL_UP) esp32.wake_on_ext0(pin=pin, level=esp32.WAKEUP_ANY_HIGH) wake_reason = machine.wake_reason() if wake_reason == machine.WAKEUP_EXT0: print("Woke up from deep sleep") machine.Pin(LED_GPIO_PIN, machine.Pin.OUT).value(1) time.sleep(1) machine.Pin(LED_GPIO_PIN, machine.Pin.OUT).value(0) else: print("Entering deep sleep") time.sleep(2) machine.deepsleep()
Expected behaviour
Wake up with change on GPIO0.
Observed behaviour
Does not wake up.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree
ports/esp32:* Implementation of deep sleep, esp32 module, machine.RTC
Note 1: Copied over from the old micropython-esp32 repo.
Note 2: Fixed the 1970/2000 bug in RTC.datetime()
Current API:
Basic sleep
import machine
machine.deepsleep() # Sleep until hard reboot
machine.deepsleep(5000) # Deep sleep for 5 seconds
machine.sleep() is implemented, but currently throws an error. If/when the IDF "light sleep" works, this can be removed.
EXT0 wakeups, using the common Micropython idiom
EXT0 wakes are for a single pin, either high or low level.
This is separate from the IRQ handler; the WAKE_LOW and WAKE_HIGH only setup the EXT0 type wake. Using a value other than WAKE_LOW or WAKE_HIGH will clear the EXT0 wake from that pin.
Additionally, any EXT0 wake will fail if esp32.wake_from_touch(True) has been called, since wake from touch and EXT0 are mutually exclusive in the IDF.
>>> import machine
>>> def h(*args): print(args)
...
>>> p1 = machine.Pin(26)
>>> p2 = machine.Pin(27)
>>> p1.irq(trigger = machine.Pin.WAKE_LOW, wake = machine.DEEPSLEEP)
<IRQ>
>>> p2.irq(trigger = machine.Pin.WAKE_LOW, wake = machine.DEEPSLEEP)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: no resources
>>> p1.irq(trigger=machine.Pin.IRQ_RISING, handler = h) # Clears EXT0 wake
>>> p2.irq(trigger = machine.Pin.WAKE_LOW, wake = machine.DEEPSLEEP) # EXT0 now assigned to p2
<IRQ>
Other changes to machine
machine.reset_cause() has been implemented, though usually returns machine.WDT_RESET since most of the time the IDF doesn't reset properly. Does properly return machine.DEEPSLEEP_RESET when waking from deep sleep.
machine.wake_reason() has been implemented.
The new top-level esp32 module
esp32.wake_on_touch(<True|False>) Configures waking on touch. Throws ValueError('no resources') in the event that EXT0 is already configured, since they are not compatible. For this to work, you need to use machine.TouchPad().config() to configure the threshold; an interrupt handler is not required.
esp32.wake_on_ext0(<Pin>, level = <0 | 1>). Configures the EXT0 wake. This will raise ValueError('no resources') if esp32.wake_on_touch(True) has been called. It will not raise this error if another pin has already been configured, it will simply configure the new pin for EXT0 and deconfigure the old pin. If level is not specified, then it is unchanged, and defaults to 0 (low).
esp32.wake_on_ext1(pins = <sequence of Pin object>, level = <esp32.WAKEUP_ALL_LOW | esp32.WAKEUP_ANY_HIGH> ): As described above, wake on multiple pins, either "all low" or "any high".
The new machine.RTC module
machine.RTC.datetime() and machine.RTC.init() work as documented in mainline MicroPython.
machine.RTC.memory() Without arguments returns the RTC nonvolatile memory, as bytes. To write memory, pass a bytes, bytearray, or str object.