UE1.1 · 6 ECTS

Programmation embarquée C/Arduino

30h CM + 45h TP — 15 séances. Maîtrisez la plateforme open-source d'électronique embarquée la plus utilisée au monde.

15 Séances 30h CM 45h TP 6 ECTS
1

Introduction Arduino — IDE, structure d'un sketch, LED

Semaine 1CM · 2h
Comprendre l'architecture d'un microcontrôleur Arduino UNO
Savoir expliquer
Installer et utiliser l'IDE Arduino
Savoir faire
Écrire un programme setup()/loop() complet
Savoir analyser
Contrôler une LED avec digitalWrite() et delay()
Savoir produire

1. Architecture de l'Arduino UNO

L'Arduino UNO est basé sur le microcontrôleur ATmega328P (8 bits, 16 MHz). Il dispose de 14 broches numériques (dont 6 PWM), 6 entrées analogiques (ADC 10 bits), 32 KB de Flash et 2 KB de RAM. C'est la carte de développement IoT la plus répandue dans le monde.

ComposantDescription
MicrocontrôleurCircuit intégré combinant processeur, mémoire et E/S sur une seule puce. Conçu pour le temps réel et la faible consommation
Pin numériqueBroche pouvant être en état HIGH (5V) ou LOW (0V). Configurée en entrée (INPUT) ou sortie (OUTPUT) avec pinMode()
Pin PWMPulse Width Modulation — simule une tension analogique en variant la durée d'une impulsion
Analogique (ADC)Convertisseur Analogique-Numérique. Convertit une tension 0-5V en valeur entière 0-1023 (10 bits)
setup()Fonction exécutée UNE SEULE FOIS au démarrage. Initialise les pins, la communication série, les variables
loop()Fonction exécutée EN BOUCLE INFINIE après setup(). Contient le code principal du programme

2. Premier programme — Blink

Le programme "Blink" est le "Hello World" de l'Arduino. Il fait clignoter la LED intégrée sur la broche 13. La structure setup() + loop() est obligatoire dans tout sketch Arduino.

blink_toliara.inoArduino
// Structure minimale d'un sketch Arduino
const int LED_PIN    = 13;   // LED intégrée sur l'UNO
const int LED_ROUGE  = 7;    // LED externe sur pin 7
const int DELAI_MS   = 500;  // Délai en ms

void setup() {
  pinMode(LED_PIN,   OUTPUT);
  pinMode(LED_ROUGE, OUTPUT);
  Serial.begin(9600);
  Serial.println("Arduino IoT MUST Toliara - Démarré !");
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(DELAI_MS);
  digitalWrite(LED_PIN, LOW);
  delay(DELAI_MS);

  Serial.print("Cycle : ");
  Serial.println(millis() / 1000);
}
💡 Conseil
La fonction delay() BLOQUE tout le programme pendant X ms. Pour des systèmes réactifs (capteurs multiples), utilisez millis() et une variable pour enregistrer le dernier temps d'action.

3. Blink sans delay() — la bonne approche

millis() retourne le nombre de ms depuis le démarrage. En comparant le temps actuel au dernier changement d'état, on peut clignoter sans bloquer le reste du programme.

blink_millis.inoArduino
const int LED_PIN = 13;
const long INTERVALLE = 500;

unsigned long dernierChangement = 0;
int etatLED = LOW;

void setup() { pinMode(LED_PIN, OUTPUT); }

void loop() {
  unsigned long maintenant = millis();

  if (maintenant - dernierChangement >= INTERVALLE) {
    dernierChangement = maintenant;

    if (etatLED == LOW) etatLED = HIGH;
    else etatLED = LOW;

    digitalWrite(LED_PIN, etatLED);
  }
  // Ici, d'autres tâches peuvent s'exécuter EN PARALLÈLE
}
Exercice 1 — Contrôle de LEDs

a) Traffic Light Toliara : Câblez 3 LEDs (rouge, orange, vert) sur les pins 7, 8, 9. Programmez le feu tricolore : Vert 5s → Orange 2s → Rouge 4s.

b) SOS en Morse : Faites clignoter la LED en Morse : S = 3 courts (200ms), O = 3 longs (600ms), S = 3 courts. Pause de 2s entre chaque SOS.

c) Variateur PWM : Utilisez analogWrite() avec une LED sur pin 9 (PWM). Montée 0→255 puis descente 255→0 — effet respiration.

