Pourquoi votre station météo ESP32 plante au bout de 24 heures (et comment y remédier)

Les projets IoT scolaires sur ESP32 plantent rarement à cause d'un problème matériel. Ils se bloquent en raison de la fragmentation de la mémoire tas (heap), de boucles bloquantes de reconnexion Wi-Fi et de chiens de garde (watchdogs) matériels non gérés.
Si la station météo ESP32 de votre classe fonctionne parfaitement sur la paillasse du laboratoire pendant la quatrième heure de cours mais s'éteint complètement le lendemain matin, la puce n'est pas défectueuse. Les microcontrôleurs ne se dégradent pas en vingt-quatre heures. En réalité, les logiciels embarqués fonctionnant en continu échouent presque toujours en raison de deux problèmes discrets et cumulatifs : la fragmentation de la mémoire tas (heap) due aux opérations textuelles dynamiques, et des pertes de réseau non gérées qui piègent le processeur dans une boucle bloquante infinie.
Résoudre ces problèmes exige d'abandonner les raccourcis de prototypage rapide pour adopter les pratiques standard de l'ingénierie embarquée : des tampons mémoire de taille fixe, des machines à états non bloquantes pour le réseau et une minuterie de chien de garde matériel (watchdog).
Coupable n° 1 : Chaînes dynamiques et fragmentation du tas (heap)
L'ESP32 dispose d'environ 320 Ko de SRAM interne utilisable. Dans une station météo qui interroge les capteurs toutes les dix secondes, un code écrit avec la classe standard Arduino String alloue, redimensionne et libère de petits blocs de mémoire des milliers de fois par jour :
// Le schéma qui casse insidieusement votre projet :
String payload = "{\"temp\": ";
payload += String(temperature);
payload += ", \"humidity\": ";
payload += String(humidity);
payload += "}";
http.POST(payload);Chaque fois que des chaînes dynamiques sont créées et concaténées dans loop(), l'environnement d'exécution C++ alloue de l'espace sur le tas. Comme d'autres tâches système en arrière-plan (telles que les piles Wi-Fi et Bluetooth) allouent de la mémoire en même temps, cette allocation et désallocation continue transforme le tas en gruyère. La mémoire libre totale peut encore indiquer 150 Ko, mais le plus grand bloc libre contigu se réduit à quelques centaines d'octets. Lorsque la pile Wi-Fi ou le sérialiseur JSON demande soudainement un bloc continu de 2 Ko pour un paquet TCP, l'allocation échoue, renvoyant un pointeur nul qui déclenche une panique de noyau silencieuse ou un plantage non géré.
La solution : utiliser des tampons de pile de taille fixe et snprintf. Le firmware d'un microcontrôleur doit allouer des tampons statiques ou sur la pile dont la taille est connue au moment de la compilation.
// Alternative robuste sans allocation sur le tas :
char payload[128];
snprintf(payload, sizeof(payload),
"{\"temp\":%.2f,\"humidity\":%.2f}",
temperature, humidity);
http.POST((uint8_t*)payload, strlen(payload));Coupable n° 2 : La boucle de reconnexion au Wi-Fi de l'établissement
Dans les établissements scolaires, le Wi-Fi est rarement stable. Les points d'accès renouvellent leurs clés de sécurité, les baux DHCP expirent, et des coupures de courant locales ou des délestages électriques (load-shedding) déconnectent brièvement les routeurs en amont, même si la station IoT fonctionne sur batterie. De nombreux tutoriels d'initiation suggèrent de se reconnecter au Wi-Fi de cette façon :
if (WiFi.status() != WL_CONNECTED) {
WiFi.reconnect();
while (WiFi.status() != WL_CONNECTED) {
delay(500); // Fatal : bloque indéfiniment le processeur
}
}Si le routeur redémarre et met deux minutes à rétablir le sous-réseau local, cette boucle while fige l'exécution. Comme FreeRTOS exécute la pile Wi-Fi et les tâches de gestion du système sur deux cœurs, bloquer la boucle principale peut priver les tâches de chien de garde en arrière-plan, entraînant une réinitialisation matérielle immédiate ou un blocage définitif des tâches.
La solution : traiter la connectivité comme une machine à états non bloquante. Ne bloquez jamais l'exécution en attendant une connexion. Si le Wi-Fi est indisponible, enregistrez les données localement dans la mémoire flash ou sur une carte SD et réessayez la connexion à intervalle régulier sans interrompre la lecture des capteurs.
Coupable n° 3 : L'absence de minuteries de chien de garde (watchdog)
Quelle que soit la qualité de votre code, des capteurs extérieurs, des pointes de tension générées par des compresseurs à proximité ou des lignes de bus I2C qui ne répondent pas (en particulier les omniprésents capteurs BME280 ou DHT22) peuvent plonger un ESP32 dans un interblocage matériel. Si un capteur ne libère pas la ligne d'horloge I2C, la bibliothèque Wire standard peut rester bloquée indéfiniment.
Une minuterie de chien de garde de tâche (TWDT, pour Task Watchdog Timer) surveille les boucles critiques. Si la boucle principale n'arrive pas à « nourrir » ou réinitialiser le chien de garde dans un délai défini (par exemple 8 secondes), l'ESP32 déclenche automatiquement un redémarrage matériel et reprend son fonctionnement de manière autonome.
#include <esp_task_wdt.h>
#define WDT_TIMEOUT_SECONDS 8
void setup() {
// Initialiser le chien de garde pour un délai de 8 secondes
esp_task_wdt_init(WDT_TIMEOUT_SECONDS, true);
esp_task_wdt_add(NULL); // Abonner le thread actuel
}
void loop() {
// Réinitialiser le chien de garde à chaque cycle
esp_task_wdt_reset();
readSensors();
sendTelemetry();
// Éviter les delay() prolongés ; utiliser des vérifications millis() non bloquantes
}Une remarque sur la stabilité de l'alimentation
Avant de supposer qu'un bug est purement logiciel, inspectez le rail d'alimentation matériel. Un ESP32 consomme de brèves impulsions de courant pouvant atteindre 350 à 500 mA lors des rafales de transmission Wi-Fi (étalonnage RF et transmission de paquets). Si la carte est alimentée par un câble USB fin relié à un ordinateur portable ou un chargeur mural 5V d'entrée de gamme, des chutes de tension sous le seuil de baisse de tension (brownout) de 2,7V amènent le détecteur de brownout interne à déclencher un redémarrage brusque.
- Placez un condensateur électrolytique de 100 µF à 470 µF entre les broches
VINetGNDpour absorber les pointes de courant transitoires. - Assurez-vous que le détecteur de brownout est activé dans votre environnement de développement plutôt que désactivé, car une sous-tension corrompt la mémoire flash interne.
Si vous concevez des stations de mesure prêtes pour le terrain destinées aux sciences environnementales ou aux espaces scolaires, notre ingénierie pédagogique chez Sheen IoT propose des architectures matérielles modulaires et des modèles de firmware prêts pour la production afin d'éviter ces pièges classiques en classe.



