Programmation embarquée avec Arduino

Bases de la programmation C/C++ sur microcontrôleur.

Se connecter pour contribuerPublié le · Dernière mise à jour le

Introduction

Programmer une carte Arduino consiste à écrire un firmware C/C++ qui pilote un microcontrôleur AVR (UNO, Nano) ou ARM (MKR, Nano 33). L'écosystème est simple, très documenté, idéal pour prototyper.

Environnement

  • Arduino IDE 2.x (moderne, autocomplete, debug).
  • PlatformIO dans VS Code (multi-plateforme, gestion bibliothèques, tests).
  • CLI arduino-cli pour l'intégration continue.
  • Bibliothèques : Wire (I2C), SPI, Servo, WiFi (ESP), FastLED.

Structure d'un programme

#include <DHT.h>
DHT dht(4, DHT22);

void setup() {
  Serial.begin(115200);
  dht.begin();
  pinMode(13, OUTPUT);
}

void loop() {
  float t = dht.readTemperature();
  Serial.println(t);
  digitalWrite(13, t > 25 ? HIGH : LOW);
  delay(2000);
}

GPIO, ADC, PWM

  • digitalRead / digitalWrite : 0 / 5 V.
  • analogRead (10 bits sur UNO, 12 sur ESP32).
  • analogWrite (PWM, 8 bits, 490 Hz).
  • tone() pour piloter un buzzer.

Communication

  • Serial.print() : UART USB pour debug.
  • Wire.begin() : I2C multi-esclave.
  • SPI.begin() : capteurs et écrans rapides.
  • SoftwareSerial : port série logiciel supplémentaire.

Interruptions

attachInterrupt(digitalPinToInterrupt(2), montisr, RISING);
volatile int compteur = 0;
void montisr() { compteur++; }

Cas d'usage : bouton poussoir sans debounce logiciel, encodeur incrémental, RTC pulse.

Multitâche non bloquant

Éviter delay(), utiliser millis() :

unsigned long lastToggle = 0;
if (millis() - lastToggle > 500) {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  lastToggle = millis();
}

Frameworks : Scheduler (SAMD), TaskScheduler (AVR).

Stockage

  • EEPROM interne (1 kB sur UNO).
  • SD Card via SPI.
  • LittleFS sur ESP.

Cas concret : station météo

  • DHT22 (T°/humidité), BMP280 (pression, altitude), BH1750 (lumière).
  • Écran OLED 128×64 SSD1306 (I2C).
  • Envoi ThingSpeak via ESP8266.
  • Alim solaire 6 V + batterie Li-ion + BQ25504.
  • Consommation moyenne 30 mA en deep sleep.

Bonnes pratiques

  • Nommer variables clairement (temperatureCelsius).
  • Séparer setup/loop en fonctions.
  • Utiliser const et #define pour les constantes.
  • Contrôler la mémoire (Arduino UNO n'a que 2 kB SRAM).
  • Documenter le brochage.

Exemple chiffré 1 — budget temps de la boucle

Sur un UNO (ATmega328P, 16 MHz), une itération de loop() contenant une lecture DHT22 (bloquante ~250 ms), un Serial.print à 115 200 bauds (40 octets → 40×10/115200=3,540 \times 10 / 115\,200 = 3{,}5 ms) et un calcul flottant (~0,1 ms) dure ≈ 254 ms.

Fréquence d'échantillonnage maximale : f=1/0,2543,9f = 1/0{,}254 \approx 3{,}9 Hz. Pour cadencer un asservissement à 100 Hz, il faut donc supprimer les attentes bloquantes (delay, capteurs lents) et passer à une machine à états + millis(), ou à un timer matériel.

Exemple chiffré 2 — résolution du convertisseur

CAN 10 bits, référence 5 V :

q=Vref2n=51024=4,88 mV/LSBq = \frac{V_{ref}}{2^n} = \frac{5}{1\,024} = 4{,}88\ \text{mV/LSB}

Avec un LM35 (10 mV/°C), la résolution en température vaut 4,88/10=0,494{,}88/10 = 0{,}49 °C. En passant VrefV_{ref} à 1,1 V interne : q=1,07q = 1{,}07 mV → 0,107 °C, soit un gain d'un facteur 4,5 sans changer de capteur.

Exemple chiffré 3 — consommation et autonomie

Nœud capteur sur 2 piles AA (2 400 mAh) :

ÉtatCourantDurée par cycle
Sommeil (power-down)0,15 mA59 s
Mesure + calcul12 mA0,3 s
Émission LoRa45 mA0,7 s

Imoy=0,15×59+12×0,3+45×0,760=8,85+3,6+31,560=0,73 mAI_{moy} = \frac{0{,}15 \times 59 + 12 \times 0{,}3 + 45 \times 0{,}7}{60} = \frac{8{,}85 + 3{,}6 + 31{,}5}{60} = 0{,}73\ \text{mA}

t=24000,733288 h137 jourst = \frac{2\,400}{0{,}73} \approx 3\,288\ \text{h} \approx 137\ \text{jours}

En espaçant les émissions à une toutes les 10 minutes, ImoyI_{moy} tombe à ~0,21 mA et l'autonomie dépasse 15 mois.

Squelette non bloquant à connaître

const unsigned long PERIODE = 100; // ms
unsigned long precedent = 0;

void loop() {
  unsigned long maintenant = millis();
  if (maintenant - precedent >= PERIODE) {
    precedent += PERIODE;      // pas de dérive cumulée
    mesurer();
    asservir();
  }
  gererCommunication();        // exécuté en continu
}

Points-clés à retenir

  • delay() gèle tout le programme : il est proscrit dès qu'il y a plusieurs tâches.
  • Toujours vérifier que le temps d'exécution de la boucle est très inférieur à la période d'échantillonnage souhaitée.
  • La consommation moyenne se calcule en pondérant chaque état par sa durée : c'est elle, et non le pic, qui fixe l'autonomie.

Quiz de révision

0/6 répondues · 0 bonne réponse
  1. Question 1.

    Quelle instruction Arduino déclare une broche comme sortie ?

  2. Question 2.

    Sur Arduino UNO, analogRead retourne une valeur entre :

  3. Question 3.

    Le protocole I2C nécessite en Arduino :

  4. Question 4.

    Pour ne pas bloquer le microcontrôleur, on préfère à delay() :

  5. Question 5.

    Une interruption externe attachée sur un front montant se déclenche quand :

  6. Question 6.

    Arduino UNO dispose d'une SRAM de :

Sources et références

Ce cours est rédigé par l'équipe RévisionBac à partir du programme officiel et des sources institutionnelles ci-dessous. Elles permettent de vérifier les définitions, les chiffres et les normes citées.

  1. 1.Programmes et ressources du lycée général et technologiqueÉduscol — Ministère de l'Éducation nationale
  2. 2.Bulletin officiel de l'Éducation nationale (programmes du baccalauréat)education.gouv.fr
  3. 3.Documentation du langage PythonPython Software Foundation
  4. 4.Bonnes pratiques de cybersécurité et réseauxANSSI
  5. 5.Spécifications des protocoles réseau (RFC)IETF
  6. 6.Archives et ressources documentairesArchives nationales

Contenu vérifié et mis à jour le 08/08/2026. Les liens renvoient vers les sites officiels des éditeurs cités.

Historique éditorial

Ce chapitre est rédigé et relu par l'équipe RévisionBac, puis enrichi par les contributions validées.

  1. Dernière mise à jour du cours (relecture et enrichissement)
  2. Première publication de la fiche de cours