d) BONUS — Minuterie : LED éteinte. Quand on appuie sur un bouton (pin 4, INPUT_PULLUP), la LED s'allume 10s puis s'éteint.

✓ Corrigé 1a — Traffic Light
traffic_light.ino
const int VERT   = 9;
const int ORANGE = 8;
const int ROUGE  = 7;

void setup() {
  pinMode(VERT, OUTPUT); pinMode(ORANGE, OUTPUT); pinMode(ROUGE, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(VERT, HIGH); digitalWrite(ORANGE, LOW); digitalWrite(ROUGE, LOW);
  Serial.println("VERT — Avancez");
  delay(5000);

  digitalWrite(VERT, LOW); digitalWrite(ORANGE, HIGH);
  Serial.println("ORANGE — Ralentissez");
  delay(2000);

  digitalWrite(ORANGE, LOW); digitalWrite(ROUGE, HIGH);
  Serial.println("ROUGE — Stop");
  delay(4000);
}
✓ Corrigé 1c — Variateur PWM
respiration.ino
const int LED_PWM = 9;

void setup() { pinMode(LED_PWM, OUTPUT); }

void loop() {
  for (int i = 0; i <= 255; i++) { analogWrite(LED_PWM, i); delay(8); }
  for (int i = 255; i >= 0; i--) { analogWrite(LED_PWM, i); delay(8); }
}
2

Entrées numériques — Boutons, pull-up, anti-rebond

Semaine 1CM+TP · 2h
Lire l'état d'un bouton poussoir avec digitalRead()
Savoir expliquer
Comprendre les résistances pull-up et pull-down
Savoir faire
Implémenter l'anti-rebond (debounce) logiciel
Savoir analyser
Utiliser les interruptions matérielles (attachInterrupt)
Savoir produire

1. Boutons et résistances de tirage

ConceptDescription
Pull-upRésistance (10kΩ) reliant le pin à VCC (5V). Sans appui : HIGH. Appuyé : LOW
Pull-downRésistance reliant le pin à GND. Sans appui : LOW. Appuyé : HIGH
INPUT_PULLUPMode Arduino activant la résistance pull-up interne (≈50kΩ)
Rebond (bouncing)Oscillation du contact pendant 5-50ms avant stabilisation
Anti-rebondAttendre 20-50ms après le premier changement avant de relire
compteur_debounce.inoArduino
const int BOUTON_PIN = 4;
const int LED_PIN    = 13;

int dernierEtat        = HIGH;
int compteur           = 0;
unsigned long dernierDebounce = 0;
const long DELAI_DEBOUNCE = 50;

void setup() {
  pinMode(BOUTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int lectureActuelle = digitalRead(BOUTON_PIN);

  if (lectureActuelle != dernierEtat) dernierDebounce = millis();

  if ((millis() - dernierDebounce) > DELAI_DEBOUNCE) {
    if (lectureActuelle == LOW && dernierEtat == HIGH) {
      compteur++;
      Serial.print("Passage n° "); Serial.println(compteur);
      digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW);
    }
  }
  dernierEtat = lectureActuelle;
}
Exercice 2 — Boutons et interactions

a) Interrupteur MARCHE/ARRÊT : Un appui allume la LED, un autre l'éteint (toggle). Afficher "LED ON/OFF".

b) Accélérateur de LEDs : 3 LEDs clignotant toutes les 2s. Chaque appui divise le délai par 2. Au-delà, revenir à 2s.

c) Clavier de sécurité : 3 boutons = 3 chiffres. L'utilisateur doit appuyer dans l'ordre 1-2-3. LED verte si correct, rouge sinon.

d) BONUS — Interruption : Utilisez attachInterrupt() sur pin 2 pour compter les appuis même pendant un delay().

✓ Corrigé 2a — Toggle ON/OFF
toggle.ino
const int BTN = 4; const int LED = 13;
bool etatLED = false;
int dernierEtat = HIGH;
unsigned long tDebounce = 0;

