Le deep sleep est le mode très basse consommation de l’ESP32 : le processeur et la radio sont coupés, la consommation tombe d’une dizaine de milliampères à une dizaine de microampères, et la puce ne se réveille qu’à un événement choisi (un délai, un bouton, un toucher). C’est ce qui rend l’ESP32 viable sur batterie : un capteur qui se réveille, mesure, envoie, puis se rendort passe l’essentiel de sa vie à ne presque rien consommer. La notion générale de gestion d’énergie est traitée dans deep sleep. Cette fiche en donne l’incarnation ESP32.

Cycle du deep sleep : la carte se réveille, travaille, arme une source de réveil puis s'endort ; le réveil suivant vient d'un timer, d'une broche externe ou d'un toucher, et redémarre la carte|640

À quoi ça sert ?

Le deep sleep répond à un besoin précis : fonctionner longtemps sur une petite batterie quand le système n’a rien à faire la plupart du temps.

  • Allonger l’autonomie d’un facteur énorme. Une station qui mesure toutes les 10 minutes peut dormir 99,9 % du temps. Le gain ne se joue pas sur la consommation active, mais sur celle du repos : passer de 20 mA à 10 µA au repos change l’autonomie d’une pile bouton de quelques jours à plusieurs mois.
  • Se réveiller au bon moment. Le réveil est déclenché par un timer (mesure périodique), un bouton/capteur (événement), ou un toucher (interaction), et la puce dort jusque-là.

Warning

Le réveil est un RESET, pas une reprise. Au réveil, l’ESP32 redémarre : setup() est rejoué depuis le début, le code placé après esp_deep_sleep_start() n’est jamais atteint, et toutes les variables ordinaires sont réinitialisées. Seule la mémoire RTC (voir plus bas) survit. C’est le contresens n°1 sur le deep sleep.

Réveil par timer (le plus courant)

Deux lignes : armer le timer, entrer en sommeil. Le délai est en microsecondes.

#define uS_PAR_S 1000000ULL          // microsecondes par seconde
 
void setup() {
  Serial.begin(115200);
  delay(100);                        // laisse le temps à l'USB de s'établir
 
  Serial.println("Reveil ! Je travaille...");
  // ... mesure, envoi ...
 
  esp_sleep_enable_timer_wakeup(10 * uS_PAR_S);  // dormir 10 s
  Serial.println("Je m'endors.");
  Serial.flush();                    // vide le port avant de couper
  esp_deep_sleep_start();            // au-delà : plus rien ne s'exécute
}
 
void loop() {}                       // jamais atteint en deep sleep

Tout le travail se fait dans setup() : à chaque réveil, la carte exécute setup(), fait sa tâche, se rendort. loop() reste vide. Ici, #define est légitime (constante d’échelle utilisée dans un calcul de durée). Pour des broches ou seuils, on préférera const.

Mémoire RTC : ce qui survit au sommeil

Pour conserver une information d’un réveil au suivant (un compteur, un état), on la place en mémoire RTC, alimentée pendant le sommeil, avec l’attribut RTC_DATA_ATTR :

RTC_DATA_ATTR int nombreReveils = 0;   // survit au deep sleep
 
void setup() {
  Serial.begin(115200);
  delay(100);
  nombreReveils++;                      // incrémente à chaque réveil
  Serial.print("Reveil n° ");
  Serial.println(nombreReveils);
 
  esp_sleep_enable_timer_wakeup(5 * 1000000ULL);
  esp_deep_sleep_start();
}
 
void loop() {}

Sans RTC_DATA_ATTR, nombreReveils repartirait de zéro à chaque réveil (puisque c’est un RESET). Avec, il s’accumule.

Exemple — Station de mesure périodique

Le motif type d’un capteur sur batterie : réveil toutes les 30 secondes, lecture d’un capteur analogique, affichage, compteur de cycles conservé, puis rendormissement.

#define uS_PAR_S 1000000ULL
const int CAPTEUR = 34;                 // ADC1
const uint64_t PERIODE_S = 30;          // intervalle entre deux mesures
 
RTC_DATA_ATTR int cycle = 0;            // conservé entre les réveils
 
void setup() {
  Serial.begin(115200);
  delay(100);
 
  cycle++;
  int mesure = analogRead(CAPTEUR);
  Serial.print("Cycle ");
  Serial.print(cycle);
  Serial.print(" — mesure = ");
  Serial.println(mesure);
  // ... ici : envoyer la mesure (Wi-Fi/BLE) avant de dormir ...
 
  esp_sleep_enable_timer_wakeup(PERIODE_S * uS_PAR_S);
  Serial.flush();
  esp_deep_sleep_start();
}
 
void loop() {}

Au moniteur série, on voit une ligne apparaître toutes les 30 secondes, le numéro de cycle s’incrémentant. Entre deux, la carte est en deep sleep : sur un module nu (sans la carte de développement), la consommation y est de l’ordre du microampère.

