From the old topic M5paper touchscreen wakeup from sleep I got the following code to go into light sleep with wakeup on a touchscreen event:
esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, LOW); // TOUCH_INT
esp_light_sleep_start();
However, the device immediately wakes with RTC_IO
as reason. If I comment out the esp_sleep_enable_ext0_wakeup
line, it stays in light sleep. I have no idea what is going on. The original (linked) topic mentions WiFi as a problem source, but I don't use WiFi in this project and so it is never enabled.
I tried gpio_pullup_en(GPIO_NUM_36);
before going to sleep but it makes no difference. I initialize the device using M5.begin(true, false, false, true, false);
so the touch screen should be enabled and active.
Any thoughts?
EDIT: maybe worth noting: this happens both when using PlatformIO in VSCode as well as with Arduino IDE. I can reproduce it with just this sketch as an .ino, which shows "Wakeup <x>" with a continuously increasing number as fast as it can:
#include <M5EPD.h>
M5EPD_Canvas canvas(&M5.EPD);
void setup(){
M5.begin();
M5.EPD.SetRotation(90);
M5.EPD.Clear(true);
M5.RTC.begin();
canvas.createCanvas(540, 50);
canvas.setTextSize(3);
canvas.drawString("Hello World", 10, 20);
canvas.pushCanvas(0, 960/2 - 50/2, UPDATE_MODE_DU4);
}
void light_sleep_with_touch_wakeup() {
esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, LOW); // TOUCH_INT
esp_light_sleep_start();
}
void loop(){
static char buffer[128];
static int i = 0;
light_sleep_with_touch_wakeup();
snprintf(buffer, sizeof(buffer), "Wakeup %d", ++i);
canvas.clear();
canvas.drawString(buffer, 10, 20);
canvas.pushCanvas(0, 960/2 - 50/2, UPDATE_MODE_DU4);
}
EDIT2: I dug a little deeper, opened up the M5Paper and probed the INT pin with a scope. Apparently it's not an ESP32 issue but a GT911 issue! I guess I must be missing some configuration for it. When I'm not touching it, it pulses high at ~24Hz. When I touch it, it pulses at ~48Hz:
EDIT3: Aha, I finally cracked it! The scope plots made me look up the datasheet of the GT911, which states the following:
The timing sequence for GT911 interrupt signal output (take the rising-edge triggered interrupt for example.
The timing for falling-edge triggered interrupt is similar to this one):
- In standby mode, INT outputs low level.
- Output rising edge when any coordinate is updated.
- After output rising edge in step 2, INT will keep outing high level until next cycle (the cycle is configurable
by setting Refresh_Rate). The host is supposed to finish the reading within one cycle and reset buffer status
(0x814E) to 0.- After output rising-edge in step 2, if the host fails to finish reading coordinates within one cycle, GT911 will
output one INT pulse again instead of update coordinates even if it detects that the coordinate is updated.- If the host still fails to read coordinate, GT911 will keep outputting INT pulse.
In other words, if you don't read the coordinates from the touch screen, it will keep outputting an interrupt until you do
So the solution ended up being to put M5.TP.flush()
before going to sleep (or calling M5.TP.update()
anywhere before going to sleep, which you would need to do anyway to respond to touch events).
Case closed :-)