void setup() {
  pinMode(BTN, INPUT_PULLUP); pinMode(LED, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int lecture = digitalRead(BTN);
  if (lecture != dernierEtat) tDebounce = millis();
  if (millis()-tDebounce > 50 && lecture==LOW && dernierEtat==HIGH) {
    etatLED = !etatLED;
    digitalWrite(LED, etatLED);
    Serial.println(etatLED ? "LED ON" : "LED OFF");
  }
  dernierEtat = lecture;
}
3

Capteurs analogiques — LDR, potentiomètre, thermistance

Semaine 3CM+TP · 2h
Comprendre le fonctionnement d'analogRead() et du convertisseur ADC
Savoir expliquer
Utiliser un diviseur de tension avec LDR et thermistance
Savoir faire
Convertir les valeurs brutes en grandeurs physiques
Savoir analyser
Contrôle automatique d'éclairage avec LDR
Savoir produire

1. Définitions et concepts

ConceptDescription
analogRead()Lit la tension sur une pin analogique (A0-A5). Retourne 0-1023 (0V-5V, 10 bits)
LDRLight Dependent Resistor. Résistance variable selon la luminosité (diminue quand la lumière augmente)
Diviseur de tensionCircuit de 2 résistances en série. V_out = V_in × R2/(R1+R2)
Thermistance NTCRésistance diminuant avec la température (Negative Temperature Coefficient)
capteurs_analogiques.inoArduino
const int LDR_PIN  = A0;
const int THERM_PIN = A1;

void setup() { Serial.begin(9600); }

void loop() {
  int valLDR = analogRead(LDR_PIN);
  float tension = valLDR * (5.0 / 1023.0);
  float lux = map(valLDR, 0, 1023, 0, 100);

  Serial.print("LDR: "); Serial.print(valLDR);
  Serial.print(" | Tension: "); Serial.print(tension, 2);
  Serial.print("V | Lumiere: "); Serial.print(lux); Serial.println(" lux");

  if (valLDR < 400) {
    digitalWrite(13, HIGH);
    Serial.println("→ Eclairage automatique active");
  } else {
    digitalWrite(13, LOW);
  }
  delay(500);
}
Exercice 3 — Capteurs analogiques

a) Réalisez le montage et le programme de lecture LDR/thermistance.

b) Testez sur 3 scénarios différents et documentez les résultats.

c) Photographiez le montage et commitez le code sur GitHub.

d) BONUS : Combinez LDR et thermistance pour une station météo simple.

4

Capteur DHT11/DHT22 — Température et humidité

Semaine 4CM+TP · 2h
Comprendre le protocole 1-wire du DHT
Savoir expliquer
Installer une bibliothèque Arduino via le gestionnaire
Savoir faire
Lire température et humidité avec le DHT
Savoir analyser
Calculer l'indice de chaleur ressenti
Savoir produire
ConceptDescription
DHT11Temp. 0-50°C (±2°C), Hum. 20-90% (±5%). Protocole 1-wire simplifié, 1 mesure/s
DHT22Temp. -40-80°C (±0.5°C), Hum. 0-100% (±2%). 0.5 mesure/s, plus précis
BibliothèqueDHT sensor library par Adafruit. Installable via Outils → Gérer bibliothèques
isnan()Fonction de vérification : retourne true si la lecture du capteur a échoué
dht_meteo.inoArduino
#include <DHT.h>

const int DHT_PIN  = 5;
const int DHT_TYPE = DHT22;

DHT dht(DHT_PIN, DHT_TYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
  Serial.println("Station météo MUST Toliara");
}

void loop() {
  float humidite    = dht.readHumidity();
  float temperature = dht.readTemperature();

  if (isnan(humidite) || isnan(temperature)) {
    Serial.println("ERREUR : Capteur DHT non trouvé !");
    return;
  }

  float ressentie = dht.computeHeatIndex(temperature, humidite, false);

  Serial.print("Temp: "); Serial.print(temperature); Serial.print("°C | ");
  Serial.print("Hum: ");  Serial.print(humidite);    Serial.print("% | ");
  Serial.print("Ressenti: "); Serial.print(ressentie); Serial.println("°C");

  delay(2000);
}
Exercice 4 — DHT11/DHT22

a) Réalisez le montage et le programme de lecture DHT.

b) Testez sur 3 scénarios différents (intérieur, extérieur, réfrigérateur).

c) Photographiez le montage et commitez le code sur GitHub.

d) BONUS : Ajoutez un capteur de lumière et affichez les 3 valeurs.

5

Communication série UART et formatage des données

