Hi, I am using light sleep, and I would like to wake up the processor with the GPIOs, in IDF the function is esp_sleep_enable_gpio_wakeup and gpio_wakeup_enable.
Is there a way to do this in Micropython? I've tried the wake argument of the Pin.irq function but it doesn't work
Thanks
GPIO wakeup enable
Re: GPIO wakeup enable
This works for me to wake up from deepsleep, transmit message, and go sleep again. btn1 and btn2 are reed switch positions (magnet close to reed or far). This way my board sleeps all time possible and only wakes up when magnet position changes. My if...elseif...else statements maybe can help you with your code.
Code: Select all
import sx127x, esp32
import cfg_lora as cfg
from machine import Pin, deepsleep, wake_reason, idle
from time import sleep
Device = 'Balkonas'
Sensor = 'Langas' # O C
def transmit(Value):
# payload = '{};{}:{}#Battery:3.82#Temp:23.2'.format(Device, Sensor, Value)
payload = '{};{}:{}'.format(Device, Sensor, Value)
lora = sx127x.SX127x(cfg.lora_spi, pins=cfg.lora_pins, parameters=cfg.lora_default)
print("LoRa Started");
print(payload)
lora.println(payload)
led1 = Pin(2, Pin.OUT)
led1.on()
wakeReason = wake_reason()
print('Wake Reason =', wakeReason)
btn1 = Pin(32, Pin.IN, Pin.PULL_DOWN) # Normally low, high when pressed
btn2 = Pin(33, Pin.IN, Pin.PULL_DOWN) # Normally low, high when pressed
if( btn1.value() == 1 and btn2.value() == 0 ):
Pin(32, Pin.IN, None)
esp32.wake_on_ext0(pin = btn2, level = esp32.WAKEUP_ANY_HIGH)
transmit("Closed")
elif( btn1.value() == 0 and btn2.value() == 1 ):
Pin(33, Pin.IN, None)
esp32.wake_on_ext0(pin = btn1, level = esp32.WAKEUP_ANY_HIGH)
transmit("Opened")
else:
esp32.wake_on_ext0(pin = btn1, level = esp32.WAKEUP_ANY_HIGH)
esp32.wake_on_ext1(pins = (btn2, ), level = esp32.WAKEUP_ANY_HIGH)
transmit("Unknown")
idle()
print("Waiting five seconds")
sleep(5) # Do NOT remove this statement
print("Going to sleep")
led1.off()
deepsleep()
Re: GPIO wakeup enable
thanks Lixas,
I have tried to wake up esp32 using ext0 and ext1 but I want to use any gpio, not just the ones that are connected to the RTC. Using light sleep, I can have more control to wake up esp using different external sources. https://docs.espressif.com/projects/esp ... sleep-only.
I have multiple external interrupts firing on falling, it's impossible to do that with ext0 or ext1.
I have tried to wake up esp32 using ext0 and ext1 but I want to use any gpio, not just the ones that are connected to the RTC. Using light sleep, I can have more control to wake up esp using different external sources. https://docs.espressif.com/projects/esp ... sleep-only.
I have multiple external interrupts firing on falling, it's impossible to do that with ext0 or ext1.
Re: GPIO wakeup enable
Hi all,
I have an additional question to this topic.
On this page https://randomnerdtutorials.com/esp32-e ... eep-sleep/
we can find C-code like this
Is there a way in micropython to get the number of the GPIO pin that causes the wakeup in the case of an external wakeup on an ESP32?
The micropython function machine.wake_reason() only returns "3" which is machine.EXT1_WAKE but not the pin number.
Thanks, Uwe
I have an additional question to this topic.
On this page https://randomnerdtutorials.com/esp32-e ... eep-sleep/
we can find C-code like this
Code: Select all
void print_GPIO_wake_up(){
int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
Serial.print("GPIO that triggered the wake up: GPIO ");
Serial.println((log(GPIO_reason))/log(2), 0);
}
The micropython function machine.wake_reason() only returns "3" which is machine.EXT1_WAKE but not the pin number.
Thanks, Uwe
Re: GPIO wakeup enable
Hi Lixas,
Thanks for posting your example, it helped me to respond to any pin change while in light sleep.
One thing I don't understand is the use of idle() in this situation and your comment 'do NOT remove this statement'. I know that you often have to have a short delay after a print statement or it doesn't print it all out.
machine.idle()
Thanks for posting your example, it helped me to respond to any pin change while in light sleep.
Code: Select all
import esp32
from machine import Pin, lightsleep, wake_reason, idle
from time import sleep
btn1 = Pin(32, Pin.IN, Pin.PULL_DOWN) # Normally low, high when pressed
esp32.wake_on_ext0(pin = btn1, level = esp32.WAKEUP_ANY_HIGH)
#idle()
#print ('waiting 5 seconds')
#sleep(5) # do NOT remove this statement
print ('Going to sleep')
sleep(1)
lightsleep(10000) # 10 seconds
wakeReason = wake_reason()
print ('Wake Reason =', wakeReason)
print ('now get on with the rest of the program')
machine.idle()
Appreciate any clarification.Gates the clock to the CPU, useful to reduce power consumption at any time during short or long periods. Peripherals continue working and execution resumes as soon as any interrupt is triggered (on many ports this includes system timer interrupt occurring at regular intervals on the order of millisecond).
Re: GPIO wakeup enable
machine.idle() does one thing: calls taskYIELD()
taskYIELD() is from FreeRTOS in the ESP-IDF, and passes control from "this" task (the currently running one, aka micropython) back to the OS (FreeRTOS). This allows the OS time to switch to tasks that have otherwise queued up and need CPU time to complete. That might be switch to another thread (possibly related to micropython, maybe dealing with input/output, networking, etc) or possibly things that the RTOS itself needs to get done.
Basically anything that's queue'd up to get done can now complete before you put the MCU to sleep.
'gating the clock to the CPU' is saying 'passing control back to the OS'.
As for why (specifically) it's needed, I don't have a direct answer in the bit of digging I did, however, it's certainly related to "letting something happen before putting the CPU to sleep" and that something might be "correctly completing the configuration the wake interrupts".
You can set the interrupts whenever you want, though, so you don't need machine.idle() to use the interrupts. It's needed in the example to complete tasks before going to sleep, e.g. setting the interrupts and going to sleep in quick succession. I use the wake interrupts and don't use machine.idle() as I set them a long time before going to sleep.
Code: Select all
STATIC mp_obj_t machine_idle(void) {
taskYIELD();
return mp_const_none;
}
Basically anything that's queue'd up to get done can now complete before you put the MCU to sleep.
'gating the clock to the CPU' is saying 'passing control back to the OS'.
As for why (specifically) it's needed, I don't have a direct answer in the bit of digging I did, however, it's certainly related to "letting something happen before putting the CPU to sleep" and that something might be "correctly completing the configuration the wake interrupts".
You can set the interrupts whenever you want, though, so you don't need machine.idle() to use the interrupts. It's needed in the example to complete tasks before going to sleep, e.g. setting the interrupts and going to sleep in quick succession. I use the wake interrupts and don't use machine.idle() as I set them a long time before going to sleep.
Re: GPIO wakeup enable
Thank you for explaining why one might want to use idle(). Something else that did concern me was ... did the pin return to normal operation after if was used as a wakeup, without the idle() statement. My testing seemed to indicate that it did. I wonder if there is a proper way to ensure that the pin does return to normal operation.
It appears it would be safer to throw the idle() back-in as originally stated.
It appears it would be safer to throw the idle() back-in as originally stated.