Ignorer et passer au contenu

Livraison offerte à partir de 50€ d'achats, livrée sous 48h !

Livraison à partir de seulement 2.50€ !

Contents Menu Expand Light mode Dark mode Auto light/dark mode

Économiser de l’énergie sur l’ESP32 grâce au Deep Sleep

(Mis à jour le 20/10/2022)

L’ESP32 possède différents modes d’énergie, qui permet de réduire la consommation en désactivant certaines fonctionnalités. C’est un peu comme lorsqu’on met en veille un appareil pour économiser de l’énergie. Parmi ces modes, le plus connu est le Deep Sleep dans lequel l’ESP32 est dans un état de veille profonde.

modes énergies esp32 fiche technique

Consommation des différents modes de l’ESP32, d’après la datasheet

Pendant ce mode, l’ESP32 peut effectuer des tâches simples et se faire réveiller pour fonctionner normalement.

Note

On emploie le terme “Deep Sleep” un peu à outrance pour désigner le mode le plus économe en énergie de l’ESP32, alors que c’est le mode “Hibernation” qui consomme le moins.

À quoi sert le mode Deep Sleep ?

Ce mode d’économie d’énergie est utile quand l’ESP32 est alimenté par batterie et que l’ESP32 « fonctionne » ponctuellement : par exemple, lire une valeur d’un capteur et l’envoyer par WiFi toutes les 10 minutes. Si l’ESP32 est allumé 24h/24, la batterie sera très vite déchargée. Avec le mode Deep Sleep, les batteries dureront beaucoup plus longtemps.

Le mode Deep Sleep plonge l’ESP32 dans un état primitif. En effet, en mode Deep Sleep, les 2 CPU de l’ESP32 ne fonctionnent plus et c’est le processeur ULP (Ultra Low Processor) qui prend le relais. C’est un processeur qui consomme très peu d’énergie et qui peut exécuter certaines actions. La Flash et la RAM ne sont plus alimentées non plus, seule la mémoire RTC est encore alimentée et peut être utilisée. Le Wifi et le Bluetooth sont aussi bien sûrs désactivés.

Avertissement

La consommation de l’ESP32 de l’ordre du µA, sera légèrement différente en fonction des tâches effectuées dans ce mode et de la source de réveil choisie.

Les sources de réveil du mode Deep Sleep de l’ESP32

Après avoir mis l’ESP32 en mode Deep Sleep, il y a plusieurs moyens de le réveiller :

  • Utiliser un timer (chronomètre) interne pour réveiller l’ESP32 à un moment choisi (réveil interne)

  • Utiliser les capteurs capacitifs tactiles

  • Utiliser les pins RTC

Note

On peut combiner différentes sources de réveil.

Il est aussi possible d’activer le mode Deep Sleep sans avoir configuré de sources de réveil. Dans ce cas l’ESP32 sera indéfiniment en mode Deep Sleep jusqu’à ce qu’on fasse un reset manuel, en appuyant sur le bouton EN/RST (ou en reflashant la carte). On ne peut donc pas bloquer l’ESP32 avec le mode Deep Sleep.

Pour des informations plus poussées sur le fonctionnement du Deep Sleep de l’ESP32, je vous encourage à consulter la documentation officielle sur ce sujet .

Mettre l’ESP32 en mode Deep Sleep avec du code Arduino

Lorsqu’on veut utiliser le mode Deep Sleep, il faut penser à :

  • Configurer le type de sources de réveil de l’ESP32 : La consommation de l’ESP32 de l’ordre du µA, sera légèrement différente de la source de réveil choisie.

  • Choisir éventuellement quels périphériques vous voulez éteindre ou garder pendant le mode Deep Sleep, par exemple, les broches qui doivent rester allumées. Par défaut, l’ESP32 éteint tous les périphériques qui ne sont pas nécessaires pour détecter la demande de réveil.

  • Utiliser la fonction esp_deep_sleep_start() pour rentrer dans le mode Deep Sleep.

Avertissement

Les mesures effectuées ont été réalisées avec la carte uPesy ESP32 Low Power Devkit , une carte optimisée pour une très faible consommation de courant lorsque l’ESP32 est en Deep Sleep. Si vous avez une carte ESP32 “générique” la consommation sera probablement plus élevée.

Note

Le même modèle uPesy ESP32 Low Power Devkit a été utilisé pour pouvoir comparer la consommation en fonction des sources de réveil. En effet, les valeurs varient de quelques µA en fonction des modèles.

Utiliser un Timer comme source de réveil

C’est la manière de réveiller l’ESP32 qui consomme le moins. Il ne reste que le RTC Timer d’allumé. C’est un compteur qui déclenche une alarme (comme un réveil) dont la période est configurable.

consommation hibernation ESP32

Consommation de 11.5µA en mode timer alimenté sous 4.2V

Voici un exemple code qui réveille l’ESP32 toutes les 5 secondes avec un timer comme source de réveil :

#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  5

RTC_DATA_ATTR int bootCount = 0;

void print_wakeup_reason(){
   esp_sleep_wakeup_cause_t source_reveil;

   source_reveil = esp_sleep_get_wakeup_cause();

   switch(source_reveil){
      case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Réveil causé par un signal externe avec RTC_IO"); break;
      case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Réveil causé par un signal externe avec RTC_CNTL"); break;
      case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Réveil causé par un timer"); break;
      case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Réveil causé par un touchpad"); break;
      default : Serial.printf("Réveil pas causé par le Deep Sleep: %d\n",source_reveil); break;
   }
}

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

   ++bootCount;
   Serial.println("----------------------");
   Serial.println(String(bootCount)+ "eme Boot ");

   //Affiche la raison du réveil
   print_wakeup_reason();

   //Configuration du timer
   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
   Serial.println("ESP32 réveillé dans " + String(TIME_TO_SLEEP) + " seconds");

   //Rentre en mode Deep Sleep
   Serial.println("Rentre en mode Deep Sleep");
   Serial.println("----------------------");
   delay(100);
   esp_deep_sleep_start();
   Serial.println("Ceci ne sera jamais affiché");
}

void loop(){
}

La fonction print_wakeup_reason() affiche la source de réveil de l’ESP32. Lors du 1er boot de l’ESP32, le réveil n’a pas été causé par le Deep Sleep mais par le « Hard resetting via RTS pin… » sur l’Arduino IDE. Ensuite lors des boots suivants, l’ESP32 est réveillé du deep sleep grâce à un timer toutes les 5 secondes.

ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
----------------------
1eme Boot
Réveil pas causé par le Deep Sleep: 0
ESP32 réveillé dans 5 seconds
Rentre en mode Deep Sleep
----------------------
ets Jun  8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
----------------------
2eme Boot
Réveil causé par un timer
ESP32 réveillé dans 5 seconds
Rentre en mode Deep Sleep
----------------------

On peut changer la durée du Deep Sleep en modifiant le timer avec la fonction esp_sleep_enable_timer_wakeup() .

Utiliser un seul pin GPIO comme source de réveil

On peut aussi utiliser un pin GPIO avec un bouton-poussoir pour réveiller l’ESP32 du Deep Sleep. C’est typiquement ce que font les appareils qui se réveillent instantanément quand on appuie sur un bouton (les téléphones par exemple).

consommation deep sleep ext0

Consommation de 13.5µA en mode deep-sleep alimenté sous 4.2V

Le pic correspond à la consommation de l’ESP32 lorsqu’il se réveille. La consommation est légèrement plus importante qu’avec un timer.

schéma des broches de l’ESP32 complet

Pinout de la carte uPesy ESP32 Wroom Devkit

Avertissement

On ne peut utiliser que les pins RTC_GPIO (encart en bleu clair)

Dans cet exemple, on utilise un bouton-poussoir avec une résistance pulldown externe relié au pin 33 :

Schéma du câblage d’un bouton en pull-down

Reveil de l’ESP32 via un bouton

Schéma du câblage d’un bouton en pull-down

Réveil de l’ESP32 via un bouton (version breadboard)

RTC_DATA_ATTR int bootCount = 0;

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

   ++bootCount;
      Serial.println("----------------------");
      Serial.println(String(bootCount)+ "eme Boot ");

   //Affiche la source du reveil
      print_wakeup_reason();

   //Configure le GPIO33 comme source de réveil quand la tension vaut 3.3V
   esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,HIGH);

      //Rentre en mode Deep Sleep
      Serial.println("Rentre en mode Deep Sleep");
      Serial.println("----------------------");
      esp_deep_sleep_start();
}

void loop(){}

void print_wakeup_reason(){
   esp_sleep_wakeup_cause_t source_reveil;

   source_reveil = esp_sleep_get_wakeup_cause();

   switch(source_reveil){
      case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Réveil causé par un signal externe avec RTC_IO"); break;
      case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Réveil causé par un signal externe avec RTC_CNTL"); break;
      case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Réveil causé par un timer"); break;
      case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Réveil causé par un touchpad"); break;
      default : Serial.printf("Réveil pas causé par le Deep Sleep: %d\n",source_reveil); break;
   }
}

Une interruption EXT0 est générée quand on appuie sur le bouton et réveille l’ESP32

On obtient dans le moniteur série :

ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
----------------------
1eme Boot
Réveil pas causé par le Deep Sleep: 0
Rentre en mode Deep Sleep
----------------------
ets Jun  8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
----------------------
2eme Boot
Réveil causé par un signal externe avec RTC_IO
Rentre en mode Deep Sleep
-----------------

Utiliser plusieurs pins GPIO pour réveiller l’ESP32

On peut aussi utiliser plusieurs broches GPIO pour déclencher le réveil de l’ESP32 quand certaines conditions sont remplies :

  • ESP_EXT1_WAKEUP_ANY_HIGH : L’ESP32 se réveille quand toutes les broches GPIO choisies sont à l’état bas

  • ESP_EXT1_WAKEUP_ALL_LOW : L’ESP32 se réveille quand une des broches GPIO choisies est à l’état haut

La consommation est la même qu’avec une seule broche GPIO.

La configuration de ce mode est un peu plus compliquée, car il faut faire un masquage de bits. On crée un masque où la position des bits du masque correspond aux numéros des broches. Supposons que l’on choisit les broches 27, 33 et 36, alors on crée un masque binaire ou les positions 27 , 33 et 36 seront des 1, et les autres des 0 :

Cette section est réservée aux abonnés. Il vous reste 86% à découvrir.

Devenir membre premium

Déjà abonné ? Connectez-vous

Utiliser un Touchpad comme source de réveil

C’est la source de réveil qui consomme la plus :

consommation deep sleep capteur capacitif

Consommation de 20µA en mode deep-sleep alimenté sous 4.2V

Le processeur ULP s’allume 40 fois par seconde pour mesurer la capacité du capteur capacitif : cela génère des pics de courants de l’ordre de 400µA.

deep sleep capteur capacitif pics

Zoom sur les pics de courants lors pour la mesure du touchpad avec l’ESP32 en Deep Sleep

Le circuit est constitué d’un seul fil branché sur la broche GPIO4 , identique à celui-ci proposé dans l’article qui explique le fonctionnement des capteurs capacitifs de l’ESP32 . Voici le code utilisé pour réveiller l’ESP32 avec les touchpads :

#define seuil 30 //Seuil de détection pour le capteur capacitif

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;

void fonction_isr(){
}

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

   ++bootCount;
   Serial.println("----------------------");
   Serial.println(String(bootCount)+ "eme Boot ");

   //Affiche la source du reveil et le numéro du touchpad
   print_wakeup_reason();
   print_wakeup_touchpad();

   //Configuration d'une interruption pour le touchpad T0 (GPIO4)
   touchAttachInterrupt(T0, fonction_isr, seuil);

   //Active le réveil par les touchpads
   esp_sleep_enable_touchpad_wakeup();

   //Rentre en mode Deep Sleep
   Serial.println("Rentre en mode Deep Sleep");
   Serial.println("----------------------");
   esp_deep_sleep_start();
}

void loop(){
}


void print_wakeup_reason(){
   esp_sleep_wakeup_cause_t source_reveil;

   source_reveil = esp_sleep_get_wakeup_cause();

   switch(source_reveil){
      case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Réveil causé par un signal externe avec RTC_IO"); break;
      case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Réveil causé par un signal externe avec RTC_CNTL"); break;
      case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Réveil causé par un timer"); break;
      case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Réveil causé par un touchpad"); break;
      default : Serial.printf("Réveil pas causé par le Deep Sleep: %d\n",source_reveil); break;
   }
}


void print_wakeup_touchpad(){
   touch_pad_t pin;
   touchPin = esp_sleep_get_touchpad_wakeup_status();
   switch(touchPin){
      case 0  : Serial.println("Fil touché au GPIO 4"); break;
      case 1  : Serial.println("Fil touché au GPIO 0"); break;
      case 2  : Serial.println("Fil touché au GPIO 2"); break;
      case 3  : Serial.println("Fil touché au GPIO 15"); break;
      case 4  : Serial.println("Fil touché au GPIO 13"); break;
      case 5  : Serial.println("Fil touché au GPIO 12"); break;
      case 6  : Serial.println("Fil touché au GPIO 14"); break;
      case 7  : Serial.println("Fil touché au GPIO 27"); break;
      case 8  : Serial.println("Fil touché au GPIO 33"); break;
      case 9  : Serial.println("Fil touché au GPIO 32"); break;
      default : Serial.println("Réveil pas causé les touchpads"); break;
   }
}

Effacement de la RAM

Quand le mode Deep Sleep est activé, le CPU et la RAM ne sont plus alimentés. Donc quand l’ESP32 se réveille, toutes les variables sauvegardées dans la RAM sont effacées. Heureusement, il existe une mémoire RAM RTC qui reste allumée pendant le Deep Sleep. Pour stocker des variables dans cette mémoire, il faut rajouter l’attribut RTC_DATA_ATTR .

Par exemple, la variable qui stocke le nombre de redémarrage de l’ESP32 dans les exemples est stockée dans cette mémoire.

RTC_DATA_ATTR int bootCount = 0;

Optimiser au maximum la consommation en Deep Sleep

Puisqu’on parle d’économiser du courant au µA près, chaque détail compte. Même s’il est en pratique impossible d’avoir les consommations indiquées dans la datasheet, car les mesures indiquées sont idéales et surtout que l’ESP32 n’est pas le seul composant sur la carte qui consomme de l’énergie, on peut encore gagner quelques µA en fonction de votre projet.

D’ailleurs à ce stade, il est plus pertinent d’utiliser directement le framework ESP-IDF en C (pas de code Arduino ou MicroPython), pour pouvoir modifier la configuration de l’ESP32 via le menuconfig , qui génère le fichier sdkconfig.h .

Cette section est réservée aux abonnés. Il vous reste 89% à découvrir.

Devenir membre premium

Déjà abonné ? Connectez-vous