ESP8266, activer le mode Deep Sleep, réveil (wake up) avec un détecteur de mouvement PIR • Domotique et objets connectés à faire soi-même

Le module ESP8266 dispose du mode deep sleep qui permet de mettre celui-ci en veille prolongée pour économiser la batterie. On peut réveiller le module à intervalle régulier pour faire des mesures et les publier sur un serveur. La broche RESET (RST) permet également de réveiller l’ESP8266. On pourra par exemple utiliser le front montant (le signal) d’un détecteur de mouvement (PIR). 

Dans ce tutoriel nous allons voir les adaptations à apporter au code Arduino et comment modifier le câblages. Si vous rencontrez des difficultés pour utiliser le mode Deep-Sleep des modules ESP8266, vous pouvez utilisez ce sujet sur le forum.

Différents modes de veille et consommation d’un module ESP8266EX

Il existe trois modes de mise en veille. Ils sont détaillés dans la documentation officielle page 6

  • Modem-Sleep. Le mode Modem-Sleep est utilisé dans les applications qui nécessitent le fonctionnement du processeur, comme dans les applications PWM ou I2S. Il est conforme à la norme 802.11 (U-APSD). Le modem Wi-Fi est arrêté tout en maintenant une connexion Wi-Fi sans transmission de données pour optimiser la consommation d’énergie. Trois modes sont disponibles, DTIM1 à 3. Par exemple dans le mode DTIM3, le modem est mis en sommeil durant 300 ms puis activé durant 3 ms. Avec ce mode, la consommation est de 15 mA.
  • Light-Sleep (sommeil léger). En plus de la suspension du modem WiFI, le CPU est mis en attente et réactivé si nécessaire.
  • Deep-Sleep (sommeil profond), c’est le seul mode le plus simple à mettre en oeuvre et le plus économe en énergie pour des projets qui fonctionnent sur batterie.

Le tableau tiré de la documentation officielle donne une petite idée de la consommation. Lorsque le mode deep-sleep est activé, la consommation chute à ~20µA.

Consommation moyenne des modules ESP8266

La consommation des modules ESP8266EX (2018) est très similaire (page 18). La consommation grimpe à 170mA avec une connexion WiFi à 11Mbps.

Consommation moyenne des modules ESP8266EX (2018)

Comment activer le mode deep sleep ?

On active le mode Deep-sleep en reliant la broche RST à la broche D0.

On active le mode deep-sleep de l’ESP8266 en reliant les broches RST et D0

Autres conséquences du mode deep-sleep

En reliant les broches D0 et RST, il n’est plus possible de téléverser un programme. Quelque soit votre environnement de développement (IDE Arduino, PlatformIO, ESP Tools), il faudra déconnecter la broche RST avant de pouvoir téléverser un programme. Il faudra donc en tenir compte lorsque vous concevez votre circuit. Le mieux est de prévoir un jumper.  

La connexion WiFi étant arrêté, vous ne pourrez plus accéder à une interface WEB de configuration. Il faudra prévoir une condition dans votre programme pour désactiver le mode deep-sleep. Par exemple en ajoutant un micro switch sur le circuit.

Activer le mode Deep-Sleep dans un programme Arduino

Maintenant que tout est prêt coté matériel, nous allons nous attaquer au code Arduino.

Ce qu’il faut garder en tête, c’est que lorsqu’on réveille le module ESP8266, le code du projet est exécuté depuis le début. Ce n’est pas une mise en veille comme on a l’habitude sur un ordinateur. Par conséquent, il est inutile de se torturer l’esprit et de prévoir des cas de re-connexion. Il suffira d’exécuter les différents traitement dans le setup() puis de rendormir l’ESP en exécutant la méthode ESP.deepsleep(durée, mode_wifi) qui prend deux paramètres :

  1. La durée de mise en veille en microsecondes. Par exemple, 1 seconde = 1000000 microsecondes
  2. Le mode du WiFi au redémarrage

Si on souhaite réveiller manuellement le module ou à l’aide d’une action extérieure, par exemple un interrupteur relié sur la broche RST, il suffit d’indiquer un temps nul (0).

