Can I lightsleep() until any of some given GPIOs go HIGH (on ESP32)?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
Frans
Posts: 7
Joined: Thu Jun 23, 2022 4:10 am

Can I lightsleep() until any of some given GPIOs go HIGH (on ESP32)?

Post by Frans » Thu Jun 23, 2022 5:07 am

I'd like to wait for a couple (i.e. more than one) of buttons (GPIOs) on an AudioKit / M5StickC (ESP32 based) to be pressed (and ideally released, too), without wasting CPU cycles (i.e. battery power).

I found machine.lightsleep() to do what I want but it looks like I can't tell it to wait for more than one Pin to go LOW with `esp32.wake_on_ext0()` or `esp32.wake_on_ext1()` - since you can only specify WAKEUP_ALL_LOW or WAKEUP_ANY_HIGH.

What I need is a way to say "lightsleep() until any of given GPIOs change" or at least ".. until any of them goes LOW" but there is no `esp32.WAKEUP_ANY_LOW`.

is `esp32.wake_on_ext0/1()` the right thing to use here anyway?

Here is, what I got:

Code: Select all

import esp32
from machine import lightsleep, Pin
from utime import sleep_ms

btn1_pin = Pin(36, Pin.IN)
btn2_pin = Pin(13, Pin.IN)

esp32.wake_on_ext0(pin=btn1_pin, level=esp32.WAKEUP_ALL_LOW)

# a second call makes the first one not work any more
#esp32.wake_on_ext0(pin=btn2_pin, level=esp32.WAKEUP_ALL_LOW)

#esp32.wake_on_ext0(pin=btn2_pin, level=esp32.WAKEUP_ALL_LOW)
#esp32.wake_on_ext1(pins=(device.pin_bA, device.pin_bB), level=esp32.WAKEUP_ALL_LOW)

print("Press buttons 1 or 2")
sleep_ms(5)

while True:
    lightsleep(2000)  # wait for button presses - works for one button only

    if btn1_pin.value() == 0:
        print("Button1 pressed")
        while btn1_pin.value() == 0:
            # I'd like to use lightsleep here, too, but I don't know how
            sleep_ms(5)
        print("Button1 released")
    
    # this won't be reached if I don't press Button1, too
    if btn2_pin.value() == 0:
        print("Button2 pressed")
        while btn2_pin.value() == 0:
            # I'd like to use lightsleep here, too, but I don't know how
            sleep_ms(5)
        print("Button2 released")
.. but this code doesn't work for more than one button, since I can only run `esp32.wake_on_ext0` once (for one Pin), while `esp32.wake_on_ext1()` can only wait for ALL GPIOs being LOW - which means pressed in my case.

Lobo-T
Posts: 36
Joined: Tue Nov 16, 2021 2:36 pm

Re: Can I lightsleep() until any of some given GPIOs go HIGH (on ESP32)?

Post by Lobo-T » Thu Jun 23, 2022 9:23 am

I don't think what you want is directly possible.

I see two soulutions:
1) The ESP32 has an "Ultra Low Power" (ULP) coprocessor" that can keep running in sleep mode and can be used to wake up. It can only access the pins marked RTC in the datasheet. You will have to learn to program this in assembler.
https://docs.espressif.com/projects/esp ... m/ulp.html
An ULP program can be loaded through Micropython: https://docs.micropython.org/en/latest/ ... -processor

2) Use external good old fashioned logic gates to generate the wakeup signal you want.
Modern 74-series gates use very little power.
From the TI SN74HCS00 datasheet:
ICC Supply current Typ: 0.1 µA
II Input leakage current Typ: ±100nA

Lobo-T
Posts: 36
Joined: Tue Nov 16, 2021 2:36 pm

Re: Can I lightsleep() until any of some given GPIOs go HIGH (on ESP32)?

Post by Lobo-T » Thu Jun 23, 2022 9:35 am

Lobo-T wrote:
Thu Jun 23, 2022 9:23 am
An ULP program can be loaded through Micropython: https://docs.micropython.org/en/latest/ ... -processor
I just noticed that ULP wasn't a possible wakeup source in Micropython until two hours ago... :?
https://github.com/micropython/micropyt ... 76ffc4866c
So use a nightly build tomorrow if you go this route. :lol:

User avatar
karfas
Posts: 193
Joined: Sat Jan 16, 2021 12:53 pm
Location: Vienna, Austria

Re: Can I lightsleep() until any of some given GPIOs go HIGH (on ESP32)?

Post by karfas » Thu Jun 23, 2022 9:38 am

3) use WAKEUP_ANY_HIGH together with pulldown resistors and wire your switches to +3.3V.
A few hours of debugging might save you from minutes of reading the documentation! :D
My repositories: https://github.com/karfas

Post Reply