Introduction
La programmation embarquée consiste à développer des logiciels pour des systèmes électroniques autonomes, appelés systèmes embarqués. Ces systèmes, basés sur des microcontrôleurs, sont omniprésents dans notre quotidien, des montres connectées aux systèmes de contrôle des véhicules. Ce cours vous initiera aux principes fondamentaux qui permettent à ces objets de percevoir leur environnement via des capteurs, de traiter l'information et d'agir via des actionneurs. Nous aborderons la chaîne complète, de la conception à la programmation.
Prenons l'exemple d'un thermostat connecté. Il mesure la température ambiante avec un capteur, traite cette donnée dans son microcontrôleur, et commande la chaudière (actionneur) pour maintenir la consigne. La programmation embarquée est ce qui définit la logique et l'intelligence de ce comportement automatisé, souvent en interaction avec d'autres appareils.
1. Les microcontrôleurs, cœur des systèmes embarqués
Un microcontrôleur est un circuit intégré qui rassemble sur une seule puce les éléments essentiels d'un ordinateur : un processeur (CPU), de la mémoire (RAM et ROM/Flash), et des périphériques d'entrée/sortie (E/S). Contrairement à un microprocesseur généraliste, il est conçu pour le contrôle en temps réel de systèmes dédiés. Son architecture est optimisée pour interagir directement avec le monde physique via ses broches d'E/S. La mémoire de programme contient le code exécuté, souvent écrit en langage C ou C++ pour un contrôle fin des ressources. La faible consommation et le coût réduit des microcontrôleurs expliquent leur utilisation massive dans l'électronique embarquée.
Par exemple, la carte Arduino Uno intègre un microcontrôleur ATmega328P. Ses broches numériques et analogiques permettent de connecter des composants externes. Une carte de développement comme celle-ci simplifie l'accès à ces broches et fournit un environnement de programmation convivial, masquant certaines complexités matérielles pour se concentrer sur la logique de l'application.
À retenir
Un microcontrôleur = CPU + Mémoire + Périphériques E/S sur une seule puce. Il est autonome, dédié à une tâche spécifique et dialogue avec le monde extérieur.
2. Acquisition des données : les capteurs
Les capteurs sont des composants qui transforment une grandeur physique (température, luminosité, pression, mouvement) en un signal électrique exploitable par le microcontrôleur. On distingue les capteurs numériques, qui délivrent directement une information binaire (tout ou rien) ou un mot numérique (via un bus comme I2C), et les capteurs analogiques, qui fournissent une tension variable proportionnelle à la mesure. Pour lire un capteur analogique, le microcontrôleur utilise un convertisseur Analogique-Numérique (CAN) intégré. La programmation consiste alors à lire la valeur numérique issue de cette conversion et à l'interpréter selon l'étalonnage du capteur.
Une photorésistance est un capteur analogique : sa résistance varie avec la lumière. Connectée à une entrée analogique de l'Arduino, on peut mesurer un niveau de luminosité. Un capteur de température numérique comme le DHT11 communique via un protocole série dédié, renvoyant directement une valeur en degrés Celsius sans nécessiter de conversion logicielle complexe.
Point clé
Capteur analogique → tension variable → nécessite un CAN. Capteur numérique → signal binaire ou mot numérique → communication via un protocole.
3. Agir sur l'environnement : les actionneurs
Les actionneurs sont les composants qui permettent au système d'agir sur son environnement physique à partir d'une commande électrique du microcontrôleur. Ils convertissent un signal électrique en une action : mouvement, lumière, son, etc. Les actionneurs courants incluent les LEDs, les buzzers, les moteurs (à courant continu, pas-à-pas) et les relais. La plupart des microcontrôleurs ne peuvent fournir qu'un faible courant et une faible tension sur leurs broches de sortie. Pour piloter des actionneurs plus puissants, il est impératif d'utiliser des interfaces de puissance comme des transistors MOSFET ou des modules relais.
Pour allumer une LED, une broche de sortie numérique suffit (avec une résistance de limitation de courant). Pour contrôler la vitesse d'un moteur à courant continu, on utilise souvent la Modulation de Largeur d'Impulsion (PWM) sur une broche spécifique, qui simule une tension variable. Un relais permet de commander un circuit haute tension (comme une lampe 230V) avec la faible tension de sécurité de la carte Arduino (5V).
Règle de sécurité
Ne jamais connecter un actionneur gourmand en courant (moteur, grosse LED) directement à une broche du microcontrôleur. Toujours utiliser un étage d'amplification (transistor, driver).
4. Programmation avec l'environnement Arduino
Arduino est à la fois une plateforme matérielle (cartes électroniques) et un environnement de développement intégré (IDE) logiciel simplifié. L'IDE Arduino permet d'écrire du code en langage C/C++, structuré autour de deux fonctions obligatoires : setup() et loop(). La fonction setup() est exécutée une seule fois à la mise sous tension et sert à initialiser les broches et les communications. La fonction loop() est ensuite exécutée en boucle infinie et contient la logique principale du programme. L'IDE gère la compilation et le téléversement du code (via un bootloader) sur la carte. Cette abstraction rend la programmation embarquée très accessible pour le prototypage.
Pour faire clignoter une LED, on déclare la broche connectée en sortie dans setup() avec pinMode(). Dans loop(), on utilise digitalWrite() pour mettre la broche à HIGH (allumé), on attend avec delay(), puis on la met à LOW (éteint). La bibliothèque Servo permet, en quelques lignes, de contrôler un servomoteur sans avoir à gérer le signal PWM manuellement.
Structure d'un programme Arduino
void setup() { // Initialisations } void loop() { // Code exécuté en boucle }
5. Communication entre systèmes : protocoles série
Pour échanger des données avec un autre microcontrôleur, un ordinateur ou des périphériques complexes (écran, module GPS), on utilise des protocoles de communication série. La communication série envoie les bits d'information les uns après les autres sur un fil (ou deux pour la transmission et la réception). Les trois protocoles majeurs sont : UART (asynchrone, point à point), I2C (synchrone, bus avec adressage, utilisant 2 fils : SCL horloge et SDA données) et SPI (synchrone, bus plus rapide, utilisant 4 fils). Le choix dépend du débit nécessaire, de la distance et du nombre d'esclaves à connecter au maître (le microcontrôleur).
L'UART est utilisé pour la communication entre l'Arduino et l'ordinateur via le port USB (pour le moniteur série). Un capteur numérique de pression BMP280 utilise souvent le bus I2C : il a une adresse fixe et partage les fils SDA/SCL avec d'autres capteurs. Un écran OLED utilise fréquemment le protocole SPI pour un rafraîchissement rapide de l'affichage.
Comparaison des protocoles
UART : simple, 2 appareils. I2C : bus, plusieurs esclaves, 2 fils, adressage. SPI : bus, plusieurs esclaves, 4 fils, plus rapide, pas d'adressage (sélection par broche dédiée).
Points clés à retenir
- Un système embarqué est dédié à une tâche spécifique et interagit avec le monde physique.
- Le microcontrôleur en est le cerveau, intégrant processeur, mémoire et interfaces.
- Les capteurs (entrées) mesurent des grandeurs physiques, les actionneurs (sorties) produisent une action.
- Arduino est une plateforme idéale pour l'apprentissage, avec un IDE et un langage simplifiés.
- Les communications série (UART, I2C, SPI) permettent l'échange de données avec d'autres dispositifs.
- La sécurité des composants et une alimentation stable sont essentielles pour la fiabilité du système.
Exercices d'application
Exercice 1
Proposez un algorithme (ou un pseudo-code) pour un système d'arrosage automatique. Le système doit activer une pompe (actionneur) pendant 10 secondes si un capteur d'humidité du sol (analogique) indique une valeur inférieure à un seuil de 30%.
Indice : Pensez à la structure setup/loop. Dans loop, lisez le capteur, comparez avec le seuil, et si condition vraie, activez la pompe avec un delay.
Exercice 2
Pourquoi ne peut-on pas connecter directement un petit moteur à courant continu (fonctionnant sous 5V et consommant 200mA) à une broche de sortie d'une carte Arduino Uno ? Quelle solution matérielle simple proposez-vous ?
Indice : Consultez la datasheet de l'ATmega328P pour connaître le courant maximum par broche. Cherchez le nom d'un composant semi-conducteur utilisé comme interrupteur commandé en courant.
Exercice 3
Vous devez connecter trois capteurs numériques identiques (chacun avec la même adresse I2C par défaut) à un microcontrôleur. Quel problème rencontrez-vous et quelles sont les solutions possibles ?
Indice : Sur un bus I2C, chaque esclave doit avoir une adresse unique. Certains capteurs ont des broches pour modifier leur adresse logiciellement ou matériellement.
