🛠 Deep sleep sur batterie avec réveil par GPIO16
Objectives
Transform the ESP8266-ESP-12E into a battery-powered sensor: in deep sleep, the chip consumes around ten microamperes, compared to several tens of milliamperes during Wi-Fi operation, enabling battery life of several months. Wake-up is handled by the internal RTC timer, and the mandatory wiring GPIO16 → RST also allows for external wake-up (GPIO16 generates a pulse that restarts the module via the reset pin). Crucial point: deep sleep erases all RAM — no counters or variables survive; we use RTC memory (RTC_SLOW_MEM) to preserve state between wake-ups, and everything must be reinitialized at each startup.
Hardware
- 1 bare ESP8266-ESP-12E module (complete NodeMCU boards consume 30 to 50 mA too much due to the regulator and USB bridge)
- 1 LiPo 3.7 V battery + low-power 3.3 V LDO regulator (type XC6206, Iq ≈ 1 µA)
- 1 wire connecting GPIO16 to RST (mandatory for wake-up)
- 100 µF capacitor at the regulator output
- Test LED to be DISCONNECTED for battery life measurements (it would consume 5 mA continuously)
Complete code
#include <ESP8266WiFi.h>
// Memoire RTC : survit au deep sleep (RAM classique : effacee !)
RTC_DATA_ATTR uint32_t compteur = 0;
extern "C" {
#include "user_interface.h"
}
void setup {
Serial.begin(115200);
compteur++;
Serial.printf("\nReveil n°%u raison: %s\n", compteur,
user_rtc_get_reset_reason == POWERON_RESET ? "mise sous tension" : "deep sleep");
// --- Travail court : lecture capteur, mesure batterie ---
uint32_t vbat = ESP.getVcc; // mV (si calibration AD0 faite)
Serial.printf("Vcc=%u mV\n", vbat);
// Optionnel : publier en Wi-Fi puis attendre 1 s que le paquet parte
// WiFi.mode(WIFI_STA); WiFi.begin(SSID, PASS);
// unsigned long t0 = millis;
// while (WiFi.status != WL_CONNECTED && millis - t0 < 8000) delay(50);
// ... publish MQTT ...
// WiFi.forceSleepBegin; // radio off avant de dormir
Serial.println("Endormissement 30 s (GPIO16 doit etre cablee a RST)");
Serial.flush;
delay(50);
ESP.deepSleep(30 * 1000000ULL); // 30 s ; 0 = attendre un reveil externe
}
void loop {
// Jamre atteint : deepSleep ne revient jamais
}
Expected verification
Unplug/replug: the counter restarts at 1 (RTC memory is also lost without power), then the module displays "Wake-up n°1" and sleeps. Approximately every 30 seconds, a new wake-up appears with the counter incremented (2, 3, 4...) while the module has not been touched — proof that the RTC timer and the GPIO16→RST wire are working. With a multimeter in series with the battery, the current should drop to a few hundred µA on average (excluding the dev board's regulator). With deepSleep(0), the module only wakes up if you briefly connect RST to ground.
Common errors
- Forgetting the GPIO16 → RST wire: the RTC timer expires but no one restarts the module, leaving it asleep forever.
- Relying on a standard variable to count wake-ups: RAM is erased, only RTC_DATA_ATTR (RTC_SLOW_MEM, 512 bytes) survives.
- Testing with an LED on GPIO2: it draws 5 mA continuously and ruins battery life; GPIO2 is also sensitive during boot.
- Using a complete NodeMCU board "to measure battery life": the onboard regulator and USB bridge consume much more than the module itself.
- Using deepSleep with a Wi-Fi transmission delay that is too short: the last packets are lost, leave ~1 s or disable the radio with forceSleepBegin before sleeping.
- GPIO16 has no interrupt, PWM, or I2C capabilities: do not try to use it for anything other than wake-up.
Other tutorials for this board
Code examples for this board
clignotante.inoArduinobouton-led.inoArduinorespiration.inoArduinodht11.inoArduinoluxmetre.inoArduinoserveur-web.inoArduino