TPs ESP32 MicroPython - 11 Projets IoT | BTS Electronique

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

⏱️ 1h 📊 Debutant 🔧 machine.Pin

🎯 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

  1. Faire clignoter 3 LEDs en sequence (chenillard)
  2. Creer un signal SOS en morse
  3. Varier la frequence de clignotement progressivement
🔘

TP2 : Lecture Bouton Poussoir

Entree numerique et interruptions

⏱️ 1h30 📊 Debutant 🔧 Pin.IRQ

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

⏱️ 1h30 📊 Intermediaire 🔧 machine.PWM

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

⏱️ 2h 📊 Intermediaire 🔧 time_pulse_us

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

⏱️ 1h30 📊 Intermediaire 🔧 dht module

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

⏱️ 2h 📊 Intermediaire 🔧 I2C ssd1306

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

⏱️ 1h30 📊 Intermediaire 🔧 PWM 50Hz

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

⏱️ 2h 📊 Intermediaire 🔧 network

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

⏱️ 3h 📊 Avance 🔧 socket HTTP

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

⏱️ 3h 📊 Avance 🔧 umqtt.simple

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

⏱️ 6h 📊 Avance 🔧 Projet complet

🎯 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

CriterePoints
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

TPs ESP32 MicroPython - 11 Projets IoT