ESP32 et Arduino

Concevoir un capteur ESP32 sur batterie : cartes, régulateurs et intervalles de publication MQTT

Un guide de conception pratique pour un capteur ESP32 sur batterie : choix de la carte, régulateurs à faible courant de repos, surveillance de la tension de la batterie, reconnexions Wi-Fi rapides et intervalles de publication MQTT qui prolongent l'autonomie.

Nœud capteur ESP32 sur batterie avec une cellule LiPo et un pont diviseur envoyant des mesures MQTT vers le cloud
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Un capteur ESP32 sur batterie peut fonctionner des mois sur une seule cellule, mais seulement si le matériel et le firmware sont conçus ensemble. Ce guide passe en revue le choix de la carte, les régulateurs, la surveillance de la batterie et le cycle de publication, pour que votre nœud MQTT se réveille, transmette et se rendorme en consommant le moins d'énergie possible.

Pourquoi l'autonomie est avant tout une décision de conception

L'ESP32 n'est pas une puce basse consommation au sens où peut l'être un microcontrôleur sans radio. Avec le Wi-Fi actif, il consomme beaucoup de courant, et les rafales d'émission sont les moments les plus coûteux de sa vie. En deep sleep, la puce elle-même descend à quelques microampères. La différence entre un nœud qui tient une semaine et un autre qui tient une saison tient au temps passé dans chaque état et à ce que le circuit environnant gaspille pendant que la puce dort.

Vous disposez donc de trois leviers : le courant de veille (généralement dominé par le régulateur, la puce USB-série et les LED, pas par l'ESP32), le temps d'éveil (démarrage, Wi-Fi, DHCP, connexion MQTT, publication) et la fréquence de réveil (diviser l'intervalle par deux double à peu près l'énergie radio). La carte est généralement le levier le plus important : commencez donc par là.

Choisir une carte pour un capteur ESP32 sur batterie

Les cartes de développement sont conçues pour le confort sur un bureau. Elles intègrent généralement un pont USB-UART toujours alimenté, une LED d'alimentation et un régulateur linéaire choisi pour son prix plutôt que pour son courant de repos. Chacun de ces éléments peut consommer bien plus en veille que l'ESP32 lui-même.

Option Comportement en veille Adaptée à
DevKit générique (ESP32-WROOM + AMS1117 + pont USB) Mauvais : le régulateur et la puce USB consomment en continu des milliampères Prototypage du firmware uniquement
Cartes vendues comme basse consommation (chargeur LiPo, LDO à faible Iq, USB commutable) Bon : conçues pour le deep sleep, souvent avec un connecteur de batterie Petites séries et pilotes sur le terrain
Module nu (ESP32-WROOM / ESP32-C3 / ESP32-C6) sur votre propre PCB Excellent : vous choisissez chaque composant Produits et déploiements longs
Cartes à base d'ESP32-C3 ou C6 Bon, simple cœur, courant actif plus faible que l'ESP32 classique pour de nombreuses charges Capteurs simples qui n'ont besoin que du Wi-Fi

Lorsque vous évaluez une carte, retirez la LED d'alimentation, vérifiez si la puce USB-série est sur le rail 3,3 V et recherchez le courant de repos du régulateur. Mesurez ensuite le courant de veille avec un multimètre en série avec la batterie ou avec un profileur de courant ; un wattmètre USB n'est pas assez sensible.

Régulateurs et chimie de la batterie

L'ESP32 a besoin d'environ 3,0 à 3,6 V et peut tirer de brèves pointes de plusieurs centaines de milliampères pendant l'émission Wi-Fi. Votre chaîne d'alimentation doit fournir ces pointes sans brownout et ne gaspiller presque rien au repos.

Une seule cellule LiPo / Li-ion (3,0 à 4,2 V). Le choix le plus courant. Utilisez un régulateur à faible chute de tension (LDO) avec un courant de repos de quelques microampères et suffisamment de marge pour les pointes d'émission. Lorsque la cellule se décharge vers 3,3 V, le LDO décroche : prévoyez donc que le nœud cesse de transmettre de façon fiable aux alentours de 3,4 à 3,5 V de tension de cellule, et signalez une batterie faible bien avant.

Cellule LiFePO4 (environ 3,2 à 3,3 V nominal). Sa tension reste dans la plage de fonctionnement de l'ESP32 pendant la majeure partie de la courbe de décharge, si bien que certaines conceptions se passent de régulateur ; comparez d'abord la tension de charge maximale aux valeurs maximales absolues.

Piles AA. Les piles alcalines s'effondrent sous les pointes d'émission, surtout par temps froid. Associez-les à un convertisseur buck-boost à faible courant de repos, ou utilisez des piles primaires au lithium.

Ajoutez un condensateur de découplage (quelques centaines de microfarads) au plus près du module. Il fournit les rafales d'émission et empêche le détecteur de brownout de réinitialiser la puce, l'une des causes les plus fréquentes de mystérieuses boucles de redémarrage sur les nœuds sur batterie.

Surveiller la tension de la batterie

Un capteur qui meurt en silence est pire qu'un capteur qui meurt en prévenant. Mesurez la cellule avec un pont diviseur relié à une broche ADC et incluez la valeur dans chaque payload MQTT.

Un diviseur de deux résistances égales de forte valeur (par exemple 2 × 1 MΩ) divise par deux la tension de la cellule pour la ramener dans la plage de l'ADC, tout en ne consommant que quelques microampères. Les diviseurs de forte valeur ont une impédance de source élevée : ajoutez donc un petit condensateur (environ 100 nF) entre la broche ADC et la masse pour offrir à l'ADC un échantillon stable. Si même ce courant de fuite compte, commutez le côté bas du diviseur avec un MOSFET piloté par un GPIO.

Sur les cores Arduino ESP32 2.x et 3.x, analogReadMilliVolts() applique l'étalonnage d'usine et renvoie directement des millivolts, ce qui est bien plus précis que de convertir vous-même les valeurs brutes de analogRead(). Faites la moyenne de plusieurs échantillons, car les lectures isolées sont bruitées. Sur l'ESP32 classique, utilisez une broche de l'ADC1 (GPIO 32 à 39), car l'ADC2 n'est pas disponible lorsque le Wi-Fi est actif.

Un schéma de firmware réveil–publication–veille

Le firmware ci-dessous est un sketch Arduino complet pour un nœud sur batterie. Il sort du deep sleep, se reconnecte au Wi-Fi à l'aide du canal et du BSSID mis en cache dans la mémoire RTC, publie un message JSON avec la tension de la batterie, se déconnecte proprement et se rendort. Il utilise le serveur MQTT public gratuit broker.connectmq.com, réservé aux tests : choisissez donc un préfixe de topic unique et n'envoyez rien de sensible.

#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* TOPIC = "connectmq/demo/7f3a91/garden-node/telemetry";

const uint64_t SLEEP_SECONDS = 600;     // publication toutes les 10 minutes
const int BATTERY_PIN = 34;             // broche ADC1, diviseur 2 x 1 MOhm
const float DIVIDER_RATIO = 2.0;

RTC_DATA_ATTR uint32_t bootCount = 0;
RTC_DATA_ATTR uint8_t savedBssid[6];
RTC_DATA_ATTR int32_t savedChannel = 0;

WiFiClient net;
PubSubClient mqtt(net);

float readBatteryVolts() {
  uint32_t sum = 0;
  for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(BATTERY_PIN);
  return (sum / 16.0f) * DIVIDER_RATIO / 1000.0f;
}

bool connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.persistent(false);
  if (savedChannel > 0) {
    WiFi.begin(WIFI_SSID, WIFI_PASS, savedChannel, savedBssid);
  } else {
    WiFi.begin(WIFI_SSID, WIFI_PASS);
  }
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - start > 10000) {
      savedChannel = 0;                 // forcer un scan complet la prochaine fois
      return false;
    }
    delay(20);
  }
  savedChannel = WiFi.channel();
  memcpy(savedBssid, WiFi.BSSID(), 6);
  return true;
}

void goToSleep() {
  mqtt.disconnect();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * 1000000ULL);
  esp_deep_sleep_start();
}

void setup() {
  bootCount++;
  float battery = readBatteryVolts();   // lire avant que la radio ne sollicite la cellule

  if (!connectWifi()) goToSleep();

  String clientId = "esp32-batt-" + String((uint32_t)ESP.getEfuseMac(), HEX);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setSocketTimeout(5);
  if (!mqtt.connect(clientId.c_str())) goToSleep();

  char payload[96];
  snprintf(payload, sizeof(payload),
           "{\"battery\":%.2f,\"boot\":%lu,\"rssi\":%d}",
           battery, (unsigned long)bootCount, WiFi.RSSI());
  mqtt.publish(TOPIC, payload);
  mqtt.loop();
  delay(50);                            // laisser la pile TCP vider ses tampons
  goToSleep();
}

void loop() {}

Quelques détails comptent ici :

  • La batterie est lue avant le démarrage du Wi-Fi. Sous la charge de l'émission, la tension de la cellule s'affaisse : une mesure prise après paraîtrait plus basse que la réalité.
  • Chaque chemin d'échec se termine par la mise en veille. Si le Wi-Fi ou le broker est injoignable, le nœud ne réessaie pas indéfiniment en vidant la cellule. Il retente au réveil suivant.
  • Le canal et le BSSID en cache permettent à la radio d'éviter le scan complet, ce qui raccourcit chaque réveil. Si le point d'accès change, le timeout vide le cache et le démarrage suivant effectue un scan normal.
  • Une IP statique (via WiFi.config()) supprime aussi l'aller-retour DHCP. Utilisez-la lorsque vous maîtrisez le réseau.

Pour approfondir les modes de veille, les sources de réveil et la conservation de l'état entre deux réveils, consultez le guide ESP32 deep sleep MQTT.

Choisir l'intervalle de publication

Le bon intervalle dépend de la vitesse à laquelle la valeur évolue et de l'ancienneté acceptable d'une mesure.

Mesure Intervalle utile typique Remarques
Température d'une pièce ou d'une serre 5 à 15 minutes Évolue lentement ; faites la moyenne de plusieurs échantillons par réveil
Humidité du sol 30 à 60 minutes Très lente ; envisagez d'échantillonner plus souvent mais de ne publier que sur changement
Niveau d'une cuve d'eau 10 à 30 minutes Ajoutez une publication immédiate lors du franchissement d'un seuil
Porte ou mouvement Piloté par événement Réveil sur GPIO (ext0/ext1), pas sur minuterie
Tension de la batterie À chaque réveil Peu coûteux à inclure ; indispensable pour la maintenance

Deux techniques étirent encore le budget. Le regroupement : réveillez-vous brièvement sans Wi-Fi pour prendre une mesure, stockez-la en mémoire RTC et ne vous connectez que tous les N réveils pour publier le lot sous forme d'un tableau JSON unique. La publication sur changement : comparez la nouvelle valeur à la dernière publiée, conservée en mémoire RTC, et évitez complètement la radio lorsqu'elle n'a pas bougé au-delà d'une bande morte. Publiez toujours au moins un heartbeat périodique pour distinguer un capteur silencieux d'un capteur mort.

Les réglages MQTT qui économisent l'énergie

Les choix de protocole côté appareil ont un coût direct en temps d'antenne :

  • QoS 0 pour la télémétrie de routine. La QoS 1 ajoute un aller-retour PUBACK et maintient la radio allumée plus longtemps. Réservez-la aux mesures que vous ne pouvez pas vous permettre de perdre ; les niveaux de QoS MQTT expliqués détaille ce compromis.
  • Retained messages pour la dernière valeur. Publiez la télémétrie avec le flag retain : un tableau de bord ou une plateforme de maison connectée comme Home Assistant, Jeedom ou Domoticz, qui se connecte entre deux réveils, voit immédiatement la dernière mesure.
  • Sessions propres et courtes. Un nœud en veille n'a pas besoin d'abonnement persistant. Connectez-vous en clean session, publiez et déconnectez-vous.
  • Payloads compacts. Des clés JSON courtes suffisent pour quelques mesures par heure.
  • Le TLS coûte un handshake. Les connexions chiffrées sur le port 8883 prennent nettement plus de temps à s'établir que le TCP en clair sur 1883 et maintiennent la radio allumée plus longtemps. En production, ce compromis en vaut la peine, et ESP32 MQTT sur SSL/TLS montre comment rendre le handshake aussi peu coûteux que possible.