Au réveil, il est possible de choisir entre 3 modes de fonctionnement du modem WiFi.

  • RF_DEFAULT c’est le mode par défaut qu’il est inutile d’indiquer. L’équivalent est RF_CAL. Dans ce mode, le modem WiFi est activé normalement. C’est à dire qu’on pourra se connecter au réseau WiFi et publier un statut sur un broker MQTT. Ce mode consomme génère un pic de consommation qui peut atteindre 170mA durant environ 1 seconde.
  • Une version alternative moins consommatrice en énergie est RF_NO_CAL (pour NO CALibration). Le modem WiFi est activé mais sans qu’aucun étalonnage du signal radio soit effectué. En théorie seulement car d’après les mesures réalisée par andre, la consommation semble identique.

RF_NO_CAL

RF_CAL

  • RF_DISABLED. Si vous n’avez pas besoin de la connexion WiFi on peut garder le modem WiFi en veille. Attention, si ce mode est activé, il devient impossible de se connecter au réseau WiFi. C’est l’équivalent du mode modem-sleep décrit précédemment.

Donc en résumé :

  • ESP.deepsleep(0), met en veille le module jusqu’à ce qu’il soit réveillé par un pic sur la broche RST
  • ESP.deepsleep(5 * 1000000), réveille le module toutes les 5 secondes
  • ESP.deepsleep(5000000, RF_DISABLED), réveille le module toutes les 5 secondes sans ré-activer le modem WiFi

Remarque. Vous pouvez également opter pour la notation scientifique et remplacer par 5e6 pour mettre le module en veille durant 5 secondes.

Test du mode Deep Sleep du module ESP8266EX

Il est temps de passer à un exemple concret. Créez un nouveau croquis et collez le code suivant. Vous disposez de plusieurs paramètres

  • SSID, le nom du réseau WiFi sur lequel doit se connecter le module
  • Password, le mot de passe réseau
  • durationSleep, la durée de mise en veille du module. Iici, elle est de 10 secondes.
  • NB_TRYWIFI, le nombre de tentative de connexion au réseau WiFI.

J’ai utilisé la librairie Tricker livrée avec le SDK ESP8266 qui permet d’exécuter à intervalle régulier une fonction pour faire clignoter la LED bleue installée sur la LoLin WeMos d1 mini. C’est une librairie plus légère que la librairie Thread qui ne nécessite aucun installation complémentaire.

Le module tente de se connecter à 10 reprises avec un temps d’attente de 500ms entre chaque tentative. Si le module ne parvient pas à se connecter à un réseau, il est plongé dans un sommeil profond jusqu’au prochain réveil et ainsi de suite. C’est une solution pour éviter de drainer la batterie. Bien évidemment, la durée du sommeil est trop courte, mais, c’est pour l’exemple.

Lorsque la connexion est possible, l’adresse IP du module est affichée sur le moniteur série.

On pourra utiliser ce mode de fonctionnement pour faire des mesures à intervalle régulier et les envoyer sur un serveur ou une base de données InfluxDB.

#include 
#include 
Ticker ticker;

const char* ssid =     "enter_your_ssid"; // WiFi SSID
const char* password = "enter_your_password"; // WiFi password
#define durationSleep  10 // secondes
#define NB_TRYWIFI     10 // nbr d'essai connexion WiFi, number of try to connect WiFi

void tick()
{
int state = digitalRead(BUILTIN_LED); // get the current state of GPIO1 pin
digitalWrite(BUILTIN_LED, !state); // set pin to the opposite state
}

void setup() {
pinMode(BUILTIN_LED, OUTPUT);
ticker.attach(0.5, tick);

Serial.begin(115200);
WiFi.begin(ssid, password);

int _try = 0;
while (WiFi.status() != WL_CONNECTED) {
Serial.print("..");
delay(500);
_try++;
if ( _try >= NB_TRYWIFI ) {
Serial.println("Impossible to connect WiFi network, go to deep sleep");
ESP.deepSleep(durationSleep * 1000000);
}
}
Serial.println("Connected to the WiFi network");
Serial.print ( "IP address: " );
Serial.println ( WiFi.localIP() );

ESP.deepSleep(durationSleep * 1000000);

}

void loop() {
}

Réveiller le module à l’aide d’un contacteur, détecteur de mouvement PIR, radar microondes…

Maintenant, ce qui peut être intéressant, c’est de réveiller le module lorsqu’un événement est détecté à l’aide d’un contacteur, d’un détecteur de mouvement par infrarouge (détecteur PIR) ou un radar micro-ondes.

Le problème, c’est que pour réveiller l’ESP8266, il faut envoyer un front montant unique sur la broche Reset. Lorsqu’on utilise un contacteur ou le signal d’un détecteur PIR, le signal envoyé n’est pas correct et on provoque une multitude de redémarrages du module. Le pic de consommation électrique se situe au démarrage du module. Si on veut éviter le gaspillage et préserver la batterie des dépenses inutiles d’énergie, il faut résoudre ce problème.

J’ai testé de nombreux montages, mais c’est celui proposé par Tomsim sur Stackoverflow qui donne le meilleur résultat.

Ici, Tomsim récupère également l’état du bouton du la broche D2. La broche RST est connectée à la broche D0 à l’aide d’une diode. Ce n’est pas obligatoire. Il faudra éviter d’envoyer un signal haut depuis la broche D0 pour éviter un Reset involontaire. Si vous voulez redémarrer manuellement depuis le programme l’Arduino le module, utilisez plutôt la méthode ESP.reset().

En fonction du capteur utilisé, voici deux circuits que vous pouvez tester.

Matériel utilisé

Voici le matériel utilisé pour ce tutoriel

Last update was on: 6 février 2021 20 h 37 min

Le premier circuit est le plus simple. On va utiliser un transistor de type NPN pour envoyer un signal sur la broche RST dès qu’un signal est envoyé par un capteur de présente ou un contacteur mécanique.

On récupère le signal sur la base du transistor NPN (broche 2). On récupère le signal de l’émetteur (broche 1) sur la broche RESET. Vous pouvez ajouter une résistance de rappel mais cela ne semble pas obligatoire. Le collecteur (broche 3) est connecté au GND.

Matériel nécessaire

Circuit avec condensateur de filtrage en amont du transistor NPN, en cas de reset multiples

Si vous rencontrez des problèmes de redémarrage multiples de l’ESP8266, vous pouvez tester ce second montage basé sur le principe de Tomsim.

L’astuce consiste à installer en amont un petit condensateur de 1µf puis de relier la sortie du condensateur à la masse par l’intermédiaire d’une résistance. Lorsqu’un signal est envoyé par le contacteur ou le capteur, le condensateur se charge et ne produit qu’un seul signal en sortie pour alimenter la base du transistor. L’énergie résiduelle est éliminée via la résistance.

Le reste du circuit reste le même. J’ai testé plusieurs valeurs de résistance de 1kΩ à 10kΩ avec succès.

Matériel nécessaire

Un système d’alarme WiFi MQTT d’appoint

Maintenant qu’on peut réveiller l’ESP8266 à l’aide d’un détecteur de présence, rien de plus facile que d’envoyer un changement d’état vers un serveur domotique ou un broker MQTT. Voici un petit exemple de programme qui envoi un changement d’état au réveil du module ESP8266.

Avant de tester le programme, modifiez les paramètres suivants :

  • Le SSID et le mot de passe du réseau WiFi
  • L’adresse IP du broker MQTT
  • NB_TRYWIFI, le nombre de tentative de connexion au réseau WiFI.

Au réveil, le module tente de se connecter à 10 reprises (NB_TRYWIFI) au réseau WiFi. Si la connexion échoue, le module se rendort pour éviter de drainer la batterie. En cas de succès, il se connecte au broker MQTT et publie l’état sur le topic DeepSleepDemo/PIR durant une seconde. La LED bleue est éteinte puis le module se rendort jusqu’à la prochaine détection de mouvement.

On pourrait améliorer le code et mesurer le temps entre deux détections de mouvement pour éviter des alertes multiples.

#include 
#include 

#include 
Ticker ticker;

#define NB_TRYWIFI    10

const char* ssid = "xxxx";
const char* password = "xxxx";
const char* mqtt_server = "xxx.xxx.xxx.xxx";

WiFiClient espClient;
PubSubClient client(espClient);

void tick()
{
  //toggle state
  int state = digitalRead(BUILTIN_LED);  // get the current state of GPIO1 pin
  digitalWrite(BUILTIN_LED, !state);     // set pin to the opposite state
}

void sendMQTTMessage(){
  if (!client.connected()) {
    reconnect();
  }
  client.publish("DeepSleepDemo/PIR", "1");
  delay(1000);
  client.publish("DeepSleepDemo/PIR", "0");
}


void setup() {
  int start = millis();
  // Fait clignoter la LED intégré durant la connexion au réseau WiFi - Blink Bleu Led during WiFi connexion
  pinMode(BUILTIN_LED, OUTPUT);
  ticker.attach(0.5, tick);
   
  Serial.begin(115200);
  // Raison du réveil - restart reason
  Serial.println(""); Serial.print("Reason startup :");Serial.println(ESP.getResetReason());
    
  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi.");
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
    _try++;
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Impossible to connect WiFi network, go to deep sleep");
        ESP.deepSleep(0);
    }
  }
  Serial.println("Connected to the WiFi network");
 
  Serial.println("Send PIR Status to MQTT broker");
  client.setServer(mqtt_server, 1883);
  sendMQTTMessage();
  
  // Durée du réveil - waking time
  Serial.println("Waking time: ");Serial.print(millis()-start);Serial.println("ms");

  ticker.detach();
  digitalWrite(BUILTIN_LED, LOW);
 
  Serial.println("Go to deep sleep");
  
  ESP.deepSleep(0);
}

void loop() {
}

boolean reconnect() {
  if (client.connect("ESP8266Client")) {
    Serial.println("Connected to server");
    return client.connected();
  }
  Serial.println("I think connection failed!");
  return 0;
}

Erreurs en téléversant un programme Arduino lorsque le mode deep-sleep est activé

De nombreux fabricants de cartes de développement ESP8266 intègrent maintenant un jumper à souder pour activer le mode deep-sleep. C’est plus propre et il n’y à rien à prévoir sur le circuit. Ici la LoLin (Wemos) d1 mini v3 (gauche) et la LoLin d1 mini Pro 2018 (droite).

Dans les deux cas, on peut suivre très facilement la piste qui relie les broches RST et D0.

Il faudra toutefois réserver cette option lorsque le projet est terminé. En effet, à chaque fois qu’on doit mettre à jour le programme, il faudra déconnecter les broches D0 et RST. En cas de besoin, il faudra retirer le jumper à l’aide d’une pompe à désouder.

Un cas typique de message d’erreur lorsque le mode deep-sleep n’est pas déconnecté.

Si la broche RST est reliée à un capteur qui peut provoquer un Reset durant l’installation du programme, vous risquez de rencontrer l’erreur FLASH_DOWNLOAD_DATA.

Autres optimisations

Bien évidemment la consommation annoncée en activant le mode Deep-Sleep ne tient pas compte du reste du montage. Si vous utilisez un capteur qui tire son alimentation directement depuis la batterie, l’autonomie en sera directement affectée. C’est le cas par exemple dès que l’on utilise les broches 5V ou 3V3.

Si vous voulez réduire la consommation des périphériques, vous pouvez utiliser une sortie numérique, à condition toutefois que la puissance nécessaire soit faible. L’intensité Imax disponible pour chaque sortie ne peut pas dépasser 12mA (page 18).

Une autre solution consiste à activer le mode d’économie d’énergie qui est proposée par la plupart des capteurs I2C. C’est au cas par cas, il faudra fouiller dans la librairie ou développer votre propre driver en vous référant à la documentation officielle du fabricant.

Avez-vous aimé cet article ?

[Total: 3 Moyenne: 5]