Cours Complet MicroPython IoT
Cours Complet MicroPython IoT
COURS COMPLET
MicroPython & IoT
Formations Innovation et Pratiques
Ce document contient :
✓ 4 semaines de cours structurés
✓ Théorie détaillée pour chaque session
✓ Exemples de code complets commentés
✓ Exercices pratiques avec corrections
✓ Mini-projets de fin de semaine
✓ 1 Projet final de démonstration
🎯 Objectifs de la session
✓
✓
Comprendre ce qu'est MicroPython et ses avantages par rapport au C/C++
✓
Installer Thonny IDE sur son ordinateur
✓
Flasher le firmware MicroPython sur une carte ESP32
Exécuter son premier programme 'Hello World'
📚 Contenu Théorique
▶ Qu'est-ce que MicroPython ?
MicroPython est une implémentation légère du langage Python 3, optimisée pour fonctionner sur des
microcontrôleurs avec des ressources limitées (RAM, flash). Il permet d'écrire des scripts Python
directement sur des cartes comme l'ESP32, l'ESP8266, le Raspberry Pi Pico, etc. Contrairement au C/C++,
MicroPython ne nécessite pas de compilation : on écrit le code et il s'exécute immédiatement (mode REPL).
▶ Matériel nécessaire
Pour cette formation, vous aurez besoin d'une carte ESP32 (ou ESP8266), d'un câble USB micro/USB-C,
d'un ordinateur avec Thonny IDE installé, et d'un kit de composants (LEDs, résistances, capteurs
DHT11/DHT22, OLED, breadboard, fils dupont).
▶ Installation de l'environnement
1. Téléchargez Thonny IDE sur [Link] 2. Téléchargez le firmware MicroPython pour ESP32 sur
[Link]/download/esp32 3. Connectez l'ESP32 via USB 4. Dans Thonny : Outils > Options >
Interpréteur > MicroPython (ESP32) 5. Flashez le firmware via [Link] ou directement depuis Thonny
💻 Exemples de Code
📄 Premier programme - Hello World
# Premier programme MicroPython
print("Bonjour, MicroPython !")
print("Je suis sur un ESP32")
# Variables de base
nom = "ESP32"
version = 3.0
actif = True
print("Carte:", nom)
print("Version Python:", version)
print("Actif:", actif)
'Bonjour MicroPython'
>>> import sys
>>> [Link]
'esp32'
✏️Exercices Pratiques
Exercice 1 : Installation et premier test
Installez Thonny IDE, flashez MicroPython sur votre ESP32, puis vérifiez que la connexion
fonctionne en tapant 'import sys; print([Link])' dans le REPL. Vous devriez voir 'esp32'.
✅ Correction :
import sys
print([Link]) # affiche: esp32
print([Link]) # affiche la version de MicroPython
✅ Correction :
prenom = "Jean"
age = 25
ville = "Cotonou"
pays = "Bénin"
✅ Correction :
nombres = [8, 15, 6, 20, 12]
somme = sum(nombres)
moyenne = somme / len(nombres)
print("Nombres:", nombres)
print("Somme:", somme)
print("Moyenne:", moyenne)
🎯 Objectifs de la session
✓
✓
Maîtriser les types de données Python (int, float, str, bool, list, dict)
✓
Utiliser les structures conditionnelles if/elif/else
✓
Implémenter les boucles for et while
Comprendre les listes et dictionnaires
📚 Contenu Théorique
▶ Types de données en MicroPython
MicroPython supporte les mêmes types que Python standard : int (entiers), float (décimaux), str (chaînes),
bool (True/False), list (listes), dict (dictionnaires), tuple (tuples immuables). La mémoire étant limitée sur
microcontrôleur, il faut éviter les structures trop volumineuses.
▶ Structures conditionnelles
Les conditions en Python utilisent l'indentation (4 espaces) et non des accolades. La structure est : if
condition: ... elif autre_condition: ... else: ... Les opérateurs de comparaison sont : ==, !=, <, >, <=, >=. Les
opérateurs logiques : and, or, not.
▶ Boucles for et while
La boucle 'for' itère sur une séquence. La boucle 'while' tourne tant qu'une condition est vraie. 'break'
interrompt la boucle, 'continue' passe à l'itération suivante. Sur microcontrôleur, les boucles infinies 'while
True' sont très courantes pour les programmes embarqués.
💻 Exemples de Code
📄 Types de données
# Types de base
entier = 42
decimal = 3.14
texte = "MicroPython"
booleen = True
# Listes
capteurs = ["DHT22", "HC-SR04", "LDR", "BMP280"]
print("Premier capteur:", capteurs[0])
print("Nombre de capteurs:", len(capteurs))
# Dictionnaire
config = {
"wifi_ssid": "MonReseau",
"wifi_password": "motdepasse123",
"intervalle": 30
}
print("SSID:", config["wifi_ssid"])
📄 Conditions et boucles
# Structure conditionnelle
temperature = 35
# Boucle for
for i in range(5):
print("Mesure", i+1, ":", temperature + i)
✏️Exercices Pratiques
Exercice 1 : Classification de température
Créez un programme qui prend une température en entrée et l'affiche avec son niveau de criticité : <
0°C = 'Gel', 0-15°C = 'Froid', 15-25°C = 'Confortable', 25-35°C = 'Chaud', > 35°C = 'Canicule'.
✅ Correction :
def classifier_temperature(temp):
if temp < 0:
niveau = "Gel"
emoji = "🧊"
elif temp < 15:
niveau = "Froid"
emoji = "🥶"
elif temp < 25:
niveau = "Confortable"
emoji = "😊"
elif temp < 35:
niveau = "Chaud"
emoji = "☀️"
else:
niveau = "Canicule"
emoji = "🔥"
# Tests
for temp in [-5, 10, 22, 30, 38]:
classifier_temperature(temp)
✅ Correction :
releves = [23.5, 25.1, 22.8, 28.4, 24.6]
# Calculs
somme = 0
for r in releves:
somme += r
moyenne = somme / len(releves)
max_temp = releves[0]
min_temp = releves[0]
for r in releves:
if r > max_temp:
max_temp = r
if r < min_temp:
min_temp = r
print(f"Moyenne: {moyenne:.1f}°C")
print(f"Maximum: {max_temp}°C")
print(f"Minimum: {min_temp}°C")
print("Relevés au-dessus de la moyenne:")
for i, r in enumerate(releves):
if r > moyenne:
print(f" Relevé {i+1}: {r}°C")
✅ Correction :
intervalles = [5, 10, 15, 30, 60] # en secondes
periodes = [3600, 86400, 604800] # 1h, 1j, 1 semaine en secondes
noms = ["1 heure", "1 jour", "1 semaine"]
🎯 Objectifs de la session
✓
✓
Créer et appeler des fonctions avec paramètres et valeurs de retour
✓
Comprendre la portée des variables (locale/globale)
✓
Importer et utiliser les modules standards MicroPython
Organiser son code en fichiers séparés
📚 Contenu Théorique
▶ Fonctions en Python
Une fonction est un bloc de code réutilisable défini avec le mot-clé 'def'. Elle peut recevoir des paramètres
(entrées) et retourner une valeur avec 'return'. Les fonctions sont essentielles pour structurer le code IoT :
une fonction par tâche (lire_capteur, envoyer_donnee, afficher_ecran).
▶ Modules importants de MicroPython
MicroPython inclut des modules spécifiques : machine (contrôle GPIO, PWM, I2C, SPI, UART), time
(temporisation, sleep), network (Wi-Fi), uos (système de fichiers), ujson (JSON), urequests (HTTP). Ces
modules sont différents de Python standard mais ont une API similaire.
💻 Exemples de Code
📄 Définition et utilisation de fonctions
# Fonctions simples
def saluer(nom):
return "Bonjour, " + nom + "!"
def calculer_moyenne(valeurs):
if len(valeurs) == 0:
return 0
return sum(valeurs) / len(valeurs)
def classer_humidite(humidite):
"""Classifie le niveau d'humidité"""
if humidite < 30:
return "Sec"
elif humidite < 60:
return "Normal"
else:
return "Humide"
# Utilisation
print(saluer("IoT"))
mesures = [45.2, 48.7, 43.1, 50.0]
moy = calculer_moyenne(mesures)
print(f"Humidité moyenne: {moy:.1f}% -> {classer_humidite(moy)}")
📄 Modules MicroPython
import machine
import time
import ujson
retour = [Link](json_str)
print("Température:", retour["temp"])
✏️Exercices Pratiques
Exercice 1 : Bibliothèque de fonctions capteurs
Créez un fichier '[Link]' avec 4 fonctions : convertir_celsius_fahrenheit(c),
convertir_hpa_mmhg(hpa), calculer_point_de_rosee(temp, hum), and formater_donnees(temp, hum,
pression). Importez et testez ces fonctions dans [Link].
✅ Correction :
# [Link]
import math
def convertir_celsius_fahrenheit(celsius):
return celsius * 9/5 + 32
def convertir_hpa_mmhg(hpa):
return hpa * 0.750062
# [Link]
✅ Correction :
import ujson
def charger_config(fichier="[Link]"):
try:
with open(fichier, "r") as f:
return [Link](f)
except:
# Config par défaut si le fichier n'existe pas
return {
"wifi_ssid": "MonReseau",
"wifi_password": "secret",
"intervalle_s": 30,
"topic_mqtt": "maison/capteur1"
}
# Test
config = charger_config()
print("Intervalle actuel:", config["intervalle_s"], "s")
config["intervalle_s"] = 60
sauvegarder_config(config)
config2 = charger_config()
print("Nouvel intervalle:", config2["intervalle_s"], "s")
🎯 Objectifs de la session
✓
✓
Comprendre les broches GPIO de l'ESP32 (entrée/sortie)
✓
Contrôler une LED (allumer, éteindre, faire clignoter)
✓
Lire l'état d'un bouton poussoir
Implémenter un anti-rebond logiciel (debounce)
📚 Contenu Théorique
▶ Les GPIO de l'ESP32
L'ESP32 possède 34 broches GPIO (General Purpose Input/Output). Certaines sont en entrée uniquement
(GPIO 34-39), d'autres en entrée/sortie. En MicroPython, on utilise [Link]() pour configurer une
broche. Les modes principaux sont : [Link] (sortie), [Link] (entrée). Les résistances pull-up/pull-down
internes sont disponibles.
▶ LED et bouton - Schéma de câblage
LED : connectez l'anode (+) à une résistance de 220Ω, puis au GPIO choisi. La cathode (-) va à GND.
Bouton : un côté au GPIO avec pull-up interne activé, l'autre côté à GND. Quand le bouton est pressé, le
GPIO lit 0 (LOW). Avec pull-down : bouton entre GPIO et VCC, lit 1 quand pressé.
▶ Anti-rebond (Debounce)
Les boutons mécaniques produisent plusieurs transitions rapides lors d'un appui ('rebonds'). Sans anti-
rebond, une pression peut être lue comme plusieurs appuis. Solution logicielle : vérifier que l'état reste
stable pendant 20-50ms avant de valider le changement.
💻 Exemples de Code
📄 Contrôle d'une LED
from machine import Pin
import time
# Allumer / éteindre
[Link](1) # Allumer
[Link](1)
[Link](0) # Éteindre
[Link](1)
# Méthode alternative
[Link]()
[Link](0.5)
[Link]()
# Clignotement en boucle
print("Clignotement - Ctrl+C pour arrêter")
try:
while True:
[Link]() # Inverse l'état
[Link](0.5)
except KeyboardInterrupt:
[Link]()
print("Arrêté.")
while True:
etat = [Link]()
maintenant = time.ticks_ms()
time.sleep_ms(10)
✏️Exercices Pratiques
Exercice 1 : SOS en morse
Programmez une LED pour envoyer le signal SOS en morse (... --- ...). Court = 200ms, Long =
600ms, Espace entre lettres = 400ms, Espace entre mots = 1000ms. Répétez 3 fois.
✅ Correction :
from machine import Pin
import time
COURT = 200
LONG = 600
ESPACE_LETTRE = 400
ESPACE_MOT = 1000
def flash(duree):
[Link]()
time.sleep_ms(duree)
[Link]()
time.sleep_ms(150)
print("Terminé.")
✅ Correction :
from machine import Pin
import time
compteur = 0
dernier_etat = 1
dernier_temps = 0
def celebration():
for _ in range(5):
[Link]()
time.sleep_ms(100)
[Link]()
time.sleep_ms(100)
while True:
etat = [Link]()
maintenant = time.ticks_ms()
if compteur >= 5:
time.sleep_ms(200)
[Link]()
celebration()
compteur = 0
print("Remise à zéro!")
dernier_etat = etat
time.sleep_ms(10)
🎯 Objectifs de la session
✓
✓
Comprendre la modulation de largeur d'impulsion (PWM)
✓
Contrôler l'intensité lumineuse d'une LED avec PWM
✓
Générer des tonalités avec un buzzer
Lire un signal analogique avec l'ADC de l'ESP32
📚 Contenu Théorique
▶ Qu'est-ce que le PWM ?
PWM (Pulse Width Modulation) est une technique qui simule une tension analogique en faisant varier
rapidement un signal numérique entre 0 et 1. Le rapport cyclique (duty cycle) définit le pourcentage du
temps où le signal est à l'état HIGH. 0% = éteint, 50% = mi-puissance, 100% = pleine puissance. Sur
ESP32, la fréquence PWM est configurable de 1Hz à 40MHz.
▶ ADC - Conversion Analogique-Numérique
L'ESP32 possède un ADC 12 bits (valeurs de 0 à 4095) sur les GPIO 32-39. Il permet de lire des capteurs
analogiques : potentiomètre, LDR (photorésistance), capteur de température NTC, joystick, etc. La tension
d'entrée doit être entre 0V et 3.3V (attention : l'ESP32 n'est PAS 5V-tolérant sur les broches ADC).
💻 Exemples de Code
📄 PWM - Variation d'intensité LED
from machine import Pin, PWM
import time
[Link]()
✏️Exercices Pratiques
Exercice 1 : Lampe d'ambiance avec potentiomètre
Connectez un potentiomètre sur GPIO34 (ADC) et une LED sur GPIO2 (PWM). La rotation du
potentiomètre doit contrôler l'intensité de la LED en temps réel. Affichez la valeur ADC et le
pourcentage d'intensité toutes les 100ms.
✅ Correction :
from machine import Pin, PWM, ADC
import time
print("Tournez le potentiomètre...")
try:
while True:
valeur_adc = [Link]() # 0-4095
intensite = valeur_adc // 4 # 0-1023 pour PWM
pourcentage = valeur_adc * 100 // 4095
led_pwm.duty(intensite)
print(f"ADC: {valeur_adc:4d} | PWM: {intensite:4d} | {pourcentage:3d}%")
time.sleep_ms(100)
except KeyboardInterrupt:
led_pwm.duty(0)
led_pwm.deinit()
✅ Correction :
from machine import Pin, PWM
import time
buzzer = PWM(Pin(15))
[Link](0)
niveaux = [
(440, 1, 500, 500, "Normal"),
(550, 1, 300, 400, "Attention"),
(660, 2, 200, 300, "Avertissement"),
(770, 3, 150, 200, "Alerte"),
(880, 4, 100, 150, "DANGER"),
(1000, 5, 80, 80, "CRITIQUE!"),
]
[Link]()
🎯 Objectifs de la session
✓
✓
Combiner GPIO, PWM, bouton et boucle principale
✓
Créer un système avec plusieurs modes de fonctionnement
✓
Structurer un projet MicroPython complet
Documenter et commenter son code
📚 Contenu Théorique
▶ Architecture d'un projet MicroPython
Un projet MicroPython bien structuré comporte : [Link] (programme principal), [Link] (configuration),
et des modules séparés pour chaque fonctionnalité. La boucle principale while True gère les états et les
transitions. Utilisez des machines à états (state machines) pour gérer plusieurs modes.
💻 Exemples de Code
📄 Projet complet - Système clignotant multi-modes
from machine import Pin, PWM
import time
# Modes disponibles
MODES = ["OFF", "LENT", "RAPIDE", "RESPIRATION", "SOS"]
mode_actuel = 0
def changer_mode():
global mode_actuel
mode_actuel = (mode_actuel + 1) % len(MODES)
print(f"Mode: {MODES[mode_actuel]}")
led_pwm.duty(0)
def mode_respiration(t):
# Calcul sinusoïdal basé sur le temps
import math
phase = (t % 2000) / 2000.0 * 2 * [Link]
val = int(([Link](phase) + 1) / 2 * 1023)
led_pwm.duty(val)
try:
print("Système démarré. Bouton pour changer de mode.")
print(f"Mode actuel: {MODES[mode_actuel]}")
while True:
maintenant = time.ticks_ms()
etat_btn = [Link]()
# Machine à états
mode = MODES[mode_actuel]
t = time.ticks_diff(maintenant, temps_debut)
if mode == "OFF":
led_pwm.duty(0)
elif mode == "LENT":
led_pwm.duty(1023 if (t // 1000) % 2 == 0 else 0)
elif mode == "RAPIDE":
led_pwm.duty(1023 if (t // 200) % 2 == 0 else 0)
elif mode == "RESPIRATION":
mode_respiration(t)
elif mode == "SOS":
# SOS simplifié basé sur le temps
seq = [1,0,1,0,1,0, 0, 1,1,0,1,1,0,1,1,0, 0, 1,0,1,0,1]
idx = (t // 300) % len(seq)
led_pwm.duty(1023 if seq[idx] else 0)
time.sleep_ms(20)
except KeyboardInterrupt:
led_pwm.duty(0)
led_pwm.deinit()
print("Arrêt propre.")
✏️Exercices Pratiques
Exercice 1 : Extension : 2 LEDs + 2 boutons
Étendez le mini-projet avec une deuxième LED (GPIO4) et un deuxième bouton (GPIO35). Le
bouton 1 change le mode de la LED 1, le bouton 2 change le mode de la LED 2. Les deux LEDs
fonctionnent indépendamment et simultanément.
✅ Correction :
# Structure recommandée :
# Créer une classe LedController pour chaque LED
# Chaque instance gère son propre mode et son propre état
class LedController:
def update(self):
maintenant = time.ticks_ms()
etat = [Link]()
t = time.ticks_diff(maintenant, [Link])
mode = [Link][[Link]]
led1 = LedController(2, 0)
led2 = LedController(4, 35)
try:
while True:
[Link]()
[Link]()
time.sleep_ms(20)
except KeyboardInterrupt:
[Link]()
[Link]()
🎯 Objectifs de la session
✓
✓
Câbler et configurer le capteur DHT11 ou DHT22
✓
Lire la température et l'humidité avec la bibliothèque dht
✓
Gérer les erreurs de lecture (timeout, CRC)
Formater et afficher les données proprement
📚 Contenu Théorique
▶ DHT11 vs DHT22
Le DHT11 mesure la température (0-50°C, ±2°C) et l'humidité (20-90%, ±5%). Le DHT22 est plus précis :
température -40 à 80°C (±0.5°C), humidité 0-100% (±2%). Les deux utilisent un protocole série propriétaire
sur une seule broche de données. Fréquence de lecture max : toutes les 2 secondes (DHT11) ou 0.5
secondes (DHT22). Résistance pull-up de 4.7kΩ recommandée sur la broche DATA.
▶ Câblage DHT11/DHT22
Broche 1 (VCC) : 3.3V ou 5V. Broche 2 (DATA) : GPIO choisi + résistance 4.7kΩ vers VCC. Broche 3 : non
connectée (sur DHT11 à 3 pattes) ou GND. Broche 4 (GND) : masse. Sur les modules avec 3 broches déjà
intégrés, la résistance est présente sur le PCB.
💻 Exemples de Code
📄 Lecture DHT22
import dht
from machine import Pin
import time
def lire_dht():
"""Lit le capteur avec gestion d'erreur"""
try:
[Link]()
temp = [Link]()
hum = [Link]()
return temp, hum
except OSError as e:
print("Erreur lecture DHT:", e)
return None, None
# Boucle de mesures
print("Lecture DHT22 - Ctrl+C pour arrêter")
print(f"{'Temps':>8} | {'Temp (°C)':>10} | {'Humidité (%)':>12}")
print("-" * 38)
debut = [Link]()
while True:
temp, hum = lire_dht()
if temp is not None:
elapsed = [Link]() - debut
print(f"{elapsed:>7}s | {temp:>10.1f} | {hum:>12.1f}")
[Link](2)
✏️Exercices Pratiques
Exercice 1 : Station météo console
Créez un programme qui lit le DHT22 toutes les 5 secondes pendant 1 minute, stocke les valeurs
dans deux listes, puis affiche un résumé statistique (min, max, moyenne) pour la température et
l'humidité.
✅ Correction :
import dht
from machine import Pin
import time
capteur = dht.DHT22(Pin(4))
temperatures = []
humidites = []
if temperatures:
print("
=== RÉSUMÉ ===")
print(f"Température: min={min(temperatures):.1f} max={max(temperatures):.1f}
moy={sum(temperatures)/len(temperatures):.1f} °C")
print(f"Humidité : min={min(humidites):.1f} max={max(humidites):.1f}
moy={sum(humidites)/len(humidites):.1f} %")
✅ Correction :
import dht
from machine import Pin, PWM
import time
capteur = dht.DHT22(Pin(4))
while True:
try:
[Link]()
t = [Link]()
h = [Link]()
confort, vert, rouge = evaluer_confort(t, h)
🎯 Objectifs de la session
✓
✓
Comprendre le principe du sonar ultrasonique
✓
Câbler et programmer le HC-SR04
✓
Calculer la distance à partir du temps de vol
Créer un détecteur de proximité avec alertes
📚 Contenu Théorique
▶ Principe de fonctionnement
Le HC-SR04 émet une impulsion ultrasonique de 40kHz via la broche TRIG (déclenchée par une impulsion
de 10µs). L'écho revient sur la broche ECHO. La durée de l'écho permet de calculer la distance : d =
(durée_µs × 0.0343) / 2, où 0.0343 cm/µs est la vitesse du son à 20°C. Portée : 2cm à 400cm, précision
±3mm.
▶ Câblage et précautions
VCC : 5V (attention ! HC-SR04 fonctionne en 5V). TRIG : GPIO quelconque en OUTPUT. ECHO : nécessite
un diviseur de tension (5V → 3.3V) car l'ESP32 n'est pas 5V-tolérant. Diviseur : résistances 1kΩ et 2kΩ. Ou
utilisez une version HC-SR04P (3.3V compatible).
💻 Exemples de Code
📄 Mesure de distance avec HC-SR04
from machine import Pin, time_pulse_us
import time
def mesurer_distance_cm():
"""Retourne la distance en cm, ou -1 si erreur"""
# Impulsion TRIG de 10µs
[Link](0)
time.sleep_us(2)
[Link](1)
time.sleep_us(10)
[Link](0)
if duree < 0:
return -1 # Timeout ou erreur
# Mesures continues
print("Mesure de distance (Ctrl+C pour arrêter)")
while True:
dist = mesurer_distance_cm()
if dist < 0:
print("Erreur de mesure")
elif dist < 5:
print(f"OBSTACLE TRÈS PROCHE: {dist} cm !!!")
elif dist < 20:
print(f"Objet détecté: {dist} cm")
else:
print(f"Distance: {dist} cm")
time.sleep_ms(100)
✏️Exercices Pratiques
Exercice 1 : Radar de recul
Simulez un radar de recul : plus l'objet est proche, plus le buzzer bipe vite. Zones : > 100cm =
silencieux, 50-100cm = bip lent (1/s), 20-50cm = bip moyen (3/s), < 20cm = bip continu. Affichez la
distance en temps réel.
✅ Correction :
from machine import Pin, PWM, time_pulse_us
import time
def mesurer():
[Link](0); time.sleep_us(2)
[Link](1); time.sleep_us(10)
[Link](0)
d = time_pulse_us(ECHO, 1, 30000)
return -1 if d < 0 else round(d * 0.0343 / 2, 1)
def bip(duree_ms):
[Link](512)
time.sleep_ms(duree_ms)
[Link](0)
try:
while True:
dist = mesurer()
if dist < 0:
print("Erreur")
time.sleep_ms(200)
continue
print(f"Distance: {dist:6.1f} cm", end=" ")
if dist < 20:
bip(50); time.sleep_ms(50)
elif dist < 50:
bip(100); time.sleep_ms(230)
elif dist < 100:
bip(100); time.sleep_ms(900)
else:
time.sleep_ms(200)
except KeyboardInterrupt:
[Link]()
🎯 Objectifs de la session
✓
✓
Monter un circuit diviseur de tension avec LDR
✓
Lire et interpréter les valeurs ADC
✓
Calibrer le capteur pour obtenir des niveaux de luminosité
Créer un système de veilleuse automatique
📚 Contenu Théorique
▶ La photorésistance LDR
Une LDR (Light Dependent Resistor) varie sa résistance selon la luminosité : faible lumière = haute
résistance (plusieurs MΩ), forte lumière = faible résistance (quelques centaines d'Ω). On la monte en
diviseur de tension avec une résistance fixe (10kΩ) : GPIO_ADC -- LDR -- 3.3V et GPIO_ADC -- 10kΩ --
GND. La valeur ADC augmente avec la luminosité.
💻 Exemples de Code
📄 Lecture LDR et veilleuse automatique
from machine import Pin, ADC, PWM
import time
adc_ldr = ADC(Pin(34))
adc_ldr.atten(ADC.ATTN_11DB) # 0-3.3V
def lire_luminosite():
"""Retourne la luminosité en % (0=obscur, 100=très lumineux)"""
val = adc_ldr.read() # 0-4095
return val * 100 // 4095
def classer_lumiere(pct):
if pct < 10: return "Nuit"
elif pct < 30: return "Sombre"
elif pct < 60: return "Normal"
elif pct < 85: return "Clair"
else: return "Très lumineux"
[Link](intensite)
print(f"Lumière: {lumiere_pct:3d}% ({label}) | LED: {intensite*100//1023:3d}
%")
time.sleep_ms(200)
except KeyboardInterrupt:
[Link](0)
[Link]()
✏️Exercices Pratiques
Exercice 1 : Datalogger de luminosité
Enregistrez les valeurs de luminosité toutes les 10 secondes pendant 2 minutes dans une liste. À la
fin, affichez un histogramme ASCII montrant la distribution des valeurs par plages de 10%.
✅ Correction :
from machine import ADC, Pin
import time
adc = ADC(Pin(34))
[Link](ADC.ATTN_11DB)
donnees = []
print("Collecte 2 minutes...")
for i in range(12):
val = [Link]() * 100 // 4095
[Link](val)
print(f" {i*10:3d}s: {val}%")
[Link](10)
# Histogramme
print("
=== HISTOGRAMME ===")
plages = [0]*10
for v in donnees:
plages[min(v//10, 9)] += 1
🎯 Objectifs de la session
✓
✓
Connecter et initialiser un écran OLED via I2C
✓
Afficher du texte, des nombres et des formes
✓
Créer un tableau de bord pour afficher les données capteurs
Animer l'affichage et gérer le rafraîchissement
📚 Contenu Théorique
▶ Le protocole I2C
I2C (Inter-Integrated Circuit) est un bus série à 2 fils : SDA (données) et SCL (horloge). L'ESP32 peut avoir
plusieurs bus I2C. Par défaut : SDA=GPIO21, SCL=GPIO22. Adresse I2C de l'OLED : généralement 0x3C
(ou 0x3D selon le module). Vitesse typique : 400kHz.
▶ Bibliothèque SSD1306
MicroPython inclut [Link] (ou on peut la télécharger). Elle offre : fill(0/1) pour effacer, text('string', x, y)
pour écrire du texte (police 8x8), pixel(x, y, c) pour un pixel, hline/vline/rect/fill_rect pour des formes, show()
pour envoyer le buffer à l'écran. Résolution : 128x64 pixels.
💻 Exemples de Code
📄 Dashboard OLED avec données capteurs
from machine import Pin, I2C
import ssd1306
import dht
import time
# Capteur DHT22
capteur = dht.DHT22(Pin(4))
# Titre
[Link]("=== METEO ===", 5, 0)
# Température
[Link]("Temp:", 0, 16)
[Link](f"{temp:.1f} C", 45, 16)
# Humidité
[Link]("Hum :", 0, 28)
[Link](f"{hum:.1f} %", 45, 28)
# Ligne séparatrice
[Link](0, 12, 128, 1)
[Link](0, 54, 128, 1)
# Statut
statut = "OK" if 15 < temp < 30 else "!"
[Link](f"Statut: {statut}", 0, 56)
[Link]()
try:
while True:
[Link]()
t = [Link]()
h = [Link]()
lum = 65 # simulé (remplacer par ADC LDR)
afficher_dashboard(t, h, lum)
[Link](2)
except KeyboardInterrupt:
[Link](0)
[Link]()
✏️Exercices Pratiques
Exercice 1 : Interface multi-pages
Créez un système avec 3 pages sur l'OLED, navigables avec un bouton : Page 1 = données en
temps réel (temp, hum), Page 2 = statistiques (min/max depuis démarrage), Page 3 = graphique
ASCII de l'historique des 10 dernières températures.
✅ Correction :
from machine import Pin, I2C
import ssd1306, dht, time
page = 0
historique = []
t_min, t_max = 99, -99
dernier_btn = 1
while True:
try:
[Link]()
t = [Link]()
h = [Link]()
[Link](t)
if len(historique) > 10: [Link](0)
if t < t_min: t_min = t
if t > t_max: t_max = t
except: pass
# Bouton
etat = [Link]()
if etat == 0 and dernier_btn == 1:
page = (page + 1) % 3
dernier_btn = etat
[Link](0)
if page == 0:
[Link]("PAGE 1: TEMPS REEL", 0, 0)
[Link](f"T: {t:.1f}C", 0, 20)
[Link](f"H: {h:.1f}%", 0, 36)
elif page == 1:
[Link]("PAGE 2: STATS", 0, 0)
[Link](f"Min: {t_min:.1f}C", 0, 20)
[Link](f"Max: {t_max:.1f}C", 0, 36)
else:
[Link]("PAGE 3: GRAPHE", 0, 0)
if historique:
mn = min(historique); mx = max(historique)
r = mx - mn if mx != mn else 1
for i, v in enumerate(historique):
h_bar = int((v - mn) / r * 40)
x = i * 12
oled.fill_rect(x, 63 - h_bar, 10, h_bar, 1)
[Link]()
[Link](2)
🎯 Objectifs de la session
✓
✓
Comprendre le système de fichiers de MicroPython (LittleFS)
✓
Lire et écrire des fichiers texte et JSON
✓
Implémenter un logger de données avec rotation
Gérer l'espace flash disponible
📚 Contenu Théorique
▶ Système de fichiers MicroPython
MicroPython utilise LittleFS (ou FAT selon la version) pour stocker des fichiers dans la flash interne.
L'espace disponible varie : ESP32 avec 4MB flash a environ 2MB pour les fichiers. Les fichiers sont
accessibles comme en Python standard avec open(). Le module uos permet de lister, créer et supprimer
des fichiers/dossiers.
💻 Exemples de Code
📄 Datalogger avec fichiers CSV
import uos
import time
import dht
from machine import Pin
capteur = dht.DHT22(Pin(4))
FICHIER_LOG = "[Link]"
MAX_LIGNES = 1000
def verifier_espace():
stats = [Link]('/')
libre = stats[0] * stats[3] # block_size * free_blocks
return libre
def compter_lignes(fichier):
try:
with open(fichier, 'r') as f:
return sum(1 for _ in f)
except:
return 0
timestamp = [Link]()
ligne = f"{timestamp},{temp:.1f},{hum:.1f}
"
print("Logging démarré...")
for i in range(10):
try:
[Link]()
t = [Link]()
h = [Link]()
logger_donnee(t, h)
libre = verifier_espace()
print(f"Log {i+1}: T={t:.1f} H={h:.1f} | Flash libre: {libre//1024}KB")
except Exception as e:
print("Erreur:", e)
[Link](5)
✏️Exercices Pratiques
Exercice 1 : Gestionnaire de configuration persistante
Créez un système de configuration qui sauvegarde dans [Link] : l'intervalle de mesure, les
seuils d'alerte, le nom de la station. Au démarrage, lisez la config. Ajoutez une fonction pour modifier
un paramètre via le REPL et le sauvegarder automatiquement.
✅ Correction :
import ujson, uos
CONFIG_DEFAULT = {
"station_name": "Station1",
"intervalle_s": 30,
"temp_max_alerte": 35.0,
"hum_min_alerte": 20.0,
"hum_max_alerte": 90.0
}
class Config:
def __init__(self, fichier="[Link]"):
[Link] = fichier
[Link] = self._charger()
def _charger(self):
try:
with open([Link]) as f:
return [Link](f)
except:
self._sauvegarder(CONFIG_DEFAULT)
return dict(CONFIG_DEFAULT)
def afficher(self):
print("=== CONFIGURATION ===")
for k, v in [Link]():
print(f" {k}: {v}")
config = Config()
[Link]()
# Modifier depuis REPL: [Link]("intervalle_s", 60)
🎯 Objectifs de la session
✓
✓
Intégrer DHT22 + LDR + OLED dans un projet complet
✓
Afficher toutes les données sur l'écran avec interface soignée
✓
Logger les données dans un fichier CSV
Gérer les erreurs et assurer la robustesse
📚 Contenu Théorique
▶ Architecture du projet
La station météo locale lit la température, l'humidité (DHT22) et la luminosité (LDR) toutes les 30 secondes.
Elle affiche les données en temps réel sur l'OLED. Elle sauvegarde dans [Link]. Elle allume une LED
rouge si les seuils sont dépassés.
💻 Exemples de Code
📄 Station météo complète
# station_meteo.py - Projet complet Semaine 2
from machine import Pin, I2C, ADC, PWM
import ssd1306, dht, uos, ujson, time
# En-tête CSV
try:
with open(LOG_FILE, 'x') as f:
[Link]("timestamp,temp_c,humidite_pct,luminosite_pct
")
except: pass
def lire_capteurs():
[Link]()
t = [Link]()
h = [Link]()
lum = [Link]() * 100 // 4095
return t, h, lum
")
✏️Exercices Pratiques
Exercice 1 : Rapport journalier
Ajoutez une fonction 'generer_rapport()' qui lit le fichier CSV, calcule les statistiques du jour (min,
max, moyenne pour chaque grandeur), et les affiche sur l'OLED page par page. Déclenchez le
rapport en appuyant sur un bouton.
✅ Correction :
def generer_rapport():
temperatures = []
humidites = []
lumieres = []
try:
with open(LOG_FILE, 'r') as f:
next(f) # Sauter l'en-tête
for ligne in f:
parts = [Link]().split(',')
if len(parts) == 4:
[Link](float(parts[1]))
[Link](float(parts[2]))
[Link](int(parts[3]))
except Exception as e:
print("Erreur lecture:", e)
return
n = len(temperatures)
if n == 0:
print("Pas de données")
return
rapport = {
"nb_mesures": n,
"temp_min": min(temperatures),
"temp_max": max(temperatures),
"temp_moy": sum(temperatures)/n,
"hum_min": min(humidites),
"hum_max": max(humidites),
"hum_moy": sum(humidites)/n,
}
[Link](0)
[Link]("RAPPORT", 35, 0)
[Link](f"N={n} mesures", 0, 12)
[Link](f"T:{rapport['temp_min']:.0f}-{rapport['temp_max']:.0f}C", 0, 24)
[Link](f"Tmoy:{rapport['temp_moy']:.1f}C", 0, 36)
[Link](f"H:{rapport['hum_min']:.0f}-{rapport['hum_max']:.0f}%", 0, 48)
[Link]()
return rapport
🎯 Objectifs de la session
✓
✓
Connecter l'ESP32 à un réseau Wi-Fi (mode Station)
✓
Créer un point d'accès Wi-Fi (mode AP)
✓
Vérifier la connexion et gérer la reconnexion automatique
Obtenir l'adresse IP et les informations réseau
📚 Contenu Théorique
▶ Modes Wi-Fi de l'ESP32
L'ESP32 supporte 3 modes Wi-Fi : STA (Station) - se connecte à un routeur existant, AP (Access Point) -
crée son propre réseau, STA+AP - les deux simultanément. Le module 'network' gère la connexion. Après
connexion, l'ESP32 reçoit une adresse IP via DHCP. La reconnexion automatique peut être configurée.
▶ Sécurité des identifiants Wi-Fi
Ne jamais écrire le SSID et le mot de passe directement dans [Link]. Utilisez un fichier [Link] qui
n'est pas partagé. Pensez aussi aux certificats SSL/TLS pour les connexions HTTPS. Pour les projets
publics, utilisez des variables d'environnement ou une interface de configuration.
💻 Exemples de Code
📄 Connexion Wi-Fi avec reconnexion auto
import network
import time
if [Link]():
print("Déjà connecté:", [Link]()[0])
return sta
debut = [Link]()
while not [Link]():
if [Link]() - debut > timeout:
print("
Echec connexion!")
return None
print(".", end="")
[Link](0.5)
# Utilisation
import ujson
with open("[Link]") as f:
cfg = [Link](f)
✏️Exercices Pratiques
Exercice 1 : Scanner Wi-Fi
Créez un programme qui scanne tous les réseaux Wi-Fi disponibles et affiche : SSID, puissance du
signal (RSSI), type de sécurité, canal. Triez les résultats par force de signal (du plus fort au plus
faible).
✅ Correction :
import network
import time
sta = [Link](network.STA_IF)
[Link](True)
[Link](1)
# Trier par RSSI (index 3), du plus fort (moins négatif) au plus faible
[Link](key=lambda x: x[3], reverse=True)
print(f"
{'SSID':<25} {'RSSI':>5} {'Auth':<12} {'Canal':>5}")
print("-" * 52)
for r in reseaux:
ssid = r[0].decode('utf-8') if r[0] else "(caché)"
rssi = r[3]
auth = auth_types[r[4]] if r[4] < len(auth_types) else "Inconnu"
canal = r[2]
# Indicateur de force
force = "████" if rssi > -50 else "███ " if rssi > -65 else "██ " if rssi > -75
print(f"
Total: {len(reseaux)} réseaux trouvés")
✅ Correction :
import network, socket, gc, sys
from machine import reset
ap = [Link](network.AP_IF)
[Link](True)
[Link](essid="ESP32-Config", password="iot12345", authmode=3)
print("AP démarré:", [Link]()[0])
s = [Link]()
[Link](('', 80))
[Link](3)
while True:
conn, addr = [Link]()
request = [Link](1024)
<html><body style='font-family:Arial;padding:20px'>
<h2>ESP32 Info</h2>
<p><b>Plateforme:</b> {[Link]}</p>
<p><b>IP AP:</b> {[Link]()[0]}</p>
<p><b>RAM libre:</b> {gc.mem_free()} bytes</p>
<p><b>MicroPython:</b> {[Link]}</p>
</body></html>"""
[Link](html)
[Link]()
🎯 Objectifs de la session
✓
✓
Comprendre les requêtes HTTP GET et POST
✓
Envoyer des données de capteurs vers une API REST
✓
Récupérer des données depuis une API (météo, heure...)
Gérer les erreurs réseau et les timeouts
📚 Contenu Théorique
▶ HTTP et API REST
HTTP (HyperText Transfer Protocol) est le protocole web. GET récupère des données, POST envoie des
données. Une API REST retourne généralement du JSON. En MicroPython, le module urequests fonctionne
comme requests en Python standard. Pour les connexions HTTPS, le module ussl est utilisé
automatiquement.
💻 Exemples de Code
📄 Envoi de données vers une API
import urequests
import ujson
import time
payload = {
"station": station_id,
"timestamp": [Link](),
"temperature": temp,
"humidite": hum
}
try:
response = [Link](
url,
data=[Link](payload),
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
print("Données envoyées:", [Link])
else:
print("Erreur HTTP:", response.status_code)
[Link]()
return response.status_code == 200
except Exception as e:
print("Erreur réseau:", e)
return False
def obtenir_heure_ntp():
"""Obtenir l'heure actuelle via une API"""
try:
r = [Link]("[Link]
data = [Link]()
[Link]()
return [Link]("datetime", "Inconnu")
except Exception as e:
print("Erreur NTP:", e)
return None
heure = obtenir_heure_ntp()
print("Heure actuelle:", heure)
✏️Exercices Pratiques
Exercice 1 : Client météo en ligne
Utilisez l'API gratuite Open-Meteo ([Link] pour récupérer la météo actuelle de
votre ville (latitude, longitude). Affichez la température extérieure et le code météo sur l'OLED.
Comparez avec le capteur DHT22.
✅ Correction :
import urequests, ujson
from machine import Pin, I2C
import ssd1306
try:
print("Récupération météo en ligne...")
r = [Link](URL)
data = [Link]()
[Link]()
meteo = data["current_weather"]
temp_ext = meteo["temperature"]
vent = meteo["windspeed"]
code = meteo["weathercode"]
[Link](0)
[Link]("METEO EN LIGNE", 0, 0)
[Link](f"Temp: {temp_ext}C", 0, 16)
[Link](f"Vent: {vent}km/h", 0, 28)
[Link](f"Code: {code}", 0, 40)
[Link]()
except Exception as e:
print("Erreur:", e)
🎯 Objectifs de la session
✓
✓
Comprendre l'architecture publish/subscribe de MQTT
✓
Se connecter à un broker MQTT (HiveMQ, Mosquitto)
✓
Publier des données de capteurs sur des topics
S'abonner à des topics pour recevoir des commandes
📚 Contenu Théorique
▶ MQTT : le protocole de l'IoT
MQTT (Message Queuing Telemetry Transport) est un protocole léger idéal pour l'IoT. Architecture : un
Broker central reçoit et redistribue les messages. Les Clients publient (publish) sur des Topics, d'autres s'y
abonnent (subscribe). Topics hiérarchiques : 'maison/salon/temperature'. QoS 0 (au plus une fois), QoS 1
(au moins une fois), QoS 2 (exactement une fois). Broker gratuit : [Link] (port 1883).
💻 Exemples de Code
📄 Publish/Subscribe MQTT
from [Link] import MQTTClient
import ujson, time, dht
from machine import Pin
# Configuration MQTT
BROKER = "[Link]"
PORT = 1883
CLIENT_ID = "esp32_station_01"
TOPIC_PUB = b"iot/meteo/donnees"
TOPIC_SUB = b"iot/meteo/commandes"
capteur = dht.DHT22(Pin(4))
if [Link]("action") == "reboot":
import machine
[Link]()
elif [Link]("action") == "led_on":
from machine import Pin
Pin(2, [Link]).value(1)
# Connexion au broker
client = MQTTClient(CLIENT_ID, BROKER, PORT)
client.set_callback(callback_message)
[Link]()
[Link](TOPIC_SUB)
print(f"Connecté à {BROKER}, abonné à {TOPIC_SUB.decode()}")
# Boucle de publication
try:
while True:
# Vérifier les messages entrants
client.check_msg()
[Link](TOPIC_PUB, payload)
print("Publié:", payload)
[Link](30)
except KeyboardInterrupt:
[Link]()
print("Déconnecté.")
✏️Exercices Pratiques
Exercice 1 : Système domotique simple
Créez un système où l'ESP32 publie les données DHT22 toutes les 30s sur 'home/room1/sensors'. Il
s'abonne aussi à 'home/room1/led' pour recevoir des commandes ON/OFF/BLINK pour la LED.
Testez avec un client MQTT desktop (MQTT Explorer).
✅ Correction :
from [Link] import MQTTClient
from machine import Pin, PWM
import dht, ujson, time
BROKER = "[Link]"
ID = "home_room1_esp32"
T_SENSOR = b"home/room1/sensors"
T_LED = b"home/room1/led"
mode_led = "OFF"
dernier_pub = 0
cligno_state = 0
while True:
client.check_msg()
maintenant = time.ticks_ms()
# LED
if mode_led == "ON":
[Link](1)
elif mode_led == "OFF":
[Link](0)
elif mode_led == "BLINK":
if time.ticks_diff(maintenant, dernier_pub) > 500:
cligno_state = 1 - cligno_state
[Link](cligno_state)
time.sleep_ms(100)
🎯 Objectifs de la session
✓
✓
Installer et configurer Node-RED sur PC
✓
Créer un flow MQTT pour recevoir les données ESP32
✓
Construire un dashboard avec graphiques et jauges
Envoyer des commandes depuis le dashboard vers l'ESP32
📚 Contenu Théorique
▶ Node-RED
Node-RED est un outil de programmation visuelle basé sur [Link], idéal pour créer des dashboards IoT
sans code complexe. Il connecte des 'nodes' (blocs) avec des fils pour créer des flows. Nodes utiles : mqtt-
in/out (MQTT), dashboard (UI), function (JavaScript), debug (affichage). Installation : npm install -g node-
red, puis node-red dans le terminal. Interface web : [Link]
▶ Node-RED Dashboard
Le module node-red-dashboard ajoute des composants UI : gauge (jauge), chart (graphique), text (texte),
button (bouton), switch (interrupteur). Chaque composant est assigné à un groupe et un onglet. Le
dashboard est accessible à [Link]
💻 Exemples de Code
📄 ESP32 : code pour Node-RED dashboard
# ESP32 envoie des données JSON formatées pour Node-RED
from [Link] import MQTTClient
import dht, ujson, time
from machine import Pin, ADC
capteur = dht.DHT22(Pin(4))
ldr = ADC(Pin(34)); [Link](ADC.ATTN_11DB)
BROKER = "[Link]"
✏️Exercices Pratiques
Exercice 1 : Dashboard complet
Configurez Node-RED avec : 1) Une jauge de température (0-50°C), 2) Une jauge d'humidité (0-
100%), 3) Un graphique historique des 30 dernières températures, 4) Un bouton pour
allumer/éteindre la LED de l'ESP32, 5) Un affichage de la dernière mise à jour.
✅ Correction :
# Voici le flow JSON Node-RED à importer (menu Import > Clipboard) :
# Copiez ce JSON dans Node-RED -> Import -> Clipboard
FLOW_NODERED = """
[
{"id":"mqtt_temp","type":"mqtt
in","topic":"nodered/esp32/temperature","broker":"hivemq"},
{"id":"mqtt_hum","type":"mqtt
in","topic":"nodered/esp32/humidite","broker":"hivemq"},
{"id":"gauge_temp","type":"ui_gauge","label":"Température °C","min":0,"max":50},
{"id":"gauge_hum","type":"ui_gauge","label":"Humidité %","min":0,"max":100},
{"id":"chart_temp","type":"ui_chart","label":"Historique
T°","xAxisLabel":"Temps","yAxisLabel":"°C"},
{"id":"btn_led","type":"ui_button","label":"LED","payload":"true"},
{"id":"fn_led","type":"function","func":"[Link]={led:[Link]=='true'};retur
n msg;"},
{"id":"mqtt_cmd","type":"mqtt
out","topic":"nodered/esp32/commande","broker":"hivemq"}
]
"""
# Côté ESP32 : le code du cours suffit pour ce dashboard
🎯 Objectifs de la session
✓
✓
Implémenter la reconnexion Wi-Fi et MQTT automatique
✓
Utiliser le watchdog timer (WDT) pour redémarrer en cas de blocage
✓
Gérer les exceptions réseau proprement
Sécuriser les identifiants et utiliser MQTT avec TLS
📚 Contenu Théorique
▶ Robustesse d'un système IoT
Un système IoT doit fonctionner sans surveillance pendant des semaines ou des mois. Les problèmes
courants : perte de connexion Wi-Fi, broker MQTT indisponible, erreur lecture capteur, mémoire saturée
(MemoryError). Solutions : try/except systématique, reconnexion automatique avec backoff exponentiel,
watchdog timer, [Link]() régulier.
▶ Watchdog Timer (WDT)
Le WDT est un minuteur matériel qui redémarre automatiquement l'ESP32 si le programme ne lui envoie
pas un 'signal de vie' (feed) avant l'expiration du délai. En MicroPython : from machine import WDT; wdt =
WDT(timeout=8000). Il faut appeler [Link]() régulièrement (toutes les < 8 secondes). Si le programme se
bloque, l'ESP32 redémarre automatiquement.
💻 Exemples de Code
📄 Système IoT robuste avec reconnexion auto
import network, time, gc
from machine import WDT, reset
from [Link] import MQTTClient
import ujson, dht
from machine import Pin
WIFI_SSID = "MonReseau"
WIFI_PASS = "motdepasse"
BROKER = "[Link]"
CLIENT_ID = "esp32_robust_01"
capteur = dht.DHT22(Pin(4))
mqtt_client = None
def connecter_wifi(max_retry=10):
sta = [Link](network.STA_IF)
[Link](True)
if [Link]():
return sta
[Link](WIFI_SSID, WIFI_PASS)
for i in range(max_retry * 2):
if [Link]():
print("Wi-Fi OK:", [Link]()[0])
return sta
[Link]()
[Link](0.5)
def connecter_mqtt():
global mqtt_client
try:
client = MQTTClient(CLIENT_ID, BROKER)
[Link]()
mqtt_client = client
print("MQTT connecté")
return True
except Exception as e:
print("MQTT erreur:", e)
return False
# Initialisation
sta = connecter_wifi()
connecter_mqtt()
erreurs_consecutives = 0
while True:
[Link]() # Vital ! Sinon redémarrage automatique
try:
[Link]()
payload = [Link]({
"t": [Link](),
"h": [Link](),
"mem": gc.mem_free()
})
ok = publier_avec_retry(b"iot/robust/data", payload)
if ok:
erreurs_consecutives = 0
print("OK:", payload)
else:
erreurs_consecutives += 1
except Exception as e:
print("Erreur boucle:", e)
# Vérifier Wi-Fi
if not [Link]():
print("Wi-Fi perdu, reconnexion...")
connecter_wifi()
[Link](30)
✏️Exercices Pratiques
Exercice 1 : Système de monitoring de santé
Créez un programme qui monitore sa propre santé et publie toutes les minutes sur un topic 'health' :
uptime (secondes depuis démarrage), mémoire libre (bytes), nombre de messages envoyés avec
succès, nombre d'erreurs. Ajoutez un WDT et une reconnexion automatique.
✅ Correction :
import time, gc, network, ujson
from machine import WDT
from [Link] import MQTTClient
wdt = WDT(timeout=20000)
debut = [Link]()
msgs_ok = 0
erreurs = 0
def uptime():
return [Link]() - debut
sta = [Link](network.STA_IF)
client = MQTTClient("health_monitor", "[Link]")
[Link]()
derniere_publication = 0
while True:
[Link]()
maintenant = [Link]()
try:
[Link](b"iot/health", [Link](sante))
msgs_ok += 1
print(f"Santé: uptime={sante['uptime_s']}s mem={sante['mem_libre']}B")
except Exception as e:
erreurs += 1
print("Erreur:", e)
try:
[Link]()
except: pass
derniere_publication = maintenant
[Link]()
[Link](1)
🎯 Objectifs de la session
✓
✓
Combiner DHT22 + LDR + OLED + Wi-Fi + MQTT
✓
Créer un système end-to-end : capteur -> MQTT -> Node-RED dashboard
✓
Recevoir des commandes du dashboard
Assurer la robustesse et la reconnexion automatique
📚 Contenu Théorique
▶ Architecture système complète
Ce projet intègre toutes les compétences de la semaine : L'ESP32 lit les capteurs, affiche sur l'OLED, et
publie via MQTT vers un broker. Node-RED souscrit, affiche un dashboard en temps réel et permet
d'envoyer des commandes. L'ensemble est robuste avec reconnexion automatique et WDT.
💻 Exemples de Code
📄 Projet S3 complet — IoT End-to-End
# projet_s3.py - Station météo IoT complète
import network, time, gc, ujson, dht
from machine import Pin, I2C, ADC, WDT
from [Link] import MQTTClient
import ssd1306
etat_led = False
mqtt_client = None
def connecter():
global mqtt_client
# Wi-Fi
sta = [Link](network.STA_IF)
[Link](True)
if not [Link]():
[Link](0); [Link]("Connexion WiFi", 5, 28); [Link]()
[Link](cfg["wifi_ssid"], cfg["wifi_password"])
for _ in range(20):
[Link]()
if [Link](): break
[Link](0.5)
# MQTT
try:
c = MQTTClient([Link]("device_id","esp32"), BROKER)
c.set_callback(on_cmd)
[Link]()
[Link](T_CMD)
mqtt_client = c
print("Connecté!")
return True
except Exception as e:
print("Connexion erreur:", e)
return False
connecter()
derniere_pub = 0
try:
while True:
[Link]()
maintenant = time.ticks_ms()
if mqtt_client:
mqtt_client.check_msg()
payload = [Link]({"t":t,"h":h,"lum":lum,"led":etat_led})
mqtt_client.publish(T_DATA, payload)
print(f"T={t:.1f} H={h:.1f} L={lum}")
afficher_oled(t, h, lum, True)
derniere_pub = maintenant
except Exception as e:
print("Erreur:", e)
afficher_oled(0, 0, 0, False)
connecter()
[Link]()
time.sleep_ms(100)
except KeyboardInterrupt:
[Link](0); [Link]()
✏️Exercices Pratiques
Exercice 1 : Alertes par MQTT
Ajoutez un système d'alertes : si la température dépasse 30°C ou l'humidité dépasse 80%, publiez
immédiatement sur un topic 'station01/alerte' avec le type d'alerte, la valeur, et l'horodatage. L'alerte
ne se publie qu'une seule fois jusqu'à ce que la valeur repasse sous le seuil.
✅ Correction :
# Ajouter dans le projet S3 :
alertes_actives = {"temp": False, "hum": False}
# Alerte humidité
if h > 80 and not alertes_actives["hum"]:
alerte = [Link]({"type": "HUM_HAUTE", "valeur": h, "seuil": 80, "ts":
[Link]()})
mqtt_client.publish(b"station01/alerte", alerte)
alertes_actives["hum"] = True
print(f"ALERTE HUM: {h}%")
elif h <= 80:
alertes_actives["hum"] = False
🎯 Objectifs de la session
✓
✓
Comprendre le protocole de contrôle PWM d'un servomoteur
✓
Contrôler la position angulaire (0° à 180°)
✓
Créer des mouvements fluides (sweep)
Intégrer le servo dans un système IoT commandé à distance
📚 Contenu Théorique
▶ Comment fonctionne un servomoteur
Un servomoteur est contrôlé par un signal PWM à 50Hz (période 20ms). La position est déterminée par la
largeur d'impulsion : 1ms = 0°, 1.5ms = 90°, 2ms = 180°. En MicroPython, on utilise [Link] avec
freq=50, puis on calcule le duty cycle correspondant. Formule : duty = angle * (duty_max - duty_min) / 180 +
duty_min.
💻 Exemples de Code
📄 Contrôle servomoteur
from machine import Pin, PWM
import time
class Servo:
"""Classe pour contrôler un servomoteur"""
def deinit(self):
[Link]()
# Utilisation
servo = Servo(pin=13)
print("Test positions")
for angle in [0, 45, 90, 135, 180]:
print(f"Angle: {angle}°")
[Link](angle)
[Link](1)
print("Balayage continu")
[Link]()
[Link]()
✏️Exercices Pratiques
Exercice 1 : Servo commandé par MQTT
Contrôlez la position du servo via MQTT. Abonnez-vous au topic 'servo/angle'. Quand un message
arrive avec un nombre entre 0 et 180, déplacez le servo vers cet angle progressivement. Publiez la
position actuelle sur 'servo/position' après chaque mouvement.
✅ Correction :
from machine import Pin, PWM
from [Link] import MQTTClient
import time
class Servo:
def __init__(self, pin):
[Link] = PWM(Pin(pin), freq=50)
[Link] = 90
self.set_angle(90)
def set_angle(self, a):
a = max(0, min(180, a))
d = 26 + a * 102 // 180
[Link](d); [Link] = a
servo = Servo(13)
client = MQTTClient("servo_ctrl", "[Link]")
servo.set_angle([Link] + step)
time.sleep_ms(15)
[Link](b"servo/position", str([Link]))
except: pass
client.set_callback(on_msg)
[Link]()
[Link](b"servo/angle")
print("En attente commandes servo...")
while True:
client.check_msg()
time.sleep_ms(50)
🎯 Objectifs de la session
✓
✓
Comprendre le fonctionnement d'un module relais
✓
Sécuriser le câblage 220V (DANGER - précautions obligatoires)
✓
Contrôler un appareil électrique via MQTT
Créer un minuteur et un planificateur
📚 Contenu Théorique
▶ SÉCURITÉ ÉLECTRIQUE - PRIORITÉ ABSOLUE
AVERTISSEMENT : Le 220V est dangereux et peut être mortel. Règles strictes : 1) Toujours couper
l'alimentation avant de câbler. 2) Ne jamais toucher les fils sous tension. 3) Utiliser des boîtiers isolés pour
les connexions 220V. 4) Les modules relais de 5V fonctionnent parfaitement avec l'ESP32 via un transistor
ou un isolateur. 5) Pour les débutants, utiliser uniquement des prises télécommandées ou des modules
avec isolation optique.
▶ Module relais
Un relais est un interrupteur électromagnétique. Le module relais prend une commande 3.3V/5V de l'ESP32
et commute un circuit 220V pouvant supporter jusqu'à 10A. Le module inclut généralement un transistor et
une diode de roue libre. Connexions : IN = signal GPIO, VCC = 3.3V ou 5V, GND = masse. Les relais sont
souvent actifs bas (LOW = fermé).
💻 Exemples de Code
📄 Contrôle relais avec timer
from machine import Pin
import time
class Relais:
def __init__(self, pin_num, actif_bas=True):
[Link] = Pin(pin_num, [Link])
self.actif_bas = actif_bas
[Link] = False
[Link]()
def allumer(self):
[Link](0 if self.actif_bas else 1)
[Link] = True
print(f"Relais GPIO{[Link]} : ON")
def eteindre(self):
[Link](1 if self.actif_bas else 0)
[Link] = False
print(f"Relais GPIO{[Link]} : OFF")
def toggle(self):
if [Link]: [Link]()
else: [Link]()
✏️Exercices Pratiques
Exercice 1 : Prise connectée intelligente
Créez un système pour une prise connectée : 1) ON/OFF via MQTT, 2) Minuterie configurable
(publier le temps en secondes), 3) Coupure automatique après 2 heures maximum (sécurité), 4)
Publication de l'état sur 'prise/etat' toutes les 30s.
✅ Correction :
from machine import Pin
from [Link] import MQTTClient
import time, ujson
def allumer():
global etat, temps_allumage
[Link](0); etat = True
temps_allumage = [Link]()
print("Prise ON")
def eteindre():
global etat, temps_allumage
[Link](1); etat = False
temps_allumage = None
print("Prise OFF")
t = [Link]()
v = [Link]()
if t == "prise/cmd":
if v == "ON": allumer()
elif v == "OFF": eteindre()
elif t == "prise/minuterie":
try:
duree = int(v)
allumer()
# Note: implémentation async requise pour production
print(f"Minuterie {duree}s")
except: pass
client.set_callback(on_cmd)
[Link]()
[Link](b"prise/cmd")
[Link](b"prise/minuterie")
derniere_pub = 0
while True:
client.check_msg()
maintenant = [Link]()
# Coupure sécurité 2h
if etat and temps_allumage and (maintenant - temps_allumage > MAX_DUREE):
print("Coupure sécurité 2h!")
eteindre()
time.sleep_ms(100)
🎯 Objectifs de la session
✓
✓
Utiliser le RTC (Real-Time Clock) interne de l'ESP32
✓
Synchroniser l'heure via NTP (Network Time Protocol)
✓
Créer un scheduler simple pour exécuter des tâches à heure fixe
Implémenter des tâches périodiques sans blocage (non-bloquant)
📚 Contenu Théorique
▶ RTC et NTP
L'ESP32 possède un RTC interne mais il perd l'heure à chaque redémarrage. NTP (Network Time Protocol)
permet de synchroniser l'heure via Internet. En MicroPython, le module ntptime synchronise [Link]().
Après synchronisation, [Link]().datetime() retourne (année, mois, jour, semaine, heure, min, sec,
sous-sec).
▶ Programmation non-bloquante
Dans les systèmes embarqués, il ne faut JAMAIS utiliser [Link]() dans la boucle principale si on a
plusieurs tâches à gérer (capteurs, MQTT, affichage...). La technique est de mémoriser le dernier temps
d'exécution et de vérifier si le délai est écoulé : if time.ticks_diff(maintenant, dernier) > intervalle.
💻 Exemples de Code
📄 NTP et scheduler non-bloquant
import ntptime
import time
from machine import RTC
def synchro_ntp(timezone_offset=1):
"""Synchronise l'heure via NTP (offset en heures par rapport UTC)"""
try:
[Link]() # UTC
# Ajuster pour le fuseau (ex: +1 pour Bénin)
r = RTC()
t = list([Link]())
t[4] = (t[4] + timezone_offset) % 24 # Ajuster les heures
[Link](tuple(t))
print(f"NTP synchro: {t[4]:02d}:{t[5]:02d}:{t[6]:02d}")
return True
except Exception as e:
print("NTP erreur:", e)
return False
def heure_actuelle():
t = RTC().datetime()
return t[4], t[5], t[6] # heure, min, sec
def formatter_heure():
h, m, s = heure_actuelle()
return f"{h:02d}:{m:02d}:{s:02d}"
class Tache:
def __init__(self, nom, intervalle_ms, fonction):
[Link] = nom
[Link] = intervalle_ms
[Link] = fonction
[Link] = 0
def executer_si_besoin(self):
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, [Link]) >= [Link]:
[Link] = maintenant
[Link]()
return True
return False
# Exemple d'utilisation
synchro_ntp()
def lire_capteurs():
print(f"[{formatter_heure()}] Lecture capteurs")
def publier_mqtt():
print(f"[{formatter_heure()}] Publication MQTT")
def afficher_ecran():
print(f"[{formatter_heure()}] Rafraîchissement écran")
taches = [
Tache("capteurs", 2000, lire_capteurs),
Tache("mqtt", 30000, publier_mqtt),
Tache("ecran", 1000, afficher_ecran),
]
print("Scheduler démarré")
while True:
for tache in taches:
tache.executer_si_besoin()
time.sleep_ms(50) # 50ms = résolution minimum
✏️Exercices Pratiques
Exercice 1 : Programmateur horaire
Créez un programmateur qui exécute des actions selon l'heure. Définissez au moins 3 règles : ex.
LED allumée de 8h à 20h, mesure capteur toutes les 5 minutes, message MQTT 'bonjour' à 7h00
chaque matin. Utilisez le scheduler non-bloquant.
✅ Correction :
import ntptime, time
from machine import RTC, Pin
from [Link] import MQTTClient
synchro_ntp()
led = Pin(2, [Link])
client = MQTTClient("scheduler", "[Link]")
[Link]()
def heure():
t = RTC().datetime()
return t[4], t[5] # heure, minutes
def regle_led_jour():
h, m = heure()
[Link](1 if 8 <= h < 20 else 0)
def regle_bonjour():
h, m = heure()
if h == 7 and m == 0:
[Link](b"maison/bonjour", "Bonjour!")
print("Message bonjour envoyé")
dernier_capteur = 0
dernier_led = 0
dernier_bonjour = 0
while True:
maintenant = time.ticks_ms()
time.sleep_ms(100)
🎯 Objectifs de la session
✓
✓
Choisir et définir votre projet IoT final
✓
Rédiger le cahier des charges
✓
Concevoir l'architecture matérielle et logicielle
Lister le matériel nécessaire et créer un schéma de câblage
📚 Contenu Théorique
▶ Idées de projets finaux
Voici des idées selon votre intérêt : Station météo complète avec dashboard web, Système d'arrosage
automatique avec capteur d'humidité du sol, Boîte aux lettres connectée (notification MQTT), Système de
surveillance de consommation électrique, Compteur de personnes dans une pièce, Aquarium intelligent
(température, pH, éclairage), Portail automatique avec capteur et application.
▶ Cahier des charges
Un bon cahier des charges IoT décrit : les capteurs utilisés et leurs branchements, les actionneurs (relais,
servo, LED, buzzer), le protocole de communication (MQTT, HTTP), le format des données échangées, les
conditions de déclenchement des alertes, l'interface utilisateur (dashboard, OLED, app mobile), les
conditions d'environnement (alimentation, boîtier).
💻 Exemples de Code
📄 Template de cahier des charges
# CAHIER DES CHARGES - PROJET FINAL IoT
# À compléter selon votre projet
PROJET = {
"nom": "Votre Projet",
"description": "Description courte du projet",
"capteurs": [
{"type": "DHT22", "pin": 4, "grandeur": "temp+hum"},
# Ajoutez vos capteurs
],
"actionneurs": [
{"type": "LED", "pin": 2, "role": "Alerte visuelle"},
# Ajoutez vos actionneurs
],
"communication": {
"protocole": "MQTT",
"broker": "[Link]",
"topics_pub": [
"projet/sensors/data",
],
"topics_sub": [
"projet/control/led",
]
},
"logique": [
"Si température > 35°C: alerte + MQTT",
# Décrivez votre logique
],
"materiel_requis": [
"ESP32",
"DHT22",
# Listez votre matériel
]
}
✏️Exercices Pratiques
Exercice 1 : Rédiger votre cahier des charges
Choisissez votre projet final parmi les idées proposées ou inventez le vôtre. Rédigez un cahier des
charges complet avec : nom, description, liste des composants, schéma de câblage (même à la
main), liste des topics MQTT, description de l'interface utilisateur, et les règles de fonctionnement
automatique.
✅ Correction :
# Exemple de projet : STATION D'ARROSAGE AUTOMATIQUE
PROJET_ARROSAGE = {
"nom": "ArroSmart",
"description": "Système d'arrosage automatique basé sur humidité du sol",
"capteurs": [
{"type": "YL-69", "pin": 34, "adc": True, "grandeur": "humidite_sol"},
{"type": "DHT22", "pin": 4, "grandeur": "temp_air+hum_air"},
],
"actionneurs": [
{"type": "Relais", "pin": 16, "role": "Pompe à eau 5V"},
{"type": "LED_verte", "pin": 2, "role": "Pompe active"},
{"type": "OLED", "bus": "I2C", "role": "Affichage état"},
],
"topics_mqtt": {
"donnees": "arrosage/sensors",
"etat_pompe": "arrosage/pompe/etat",
"cmd_pompe": "arrosage/pompe/cmd",
"alerte": "arrosage/alerte"
},
"regles": [
"Humidité sol < 30% ET heure entre 6h-20h -> allumer pompe 60s",
"Humidité sol > 70% -> arrêter pompe",
"Pompe allumée > 5min -> arrêt forcé + alerte",
],
"frequence": 60
}
🎯 Objectifs de la session
✓
✓
Coder le programme principal du projet
✓
Intégrer tous les composants matériels
✓
Connecter et tester la communication MQTT
Créer le dashboard Node-RED du projet
📚 Contenu Théorique
▶ Structure recommandée du projet final
Organisez votre projet en plusieurs fichiers : [Link] (boucle principale + orchestration), [Link]
(configuration Wi-Fi, MQTT, seuils), [Link] (fonctions de lecture des capteurs), [Link] (fonctions
de contrôle des actionneurs), [Link] (fonctions d'affichage OLED), mqtt_handler.py (gestion connexion
et messages MQTT). Cette séparation rend le code maintenable et testable.
💻 Exemples de Code
📄 Architecture projet final - [Link]
# [Link] - Projet Final IoT
# Structure recommandée pour un projet complet
import time, gc
from machine import WDT
wdt = WDT(timeout=60000)
# Tâches non-bloquantes
TACHES = {
"capteurs": {"intervalle": 2000, "dernier": 0},
"mqtt_pub": {"intervalle": 30000, "dernier": 0},
"affichage": {"intervalle": 1000, "dernier": 0},
"securite": {"intervalle": 5000, "dernier": 0},
"gc": {"intervalle": 60000, "dernier": 0},
}
# État global
etat = {
"temperature": 0.0,
"humidite": 0.0,
"alarme": False,
"connexion_ok": False,
}
def tick_tache(nom):
"""Vérifie si une tâche doit s'exécuter"""
t = TACHES[nom]
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, t["dernier"]) >= t["intervalle"]:
t["dernier"] = maintenant
return True
return False
while True:
[Link]()
if tick_tache("capteurs"):
# lire les capteurs et mettre à jour etat
pass # Remplacer par vos lectures réelles
if tick_tache("mqtt_pub"):
# publier les données
pass
if tick_tache("affichage"):
# rafraîchir l'OLED
pass
if tick_tache("securite"):
# vérifier les seuils et déclencher alertes
pass
if tick_tache("gc"):
[Link]()
time.sleep_ms(50) # 20 Hz boucle
✏️Exercices Pratiques
Exercice 1 : Implémenter votre projet complet
Développez votre projet final en suivant l'architecture recommandée. Créez tous les fichiers
nécessaires ([Link], [Link], [Link], mqtt_handler.py, [Link], [Link]). Testez
chaque module séparément avant d'intégrer dans [Link].
✅ Correction :
# [Link] - Module capteurs
import dht
from machine import Pin, ADC
class CapteursDHT22:
def __init__(self, pin):
[Link] = dht.DHT22(Pin(pin))
def lire(self):
[Link]()
return {
"temperature": round([Link](), 1),
"humidite": round([Link](), 1)
class LED:
def __init__(self, pin): [Link] = Pin(pin, [Link])
def on(self): [Link](1)
def off(self): [Link](0)
def toggle(self): [Link]()
class MQTTHandler:
def __init__(self, client_id, broker, callback=None):
[Link] = MQTTClient(client_id, broker)
if callback: [Link].set_callback(callback)
[Link]()
def check(self):
[Link].check_msg()
🎯 Objectifs de la session
✓
✓
Tester toutes les fonctionnalités du projet
✓
Identifier et corriger les bugs avec des techniques de débogage
✓
Optimiser la consommation mémoire
Mesurer les performances et les temps de réponse
📚 Contenu Théorique
▶ Techniques de débogage MicroPython
Outils de débogage : 1) print() avec timestamps pour tracer l'exécution. 2) try/except avec affichage de
l'exception complète (import sys; sys.print_exception(e)). 3) gc.mem_free() pour surveiller la mémoire. 4)
Tester chaque module indépendamment avant l'intégration. 5) Utiliser le REPL pour tester des fonctions
isolées. 6) micropython.mem_info() pour le détail de la mémoire.
💻 Exemples de Code
📄 Outils de débogage et test
import sys, gc, time
try:
resultat = fonction(*args)
duree = time.ticks_diff(time.ticks_ms(), debut)
mem_apres = gc.mem_free()
mem_utilise = mem_avant - mem_apres
print(f" SUCCÈS en {duree}ms | Mémoire: -{mem_utilise}B | Résultat:
{resultat}")
return True
except Exception as e:
print(f" ÉCHEC: ", end="")
sys.print_exception(e)
return False
def rapport_systeme():
"""Affiche l'état complet du système"""
import micropython, os
print("
=== RAPPORT SYSTÈME ===")
print(f"Mémoire libre: {gc.mem_free()} bytes")
print(f"Mémoire allouée: {gc.mem_alloc()} bytes")
try:
stats = [Link]('/')
flash_libre = stats[0] * stats[3]
print(f"Flash libre: {flash_libre // 1024} KB")
except: pass
print(f"Version: {[Link]}")
print("=" * 22)
def test_dht(pin=4):
import dht
from machine import Pin
c = dht.DHT22(Pin(pin))
[Link]()
return f"T={[Link]()} H={[Link]()}"
rapport_systeme()
test_composant("Wi-Fi", test_wifi)
test_composant("DHT22", test_dht, 4)
✏️Exercices Pratiques
Exercice 1 : Suite de tests automatisés
Créez un fichier test_projet.py avec une suite de tests automatisés pour votre projet. Testez :
connexion Wi-Fi, lecture de chaque capteur, connexion MQTT, publication d'un message test,
réception d'une commande test. Générez un rapport avec le résultat de chaque test (PASS/FAIL) et
le temps d'exécution.
✅ Correction :
import sys, gc, time, network, ujson
from [Link] import MQTTClient
resultats = []
# Tests
def t_wifi():
sta = [Link](network.STA_IF)
assert [Link](), "Non connecté"
return [Link]()[0]
def t_dht():
import dht; from machine import Pin
c = dht.DHT22(Pin(4)); [Link]()
assert -10 < [Link]() < 60
return f"{[Link]()}°C"
def t_mqtt():
c = MQTTClient("test_tmp", "[Link]")
[Link](); [Link](b"test/ping", b"ok"); [Link]()
return "OK"
# Rapport
ok = sum(1 for _,p,_,_ in resultats if p)
total = len(resultats)
print(f"
=== {ok}/{total} tests passés ===")
🎯 Objectifs de la session
✓
✓
Rédiger un [Link] complet pour le projet
✓
Documenter le code avec des docstrings
✓
Créer des schémas de câblage et diagrammes
Préparer une présentation du projet
📚 Contenu Théorique
▶ Importance de la documentation
Un projet bien documenté : facilite la maintenance (vous en aurez besoin dans 6 mois !), permet le partage
avec la communauté (GitHub), démontre le professionnalisme, et aide au débogage. Un bon README
contient : description, prérequis matériels et logiciels, schéma de câblage, instructions d'installation,
exemples d'utilisation, description des topics MQTT, et captures du dashboard.
💻 Exemples de Code
📄 Template [Link]
# Documentation - Template [Link]
# Voici le contenu que vous devriez écrire dans votre [Link]
README_CONTENU = """
# NOM_DU_PROJET
## Matériel requis
## Installation
## Configuration
Editez [Link] :
{
"wifi_ssid": "VOTRE_SSID",
"wifi_password": "VOTRE_MOT_DE_PASSE",
"mqtt_broker": "[Link]",
"device_id": "mon_esp32"
}
## Topics MQTT
## Dashboard
## Schéma de câblage
## Auteur
print(README_CONTENU)
✏️Exercices Pratiques
Exercice 1 : Documenter votre projet
Rédigez la documentation complète de votre projet. Créez un [Link] avec toutes les sections
du template. Ajoutez des docstrings à toutes vos fonctions (description, paramètres, retour). Créez
un schéma de câblage sur papier ou avec un outil en ligne ([Link], [Link]).
✅ Correction :
# Exemple de fonctions bien documentées
def lire_temperature(capteur_dht):
"""
Lit la température depuis un capteur DHT22.
Args:
capteur_dht: Instance dht.DHT22 initialisée
Returns:
float: Température en Celsius, arrondie à 1 décimale
Raises:
OSError: Si le capteur ne répond pas
Example:
>>> from machine import Pin
>>> import dht
>>> c = dht.DHT22(Pin(4))
>>> temp = lire_temperature(c)
>>> print(f"Temp: {temp}°C")
Temp: 25.3°C
"""
capteur_dht.measure()
return round(capteur_dht.temperature(), 1)
Args:
client: Instance MQTTClient connectée
topic (bytes): Topic MQTT (ex: b'maison/temp')
donnees (dict): Dictionnaire de données à sérialiser en JSON
Returns:
bool: True si succès, False si erreur
Example:
>>> publier_mqtt(client, b'capteur/data', {'temp': 25.3})
True
"""
import ujson
try:
[Link](topic, [Link](donnees))
return True
except Exception as e:
print(f"Erreur MQTT publish: {e}")
return False
🎯 Objectifs de la session
✓
✓
Réviser tous les concepts clés du mois
✓
Identifier et combler les lacunes
✓
Pratiquer des exercices récapitulatifs
Préparer la démonstration finale
📚 Contenu Théorique
▶ Récapitulatif du mois de formation
Semaine 1 - Fondamentaux MicroPython : Installation, syntaxe Python, fonctions, GPIO, PWM. Semaine 2 -
Capteurs : DHT22, HC-SR04, LDR, OLED SSD1306, stockage fichiers. Semaine 3 - Connectivité IoT : Wi-
Fi, HTTP/REST, MQTT publish/subscribe, Node-RED dashboard. Semaine 4 - Automatisation :
Servomoteur, relais 220V, RTC/NTP, scheduler non-bloquant, débogage, documentation.
💻 Exemples de Code
📄 Quiz de révision interactif
# Quiz de révision - exécutez et répondez dans le REPL
QUIZ = [
{
"q": "Quelle est la fréquence PWM pour un servomoteur ?",
"r": "50 Hz",
"explication": "Les servos attendent un signal PWM à 50Hz (période 20ms)"
},
{
"q": "Quel module MicroPython gère le Wi-Fi ?",
"r": "network",
"explication": "import network; sta = [Link](network.STA_IF)"
},
{
"q": "Quelle est la résistance recommandée pour le pull-up DHT22 ?",
"r": "4.7kΩ",
"explication": "Entre DATA et VCC, pour stabiliser le bus 1-wire du DHT"
},
{
"q": "Quel est le port MQTT par défaut (non chiffré) ?",
"r": "1883",
"explication": "MQTT standard=1883, MQTT avec TLS=8883"
},
{
"q": "Comment éviter de bloquer la boucle principale avec des tâches
multiples ?",
"r": "time.ticks_diff avec timestamp (non-bloquant)",
"explication": "Mémoriser le dernier temps d'exécution et vérifier si le
délai est écoulé"
},
{
"q": "Quelle fonction MicroPython redémarre l'ESP32 ?",
"r": "[Link]()",
"explication": "from machine import reset; reset()"
},
{
"q": "Comment libérer la mémoire RAM en MicroPython ?",
"r": "[Link]()",
"explication": "import gc; [Link]() - lance le garbage collector"
},
{
"q": "Quelle est la tension max d'entrée sur les GPIO ADC de l'ESP32 ?",
"r": "3.3V",
"explication": "L'ESP32 fonctionne en 3.3V et n'est pas 5V-tolérant sur les
ADC"
},
]
score = 0
for i, q in enumerate(QUIZ):
print(f"
Q{i+1}: {q['q']}")
reponse = input("Votre réponse: ")
if [Link]().strip() in q['r'].lower():
print(f"✓ CORRECT! {q['explication']}")
score += 1
else:
print(f"✗ La bonne réponse: {q['r']}")
print(f" {q['explication']}")
print(f"
Score final: {score}/{len(QUIZ)}")
✏️Exercices Pratiques
Exercice 1 : Mini-projet récapitulatif
En 2 heures, créez un projet complet qui utilise : 1 capteur DHT22, 1 LED PWM, MQTT pour publier
les données, et une condition d'alerte. Le projet doit être robuste (reconnexion automatique, WDT) et
bien structuré (plusieurs fichiers). C'est votre dernière pratique avant la présentation finale !
✅ Correction :
# Solution récapitulative complète
# Fichier: recap_final.py
# Watchdog
wdt = WDT(timeout=30000)
# Hardware
capteur = dht.DHT22(Pin(4))
led = PWM(Pin(2), freq=1000)
# Wi-Fi
sta = [Link](network.STA_IF)
[Link](True)
[Link]("SSID", "PASSWORD")
while not [Link](): [Link](); [Link](0.5)
print("IP:", [Link]()[0])
# MQTT
client = MQTTClient("recap", "[Link]")
client.set_callback(on_cmd)
[Link]()
[Link](b"recap/cmd")
# Boucle principale
dernier = 0
while True:
[Link]()
client.check_msg()
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, dernier) > 10000:
try:
[Link]()
t = [Link]()
h = [Link]()
payload = [Link]({"t":t,"h":h,"mem":gc.mem_free()})
[Link](b"recap/data", payload)
print(f"T={t:.1f} H={h:.1f}")
except Exception as e:
print("Erreur:", e)
try: [Link]()
except: pass
[Link]()
dernier = maintenant
time.sleep_ms(100)
🎯 Objectifs de la session
✓
✓
Présenter votre projet complet en fonctionnement
✓
Expliquer les choix techniques
✓
Faire une démonstration live du système
Réfléchir aux améliorations possibles
📚 Contenu Théorique
▶ Félicitations !
Vous avez terminé un mois de formation intensive MicroPython & IoT. Vous maîtrisez maintenant : la
programmation embarquée avec MicroPython, la lecture de capteurs (température, humidité, distance,
lumière), l'affichage sur OLED, la communication Wi-Fi, les protocoles HTTP et MQTT, la création de
dashboards IoT avec Node-RED, le contrôle d'actionneurs (LED, servos, relais), la robustesse et la
documentation. Continuez à pratiquer, rejoignez des communautés, et publiez vos projets sur GitHub !
💻 Exemples de Code
📄 Checklist de présentation finale
# CHECKLIST PRÉSENTATION FINALE
# Vérifiez chaque point avant votre démonstration
CHECKLIST = {
"Matériel": [
"ESP32 chargé avec le code final",
"Tous les capteurs correctement câblés",
"Alimentation stable (USB ou batterie)",
"Connexion Wi-Fi disponible",
],
"Logiciel": [
"[Link] à jour avec les bons identifiants",
"Code testé et fonctionnel",
"Pas d'erreurs dans la console au démarrage",
"WDT configuré pour la robustesse",
],
"Dashboard": [
"Node-RED lancé sur l'ordinateur",
"Flow MQTT importé et déployé",
"Connexion au broker HiveMQ établie",
"Tous les widgets affichent des données",
],
"Documentation": [
"[Link] rédigé",
"Code commenté avec docstrings",
"Schéma de câblage disponible",
"Topics MQTT documentés",
],
"Présentation": [
"Préparer une introduction de 2 minutes",
"Démonstration live de toutes les fonctionnalités",
"Expliquer un problème rencontré et sa solution",
"Présenter les pistes d'amélioration",
]
}
print("
✏️Exercices Pratiques
Exercice 1 : Présentation et démonstration
Préparez une démonstration de 10-15 minutes de votre projet. Montrez : le démarrage du système,
les données en temps réel sur le dashboard, une action commandée depuis le dashboard, le
comportement lors d'une alerte. Expliquez votre code et vos choix techniques. Listez 3 améliorations
que vous pourriez apporter si vous aviez plus de temps.
✅ Correction :
# Guide de présentation
PRESENTATION = {
"introduction": [
"Présenter le problème résolu",
"Montrer le système physique (câblage)",
"Expliquer l'architecture globale",
],
"demonstration_live": [
"Démarrer l'ESP32 - montrer la connexion Wi-Fi et MQTT",
"Montrer les données en temps réel sur Node-RED",
"Déclencher une alerte en modifiant la valeur d'un capteur",
"Envoyer une commande depuis le dashboard",
"Montrer la robustesse (simuler une perte connexion)",
],
"explication_code": [
"Montrer la structure des fichiers",
"Expliquer la boucle principale non-bloquante",
"Montrer la gestion des erreurs et reconnexion",
],
"reflexion": [
"Difficulté principale rencontrée et solution",
"Ce qui a le mieux fonctionné",
"3 améliorations possibles",
"Prochaine étape d'apprentissage",
]
}
🎓 FÉLICITATIONS !
Vous avez complété la formation MicroPython & IoT
Pro Technology Plus — 9 mars 2026