ESP32/Sleep and wake-up/71. Waking on a pin or a touch
Your chip
Your language
Sleep and wake-up · 71 of 81

Waking on a pin or a touch

Three ways to wake a sleeping chip from the outside — one pin, several pins, or a touch pad — and the reason a board that never wakes is nearly always a pin that was never eligible.

/esp32/gpio-and-touch-wake-up · arduino · S3

Only some pins are eligible

Pins that can wake a sleeping chip
GPIO 33 works
Wake source
Chosen pin
GPIO 33
Eligible pins
16
This one
wakes
ext0 — one pin. One RTC pin, one level. It can hold an internal pull-up while the chip sleeps, which is the reason to prefer it for a single button.

While the chip is in deep sleep, most of it has no power — including most of the GPIO block. The pins that can still notice anything are the ones wired into the RTC power domain, and on the classic ESP32 that is sixteen of them.

Ask any other pin to wake the chip and the call returns an error code, the board goes to sleep, and it never comes back. From the outside that looks exactly like a dead board, which is why this is worth checking before anything else.

Which of the three

ext0 — one pin, one level, and it can ask the RTC to hold an internal pull-up while asleep. That last part is why it is the right choice for a single button: no external resistor.

ext1 — a bitmask of pins, waking on any-high or all-low. It works in hibernation, where ext0 does not, and it tells you which pin fired. It cannot hold internal pull-ups, so every pin in the mask needs a physical resistor.

touch — a pad, a threshold, no moving parts and nothing to wear out. Only on chips with touch hardware; the C3 and C6 have none and the call quietly does nothing there. It also keeps the RTC peripherals powered, so it rules out hibernation.

Hold the pin during sleep

If a pin was an output driving something before the sleep, its state is not kept unless the RTC is asked to hold it. rtc_gpio_hold_en() freezes it at its current level for the duration; gpio_hold_dis() on the next boot releases it.

Without that, a relay or a MOSFET gate driven high before sleeping goes floating the instant the chip powers down — which is a class of "it turns itself off overnight" bug that is very hard to see.

Say why it woke

esp_sleep_get_wakeup_cause() is one call and it changes what the sketch should do. A timer wake is a scheduled reading; a button wake is a user standing there waiting. Handling them identically is the commonest reason a battery remote feels slow.

On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

ext0 for a single button, ext1 for several. Both need RTC-capable pins, and ext1 needs external resistors because it cannot hold a pull-up while asleep.

wakepin.ino
#include <esp_sleep.h>
#include <driver/rtc_io.h>

#define BTN GPIO_NUM_33
#define MASK ((1ULL << GPIO_NUM_32) | (1ULL << GPIO_NUM_33))

void setup() {
  Serial.begin(115200);
  delay(100);

  switch (esp_sleep_get_wakeup_cause()) {
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("woken by the button on GPIO 33"); break;
    case ESP_SLEEP_WAKEUP_EXT1:
      Serial.printf("woken by mask %llx\n", esp_sleep_get_ext1_wakeup_status()); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD:
      Serial.printf("woken by pad %d\n", esp_sleep_get_touchpad_wakeup_status()); break;
    default:
      Serial.println("cold boot"); break;
  }

  // One pin, active low, with the RTC holding the pull-up while asleep.
  rtc_gpio_pullup_en(BTN);
  rtc_gpio_pulldown_dis(BTN);
  esp_sleep_enable_ext0_wakeup(BTN, 0);

  // Or several, waking when any of them goes high. No internal pull-ups here.
  // esp_sleep_enable_ext1_wakeup(MASK, ESP_EXT1_WAKEUP_ANY_HIGH);

  Serial.flush();
  esp_deep_sleep_start();
}

void loop() {}

esp_sleep_get_ext1_wakeup_status returns a mask of which pin fired. Without it you know the board woke and not what woke it, which for a three-button remote is the only interesting question.

When it does not work

The button never wakes the board

The pin is probably not in the RTC power domain. Only some GPIOs are, the rest are unpowered while the chip sleeps, and the enable call returns an error most sketches never check. Pick from the eligible list.

It wakes immediately, over and over

The pin is floating, or already at the trigger level when you sleep. ext1 has no internal pull-ups while asleep, so every pin in the mask needs a real resistor. Read the pin before sleeping and wait for it to settle.

One press wakes it two or three times

Switch bounce, seen by hardware that reacts in microseconds. Wake, then wait a few tens of milliseconds and check the pin is still pressed before treating it as real.

Touch wake works and the current is twice what it should be

Touch needs the RTC peripherals powered to notice a touch, so it rules out hibernation. Roughly 10 µA rather than 5 µA is the price, which is usually worth it and should be a decision rather than a surprise.

Where this goes next

The board woke up. Three ways to have left yourself a note, and only one of them still says anything after a power cut.

What survives deep sleep

Edit this page — content/esp32/gpio-and-touch-wake-up.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum