🔥
TPs ESP32 MicroPython
11 Projets IoT avec WiFi, Capteurs et Actionneurs
🔥 ESP32
🐍 MicroPython
📋 11 TPs IoT
TP1 : Clignotement LED (Blink)
Premier programme MicroPython - GPIO Output
🎯 Objectifs pedagogiques
- Installer MicroPython sur ESP32
- Utiliser Thonny IDE
- Configurer une broche GPIO en sortie
- Comprendre les classes Pin et time
Materiel necessaire
Liste du materiel
- 1× ESP32 DevKit
- 1× LED rouge 5mm
- 1× Resistance 220Ω
- Breadboard + fils
Schema de câblage
ESP32 DevKit LED
┌─────────────┐
│ │ ┌───┐
│ GPIO2 ├───[220Ω]──────┤LED├─── GND
│ │ └───┘
│ GND ├───────────────────────
└─────────────┘
Note: GPIO2 est souvent connecte a la LED integree sur ESP32
Code MicroPython
# TP1 : Clignotement LED - ESP32 MicroPython # BTS Electronique from machine import Pin import time # Configuration de la broche LED en sortie led = Pin(2, Pin.OUT) # Boucle principale while True: led.value(1) # Allumer LED (HIGH) time.sleep(1) # Attendre 1 seconde led.value(0) # Éteindre LED (LOW) time.sleep(1) # Attendre 1 seconde
Version avec toggle
from machine import Pin import time led = Pin(2, Pin.OUT) while True: led.value(not led.value()) # Toggle (inverser l'etat) time.sleep_ms(500) # 500 millisecondes
Exercices
- Faire clignoter 3 LEDs en sequence (chenillard)
- Creer un signal SOS en morse
- Varier la frequence de clignotement progressivement
TP2 : Lecture Bouton Poussoir
Entree numerique et interruptions
Code : Lecture par polling
# TP2 : Bouton poussoir - Polling from machine import Pin import time # Configuration button = Pin(15, Pin.IN, Pin.PULL_UP) # Resistance pull-up interne led = Pin(2, Pin.OUT) while True: if button.value() == 0: # Bouton appuye (LOW avec pull-up) led.value(1) print("Bouton appuye!") else: led.value(0) time.sleep_ms(50) # Anti-rebond simple
Code : Interruption (IRQ)
# TP2 : Bouton avec interruption from machine import Pin import time led = Pin(2, Pin.OUT) led_state = False last_time = 0 def button_handler(pin): global led_state, last_time # Anti-rebond logiciel (200ms) current_time = time.ticks_ms() if time.ticks_diff(current_time, last_time) > 200: led_state = not led_state led.value(led_state) print(f"LED: {'ON' if led_state else 'OFF'}") last_time = current_time # Configuration bouton avec interruption sur front descendant button = Pin(15, Pin.IN, Pin.PULL_UP) button.irq(trigger=Pin.IRQ_FALLING, handler=button_handler) print("Appuyez sur le bouton...") # Boucle principale (peut faire autre chose) while True: time.sleep(1)
TP3 : PWM - LED RGB
Modulation de largeur d'impulsion
Code : Fade LED
# TP3 : PWM - Effet Fade from machine import Pin, PWM import time # Configuration PWM (frequence 1000Hz) led_pwm = PWM(Pin(2), freq=1000) while True: # Augmentation (0 → 1023) for duty in range(0, 1024, 8): led_pwm.duty(duty) time.sleep_ms(10) # Diminution (1023 → 0) for duty in range(1023, -1, -8): led_pwm.duty(duty) time.sleep_ms(10)
Code : LED RGB Rainbow
# TP3 : LED RGB - Effet Rainbow from machine import Pin, PWM import time # Configuration PWM pour RGB red = PWM(Pin(25), freq=1000) green = PWM(Pin(26), freq=1000) blue = PWM(Pin(27), freq=1000) def set_color(r, g, b): # Conversion 0-255 → 0-1023 red.duty(r * 4) green.duty(g * 4) blue.duty(b * 4) def hsv_to_rgb(h, s, v): """Conversion HSV vers RGB (h: 0-360, s,v: 0-1)""" if s == 0: return int(v*255), int(v*255), int(v*255) h = h / 60 i = int(h) f = h - i p = v * (1 - s) q = v * (1 - s * f) t = v * (1 - s * (1 - f)) if i == 0: r, g, b = v, t, p elif i == 1: r, g, b = q, v, p elif i == 2: r, g, b = p, v, t elif i == 3: r, g, b = p, q, v elif i == 4: r, g, b = t, p, v else: r, g, b = v, p, q return int(r*255), int(g*255), int(b*255) # Animation Rainbow while True: for hue in range(0, 360, 5): r, g, b = hsv_to_rgb(hue, 1, 1) set_color(r, g, b) time.sleep_ms(50)
TP4 : Capteur Ultrason HC-SR04
Mesure de distance
Code : Mesure de distance
# TP4 : Capteur Ultrason HC-SR04 from machine import Pin, time_pulse_us import time # Configuration broches trigger = Pin(5, Pin.OUT) echo = Pin(18, Pin.IN) def get_distance(): """Mesure la distance en cm""" # Envoyer impulsion trigger de 10µs trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) # Mesurer duree de l'echo duration = time_pulse_us(echo, 1, 30000) if duration < 0: return -1 # Timeout # Calculer distance (vitesse son = 343 m/s) distance = (duration * 0.0343) / 2 return distance # Boucle de mesure while True: dist = get_distance() if dist > 0: print(f"Distance: {dist:.1f} cm") else: print("Hors portee") time.sleep_ms(500)
Code : Radar avec LEDs
# Radar de recul avec LEDs indicatrices from machine import Pin, PWM, time_pulse_us import time trigger = Pin(5, Pin.OUT) echo = Pin(18, Pin.IN) led_green = Pin(25, Pin.OUT) led_yellow = Pin(26, Pin.OUT) led_red = Pin(27, Pin.OUT) buzzer = PWM(Pin(32), freq=1000, duty=0) def get_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, 30000) if duration < 0: return 999 return (duration * 0.0343) / 2 while True: dist = get_distance() # Éteindre toutes les LEDs led_green.value(0) led_yellow.value(0) led_red.value(0) buzzer.duty(0) if dist < 10: led_red.value(1) buzzer.duty(512) # Alarme sonore elif dist < 30: led_yellow.value(1) elif dist < 100: led_green.value(1) print(f"Distance: {dist:.1f} cm") time.sleep_ms(200)
TP5 : Capteur DHT11/DHT22
Temperature et humidite
Code : Lecture DHT11
# TP5 : Capteur DHT11/DHT22 from machine import Pin import dht import time # Configuration capteur (DHT11 ou DHT22) sensor = dht.DHT11(Pin(4)) # sensor = dht.DHT22(Pin(4)) # Pour DHT22 while True: try: # Mesure sensor.measure() # Lecture des valeurs temp = sensor.temperature() hum = sensor.humidity() print(f"🌡️ Temperature: {temp}°C") print(f"💧 Humidite: {hum}%") print("─" * 25) except OSError as e: print("Erreur de lecture DHT") time.sleep(2) # DHT11 necessite 2s entre lectures
TP6 : Écran OLED SSD1306
Affichage I2C 128x64
Code : Affichage OLED
# TP6 : Écran OLED SSD1306 I2C from machine import Pin, I2C import ssd1306 import time # Configuration I2C i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000) # Initialisation OLED (128x64 pixels) oled = ssd1306.SSD1306_I2C(128, 64, i2c) # Effacer l'ecran oled.fill(0) # Afficher du texte oled.text("ESP32 MicroPython", 0, 0) oled.text("BTS Electronique", 0, 16) oled.text("TP6: OLED", 0, 32) # Dessiner des formes oled.rect(0, 50, 128, 14, 1) # Rectangle oled.fill_rect(100, 0, 28, 10, 1) # Rectangle plein # Mettre a jour l'affichage oled.show()
Code : Station Meteo OLED + DHT
# Station meteo avec OLED + DHT11 from machine import Pin, I2C import ssd1306 import dht import time # Configuration i2c = I2C(0, scl=Pin(22), sda=Pin(21)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) sensor = dht.DHT11(Pin(4)) while True: try: sensor.measure() temp = sensor.temperature() hum = sensor.humidity() oled.fill(0) oled.text("=== METEO ===", 15, 0) oled.text(f"Temp: {temp} C", 10, 20) oled.text(f"Hum: {hum} %", 10, 35) oled.text("BTS Tanger", 25, 54) oled.show() except: oled.fill(0) oled.text("Erreur capteur", 10, 25) oled.show() time.sleep(2)
TP7 : Servomoteur
Controle de position angulaire
Code : Controle Servomoteur
# TP7 : Servomoteur SG90 from machine import Pin, PWM import time # Configuration PWM pour servo (50Hz) servo = PWM(Pin(13), freq=50) def set_angle(angle): """Convertir angle (0-180) en duty cycle""" # Servo: 0.5ms (0°) a 2.5ms (180°) sur periode 20ms # Duty: 26 (0°) a 128 (180°) sur echelle 0-1023 duty = int(26 + (angle / 180) * (128 - 26)) servo.duty(duty) # Test: balayage 0° → 180° → 0° while True: for angle in range(0, 181, 5): set_angle(angle) print(f"Angle: {angle}°") time.sleep_ms(50) for angle in range(180, -1, -5): set_angle(angle) time.sleep_ms(50)
TP8 : Connexion WiFi
Station et Point d'acces
Code : Connexion WiFi (Station)
# TP8 : Connexion WiFi - Mode Station import network import time # Configuration WiFi SSID = "NomDuReseau" PASSWORD = "MotDePasse" def connect_wifi(): # Activer interface WiFi station wlan = network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print(f"Connexion a {SSID}...") wlan.connect(SSID, PASSWORD) # Attendre la connexion (timeout 10s) timeout = 10 while not wlan.isconnected() and timeout > 0: print(".", end="") time.sleep(1) timeout -= 1 if wlan.isconnected(): print("\n✅ Connecte!") print(f"📍 IP: {wlan.ifconfig()[0]}") return wlan else: print("\n❌ Échec de connexion") return None # Connexion wifi = connect_wifi()
Code : Point d'acces (AP)
# ESP32 comme Point d'Acces WiFi import network # Configuration AP ap = network.WLAN(network.AP_IF) ap.active(True) ap.config(essid="ESP32_BTS", password="12345678", authmode=network.AUTH_WPA2_PSK) print(f"📶 AP cree: ESP32_BTS") print(f"📍 IP: {ap.ifconfig()[0]}")
TP9 : Serveur Web
Controle via navigateur
Code : Serveur Web LED Control
# TP9 : Serveur Web - Controle LED import network import socket from machine import Pin import time # Configuration led = Pin(2, Pin.OUT) SSID = "VotreWiFi" PASSWORD = "VotreMotDePasse" # Connexion WiFi wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(SSID, PASSWORD) while not wlan.isconnected(): time.sleep(1) print(f"IP: {wlan.ifconfig()[0]}") # Page HTML def web_page(): led_state = "ON" if led.value() else "OFF" html = f"""<!DOCTYPE html> <html> <head> <title>ESP32 LED Control</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body {{ font-family: Arial; text-align: center; margin-top: 50px; background: #1a1a2e; color: white; }} .btn {{ padding: 20px 40px; font-size: 24px; margin: 10px; border: none; border-radius: 10px; cursor: pointer; }} .on {{ background: #3fb950; color: white; }} .off {{ background: #f85149; color: white; }} .status {{ font-size: 32px; margin: 30px; padding: 20px; background: #222; border-radius: 10px; }} </style> </head> <body> <h1>🔥 ESP32 LED Control</h1> <div class="status">LED: {led_state}</div> <a href="/on"><button class="btn on">💡 ON</button></a> <a href="/off"><button class="btn off">🔌 OFF</button></a> </body> </html>""" return html # Serveur socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', 80)) s.listen(5) print("🌐 Serveur Web demarre") while True: conn, addr = s.accept() print(f"Connexion de {addr}") request = conn.recv(1024).decode() if "/on" in request: led.value(1) elif "/off" in request: led.value(0) response = web_page() conn.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" + response) conn.close()
TP10 : MQTT - Communication IoT
Publish/Subscribe avec broker
Code : MQTT Publisher (Capteur)
# TP10 : MQTT Publisher - Envoi donnees capteur from umqtt.simple import MQTTClient import network import dht from machine import Pin import time import json # Configuration WIFI_SSID = "VotreWiFi" WIFI_PASS = "VotreMotDePasse" MQTT_BROKER = "broker.hivemq.com" # Broker public gratuit MQTT_CLIENT_ID = "esp32_bts_tanger" MQTT_TOPIC = "bts/tanger/meteo" sensor = dht.DHT11(Pin(4)) # Connexion WiFi wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(WIFI_SSID, WIFI_PASS) while not wlan.isconnected(): time.sleep(1) print(f"WiFi connecte: {wlan.ifconfig()[0]}") # Connexion MQTT client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER) client.connect() print("MQTT connecte!") # Boucle d'envoi while True: try: sensor.measure() data = { "temperature": sensor.temperature(), "humidity": sensor.humidity(), "device": "ESP32_BTS" } payload = json.dumps(data) client.publish(MQTT_TOPIC, payload) print(f"📤 Publie: {payload}") except Exception as e: print(f"Erreur: {e}") time.sleep(10)
Code : MQTT Subscriber (LED)
# MQTT Subscriber - Controle LED a distance from umqtt.simple import MQTTClient import network from machine import Pin import time led = Pin(2, Pin.OUT) MQTT_TOPIC_CMD = "bts/tanger/led/cmd" def callback(topic, msg): print(f"📥 Recu: {msg}") if msg == b"ON": led.value(1) elif msg == b"OFF": led.value(0) # ... (connexion WiFi) client = MQTTClient("esp32_sub", "broker.hivemq.com") client.set_callback(callback) client.connect() client.subscribe(MQTT_TOPIC_CMD) print("🎧 En ecoute...") while True: client.check_msg() time.sleep_ms(100)
TP11 : Projet Final - Station IoT Complete
Integration capteurs + WiFi + Web + MQTT
🎯 Objectifs du projet
- Lire plusieurs capteurs (DHT, ultrason, LDR)
- Afficher sur ecran OLED
- Serveur Web avec interface responsive
- Publication MQTT des donnees
- Controle a distance des actionneurs
Architecture du projet
┌────────────────────────────────────────────────────────────┐
│ STATION IoT ESP32 │
├────────────────────────────────────────────────────────────┤
│ │
│ CAPTEURS ESP32 ACTIONNEURS │
│ ┌──────┐ ┌─────────┐ ┌──────┐ │
│ │DHT11 ├──GPIO4────┤ ├──GPIO2────┤ LED │ │
│ └──────┘ │ │ └──────┘ │
│ ┌──────┐ │ │ ┌──────┐ │
│ │HC-SR04├─GPIO5/18─┤ ESP32 ├──GPIO13───┤Servo │ │
│ └──────┘ │ │ └──────┘ │
│ ┌──────┐ │ │ ┌──────┐ │
│ │ LDR ├───ADC─────┤ ├──GPIO32───┤Buzzer│ │
│ └──────┘ │ │ └──────┘ │
│ │ ┌─────┐ │ │
│ │ │OLED │ │ │
│ │ │I2C │ │ │
│ │ └─────┘ │ │
│ └────┬────┘ │
│ │ │
│ WiFi 📶 │
│ │ │
│ ┌────────────┴────────────┐ │
│ │ │ │
│ Web Server MQTT Broker │
│ (port 80) (HiveMQ) │
│ │ │ │
│ Navigateur Dashboard │
│ 📱 💻 Node-RED │
└────────────────────────────────────────────────────────────┘
Code : Projet Station IoT
# TP11 : Station IoT Complete # BTS Electronique - ESP32 MicroPython import network import socket import time import json from machine import Pin, I2C, PWM, ADC, time_pulse_us import dht import ssd1306 from umqtt.simple import MQTTClient import _thread # ============ CONFIGURATION ============ WIFI_SSID = "VotreWiFi" WIFI_PASS = "VotreMotDePasse" MQTT_BROKER = "broker.hivemq.com" MQTT_TOPIC = "bts/tanger/station" # ============ INITIALISATION ============ # Capteurs dht_sensor = dht.DHT11(Pin(4)) trigger = Pin(5, Pin.OUT) echo = Pin(18, Pin.IN) ldr = ADC(Pin(34)) ldr.atten(ADC.ATTN_11DB) # Actionneurs led = Pin(2, Pin.OUT) buzzer = PWM(Pin(32), freq=1000, duty=0) # OLED i2c = I2C(0, scl=Pin(22), sda=Pin(21)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) # Variables globales sensor_data = {"temp": 0, "hum": 0, "dist": 0, "light": 0} # ============ FONCTIONS ============ def get_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) dur = time_pulse_us(echo, 1, 30000) return (dur * 0.0343) / 2 if dur > 0 else 999 def read_sensors(): global sensor_data try: dht_sensor.measure() sensor_data["temp"] = dht_sensor.temperature() sensor_data["hum"] = dht_sensor.humidity() except: pass sensor_data["dist"] = get_distance() sensor_data["light"] = ldr.read() def update_oled(): oled.fill(0) oled.text("=== IoT Station ===", 0, 0) oled.text(f"T:{sensor_data['temp']}C H:{sensor_data['hum']}%", 0, 16) oled.text(f"Dist: {sensor_data['dist']:.0f} cm", 0, 32) oled.text(f"Lum: {sensor_data['light']}", 0, 48) oled.show() def web_page(): return f"""<!DOCTYPE html> <html><head> <meta name="viewport" content="width=device-width"> <meta http-equiv="refresh" content="5"> <style> body{{font-family:Arial;background:#1a1a2e;color:#fff;text-align:center;padding:20px}} .card{{background:#16213e;border-radius:15px;padding:20px;margin:10px;display:inline-block;min-width:140px}} .val{{font-size:36px;color:#00f5d4}} .btn{{padding:15px 30px;margin:5px;border:none;border-radius:8px;font-size:18px;cursor:pointer}} .on{{background:#3fb950}}.off{{background:#f85149}} </style> </head><body> <h1>🏠 Station IoT ESP32</h1> <div class="card"><div>🌡️ Temp</div><div class="val">{sensor_data['temp']}°C</div></div> <div class="card"><div>💧 Humid</div><div class="val">{sensor_data['hum']}%</div></div> <div class="card"><div>📏 Distance</div><div class="val">{sensor_data['dist']:.0f}cm</div></div> <div class="card"><div>☀️ Lumiere</div><div class="val">{sensor_data['light']}</div></div> <h2>💡 Controle LED</h2> <a href="/led/on"><button class="btn on">ON</button></a> <a href="/led/off"><button class="btn off">OFF</button></a> </body></html>""" # ============ CONNEXION WIFI ============ wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(WIFI_SSID, WIFI_PASS) while not wlan.isconnected(): time.sleep(1) ip = wlan.ifconfig()[0] print(f"IP: {ip}") # ============ MQTT ============ mqtt = MQTTClient("esp32_station", MQTT_BROKER) mqtt.connect() # ============ SERVEUR WEB ============ s = socket.socket() s.bind(('', 80)) s.listen(5) s.setblocking(False) # ============ BOUCLE PRINCIPALE ============ last_mqtt = 0 while True: # Lecture capteurs read_sensors() update_oled() # Publication MQTT toutes les 10s if time.time() - last_mqtt > 10: mqtt.publish(MQTT_TOPIC, json.dumps(sensor_data)) last_mqtt = time.time() # Gestion requetes Web try: conn, addr = s.accept() req = conn.recv(1024).decode() if "/led/on" in req: led.value(1) if "/led/off" in req: led.value(0) conn.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" + web_page()) conn.close() except: pass time.sleep_ms(500)
Criteres d'evaluation
| Critere | Points |
|---|---|
| Câblage propre et fonctionnel | /3 |
| Lecture capteurs correcte | /3 |
| Affichage OLED | /2 |
| Serveur Web fonctionnel | /4 |
| Communication MQTT | /4 |
| Rapport et documentation | /4 |
| Total | /20 |