Semaine 5CM+TP · 2h
Comprendre l'UART (Universal Asynchronous Receiver-Transmitter)
Savoir expliquer
Utiliser Serial.print() et Serial.println()
Savoir faire
Formater les données en CSV pour parsing Python
Savoir analyser
Lire les données Arduino depuis Python avec pyserial
Savoir produire
ConceptDescription
UARTCommunication série asynchrone : TX envoie, RX reçoit. 9600 bauds par défaut
Baud rateVitesse en bits/s. 9600 pour consoles, 115200 pour transmissions rapides
Serial.print()Envoie des données vers le PC via USB. println() ajoute un retour à la ligne
Format CSVValeurs séparées par des virgules. Facile à parser avec Python/Pandas
serial_csv.inoArduino
void setup() {
  Serial.begin(115200);
  Serial.println("timestamp_ms,temperature,humidite,ldr");
}

void loop() {
  float temp = 28.5 + random(-10, 10) / 10.0;
  float hum  = 70.0 + random(-5, 5) / 10.0;
  int   ldr  = analogRead(A0);

  Serial.print(millis());     Serial.print(",");
  Serial.print(temp, 1);      Serial.print(",");
  Serial.print(hum, 1);       Serial.print(",");
  Serial.println(ldr);

  delay(1000);
}
Exercice 5 — Communication série

a) Envoyez les données des capteurs au format CSV via Serial.

b) Testez avec différents baud rates (9600, 57600, 115200).

c) Écrivez un script Python qui lit et affiche les données.

d) BONUS : Ajoutez un timestamp NTP avant chaque ligne CSV.

6

Moteurs DC, servo et contrôle d'actionneurs

Semaine 6CM+TP · 2h
Comprendre le pont en H (L298N) pour moteurs DC
Savoir expliquer
Contrôler un servo-moteur avec Servo.h
Savoir faire
Comprendre le rapport cyclique PWM
Savoir analyser
Ouvrir/fermer une porte avec servo + bouton
Savoir produire
servo_porte.inoArduino
#include <Servo.h>

Servo servoPorte;
const int SERVO_PIN = 9;
const int BTN_PIN   = 4;

void setup() {
  servoPorte.attach(SERVO_PIN);
  pinMode(BTN_PIN, INPUT_PULLUP);
  servoPorte.write(0);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(BTN_PIN) == LOW) {
    Serial.println("Ouverture porte...");
    servoPorte.write(90);
    delay(3000);
    servoPorte.write(0);
    Serial.println("Porte fermee");
    delay(500);
  }
}
Exercice 6 — Actionneurs

a) Contrôlez un servo qui balaye 0°→180°→0° en continu.

b) Ajoutez un potentiomètre pour contrôler la position du servo.

c) BONUS : Pilotez un moteur DC avec pont en H L298N.

7

I2C — Capteur BMP280 (pression/température)

Semaine 7CM+TP · 2h
Comprendre le bus I2C (SDA, SCL, adresses)
Savoir expliquer
Scanner le bus I2C pour trouver les adresses
Savoir faire
Lire pression et température du BMP280
Savoir analyser
Calculer l'altitude barométrique
Savoir produire
ConceptDescription
I2CBus série 2 fils (SDA données, SCL horloge). Jusqu'à 127 périphériques
Adresse I2CIdentifiant unique (ex: 0x76 pour BMP280). Configurable via pont
BMP280Pression 300-1100 hPa (±1 hPa), Temp. −40 à +85°C (±1°C)
Altitude barométriqueCalculée à partir de la pression : plus on monte, moins la pression est élevée
bmp280_station.inoArduino
#include <Wire.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp;

void setup() {
  Serial.begin(9600);
  Wire.begin();

  if (!bmp.begin(0x76)) {
    Serial.println("ERREUR : BMP280 non trouvé !");
    while (1);
  }
  Serial.println("Station météo BMP280 - Toliara");
}

void loop() {
  float temp     = bmp.readTemperature();
  float pression = bmp.readPressure() / 100.0F;
  float altitude = bmp.readAltitude(1013.25);

  Serial.print("T="); Serial.print(temp, 1); Serial.print("°C  ");
  Serial.print("P="); Serial.print(pression, 1); Serial.print("hPa  ");
  Serial.print("Alt="); Serial.print(altitude, 1); Serial.println("m");

  delay(1000);
}
Exercice 7 — I2C et BMP280

a) Câblez le BMP280 sur le bus I2C et affichez pression + altitude.

b) Ajoutez un affichage LCD I2C pour les mesures.

c) BONUS : Détectez les changements de météo (baisse rapide de pression = pluie).

8

SPI — Carte SD et journalisation des données

Semaine 8CM+TP · 2h
Comprendre le bus SPI (MOSI, MISO, SCK, CS)
Savoir expliquer
Utiliser la bibliothèque SD.h pour lire/écrire
Savoir faire
Créer un datalogger avec horodatage
Savoir analyser
Journaliser température/humidité sur carte SD
Savoir produire
ConceptDescription
SPIBus série 4 fils : MOSI (sortie), MISO (entrée), SCK (horloge), CS (sélection)
Carte SDStockage FAT32. Utilise la broche CS (Chip Select) pour la sélection
DataloggerEnregistre les mesures avec horodatage pour analyse ultérieure
datalogger_sd.inoArduino
#include <SPI.h>
#include <SD.h>
#include <DHT.h>

const int SD_CS_PIN = 10;
const int DHT_PIN   = 5;
DHT dht(DHT_PIN, DHT22);

void setup() {
  Serial.begin(9600);
  dht.begin();

  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("ERREUR : Carte SD non trouvée !");
    while (1);
  }

  File fichier = SD.open("meteo.csv", FILE_WRITE);
  if (fichier) {
    fichier.println("timestamp_ms,temperature,humidite");
    fichier.close();
  }
}

void loop() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  File f = SD.open("meteo.csv", FILE_APPEND);
  if (f) {
    f.print(millis()); f.print(",");
    f.print(t, 1);     f.print(",");
    f.println(h, 1);
    f.close();
  }

  Serial.print("Enregistré : T="); Serial.print(t);
  Serial.print("°C H="); Serial.println(h);
  delay(60000);
}
Exercice 8 — Datalogger SD

a) Créez un datalogger qui enregistre température et humidité sur SD toutes les minutes.

b) Ajoutez le capteur BMP280 pour enregistrer pression aussi.

c) BONUS : Ajoutez un RTC (DS3231) pour horodater les mesures.

9

Écran LCD I2C et affichage d'informations

Semaine 9CM+TP · 2h
Configurer un LCD 16×2 avec module I2C
Savoir expliquer
Afficher du texte sur les 2 lignes
Savoir faire
Afficher des données capteurs en temps réel
Savoir analyser
Créer un affichage cyclique multi-écrans
Savoir produire
lcd_meteo.inoArduino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
DHT dht(5, DHT22);

void setup() {
  lcd.init(); lcd.backlight();
  dht.begin();

  lcd.setCursor(0, 0);
  lcd.print("IoT MUST Toliara");
  lcd.setCursor(0, 1);
  lcd.print("Initialisation...");
  delay(2000);
}

void loop() {
  float temp = dht.readTemperature();
  float hum  = dht.readHumidity();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temp: "); lcd.print(temp, 1);
  lcd.print((char)223); lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Hum:  "); lcd.print(hum, 1);
  lcd.print("%");

  delay(2000);
}
Exercice 9 — LCD I2C

a) Affichez température et humidité sur LCD.

b) Créez un écran défilant qui alterne entre 3 pages d'infos.

c) BONUS : Ajoutez des icônes personnalisées (cœur, soleil, pluie) avec créateChar().

10

ESP8266/ESP32 — WiFi et protocole HTTP

Semaine 10CM+TP · 2h
Comprendre l'ESP32 et son WiFi intégré
Savoir expliquer
Connecter l'ESP32 à un réseau WiFi
Savoir faire
Envoyer des données en HTTP POST
Savoir analyser
Créer un payload JSON pour API REST
Savoir produire
esp32_http.inoArduino (ESP32)
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>

const char* SSID     = "Must_Toliara_WiFi";
const char* PASSWORD = "motDePasseWiFi";
const char* SERVER   = "http://192.168.1.100:5000/api/mesures";

DHT dht(4, DHT22);

void setup() {
  Serial.begin(115200);
  dht.begin();

  WiFi.begin(SSID, PASSWORD);
  Serial.print("Connexion WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.print("\nIP : "); Serial.println(WiFi.localIP());
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(SERVER);
    http.addHeader("Content-Type", "application/json");

    String payload = "{\"temp\":" + String(dht.readTemperature(), 1)
                   + ",\"hum\":"  + String(dht.readHumidity(), 1) + "}";

    int code = http.POST(payload);
    Serial.print("Envoyé | HTTP "); Serial.println(code);
    http.end();
  }
  delay(30000);
}
Exercice 10 — ESP32 WiFi

a) Connectez l'ESP32 au WiFi et affichez son IP sur le moniteur série.

b) Envoyez les données DHT22 à un serveur HTTP.

c) BONUS : Créez un serveur web sur l'ESP32 avec ESPAsyncWebServer.

11

MQTT — Protocole de messagerie IoT

Semaine 11CM+TP · 2h
Comprendre le modèle publish/subscribe MQTT
Savoir expliquer
Se connecter à un broker MQTT (Mosquitto)
Savoir faire
Publier sur un topic et s'abonner aux commandes
Savoir analyser
Comprendre QoS (Quality of Service)
Savoir produire
ConceptDescription
MQTTMessage Queuing Telemetry Transport. Protocole publish/subscribe léger pour IoT
BrokerServeur central qui reçoit/redistribue les messages. Ex: Mosquitto, HiveMQ
TopicAdresse hiérarchique. Ex: must/toliara/capteur01/temperature
QoSQuality of Service : 0=au plus 1 fois, 1=exactement 1 fois, 2=exactement 1 fois garanti
esp32_mqtt.inoArduino (ESP32)
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

WiFiClient espClient;
PubSubClient mqtt(espClient);

const char* MQTT_BROKER = "192.168.1.100";
const int   MQTT_PORT   = 1883;
const char* CLIENT_ID   = "capteur_must_01";

void reconnect_mqtt() {
  while (!mqtt.connected()) {
    Serial.print("Connexion MQTT...");
    if (mqtt.connect(CLIENT_ID)) {
      Serial.println(" OK");
      mqtt.subscribe("must/commandes");
    } else {
      Serial.print(" Echec RC="); Serial.println(mqtt.state());
      delay(5000);
    }
  }
}

void loop() {
  if (!mqtt.connected()) reconnect_mqtt();
  mqtt.loop();

  String temp = String(dht.readTemperature(), 1);
  mqtt.publish("must/toliara/temp", temp.c_str());
  Serial.println("Publié : " + temp);
  delay(5000);
}
Exercice 11 — MQTT

a) Installez Mosquitto sur votre PC/RPi et publiez un message de test.

b) Connectez l'ESP32 au broker et publiez température toutes les 5s.

c) BONUS : Abonnez-vous à un topic pour contrôler une LED à distance.

12

Arduino et Python — Liaison série et dashboard

Semaine 12CM+TP · 2h
Comprendre pyserial pour la communication PC ↔ Arduino
Savoir expliquer
Lire des données série depuis Python
Savoir faire
Créer un dashboard temps réel avec matplotlib
Savoir analyser
Afficher les données en direct
Savoir produire
dashboard_temps_reel.pyPython
import serial, time, matplotlib.pyplot as plt
import matplotlib.animation as animation
from collections import deque

ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)
time.sleep(2)

temperatures = deque(maxlen=60)
timestamps   = deque(maxlen=60)

fig, ax = plt.subplots(figsize=(10, 4))

def lire_arduino(frame):
    ligne = ser.readline().decode("utf-8").strip()
    if "," in ligne:
        parts = ligne.split(",")
        if len(parts) >= 2:
            temperatures.append(float(parts[1]))
            timestamps.append(len(temperatures))
            ax.clear()
            ax.plot(list(timestamps), list(temperatures), "g-", lw=2)
            ax.set_title("Température en temps réel — Toliara")
            ax.set_ylabel("°C"); ax.set_xlabel("Mesures")
            ax.grid(True)

ani = animation.FuncAnimation(fig, lire_arduino, interval=1000)
plt.show()
ser.close()
Exercice 12 — Python + Arduino

a) Écrivez un script Python qui lit les données série et les affiche.

b) Créez un dashboard matplotlib avec température et humidité.

c) BONUS : Ajoutez des alertes quand la température dépasse un seuil.

13

Capteur ultrasonique HC-SR04 et détection de présence

