The compiler error 'gpio_wakeup_enable' was not declared in this scope means your C/C++ build environment cannot find the function prototype required to configure an ESP32's GPIO pin to trigger a wake-up from light sleep, almost always caused by a missing #include "driver/gpio.h" header, an API deprecation in ESP-IDF v5.x, or compiling for a non-ESP32 architecture. In a physical circuit, failing to resolve this and properly route the wake-up interrupt prevents the Real-Time Clock (RTC) controller from monitoring the pin, meaning your battery-powered sensor node will either sleep forever or crash-loop, rapidly draining the battery.
Think of the ESP32's main CPU as the day-shift manager and the RTC controller as the night-shift security guard. When the chip goes to sleep, the manager goes home (powers down). The gpio_wakeup_enable function is the explicit set of instructions you hand to the security guard, telling them exactly which door (GPIO pin) to watch and what action (HIGH or LOW signal) should trigger an alarm to wake the manager back up. If you forget to hand over those instructions (the missing header or wrong API), the guard sits idle, and the manager never returns to work.
The Anatomy of the Scope Error and Sleep Mode Matrix
In C and C++, a function must be declared before it is used. The ESP32 Arduino core and ESP-IDF (Espressif IoT Development Framework) split hardware peripherals into distinct header files to save compilation memory. When you call gpio_wakeup_enable(gpio_num, level) without including the correct driver header, the compiler throws a scope error because it literally does not know the function exists.
However, the most dangerous trap for embedded developers is not just the compiler error itself, but what people commonly confuse it with. Makers frequently confuse light sleep GPIO wake-up with deep sleep wake-up functions. They attempt to use gpio_wakeup_enable and then immediately call esp_deep_sleep_start(). This compiles fine (once the header is added), but it fails in hardware: during deep sleep, the digital GPIO domain is completely powered off. Only the RTC domain remains alive. Therefore, a digital GPIO cannot wake the chip from deep sleep; you must use the EXT0 or EXT1 RTC-specific functions.
| Function | Required Header | Sleep Mode | Wake-up Source | RTC Domain Required? |
|---|---|---|---|---|
gpio_wakeup_enable() |
driver/gpio.h |
Light Sleep | Any digital GPIO | No |
esp_sleep_enable_gpio_wakeup() |
esp_sleep.h |
Light Sleep | Any digital GPIO (IDF v5+) | No |
esp_sleep_enable_ext0_wakeup() |
esp_sleep.h |
Deep Sleep | Single RTC GPIO only | Yes |
esp_sleep_enable_ext1_wakeup() |
esp_sleep.h |
Deep Sleep | Multiple RTC GPIOs (bitmask) | Yes |
Where You Meet This in Practice: The Cost of a Crash Loop
To understand why resolving this scope error and configuring the correct sleep function is critical, let us look at a worked numeric example involving a remote soil moisture sensor built on an ESP32-C3, powered by a standard 2500 mAh (2.5 Ah) 18650 LiFePO4 cell.
Target Deep Sleep Current: 10 µA (0.01 mA)
Active Awake Current: 120 mA (transmitting via WiFi/MQTT)
Awake Duration: 500 milliseconds (0.000138 hours)
If your firmware correctly compiles, configures esp_sleep_enable_ext0_wakeup() on an RTC pin, and enters deep sleep, the chip draws 10 µA. The theoretical battery life is 2.5 Ah / 0.00001 A = 250,000 hours, or roughly 28.5 years. (In reality, battery self-discharge and environmental factors cap this at about 2 to 3 years, which is still excellent).
Now, assume you ignored the scope error, stripped out the sleep logic to force a compile, or misconfigured the wake-up pin so the chip fails to wake and instead relies on a 5-second watchdog timer reset loop. The chip wakes up, draws 120 mA for 500ms, fails to find a wake-up trigger, and resets. The average current draw becomes approximately 60 mA. At 60 mA, your 2500 mAh battery will be completely dead in 41.6 hours. A missing header file or misunderstood API literally turns a multi-year deployment into a two-day failure.
Step-by-Step Resolution and Code Fixes
When the compiler halts with 'gpio_wakeup_enable' was not declared in this scope, follow this decision path to fix it based on your specific development environment.
Scenario A: The Missing Header (Arduino IDE & ESP-IDF v4.x)
If you are using the Arduino-ESP32 core or an older ESP-IDF v4.x environment, the function exists but is hidden behind the GPIO driver header. Add the include at the very top of your sketch.
#include "driver/gpio.h"
#include "esp_sleep.h"
void setup() {
// Configure GPIO 33 as input
pinMode(33, INPUT_PULLUP);
// Enable wake-up on LOW state for Light Sleep
gpio_wakeup_enable((gpio_num_t)33, GPIO_INTR_LOW_LEVEL);
esp_sleep_enable_gpio_wakeup();
}
Scenario B: ESP-IDF v5.x API Migration
Espressif heavily refactored the sleep APIs in ESP-IDF v5.0. The standalone gpio_wakeup_enable function was largely superseded by the unified sleep configuration functions to prevent the exact light-sleep vs. deep-sleep confusion mentioned earlier. If you are on IDF v5.x or Arduino-ESP32 core v3.x, replace the deprecated calls with the unified sleep API.
#include "esp_sleep.h"
#include "driver/gpio.h"
void setup() {
// IDF v5.x unified light sleep wake-up configuration
esp_sleep_enable_gpio_wakeup();
gpio_wakeup_enable((gpio_num_t)33, GPIO_INTR_LOW_LEVEL);
// Note: For deep sleep, you MUST use EXT0/EXT1 instead:
// esp_sleep_enable_ext0_wakeup((gpio_num_t)33, 0);
}
Scenario C: Architecture Mismatch (ESP8266 vs ESP32)
The gpio_wakeup_enable function is specific to the ESP32 family's RTC architecture. If you have an ESP8266 board (like the NodeMCU v3 or Wemos D1 Mini) selected in your IDE's board manager, the compiler will throw this scope error because the ESP8266 uses a completely different wake-up mechanism (ESP.deepSleep(microseconds) tied strictly to the RST pin). Verify your board selection and ensure you are compiling for an ESP32 variant.
Hardware Edge Cases: RTC vs Digital GPIOs
Even after you resolve the compiler error, your circuit might still refuse to wake up. This is where hardware design meets firmware configuration. According to the Espressif GPIO API Reference, not all pins are created equal when the main power domains are shut down.
Critical Hardware Warning: If you are designing a custom PCB for deep sleep wake-up, you cannot use GPIO 2, 4, 5, 12-33 for esp_sleep_enable_ext0_wakeup on the original ESP32-WROOM-32. You must route your wake-up button or sensor interrupt to the RTC-capable pins: GPIO 34, 35, 36, or 39.
Furthermore, GPIO 34-39 are input-only pins on the original ESP32. They do not have internal pull-up or pull-down resistors. If you configure esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, 0) to wake on a LOW signal, but you forget to solder a physical 10kΩ external pull-up resistor to the 3.3V rail on your breadboard or PCB, the pin will float. The RTC controller will read random electromagnetic noise as a LOW signal, causing the ESP32 to wake up instantly, read the sensor, go back to sleep, and immediately wake up again—triggering the exact 41-hour battery death loop described in our numeric example.
Always verify your physical pull-up/pull-down resistor network with a multimeter before flashing the final sleep firmware. Measure the resistance between the wake-up GPIO and the 3.3V/GND rail; it should read exactly the value of your physical resistor (e.g., 10.0kΩ) when the chip is unpowered.






