Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

machine.deepsleep() in main.py results in unusable device #8153

Open
mwilliams181 opened this issue Jan 10, 2022 · 6 comments
Open

machine.deepsleep() in main.py results in unusable device #8153

mwilliams181 opened this issue Jan 10, 2022 · 6 comments

Comments

@mwilliams181
Copy link

Hi all,

When I use machine.deepsleep() in main.py, I am no longer able to program or connect to the device anymore. I try to send CTRL+C command, but it does not get back to the REPL. Any ideas on how to kill the program and get back to the REPL? Any workarounds?

The only workaround I can think of is to add a time.sleep(100) before the machine.deepsleep() command, which does work, but this requires me to unplug the device then plug it back in if we surpass the 100 seconds and reach the machine.deepsleep(). I don't like this solution because my students will think that their device is broken after 100 seconds and will be very confused!

Note: I am using an ESP32

@peterhinch
Copy link
Contributor

This might be seen by more people if you posted in the forum.

@stephanelsmith
Copy link
Sponsor Contributor

Peter, much appreciate the tip. Will pop on over and post there. I'll keep looking at the issue myself in parallel and update here as well.

@stephanelsmith
Copy link
Sponsor Contributor

I just posted the same issue.
#8148

I notice this issue on S3, but S2 and D4 are working for me. For me, when I put S3 in deep sleep, the wake sources are not working, timer or external interrupt. Same code compiled but switch to S2/D4 boards is working as expected. Maybe my older IDF version that works for compiling S3 could be the issue.

@mwilliams181
Copy link
Author

Hi Stephane, I think the issue your'e seeing is a bit different than mine. My programs interrupt successfully using:
esp32.wake_on_ext0(pin = button, level = esp32.WAKEUP_ANY_HIGH)

The problem is that once the device is in deepsleep (has reached the machine.deepsleep() line of the program), I cannot get back to the REPL using CTRL+C.

Am I right that our issues are different?

@stephanelsmith
Copy link
Sponsor Contributor

Likely. My issue is S3 specific. I succesfully wake on S2 and D4.

I may be wrong, but, I don't think you can wake from CTRL+C from deepsleep as nominal behavior. The UART is down, and the CTRL+C reset is a micropython specific thing, and does not exist at a lower level. You should be able to wake on UART pin toggle if your pins are RTC pins.

That said, if you are using ESP32 without built in USB (eg. D4), you can do a reset by toggling the RTS/DTR pins, the same way esptool does. I believe DTR =1 and RTS = 0 puts the chip in reset (EN pin low). Then nominal behavior is DTR=1 and RTS=1.

@marcidy
Copy link
Contributor

marcidy commented Jan 14, 2022

with machine.deepsleep turns off the CPU and all peripherals except those related to the RTC. The CPU isn't running, the UART isn't running. The only thing that's running is logic in the RTC's power domain (including the ULP if used), which has access to the RTC_GPIOs. It's quite literally a separate controller embedded in the MCU.

If you look at this chart, you'll see which GPIO are accessible by the RTC:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html

There is also separate “RTC GPIO” support, which functions when GPIOs are routed to the “RTC” low-power and analog subsystem. These pin functions can be used when:

    In deep sleep
    The Ultra Low Power co-processor is running
    Analog functions such as ADC/DAC/etc are in use.

And read here to learn more about ESP32s power modes:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html

Note that GPIO1 and GPIO3 are not accessible, so the UART rx/tx will not work in deepsleep. The RTS/DTR for a reset will always work when the board implements one of those connected to ESP32's enable pin (like most boards espressif creates, and many others). It's a hardware reset, connected to ESP32's enable pin. It's not a software reset.

Also note that waking from deepsleep will always result in a reset. As noted on the forum, the CPU is off, so it must be reinitialized, which is a reset. The main memory is not energized so it's state is undetermined. Everything must be restarted from scratch. lightsleep keeps the memory energized and used to resume.

The result here is if you really want to use deepsleep and reset over the USB port, use the RTS/DTR as noted by stephanelsmith to trigger a hardware reset. Ctrl-C will not work as the rx/tx pins do not connect to the RTC peripheral, and the CPU is off. The data will never make it through the UART peripheral. Even if it did, nothing is running to interpret "CTRL-C" as a KeyboardInterrupt. It's not even a software reset, it just interrupts the interpreter and drops you into a prompt. This is incompatible with deepsleep, since a keyboard interrupt doesn't reinitialize anything, so they cannot be equated. Once deepsleep is entered, the only valid expectation is a full reset.

  • edited references to ULP for clarity, it's not necessarily running.

tannewt pushed a commit to tannewt/circuitpython that referenced this issue Jul 11, 2023
…n-main

Translations update from Hosted Weblate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants