L’ESP32 permet de gérer très finement l’alimentation des différents composants du processeur pour optimiser la durée de vie pour les projets d’objets connectés fonctionnant sur batterie. Dans ce tutoriel, nous allons apprendre comment mettre en sommeil léger (Light Sleep) ou profond (Deep Sleep) le processeur ainsi que les principales méthodes de réveil. Minuteur (Timer), à l’aide d’une touche tactile capacitive (Touch Pad), réveil externe à l’aide d’une (ext0) ou plusieurs broches (ext1) RTC.
Contrairement à l’ESP8266 qui nécessite un câblage particulier pour activer le mode Deep-Sleep, tout peut se faire par programmation avec l’ESP32.
Sommaire
- 1 Les différents modes d’alimentation de l’ESP32
- 2 Remarques sur le WiFi et le bluetooth
- 3 Les broches du GPIO RTC et Touch permettant de sortir de veille l’ESP32
- 4 Comment réveiller un ESP32 ?
- 5 Compatibilité des méthodes de réveil en fonction du type de sommeil
- 6 Réveiller l’ESP32 de veille à l’aide d’un Minuteur (Timer)
- 7 Comment connaître l’origine du réveil ?
- 8 Réveiller l’ESP32 de veille une touche tactile
- 9 Réveil externe
Les différents modes d’alimentation de l’ESP32
Il est possible d’optimiser finement l’alimentation de chaque fonction de l’ESP32 pour économiser la batterie. Pour cela, L’ESP32 dispose de 5 modes de fonctionnement que voici.
Active mode fonctionnement normal
GPIO | WiFi | Bluetooth | CPU | ULP | RTC | Consommation* |
95 ~ 240 mA |
Modem Sleep Mode le processeur est opérationnelle. Les fonctions radio Wi-Fi et Bluetooth sont désactivées. Il est possible de réduire la consommation en limitant à un seul Core et en baissant la fréquence du CPU à 80MHz.
Utiliser les méthodes suivante pour interrompre les fonctions Modem
- Arrêter le modem Bluetooth : esp_bluedroid_disable() ou esp_bt_controller_disable()
- Arrêter le modem WiFi esp_wifi_stop()
GPIO | WiFi | Bluetooth | CPU | ULP | RTC | Consommation* |
20 ~ 68 mA |
Light Sleep Mode le processeur est en pause. La mémoire RTC et les périphériques RTC (liste), ainsi que le coprocesseur ULP fonctionnent. Tout événement (MAC, hôte, minuterie RTC ou interruptions externes) pourra réveiller la puce.
La méthode esp_light_sleep_start()permet de mettre en sommeil léger le processeur et les périphériques suivant ce schéma.
GPIO | WiFi | Bluetooth | CPU | ULP | RTC | Consommation* |
0,8 mA | ||||||
RTC uniquement | Core en pause |
Deep sleep Mode uniquement la mémoire RTC et les périphériques RTC (liste) sont sous tension. Les données de connexion Wi-Fi et Bluetooth sont stockées dans la mémoire RTC. Le coprocesseur ULP est fonctionnel.
La méthode esp_deep_sleep_start()permet de mettre en sommeil profond le processeur et les périphériques suivant ce schéma.
GPIO | WiFi | Bluetooth | CPU | ULP | RTC | Consommation* |
10 ~ 150 μA | ||||||
RTC uniquement |
Hibernation La mémoire de récupération RTC est mise hors tension. Un seul minuteur RTC sur l’horloge lente et certains GPIO RTC sont actifs. Le minuteur RTC ou les GPIO RTC peuvent sortir la puce du mode Hibernation.
GPIO | WiFi | Bluetooth | CPU | ULP | RTC | Consommation* |
1 μA | ||||||
RTC uniquement | x1 |
Les modes sont disponibles pour les versions suivantes des SoC ESP32 : ESP32-D0WD-V3, ESP32-D0WDQ6-V3, ESP32-D0WD, ESP32-D0WDQ6, ESP32-D2WD, ESP32-S0WD et ESP32-U4WDH.
(*) Consommation énergétique indicative. La consommation dépend fortement de la charge du CPU (ce que fait le programme), la fréquence et l’utilisation des fonctions radio (WiFi, Bluetooth).
Vous pouvez comparer les cinq modes différents sur le tableau suivant de la fiche technique ESP32 Espressif.
Consommation d’énergie en fonction du mode d’alimentation, page 23 de la documentation technique.
Lorsque le Mode Active est sélectionné (fonctionnement par défaut), le tableau 15 donne une estimation de la consommation énergétique en fonction du type de communication (WiFi ou Bluetooth) en emission ou en réception.
Bien évidemment, c’est une enveloppe grossière qui dépend fortement du projet.
Consommation électrique moyenne en fonction du type de communication (en réception et émission). Table 15 de la documentation technique.
Remarques sur le WiFi et le bluetooth
Avant d’entrer dans un sommeil profond ou en sommeil léger, les applications doivent désactiver le WiFi et BT en utilisant des appels appropriés (esp_bluedroid_disable(), esp_bt_controller_disable(), esp_wifi_stop()). Les connexions WiFi et BT ne seront pas maintenues en veille profonde ou en veille légère, même si ces fonctions ne sont pas appelées.
Les broches du GPIO RTC et Touch permettant de sortir de veille l’ESP32
Seules certaines broches permettent de sortir le processeur d’un mode de veille veille :
- 18 broches marquées RTC numérotées et 0 à 17.
- 10 broches pour écrans tactiles (Touch screen) numérotées de 0 à 9.
Seules certaines broches RTC sont exposées en fonction de la carte de développement utilisée. Le tableau suivant récapitule la liste des broches RTC et Touch des cartes de développement Espressif ESP32-DevKitC v4 (2020) et ESP32-DevKitC v2 (obsolète).
Libellé broche RTC | Broche capacitive (Touch Pad) | Repère de la broche sur une carte ESP32 DevKitC version 4 (2020) | Repère de la broche sur une carte ESP32-DevKitC V2 (obsolète) | ||
Repère carte | Broche CPU (49 broches) | Repère carte | Broche CPU (39 broches) | ||
RTC_GPIO0 | VP | 5 | VP | 4 | |
RTC_GPIO1 | Non exposée | 37 | Non exposée | – | |
RTC_GPIO2 | Non exposée | 7 | Non exposée | – | |
RTC_GPIO3 | VN | 8 | VN | 5 | |
RTC_GPIO4 | 34 | 10 | IO34 | 6 | |
RTC_GPIO5 | 35 | 11 | IO35 | 7 | |
RTC_GPIO6 | 25 | 14 | IO25 | 10 | |
RTC_GPIO7 | 26 | 15 | IO26 | 11 | |
RTC_GPIO8 | Touch8 | 33 | 13 | IO33 | 9 |
RTC_GPIO9 | Touch9 | 32 | 12 | IO32 | 8 |
RTC_GPIO10 | Touch0 | 24 | 4 | IO4 | 26 |
RTC_GPIO11 | Touch1 | 23 | 0 | IO0 | 25 |
RTC_GPIO12 | Touch2 | 22 | 2 | IO2 | 24 |
RTC_GPIO13 | Touch3 | 21 | 15 | IO15 | 23 |
RTC_GPIO14 | Touch4 | 20 | 13 | IO13 | 16 |
RTC_GPIO15 | Touch5 | 18 | 12 | IO12 | 14 |
RTC_GPIO16 | Touch6 | 14 | 17 | IO14 | 16 |
RTC_GPIO17 | Touch7 | 27 | 16 | IO27 | 12 |
Comme vous pouvez le constater, le repérage des broches est très différent d’une version à l’autre.
Repérage des broches (pinout) du kit de ESP32 DevKitC version 4 (2020)
C’est plus facile de s’y retrouver avec un schéma.
Source : repérage des broches (pinout) RTC et capacitives (Touch) du kit officiel ESP32 DevkitC v4. d’après la documentation officielle Espressif.
Comment réveiller un ESP32 ?
Contrairement à l’ESP8266, il est nécessaire de configurer dans le code comment on souhaite réveiller le processeur avant de le mettre en veille. On dispose pour cela de 7 sources (et méthodes) pour réveiller un ESP32 endormi
- Minuteur (Timer) la méthode esp_sleep_enable_timer_wakeup permet de programmer un timer qui réveillera le module ESP32 à intervalle régulier.
- Broches tactiles (Touch) la méthode esp_sleep_enable_touchpad_wakeup() permet de réveiller le processeur à l’aide d’une broche capacitive (un simple fil de cuivre peut suffire).
- Interruptions Il existe deux possibilités de réveil externe :
- ext0 permet de réveiller la puce avec une broche RTC. Activer avec la méthode esp_sleep_enable_ext0_wakeup(RTC_PIN, MODE)
- ext1 permet de définir plusieurs broches RTC pour réveiller la puce. Activer avec la méthode esp_sleep_enable_ext1_wakeup(MASQUE, MODE)
- GPIO la méthode esp_sleep_enable_gpio_wakeup() peut être utilisée pour réveiller le processeur à l’aide de n’importe quelle broche.
- Port série (UART) la méthode esp_sleep_enable_uart_wakeup() permet de réveiller le processeur à l’aide d’un autre appareil
- ULP le coprocesseur ULP peut réveiller le coeur de l’ESP32 par programmation. Utiliser la méthode esp_sleep_enable_ulp_wakeup() pour activer cette source de réveil.
Compatibilité des méthodes de réveil en fonction du type de sommeil
Voici un tableau de synthèse qui permet de vérifier qu’une méthode permet de réveiller le processeur en fonction du type de veille activé.
Réveiller l’ESP32 de veille à l’aide d’un Minuteur (Timer)
La méthode la plus simple consiste à réveiller le processeur à intervalle régulier. C’est typiquement le cas d’un système d’acquisition de données qui transmet à intervalle régulier ses mesures.
C’est par exemple le cas d’une station météo, la surveillance de la qualité de l’air, de l’ambiance lumineuse ou sonore. Aucune interaction avec l’utilisateur n’est nécessaire.
#include
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */
void setup(){
Serial.begin(115200);
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
Serial.println("Going to sleep now");
delay(1000);
Serial.flush();
esp_deep_sleep_start();
Serial.println("This message will never be printed");
}
void loop(){
}
Comment fonctionne ce code ?
On indique que le processeur devra être réveillé à l’aide d’un minuteur. Le temps doit être indiqué en microsecondes
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Ensuite, on peut endormir le processeur.
En sommeil léger | En sommeil profond |
|
|
Comment connaître l’origine du réveil ?
Il peut être intéressant de connaître la cause du réveil pour réaliser un traitement particulier. Par exemple, lorsqu’on appuie sur un bouton (tactile ou pas), on pourra déclencher l’envoie d’une information sur un serveur tiers. Pratique pour signaler un défaut sur une ligne de production, incrémenter un compteur, signaler qu’une tâche vient de se terminer…
La méthode esp_sleep_get_wakeup_cause() permet de connaître la dernière cause de réveil et les constantes associées :
- ESP_SLEEP_WAKEUP_TIMER Minuteur, timer
- ESP_SLEEP_WAKEUP_TOUCHPAD touche tactile
- ESP_SLEEP_WAKEUP_EXT0 ou ESP_SLEEP_WAKEUP_EXT1
- ESP_SLEEP_WAKEUP_ULP réveillé par le co-processeur ULP
- ESP_SLEEP_WAKEUP_GPIO réveillé par le GPIO
- ESP_SLEEP_WAKEUP_UART réveillé par le port série
Voici une méthode que vous pouvez intégrer au début de vos programmes
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
case ESP_SLEEP_WAKEUP_GPIO : Serial.println("Wakeup caused by GPIO"); break;
case ESP_SLEEP_WAKEUP_UART : Serial.println("Wakeup caused by UART"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
Il suffit ensuite d’appeler quand c’est nécessaire la méthode print_wakeup_reason() pour connaître l’origine du réveil.
Réveiller l’ESP32 de veille une touche tactile
Connecter un simple fil de cuivre sur une broche tactile. Ici par exemple, on branchera simplement un jumper sur la broche 14 qui correspond à la Touch6.
Créer un nouveau croquis et téléverser ce code
#include
/*
Wakeup ESP32 with Touch Pad
Réveille un ESP32 en veille profonde à l'aide d'une touche tactile
====================================
http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
code inspired by Pranav Cherukupalli
*/
#define Threshold 40 /* Greater the value, more the sensitivity */
// Display touchpad origin
void print_wakeup_touchpad(){
touch_pad_t touchPin;
touchPin = esp_sleep_get_touchpad_wakeup_status();
switch(touchPin)
{
case 0 : Serial.println("Touch detected on GPIO 4"); break;
case 1 : Serial.println("Touch detected on GPIO 0"); break;
case 2 : Serial.println("Touch detected on GPIO 2"); break;
case 3 : Serial.println("Touch detected on GPIO 15"); break;
case 4 : Serial.println("Touch detected on GPIO 13"); break;
case 5 : Serial.println("Touch detected on GPIO 12"); break;
case 6 : Serial.println("Touch detected on GPIO 14"); break;
case 7 : Serial.println("Touch detected on GPIO 27"); break;
case 8 : Serial.println("Touch detected on GPIO 33"); break;
case 9 : Serial.println("Touch detected on GPIO 32"); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
// Display wakeup origine
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
case ESP_SLEEP_WAKEUP_GPIO : Serial.println("Wakeup caused by GPIO"); break;
case ESP_SLEEP_WAKEUP_UART : Serial.println("Wakeup caused by UART"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
// Execute this function when Touch Pad in pressed
void callback() {
Serial.println("Do something when Touch Pad is pressed");
}
void setup(){
Serial.begin(115200);
print_wakeup_reason();
//Print the wakeup reason for ESP32 and touchpad too
print_wakeup_reason();
print_wakeup_touchpad();
//Setup interrupt on Touch Pad 6 (GPIO14)
touchAttachInterrupt(T6, callback, Threshold);
//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup();
//esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep until Touch Pad will be pressed");
Serial.println("Going to sleep now");
delay(1000);
Serial.flush();
esp_deep_sleep_start();
Serial.println("This message will never be printed");
}
void loop(){
}
Comment fonctionne ce code ?
On commence par attacher une interruption pour chaque touche tactile que l’on souhaite utiliser. Ici, on va surveiller la Touch6 connectée au GPIO14.
touchAttachInterrupt(T6, callback, Threshold);
La méthode touchAttachInterrupt() prend 3 paramètres :
- T6 une constante qui correspond à la touche sous la forme Tx. x varie de 0 à 9
- callback une méthode qui sera appelée immédiatement au réveil du processeur
- Threshold est le seuil en dessous duquel le processeur est réveillé. Par défaut, le seuil est fixé à 40. Il est possible de modifier la sensibilité en ajustant la constante Threshold au début du programme
#define Threshold 40
On active ensuite le réveil
esp_sleep_enable_touchpad_wakeup();
Avant d’endormir le processeur.
En sommeil léger | En sommeil profond |
|
|
Il est possible de connaître la touche ayant provoqué le réveil afin de brancher le traitement approprié
void print_wakeup_touchpad(){
touch_pad_t touchPin;
touchPin = esp_sleep_get_touchpad_wakeup_status();
switch(touchPin)
{
case 0 : Serial.println("Touch detected on GPIO 4"); break;
case 1 : Serial.println("Touch detected on GPIO 0"); break;
case 2 : Serial.println("Touch detected on GPIO 2"); break;
case 3 : Serial.println("Touch detected on GPIO 15"); break;
case 4 : Serial.println("Touch detected on GPIO 13"); break;
case 5 : Serial.println("Touch detected on GPIO 12"); break;
case 6 : Serial.println("Touch detected on GPIO 14"); break;
case 7 : Serial.println("Touch detected on GPIO 27"); break;
case 8 : Serial.println("Touch detected on GPIO 33"); break;
case 9 : Serial.println("Touch detected on GPIO 32"); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
Réveil externe
Il existe deux types de déclencheurs externes pour sortir ESP32 du sommeil profond.
- ext0 permet de réveiller la puce avec une broche RTC.
- ext1 permet de définir plusieurs broches RTC pour réveiller la puce
ext0 : réveiller la puce avec une broche RTC
Le contrôleur RTC contient une logique pour déclencher le réveil lorsqu’une broche est activée. Il faut utiliser une broches compatible RTC. Elles sont repérées RTC_GPIOX dans la documentation technique. Ce sont les broches listées au paragraphe précédent : 39, 38, 37, 36, 35, 34, 33, 32, 27, 26, 25, 15, 14, 13, 12, 4, 2, 0.
On active le réveil par une broche à l’aide de la méthode esp_sleep_enable_ext0_wakeup(GPIO_PIN,LOGIC_LEVEL) qui prend deux paramètres :
- GPIO_PIN la broche RTC à choisir dans la liste ci-dessus.
- LOGIC_LEVEL déclenchement lorsqu’on appuie sur le bouton (1) ou descendant (0), lorsqu’on relâche le bouton.
La broche doit être indiquée sous la forme GPIO_NUM_X ou X correspond au numéro de la broche sur la carte de développement ESP32.
Ensuite, comme précédemment, on active la mise en veille légère ou profonde
esp_deep_sleep_start();
Circuit
Connecter la sortie du bouton à l’entrée repérée 34 sur la carte ESP32. Placer une résistance de rappel (10KΩ par exemple) entre la sortie du bouton et le GND.
Téléverser le code ext0
Créer un nouveau croquis et téléverser l’exemple ci-dessous
#include
void print_wakeup_reason();
void setup(){
Serial.begin(115200);
//Print the wakeup reason for ESP32
print_wakeup_reason();
//Reveille le processeur en appuyant sur un bouton connecte au GPIO34
esp_sleep_enable_ext0_wakeup(GPIO_NUM_34,1);
//Go to sleep now
esp_deep_sleep_start();
}
void loop(){}
//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by touchpad"); break;
case 4 : Serial.println("Wakeup caused by timer"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
ext1 : réveiller la puce avec plusieurs broches RTC
Dans le mode ext1 plusieurs broches RTC peuvent réveiller la puce. Pour cela, on doit indiquer sous la forme d’un masque des broches à surveiller.
Circuit
Ajoutez un second bouton sur l’entrée 35.
Comment créer le masque ext1 ?
Le repère de la broche la plus élevée est 39. Ouvrez un tableur et créez un tableau composé de 40 colonnes. Le GPIO0 compte pour une colonne. Le GPIO39 prend place dans la première colonne, GPIO0 à la 39ème colonne.
Ensuite remplissez par des 0 sauf 1 en dessous de la broche GPIO34.
GPIO39 | GPIO38 | … | GPIO35 | GPIO34 | GPIO33 | … | GPIO2 | GPIO1 | GPIO0 |
0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
Ce qui donne le chiffre binaire suivant
000011000000000000000000000000000000000
Qu’il ne reste plus qu’à convertir en hexadécimal à l’aide d’un convertisseur en ligne tel que celui-ci ou d’une calculatrice, c
ce qui donne en hexa
0xC
Exemple de conversion binaire en hexa
Téléverser pour réveiller la puce ESP32 avec plusieurs broches RTC
Créer un nouveau croquis et téléverser le code ci-dessous
#include
// Only GPIO35 and GPIO34 can wakeup ESP32 chip
// 000011000000000000000000000000000000000
#define BUTTON_PIN_BITMASK 0xC00000000
void print_wakeup_reason();
void setup(){
Serial.begin(115200);
//Print the wakeup reason for ESP32
print_wakeup_reason();
//Configure mask as ext1 wake up source for HIGH logic level
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH);
//Go to sleep now
esp_deep_sleep_start();
}
void loop(){}
//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
Comment fonctionne ce code ?
On ajoute une nouvelle variable qui contient le masque qui permettra de déclencher le réveil de la puce. Le masque doit être au format hexadécimal.
#define BUTTON_PIN_BITMASK 0x200000000
La méthode esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, MODE)prend deux paramètres :
- BUTTON_PIN_BITMASK