Chaque réveil étant un redémarrage, chaque ligne est précédée du journal de démarrage de la puce, omis ici :

Cycle 1 — mesure = 2043
Cycle 2 — mesure = 2051
Cycle 3 — mesure = 1998
Cycle 4 — mesure = 2012

Le numéro ne repart pas de 1 : c’est toute la démonstration de RTC_DATA_ATTR. Sans lui, les quatre lignes afficheraient Cycle 1.

Réveil par un événement externe

Au lieu (ou en plus) du timer, l’ESP32 peut se réveiller sur une broche :

  • esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, niveau) — réveil sur une broche (un bouton), au niveau 0 (LOW) ou 1 (HIGH).
  • esp_sleep_enable_ext1_wakeup(masque, mode) — réveil sur plusieurs broches à la fois.

Ces réveils n’acceptent que les broches RTC (GPIO0, 2, 4, 12-15, 25-27, 32-39). Une broche ordinaire ne réveille pas la puce. Après le réveil, esp_sleep_get_wakeup_cause() indique pourquoi la carte s’est réveillée (timer, ext0, touch…), pour réagir différemment selon la source.

Câblage du réveil par bouton : bouton entre GPIO33 et GND, résistance externe de 10 kΩ tirant GPIO33 vers 3V3, les tirages internes n'étant pas garantis pendant le sommeil|600

Pièges

Croire que le code reprend où il s’était arrêté. Le réveil est un RESET : setup() rejoué, loop() jamais atteint avant le sommeil, variables remises à zéro. Tout le travail va dans setup(), avant esp_deep_sleep_start().

Variable perdue entre deux réveils. Un compteur ou un état déclaré normalement repart de zéro à chaque réveil. Le déclarer RTC_DATA_ATTR pour qu’il survive.

Broche non-RTC pour un réveil externe. ext0/ext1 n’acceptent que les broches RTC. Une broche ordinaire est ignorée, et la carte ne se réveille jamais.

Bouton flottant en sommeil. Pendant le deep sleep, les résistances de tirage internes ne sont pas garanties. Un bouton de réveil exige une résistance externe (ou l’activation explicite du tirage RTC), sinon des réveils intempestifs sur du bruit.

Serial coupé trop tôt. Sans Serial.flush() avant esp_deep_sleep_start(), les derniers messages peuvent ne pas partir. Et un delay(100) en début de setup() laisse le temps à l’USB de se rétablir avant d’imprimer.

Consommation décevante sur carte de développement. La carte de dev (DevKit) garde sous tension sa puce USB-série, sa LED d’alimentation et son régulateur. Elle consomme bien plus que le microampère annoncé. La très basse consommation se mesure sur le module nu, pas sur le kit de dev.

Exercices

Exercice 1 — Réveil au bouton + cause du réveil

Configurez un réveil timer (toutes les 20 s) et un réveil bouton sur GPIO33. À chaque réveil, affichez pourquoi la carte s’est réveillée (timer ou bouton).

Exercice 2 — Estimer l'autonomie

Une carte (module nu) consomme 80 mA pendant 2 s d’activité (réveil, mesure, envoi Wi-Fi), puis 10 µA en deep sleep, avec un cycle toutes les 10 minutes. Estimez la consommation moyenne. Ordre de grandeur de l’autonomie sur une pile de 1000 mAh ?

Cas particulier — Light sleep

Entre le fonctionnement normal et le deep sleep existe le light sleep : la puce suspend le processeur mais conserve l’état (RAM, périphériques), et reprend l’exécution là où elle s’était arrêtée au réveil, sans RESET. La consommation est intermédiaire (quelques centaines de µA à quelques mA). On le choisit quand on veut économiser sans perdre le contexte (latence de réveil faible), là où le deep sleep impose de tout reconstruire à chaque cycle.

Raccrochage projet

  • Étape 4 de la phase de preuve de concept. Si le projet est alimenté sur batterie, valider tôt un cycle réveil → mesure → sommeil et mesurer la consommation réelle lève l’incertitude d’autonomie, souvent dimensionnante pour un objet connecté.
  • Dimensionnement de l’alimentation. L’estimation de consommation moyenne (cf. exercice 2) conditionne le choix de la batterie et entre dans le dossier technique.

Penser le système autour du cycle veille/réveil dès la conception (que faire au réveil, qu’est-ce qui doit survivre) évite de découvrir trop tard qu’une architecture « toujours active » condamne l’autonomie visée.

Aller plus loin

  • Deep sleep — la notion d’économie d’énergie par mise en veille (transverse).
  • Wi-Fi · Bluetooth LE — réveiller, échanger, se rendormir : le motif des objets connectés sur batterie.
  • ULP (Ultra Low Power coprocessor) — un cœur minuscule qui peut surveiller un capteur pendant que le processeur principal dort, et ne le réveiller qu’au seuil utile.
  • Documentation Sleep Modes d’Espressif — sources de réveil détaillées, mesures de consommation.

Voir aussi