Liste de contrôle terrain avant déploiement

  1. Mesurez le courant en deep sleep de la carte finale.
  2. Journalisez le temps d'éveil par cycle et repérez les valeurs aberrantes dues aux tentatives Wi-Fi.
  3. Vérifiez que le nœud survit à un démarrage à froid à la tension de cellule la plus basse attendue, sans boucle de brownout.
  4. Publiez la tension de la batterie et un compteur de démarrages dans chaque message.
  5. Définissez une alerte de tableau de bord sur la tension de batterie faible et sur les messages manquants.
  6. Scellez le boîtier mais gardez l'antenne à l'écart du métal et des batteries.
  7. Passez de la zone publique de test à des identifiants privés avant d'installer quoi que ce soit ailleurs que sur votre bureau.

Passer du serveur MQTT public gratuit à la production

Le serveur MQTT public gratuit broker.connectmq.com est idéal pour les tests et les prototypes pendant que vous ajustez les intervalles, car vous pouvez voir les messages arriver avec mosquitto_sub sans inscription. Pour de vrais déploiements, passez à un broker privé afin que personne d'autre ne puisse lire vos données. ConnectMQ fournit pour chaque broker des identifiants générés et un client ID qui leur est associé ; seul l'appel de connexion change :

mqtt.setServer("broker.connectmq.com", 8883);   // avec WiFiClientSecure et la CA ISRG Root X1
mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD");

Dans le portail ConnectMQ, l'explorateur de topics en direct et les règles d'alerte à seuil vous permettent de suivre la tension des batteries de toute la flotte et d'être prévenu lorsqu'un nœud passe sous votre seuil de remplacement. Si vous construisez de nombreux nœuds, le tutoriel IoT ESP32, plus général, montre comment la partie appareil s'intègre dans un projet complet, et le guide du broker MQTT cloud explique ce qu'un broker hébergé vous enlève comme travail.

Démarrez avec ConnectMQ

Prototypez dès aujourd'hui votre nœud sur batterie avec broker.connectmq.com, puis créez un broker privé avec l'offre gratuite Serverless sur app.connectmq.com, sans carte bancaire. C'est un broker MQTT managé : vous consacrez votre temps aux budgets énergétiques plutôt qu'à la maintenance du broker.

Questions fréquentes

Combien de temps un capteur ESP32 sur batterie peut-il fonctionner avec une cellule LiPo ?

Cela dépend du courant de veille de la carte, de la durée de chaque réveil et de l'intervalle de publication. Une carte avec un régulateur à faible courant de repos et sans puce USB toujours alimentée, qui se réveille toutes les quelques minutes pour une courte publication, peut tenir des mois ; un DevKit standard sur la même cellule ne tiendra parfois que quelques jours.

Faut-il utiliser le deep sleep ou le light sleep pour un capteur MQTT ?

Utilisez le deep sleep lorsque le nœud transmet périodiquement et n'a pas besoin de maintenir une connexion. Le light sleep conserve la RAM et peut maintenir une association Wi-Fi, mais son courant au repos est bien plus élevé : il convient aux nœuds qui doivent réagir rapidement aux commandes.

Pourquoi mon ESP32 sur batterie redémarre-t-il sans cesse au démarrage du Wi-Fi ?

C'est généralement le détecteur de brownout qui réagit à la chute de tension pendant les rafales d'émission. Ajoutez un condensateur de découplage près du module, utilisez un régulateur capable de fournir le courant de crête et vérifiez la résistance interne de la batterie, surtout par temps froid.

Peut-on mesurer la tension de la batterie sans gaspiller de courant ?

Oui. Utilisez un diviseur de forte valeur avec un petit condensateur sur la broche ADC, ou coupez le diviseur avec un MOSFET entre deux mesures, et lisez-le avec analogReadMilliVolts() sur une broche de l'ADC1.

Articles liés

Exemple MQTT ESP-IDF : construire un client esp-mqtt à partir de zéro

Construisez un projet ESP-IDF à partir d'un dossier vide avec le composant esp-mqtt : configuration du Wi-Fi en mode station, gestionnaire d'événements MQTT, publication et abonnement, propriétés MQTT 5 et TLS avec le bundle de certificats.

9 min de lecture

Horodatage NTP ESP32 MQTT : ajouter une heure précise à chaque message

Synchronisez l'horloge de l'ESP32 avec NTP, formatez des horodatages ISO 8601 et epoch en millisecondes, et joignez-les aux payloads MQTT pour que les mesures conservent leur véritable heure de capture même lorsqu'elles sont publiées en retard.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.