Un microcontrôleur n'est pas un ordinateur
Jour 1 · Descendre dans l'objet · 20 min
Au module M1, vous avez fait tourner un broker et des scripts Python sur votre poste. Vous descendez maintenant dans l'objet lui-même — et les règles y sont différentes.
| Votre poste | ESP32 | |
|---|---|---|
| Mémoire vive | 16 Go | 520 Ko |
| Stockage | 500 Go | 4 Mo de flash |
| Processeur | quelques GHz | 240 MHz, deux cœurs |
| Système | macOS, Linux, Windows | FreeRTOS, ou rien du tout |
| Alimentation | secteur | pile ou batterie |
| Si le programme plante | on le relance | l'objet est mort sur son poteau |
Un capteur installé sur un toit ou dans une gaine technique n'est pas redémarrable. Le firmware doit tenir des mois sans intervention : pas de fuite mémoire, pas de blocage, et un chien de garde qui redémarre si tout se fige.
Ce qui remplace le système d'exploitation
L'ESP32 fait tourner FreeRTOS, un ordonnanceur temps réel minimal. Il ne gère ni fichiers ni utilisateurs : il découpe le temps entre des tâches, chacune avec sa priorité et sa propre pile mémoire.
C'est ce qui permet de lire un capteur toutes les secondes pendant qu'une autre tâche maintient la connexion Wi-Fi, sans que l'une bloque l'autre.
L'ESP32 en a deux. Par convention, le cœur 0 porte la pile réseau — Wi-Fi et Bluetooth —, le cœur 1 votre application. Cette séparation évite qu'un traitement un peu long fasse tomber la connexion.
Le fil du module
Vous allez reprendre le capteur Thermeo de M1 et le rendre autonome : capable de mesurer, de filtrer le bruit, de décider seul si la valeur mérite d'être transmise, et de dormir entre deux mesures assez profondément pour tenir cinq ans sur pile.
Lire une grandeur physique
Jour 1 · Descendre dans l'objet · 25 min
Un capteur de température ne renvoie pas « 21,4 ». Il renvoie une tension, que le convertisseur analogique-numérique traduit en nombre entier. Tout le reste est votre travail.
Le convertisseur
L'ADC de l'ESP32 est un 12 bits : il rend une valeur entre 0 et 4095 pour une tension entre 0 et 3,3 V. La conversion est donc directe :
float tension = lecture * 3.3 / 4095.0;Il n'est pas linéaire aux extrémités : évitez les valeurs sous 0,15 V et au-dessus de 3,1 V.
Il est bruité : deux lectures consécutives sur une entrée stable diffèrent de quelques unités. C'est le sujet du jour 2.
Les broches de l'ADC2 sont indisponibles quand le Wi-Fi tourne sur ESP32. Utilisez l'ADC1 — les GPIO 32 à 39.
Capteurs numériques
Beaucoup de capteurs font la conversion eux-mêmes et exposent une valeur via un bus. C'est le cas du DHT22 que vous utiliserez, et plus généralement des capteurs I²C. On y gagne en précision et en simplicité — au prix d'une dépendance à une bibliothèque.
| Bus | Usage | Remarque |
|---|---|---|
| Analogique | Capteurs simples, potentiomètres | Conversion et bruit à votre charge |
| I²C | La majorité des capteurs environnementaux | Deux fils, plusieurs capteurs |
| SPI | Capteurs rapides, écrans, mémoires | Plus rapide, plus de fils |
| 1-Wire | DS18B20, DHT22 | Un seul fil de données |
Et le STM32 ?
Le programme du parcours mentionne le STM32 — HAL, interruptions, DMA. Nous le traiterons en comparaison, pas en pratique.
L'émulation QEMU d'un STM32 n'implémente pas fidèlement les périphériques analogiques : un TP d'acquisition ADC y donnerait des résultats qui n'ont rien à voir avec le matériel. Mieux vaut maîtriser une plateforme réellement simulable que se donner l'illusion d'en connaître deux.
Les concepts — interruptions, DMA, horloges — sont transposables ; c'est ce que nous travaillerons. Si des cartes sont approvisionnées, ce point sera repris.
Quiz — Microcontrôleur et acquisition
Jour 1 · Descendre dans l'objet · 8 min
1. Pourquoi le cœur 0 de l'ESP32 est-il réservé à la pile réseau ?
2. Une lecture ADC vaut 2048 sur un ESP32. Quelle tension approximative ?
3. Votre montage utilise le Wi-Fi et lit un capteur analogique. Quelle broche éviter ?
4. Pourquoi ne traitons-nous pas le STM32 en TP ?
TP 1 — Deux tâches qui cohabitent
Jour 1 · Descendre dans l'objet · 1 h
Structurer un firmware en tâches FreeRTOS plutôt qu'en une boucle unique.
Wokwi, projet ESP32, capteur DHT22 sur la GPIO 15 — le même montage qu'au TP 2 du jour 3 de M1. Vous pouvez repartir de ce projet.
- Créez un projet ESP32 sur Wokwi avec un DHT22 sur la GPIO 15 et une LED sur la GPIO 2.
- Écrivez un firmware à deux tâches : l'une lit le capteur toutes les deux secondes, l'autre fait clignoter la LED toutes les 200 ms. Notez qu'aucune ne bloque l'autre :
#include "DHTesp.h" DHTesp dht; volatile float derniere = 0; void tacheCapteur(void *p) { for (;;) { derniere = dht.getTempAndHumidity().temperature; Serial.printf("mesure %.1f\n", derniere); vTaskDelay(pdMS_TO_TICKS(2000)); } } void tacheLed(void *p) { pinMode(2, OUTPUT); for (;;) { digitalWrite(2, !digitalRead(2)); vTaskDelay(pdMS_TO_TICKS(200)); } } void setup() { Serial.begin(115200); dht.setup(15, DHTesp::DHT22); xTaskCreatePinnedToCore(tacheCapteur, "capteur", 4096, NULL, 1, NULL, 1); xTaskCreatePinnedToCore(tacheLed, "led", 2048, NULL, 1, NULL, 1); } void loop() { vTaskDelay(pdMS_TO_TICKS(1000)); } - Lancez la simulation : la LED clignote régulièrement pendant que les mesures s'affichent. Les deux tâches progressent en parallèle.
- Faites l'expérience inverse pour comprendre l'intérêt : remplacez
vTaskDelaypardelaydans la tâche capteur, et mettez tout dansloop():void loop() { float t = dht.getTempAndHumidity().temperature; Serial.printf("mesure %.1f\n", t); delay(2000); // bloque tout pendant 2 s digitalWrite(2, !digitalRead(2)); } - Observez : la LED ne clignote plus qu'une fois toutes les deux secondes. C'est exactement le problème que FreeRTOS résout.
- Revenez à la version à deux tâches. Réduisez la pile de la tâche capteur à 512 octets et relancez : le firmware plante. Lisez le message — c'est un débordement de pile, la panne la plus courante en embarqué.
- Quelle différence exacte entre
delay()etvTaskDelay()? - Pourquoi
derniereest-elle déclaréevolatile? - Comment dimensionner la pile d'une tâche sans procéder par essais et erreurs ?
TP 2 — Échantillonner régulièrement
Jour 1 · Descendre dans l'objet · 1 h
Acquérir à cadence fixe par interruption de timer, et non par attente active.
- Un traitement de signal exige un échantillonnage régulier. Une boucle avec
delaydérive : le temps de traitement s'ajoute à l'attente. - Mettez en place un timer matériel qui déclenche une interruption à 10 Hz. Notez
IRAM_ATTR: la routine doit résider en RAM interne :hw_timer_t *timer = NULL; volatile bool tick = false; void IRAM_ATTR surTimer() { tick = true; } void setup() { Serial.begin(115200); timer = timerBegin(0, 80, true); // 80 MHz / 80 = 1 MHz timerAttachInterrupt(timer, &surTimer, true); timerAlarmWrite(timer, 100000, true); // 100 000 µs = 100 ms timerAlarmEnable(timer); } void loop() { if (tick) { tick = false; int brut = analogRead(34); Serial.println(brut); } } - Ajoutez un potentiomètre sur la GPIO 34 dans le schéma Wokwi et faites-le varier : les valeurs suivent.
- Vérifiez la régularité : affichez
micros()à chaque tick et calculez l'écart entre deux mesures successives sur cinquante échantillons. Il doit rester très proche de 100 000 µs. - Comparez avec une boucle à
delay(100)qui contient un traitement de 30 ms. Mesurez la période réelle :void loop() { unsigned long t0 = micros(); analogRead(34); delay(30); // simule un traitement delay(100); Serial.println(micros() - t0); } - L'écart est visible : 130 ms au lieu de 100. Consignez les deux mesures, c'est le livrable de ce TP.
- Pourquoi une routine d'interruption ne doit-elle contenir ni
Serial.printni allocation mémoire ? - À quoi sert le drapeau
tickplutôt que de lire le capteur directement dans l'interruption ? - Quelle fréquence d'échantillonnage retenir pour un signal dont on veut observer des variations à 2 Hz ?
Point de contrôle — fin du jour 1
Jour 1 · Descendre dans l'objet · 15 min
delay() et je sais l'expliquerdelay et je l'ai chiffréeIl vous demandera de montrer la dérive : les deux séries de mesures, et l'écart chiffré entre la période visée et la période réelle. Un ordre de grandeur ne suffira pas.
Pourquoi traiter dans l'objet
Jour 2 · Traiter à la source · 20 min
Le réflexe naturel est d'envoyer tout au cloud et de laisser le serveur trier. Sur un capteur sur pile, c'est la garantie de l'échec.
Quatre raisons de traiter à la source
| Raison | Ce que cela évite |
|---|---|
| Énergie | Chaque émission radio coûte cent fois plus qu'un calcul local. Émettre 100 fois par jour au lieu de 86 400 change l'autonomie d'un facteur mille. |
| Bande passante | Cent capteurs à 1 Hz saturent un réseau LPWAN, dont le quota se compte en dizaines de messages par jour. |
| Latence | Une détection de seuil qui doit déclencher une action locale ne peut pas attendre un aller-retour cloud. |
| Confidentialité | Ce qui n'est jamais transmis ne peut pas fuiter. Un capteur de présence peut n'émettre qu'un compteur, jamais le signal brut. |
Cette valeur apprend-elle quelque chose ? Une température identique à la précédente à 0,1 °C près n'apprend rien. Un écart de 3 °C en dix secondes, si.
C'est le principe de l'émission sur événement plutôt que périodique, que vous mettrez en œuvre au TP 4.
Ce qui reste au cloud
Le traitement local ne remplace pas le serveur : il le décharge. L'historisation longue, les corrélations entre capteurs, les tableaux de bord et les modèles restent côté cloud. L'objet décide seulement quoi émettre, et quand.
Ce qui n'est pas transmis est perdu à jamais. Si votre seuil est mal réglé, vous ne pourrez pas réanalyser après coup : la donnée brute n'a jamais quitté l'objet. D'où la pratique courante d'un battement de cœur — une valeur transmise périodiquement même sans événement, pour garder une trace et prouver que le capteur vit.
Filtrer un signal bruité
Jour 2 · Traiter à la source · 25 min
Deux lectures ADC successives sur une entrée parfaitement stable ne donnent pas la même valeur. Ce bruit vient du convertisseur, de l'alimentation, du capteur lui-même. Le filtrer est la première opération de tout traitement embarqué.
Trois filtres, du plus simple au plus fin
La moyenne glissante
On garde les N dernières mesures et on en fait la moyenne. Simple, efficace, mais il faut stocker N valeurs et la réponse est lente.
#define N 10
float buf[N]; int idx = 0;
float moyenne(float v) {
buf[idx] = v; idx = (idx + 1) % N;
float s = 0;
for (int i = 0; i < N; i++) s += buf[i];
return s / N;
}Le filtre exponentiel
Une seule variable en mémoire, une seule multiplication. C'est le filtre du pauvre, et c'est presque toujours le bon choix en embarqué.
float y = 0;
const float alpha = 0.2; // entre 0 et 1
float lisser(float v) {
y = alpha * v + (1 - alpha) * y;
return y;
}Proche de 1, le filtre suit vite mais laisse passer le bruit. Proche de 0, il lisse fort mais réagit lentement. 0,1 à 0,3 convient à une grandeur physique lente comme une température. Vous le vérifierez expérimentalement au TP.
La médiane
On trie les N dernières valeurs et on prend celle du milieu. C'est le seul qui élimine complètement une valeur aberrante isolée — un pic parasite — là où une moyenne se laisse contaminer.
| Filtre | Mémoire | Calcul | Bon pour |
|---|---|---|---|
| Moyenne glissante | N valeurs | N additions | Bruit régulier |
| Exponentiel | 1 valeur | 2 opérations | Le cas général |
| Médiane | N valeurs | un tri | Pics parasites isolés |
Un filtre lisse les variations rapides. Si vous cherchez précisément à détecter une variation brutale, un filtre trop agressif l'effacera. Filtrer et détecter demandent des réglages opposés — c'est le piège du TP 4.
Quiz — Edge computing et filtrage
Jour 2 · Traiter à la source · 8 min
1. Pourquoi émettre coûte-t-il tellement plus que calculer ?
2. Quel filtre élimine un pic parasite isolé sans se laisser contaminer ?
3. Vous mettez alpha à 0,9 dans un filtre exponentiel. Que se passe-t-il ?
4. Pourquoi conserver un battement de cœur périodique malgré l'émission sur événement ?
TP 3 — Dompter le bruit
Jour 2 · Traiter à la source · 1 h 15
Implémenter et comparer trois filtres sur un signal réellement bruité.
- Reprenez le montage du TP 2 avec le potentiomètre sur la GPIO 34.
- Implémentez les trois filtres et affichez les quatre valeurs côte à côte, pour les tracer ensuite :
float expo = 0; const float ALPHA = 0.2; #define N 9 float buf[N]; int idx = 0; bool plein = false; float mediane() { float c[N]; memcpy(c, buf, sizeof(buf)); for (int i = 1; i < N; i++) // tri par insertion, N est petit for (int j = i; j > 0 && c[j-1] > c[j]; j--) { float t = c[j]; c[j] = c[j-1]; c[j-1] = t; } return c[N/2]; } void loop() { if (!tick) return; tick = false; float brut = analogRead(34); buf[idx] = brut; idx = (idx + 1) % N; if (idx == 0) plein = true; expo = ALPHA * brut + (1 - ALPHA) * expo; float moy = 0; for (int i = 0; i < N; i++) moy += buf[i]; moy /= N; Serial.printf("%.0f,%.1f,%.1f,%.1f\n", brut, moy, expo, mediane()); } - Laissez le potentiomètre immobile trente secondes et copiez la sortie du moniteur série. Collez-la dans un tableur et tracez les quatre courbes.
- Mesurez l'écart-type de chaque série sur cette période stable. Vous devez constater une réduction nette du bruit, chiffrée.
- Faites maintenant varier brusquement le potentiomètre et observez : chaque filtre met un temps différent à rattraper la nouvelle valeur. Mesurez ce temps de réponse.
- Refaites l'expérience avec alpha à 0,05 puis à 0,8. Consignez les trois couples (bruit résiduel, temps de réponse) : c'est le compromis fondamental du filtrage.
- Simulez un pic parasite en touchant brièvement l'entrée. Vérifiez que seule la médiane l'ignore complètement.
- Quel filtre retenez-vous pour Thermeo, et pourquoi ?
- Le tri de la médiane coûte N² comparaisons. À partir de quel N cela devient-il gênant à 10 Hz ?
- Pourquoi l'écart-type est-il une meilleure mesure du bruit que l'écart maximal observé ?
Décider dans l'objet
Jour 2 · Traiter à la source · 20 min
Filtrer ne suffit pas : il faut décider quoi émettre. C'est là que le capteur devient intelligent — et que l'autonomie se gagne.
Trois stratégies
| Stratégie | Règle | Messages par jour |
|---|---|---|
| Périodique | J'émets toutes les N secondes | 86 400 à 1 Hz — inacceptable |
| Sur seuil | J'émets si la valeur dépasse une borne | Variable, potentiellement zéro… ou un déluge si le signal oscille autour du seuil |
| Sur variation | J'émets si l'écart avec la dernière valeur émise dépasse δ | Proportionnel à l'activité réelle — c'est généralement le bon choix |
Un signal qui fluctue autour de la borne déclenche à chaque passage : 21,0 / 21,1 / 20,9 / 21,1 sur un seuil à 21 produit une rafale d'alertes.
La parade est l'hystérésis : on déclenche à 21,5 et on ne réarme qu'en dessous de 20,5. Deux bornes au lieu d'une, et le bavardage disparaît.
Le motif complet
Un capteur bien conçu combine trois règles :
- Émission sur variation — dès que l'écart dépasse δ.
- Battement de cœur — au moins une valeur toutes les quinze minutes, même sans variation, pour prouver qu'il vit.
- Plafond d'émission — jamais plus d'un message par minute, pour se protéger d'un capteur défaillant qui bavarderait sans fin.
Un capteur dont l'entrée se déconnecte produit du bruit pur : sans plafond, il émet en continu, vide sa pile en quelques heures et sature le broker. La règle du plafond est ce qui distingue une maquette d'un produit.
TP 4 — Un capteur qui décide
Jour 2 · Traiter à la source · 1 h 15
Mettre en œuvre l'émission sur variation, l'hystérésis et le plafond.
- Repartez du TP 3 en gardant le filtre exponentiel — c'est celui que vous conserverez.
- Implémentez les trois règles :
const float DELTA = 0.5; // variation qui justifie une émission const unsigned long COEUR = 900000; // battement : 15 min const unsigned long PLAFOND = 60000; // au plus un message par minute float derniereEmise = -999; unsigned long tEmission = 0; bool doitEmettre(float v, unsigned long maintenant) { if (maintenant - tEmission < PLAFOND) return false; // plafond if (fabs(v - derniereEmise) >= DELTA) return true; // variation if (maintenant - tEmission >= COEUR) return true; // battement return false; } - Ajoutez un compteur de messages émis et de mesures effectuées, affiché toutes les trente secondes. Le rapport entre les deux est votre gain.
- Laissez tourner deux minutes en faisant varier lentement le potentiomètre. Relevez le rapport mesures / émissions.
- Ajoutez maintenant une alarme de seuil avec hystérésis :
const float HAUT = 24.0, BAS = 23.0; bool enAlarme = false; void verifierAlarme(float v) { if (!enAlarme && v > HAUT) { enAlarme = true; Serial.println("ALARME"); } else if (enAlarme && v < BAS) { enAlarme = false; Serial.println("fin alarme"); } } - Faites osciller la valeur autour de 24 et vérifiez qu'une seule alarme est déclenchée, pas une rafale.
- Retirez l'hystérésis — un seul seuil à 24 — et refaites la même manipulation. Comptez les déclenchements :
if (v > 24.0) Serial.println("ALARME"); // sans hystérésis - Consignez les deux comptages. C'est la démonstration la plus parlante du module.
- Quelles valeurs de δ, de battement et de plafond retiendriez-vous pour Thermeo ?
- Que se passe-t-il si δ est plus petit que le bruit résiduel du filtre ?
- Un capteur qui n'émet rien pendant une heure : comment distinguer « rien à signaler » de « en panne » ?
Point de contrôle — fin du jour 2
Jour 2 · Traiter à la source · 15 min
Faire durer une pile cinq ans
Jour 3 · Énergie, sécurité et assemblage · 25 min
Thermeo vise cinq ans d'autonomie. Ce n'est pas une question de composants, mais d'arithmétique — et le calcul est à la portée de tous.
Les modes de l'ESP32
| Mode | Consommation | Ce qui reste actif |
|---|---|---|
| Actif, Wi-Fi émettant | ~160 mA | Tout |
| Actif, radio éteinte | ~40 mA | Processeur |
| Light sleep | ~0,8 mA | RAM conservée, réveil rapide |
| Deep sleep | ~10 µA | Un minuteur, et la mémoire RTC |
Entre le mode actif et le sommeil profond, il y a un rapport de 16 000. L'autonomie ne se joue donc pas sur ce que consomme l'objet endormi, mais sur la fraction de temps qu'il passe éveillé.
Le calcul
Prenons un capteur qui se réveille toutes les quinze minutes, reste éveillé trois secondes pour mesurer et émettre, sur une pile de 3 000 mAh.
Réveils par jour : 24 x 4 = 96
Temps éveillé : 96 x 3 s = 288 s = 0,08 h
Charge éveillé : 0,08 h x 160 mA = 12,8 mAh/j
Charge endormi : 23,92 h x 0,01 mA = 0,24 mAh/j
─────────────
Total quotidien = 13,04 mAh/j
Autonomie : 3000 / 13,04 = 230 joursSept mois. Loin des cinq ans visés. Le poste dominant saute aux yeux : les trois secondes de réveil pèsent cinquante fois plus que les vingt-quatre heures de sommeil.
Où agir
- Raccourcir le réveil. Trois secondes, c'est surtout l'association Wi-Fi. La mémoriser en RAM RTC fait tomber à moins d'une seconde.
- Espacer les réveils. Passer à une heure divise la consommation par quatre.
- Grouper les émissions. Mesurer toutes les quinze minutes en gardant les valeurs en RAM RTC, et n'émettre qu'une fois par heure.
Vous refaites ce calcul avec les trois optimisations et vous cherchez la combinaison qui atteint cinq ans. C'est un travail de dimensionnement, pas de code — et c'est exactement ce qu'on attendra de vous en projet.
Quiz — Énergie
Jour 3 · Énergie, sécurité et assemblage · 6 min
1. Dans le calcul ci-dessus, quel poste domine ?
2. Vous doublez l'intervalle entre deux réveils. Quel effet ?
3. Que conserve le deep sleep de l'ESP32 ?
TP 5 — Dormir et se souvenir
Jour 3 · Énergie, sécurité et assemblage · 1 h
Mettre l'objet en sommeil profond et conserver son état d'un réveil à l'autre.
Wokwi simule le cycle de sommeil et le redémarrage, mais ne mesure pas la consommation. Vous vérifierez la logique ici, et calculerez l'énergie avec les valeurs constructeur de la leçon.
- Écrivez un firmware qui compte ses réveils. Notez
RTC_DATA_ATTR: c'est ce qui place la variable dans la mémoire qui survit au sommeil :RTC_DATA_ATTR int nbReveils = 0; RTC_DATA_ATTR float mesures[4]; #define uS_PAR_S 1000000ULL #define DUREE_SOMMEIL 10 // 10 s pour le TP, 900 en production void setup() { Serial.begin(115200); delay(200); nbReveils++; Serial.printf("reveil numero %d\n", nbReveils); float v = analogRead(34) * 3.3 / 4095.0; mesures[(nbReveils - 1) % 4] = v; Serial.printf("mesure %.2f V\n", v); if (nbReveils % 4 == 0) { Serial.print("lot a emettre :"); for (int i = 0; i < 4; i++) Serial.printf(" %.2f", mesures[i]); Serial.println(); } esp_sleep_enable_timer_wakeup(DUREE_SOMMEIL * uS_PAR_S); Serial.println("dodo"); esp_deep_sleep_start(); } void loop() { } // jamais atteint : le reveil repart de setup() - Lancez et observez plusieurs cycles. Le compteur s'incrémente alors que le programme repart de
setup()à chaque fois : c'est la mémoire RTC qui travaille. - Retirez
RTC_DATA_ATTRdevantnbReveilset relancez. Le compteur reste bloqué à 1 : la variable ordinaire ne survit pas. - Notez le motif de groupement : quatre mesures gardées en mémoire, une seule émission. C'est la troisième optimisation de la leçon, en pratique.
- Reprenez le calcul d'autonomie de la leçon avec vos propres hypothèses : durée de réveil, intervalle, groupement. Cherchez la combinaison qui atteint cinq ans sur 3 000 mAh, et justifiez-la.
- Vérifiez la cohérence de votre solution : un intervalle de six heures atteindrait les cinq ans, mais Thermeo veut détecter un problème de chauffage. Quel compromis retenez-vous ?
- Pourquoi le programme repart-il de
setup()et non deloop()? - Quelle taille fait la mémoire RTC, et que ne peut-on pas y mettre ?
- Le groupement retarde la détection d'un incident. Comment concilier les deux ?
Sécuriser et mettre à jour l'objet
Jour 3 · Énergie, sécurité et assemblage · 20 min
Au module M1, vous avez sécurisé le broker. Reste l'autre bout de la chaîne : l'objet lui-même.
TLS sur un microcontrôleur
L'ESP32 sait faire du TLS, mais le coût est réel : la poignée de main consomme de la mémoire et allonge le temps de réveil — donc l'énergie.
| Poste | Impact |
|---|---|
| Mémoire | Une session TLS occupe 20 à 40 Ko de RAM sur les 520 disponibles |
| Temps | La poignée de main ajoute 1 à 3 s au réveil — le poste dominant du budget |
| Stockage | Le certificat de l'autorité doit être embarqué dans le firmware |
TLS permet de reprendre une session précédente sans refaire toute la poignée de main. En stockant le ticket en mémoire RTC, un capteur qui se réveille toutes les quinze minutes économise l'essentiel du coût. C'est exactement le genre d'optimisation qui décide de l'autonomie.
La mise à jour à distance
Un parc de cent capteurs sur des toits ne se met pas à jour à la main. L'OTA — over the air — est indispensable, et c'est aussi la plus grosse porte d'entrée d'un objet connecté.
Trois exigences non négociables :
- Signature du firmware. L'objet vérifie que la mise à jour vient bien de vous. Sans cela, quiconque atteint l'objet peut y installer son propre code.
- Double partition. On écrit dans la partition inactive, on bascule au redémarrage. Une coupure pendant le transfert laisse l'ancienne version intacte.
- Retour arrière automatique. Si la nouvelle version ne confirme pas son bon démarrage, l'objet repart sur l'ancienne.
Une mise à jour non signée, poussée sans double partition, sur cent capteurs simultanément. Une erreur dans le firmware et le parc entier devient inaccessible — il faut aller rechercher chaque objet physiquement.
La règle de terrain : déployer par vagues. Un objet, puis dix, puis le reste.
TP 6 — Le nœud complet
Jour 3 · Énergie, sécurité et assemblage · 1 h 30
Assembler acquisition, filtrage, décision, sommeil et émission sécurisée.
- Vous assemblez maintenant tout le module en un seul firmware. C'est le livrable de M2.
- Reprenez le montage ESP32 + DHT22 + potentiomètre, et le broker sécurisé de M1.
- Structurez le firmware selon la séquence de réveil :
// 1. reveil -> lire le capteur // 2. filtrer (exponentiel, etat conserve en RAM RTC) // 3. decider : variation, battement ou plafond ? // 4. si emission : Wi-Fi, TLS, MQTT publish, statut en-ligne retenu // 5. rendormir RTC_DATA_ATTR float etatFiltre = 0; RTC_DATA_ATTR float derniereEmise = -999; RTC_DATA_ATTR int cyclesSansEmission = 0; - Le testament MQTT vu en M1 pose ici une vraie question : un objet qui dort se déconnecte proprement à chaque cycle, donc le testament ne se déclenche pas. Comment détecter alors qu'il est mort ? Traitez ce point explicitement dans votre rendu.
- Mesurez sur dix cycles : nombre de mesures, nombre d'émissions, temps de réveil moyen.
- Vérifiez côté broker que les messages arrivent bien, avec les ACL de M1 actives.
- Rédigez une note d'une page : votre dimensionnement énergétique, les paramètres retenus et leur justification, et la réponse à la question du testament.
- Un objet qui dort ne peut pas recevoir de commande. Comment lui transmettre une nouvelle consigne ?
- Où placeriez-vous la reprise de session TLS dans votre séquence de réveil ?
- Que faudrait-il changer pour passer ce nœud sur LoRaWAN plutôt que Wi-Fi ?
Point de contrôle — fin du module M2
Jour 3 · Énergie, sécurité et assemblage · 20 min
Votre encadrant vous fera dérouler le nœud complet et défendre votre dimensionnement. Le calcul d'autonomie est le cœur de l'évaluation : c'est ce qui distingue un firmware qui marche d'un capteur déployable.
Le module M3 enchaîne mardi 11 : vos données quitteront enfin l'objet pour une plateforme cloud.