Semaine 13CM+TP · 2h
Comprendre le principe de mesure par ultrasons
Savoir expliquer
Utiliser pulseIn() pour mesurer des durées
Savoir faire
Calculer une distance (durée × vitesse son / 2)
Savoir analyser
Détecter une présence et allumer une LED
Savoir produire
hcsr04_presence.inoArduino
const int TRIG_PIN = 10;
const int ECHO_PIN = 11;
const int LED_PIN  = 13;

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(LED_PIN,  OUTPUT);
  Serial.begin(9600);
}

float mesurer_distance() {
  digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duree = pulseIn(ECHO_PIN, HIGH, 30000);
  float distance = (duree * 0.034) / 2.0;
  return distance;
}

void loop() {
  float dist = mesurer_distance();
  Serial.print("Distance : "); Serial.print(dist, 1); Serial.println(" cm");

  if (dist > 0 && dist < 30) {
    digitalWrite(LED_PIN, HIGH);
    Serial.println("→ PRESENCE DETECTEE !");
  } else {
    digitalWrite(LED_PIN, LOW);
  }
  delay(200);
}
Exercice 13 — HC-SR04

a) Mesurez la distance d'un objet avec HC-SR04.

b) Allumez une LED si un objet est à moins de 30 cm.

c) BONUS : Créez un radar avec servo + HC-SR04 qui scanne 0-180°.

14

OTA — Mise à jour Over-The-Air et watchdog

Semaine 14CM+TP · 2h
Comprendre le concept OTA (Over-The-Air)
Savoir expliquer
Configurer ArduinoOTA sur ESP32
Savoir faire
Utiliser le DeepSleep pour économiser la batterie
Savoir analyser
Implémenter un watchdog timer
Savoir produire
ConceptDescription
OTAMise à jour du firmware sans connexion physique (via WiFi)
WatchdogTimer matériel qui redémarre le µC si le programme se bloque
DeepSleepMode économie extrême (10µA). Idéal pour capteurs sur batterie
FirmwareProgramme dans la mémoire Flash du microcontrôleur
esp32_ota_deepsleep.inoArduino (ESP32)
#include <WiFi.h>
#include <ArduinoOTA.h>
#include <DHT.h>

RTC_DATA_ATTR int compteurMesures = 0;

void setup() {
  Serial.begin(115200);
  compteurMesures++;

  WiFi.begin("SSID", "PASS");
  while (WiFi.status() != WL_CONNECTED) delay(500);

  ArduinoOTA.setHostname("capteur-must-01");
  ArduinoOTA.setPassword("ota_password");
  ArduinoOTA.begin();

  DHT dht(4, DHT22); dht.begin();
  float temp = dht.readTemperature();
  // envoyer_mesure(temp);

  unsigned long debut = millis();
  while (millis() - debut < 10000) ArduinoOTA.handle();

  esp_deep_sleep(5 * 60 * 1000000ULL);
}

void loop() {}
Exercice 14 — OTA et veille

a) Configurez OTA sur ESP32 et flashez sans fil.

b) Mettez l'ESP32 en DeepSleep 30s entre chaque mesure.

c) BONUS : Calculez l'autonomie avec une batterie 18650 (3000 mAh).

15

Projet Arduino S1 — Système de monitoring IoT complet

Semaine 15CM+TP · 2h
Intégrer tous les capteurs dans un seul projet
Savoir expliquer
Structurer le code avec des fonctions modulaires
Savoir faire
Publier les données via MQTT
Savoir analyser
Préparer le pipeline IoT complet
Savoir produire

Architecture du projet

ESP32 + DHT22 + BMP280 + HC-SR04 + Carte SD → MQTT Broker → Python Consumer → PostgreSQL → Grafana

projet_monitoring.inoArduino (ESP32)
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

void publier_mesures(float temp, float hum, float dist) {
  StaticJsonDocument<200> doc;
  doc["device"]  = "esp32-must-01";
  doc["temp"]    = temp;
  doc["hum"]     = hum;
  doc["dist"]    = dist;
  doc["ts_ms"]   = millis();

  String payload;
  serializeJson(doc, payload);
  mqtt.publish("must/monitoring", payload.c_str());
}
Exercice 15 — Projet intégré

a) Réalisez le système complet : capteurs → ESP32 → MQTT → dashboard.

b) Documentez l'architecture dans un schéma.

c) BONUS : Ajoutez une alerte email si température > 40°C.