MakerSpace Amiens · Microcontrôleurs
Découvrir le microcontrôleur
CM1 : de la puce au premier programme
Alban Petit
Au programme
Un ordinateur sur une puce
Sous le capot
Du code à la puce
Votre premier programme
1 h 30 de cours, sans manipulation. Fil rouge de tout l’atelier : un Pong 2 joueurs sur ESP32-S3, puis un Snake multijoueur en projet.
Parties 1 et 2 : le vocabulaire et la puce. Parties 3 et 4 : la chaîne de développement, plus concrètes, à garder pour la seconde moitié quand l’attention baisse.
2
Ce que vous saurez faire
À la fin de ce cours, vous saurez :
dire ce qu’est un microcontrôleur, et ce qui le distingue d’un PC
nommer les blocs d’une puce : CPU, Flash, RAM, périphériques, bus
expliquer ce qu’est un registre , et à quoi sert une interruption
suivre le trajet du code source jusqu’à l’exécution sur la puce
dire pourquoi delay() pose problème dans une loop()
Fil rouge de l’atelier : un Pong 2 joueurs , puis un Snake multijoueur .
L’atelier Microcontrôleurs
3
Un ordinateur sur une puce
Percevoir, décider, agir
Activité : comptez-les autour de vous
Toute la classe 3 min Sans PC
Combien d’ordinateurs y a-t-il dans cette pièce ?
Une réponse par personne, à voix haute
On note les chiffres au tableau, du plus petit au plus grand
Les réponses tournent en général autour du nombre de PC portables. Dévoiler ensuite la slide suivante : on est deux ordres de grandeur en dessous.
5
Il y en a des centaines
Le micro-ondes qui compte les secondes et fait tourner le plateau
La machine à laver qui enchaîne lavage, rinçage, essorage
La télécommande , les écouteurs sans fil , la manette de jeu
La trottinette , le thermostat , le détecteur de fumée
Et 50 à 150 dans une voiture récente : vitres, clignotants, airbags, injection
Aucun n’a besoin d’un « vrai » ordinateur. Ils ont besoin d’une puce à quelques euros, qui démarre instantanément et fait sa tâche en boucle.
Qu’est-ce qu’un microcontrôleur ?
6
Toujours la même boucle
flowchart LR
A["Percevoir<br/>(capteurs)"] --> B["Décider<br/>(le programme)"]
B --> C["Agir<br/>(actionneurs)"]
C -.-> A
Un thermostat perçoit la température, décide qu’il fait trop froid, agit en allumant le chauffage. Puis il recommence, indéfiniment.
Cette boucle, vous la retrouverez telle quelle dans votre Pong : lire le joystick, calculer la position de la balle, redessiner l’écran.
Qu’est-ce qu’un microcontrôleur ? Les capteurs
7
Le « décider », c’est vous.
Le microcontrôleur ne sait rien faire tout seul. Sans programme, c’est une puce inerte : tout l’atelier consiste à écrire ce comportement.
8
Le vocabulaire de l’atelier
Terme
Ce que c’est
Exemples du projet
Capteur
Traduit une grandeur physique en signal électrique
bouton, joystick, potentiomètre
Actionneur
Transforme un signal électrique en action
LED, écran, moteur, buzzer
Broche (pin )
Une patte de la puce, reliée au monde extérieur
GPIO5, GPIO1
Programme
La suite d’instructions que vous écrivez
main.cpp
Un bouton est un capteur, une LED est un actionneur.
Les capteurs
9
Pourquoi pas un « vrai » ordinateur ?
Ordinateur classique
Microcontrôleur
Tâches
Des milliers, en même temps
Une seule, en boucle
Prix
Plusieurs centaines d’€
Quelques euros, parfois centimes
Énergie
Se branche au secteur
Des mois sur une pile
Démarrage
Plusieurs secondes
Instantané
Système
Un OS complet
Aucun, en général
C’est cette sobriété qui le rend si présent : on peut en mettre partout, pour presque rien, sans y penser.
Qu’est-ce qu’un microcontrôleur ?
10
Et le Raspberry Pi, alors ?
Microcontrôleur
Une seule tâche, du temps réel, très peu d’énergie, démarrage immédiat.
ESP32-S3, Arduino, STM32
Nano-ordinateur
Un vrai système d’exploitation (Linux), un écran, le réseau complet, beaucoup de mémoire.
Raspberry Pi
La question à se poser n’est pas « lequel est le plus puissant » mais « de quoi ai-je réellement besoin ». Un Raspberry Pi qui met 20 secondes à démarrer ne peut pas déclencher un airbag.
Qu’est-ce qu’un microcontrôleur ?
11
Notre puce : l’ESP32-S3
Caractéristique
Valeur
CPU
Xtensa LX7 dual-core 32 bits, 240 MHz
RAM
512 Ko SRAM (+ 8 Mo PSRAM en option)
Flash
16 Mo, externe via SPI
GPIO
45 broches, dont 20 capables d’ADC
Tension logique
3,3 V
Connectivité
Wi-Fi 802.11 b/g/n + Bluetooth 5
Prix
~8 € la carte de développement
Le sans-fil servira au projet Snake. ↓ pour le brochage de la carte.
ESP32-S3-DevKitC-1
12
La fiche de la carte
12.1
Relier une broche GPIO directement à du 5 V (un Arduino Uno, un capteur alimenté en 5 V) peut détruire la puce de façon irréversible. C’est l’erreur la plus fréquente et la plus coûteuse de l’atelier : avant de brancher un module, cherchez sa tension d’alimentation.
GPIO et monde numérique
13
Sous le capot
CPU, mémoires, périphériques, bus
Cinq briques, une seule puce
Bloc
Rôle
Accès logiciel
CPU
Exécute les instructions une par une
direct
Flash
Stocke le programme (persistant)
lecture à l’exécution
RAM
Variables, pile d’appels (volatile)
lecture/écriture rapide
Périphériques
GPIO, ADC, UART, SPI, PWM
via registres
Bus
Relie tout le monde
transparent sous Arduino
Tout est sur le même silicium : un système sur puce . Il suffit de l’alimenter.
Architecture d’un microcontrôleur
16
Le CPU ne sait faire qu’une chose
Fetch : aller chercher en Flash l’instruction suivante, à l’adresse indiquée par le compteur de programme.
17
Le CPU ne sait faire qu’une chose
Decode : comprendre ce que l’instruction demande, et sur quelles données.
18
Le CPU ne sait faire qu’une chose
Execute : calculer dans l’ALU , ou transférer une donnée. Puis recommencer, 240 millions de fois par seconde .
Au fond, un CPU ne fait que deux choses : calculer, et déplacer des octets d’un endroit à un autre.
Architecture d’un microcontrôleur
19
240 MHz, ça veut dire quoi ?
Opération
Ordre de grandeur
Un digitalWrite()
quelques cycles
Une multiplication entière
quelques dizaines de cycles
Redessiner un écran 240×240 en SPI
quelques millions de cycles
Établir une connexion Wi-Fi
plusieurs centaines de millions
À 60 images par seconde, chaque image dispose de 4 millions de cycles .
Architecture d’un microcontrôleur
20
Deux cœurs, et le droit de dormir
L’ESP32-S3 a deux cœurs Xtensa LX7 : sous Arduino, setup()/loop() tournent sur le cœur 1, le Wi-Fi occupe le cœur 0 en arrière-plan
Couper l’horloge d’un périphérique inutilisé économise de l’énergie
Les modes veille (light sleep , deep sleep ) éteignent tout ou partie de la puce
Le RTC continue de tourner en veille profonde pour réveiller la carte à l’heure dite
C’est ce qui permet à un capteur sur pile de tenir des mois : il dort 99,9 % du temps.
Architecture d’un microcontrôleur
21
Deux mémoires, deux usages
Flash
RAM (SRAM)
Contenu
Programme compilé, constantes
Variables, pile, heap
Persistance
Survit au reset
Perdue à l’extinction
Vitesse
Plus lente
Très rapide
Taille
16 Mo
512 Ko
Deux espaces d’adressage séparés : une architecture Harvard modifiée .
Architecture d’un microcontrôleur
22
Le glossaire des périphériques
Sigle
Nom complet
Rôle
GPIO
General Purpose Input/Output
Entrée ou sortie numérique
ADC
Analog to Digital Converter
Tension vers nombre
UART / I2C / SPI
Bus série
Timer
Compteur matériel
Événements périodiques, PWM
DMA
Direct Memory Access
Transfert sans le CPU
RTC
Real-Time Clock
Horloge, même en veille
Watchdog
Chien de garde
Redémarre si blocage
Chaque sigle aura sa slide au CM2 ou au CM3.
Architecture d’un microcontrôleur
23
Contrairement à l’ESP32 d’origine, l’ESP32-S3 n’a pas de convertisseur numérique-analogique matériel. Pour produire une tension variable, il faudra passer par du PWM, qu’on verra au CM2.
ADC et PWM
24
Le bus : une autoroute partagée
flowchart TB
CPU["CPU (pilote le bus)"]
BUS["Bus partagé : adresses · données · contrôle"]
RAM["RAM"]
PA["Périph. A<br/>(émetteur actif)"]
PB["Périph. B<br/>(haute impédance)"]
CPU --- BUS
BUS --- RAM
BUS --- PA
BUS --- PB
Trois faisceaux : l’adresse dit à qui on parle, les données transitent, le contrôle précise « je lis » ou « j’écris ».
Architecture d’un microcontrôleur
25
Un seul composant parle à la fois
Si deux périphériques poussaient une valeur en même temps sur le bus de données, l’un forçant un 0 et l’autre un 1, ce serait un court-circuit .
D’où les sorties trois états : en plus de 0 et 1, un état de haute impédance qui déconnecte électriquement le composant de la ligne.
À tout instant, un seul émetteur est actif ; tous les autres sont à l’écoute. C’est l’adresse qui désigne celui qui a le droit de répondre.
Retenez le mot haute impédance : il reviendra au CM2 avec les entrées flottantes, et au CM3 avec l’I2C.
Architecture d’un microcontrôleur
26
Les registres : l’interface matériel / logiciel
Chaque périphérique se pilote par des registres : de simples cases mémoire à une adresse fixe.
Écrire dans un registre allume une LED
Lire un registre donne l’état d’un bouton
digitalWrite(LED, HIGH) écrit dans le bon registre
Ranger une variable et allumer une LED : la même opération, poser une valeur à une adresse.
Architecture d’un microcontrôleur
27
Réagir sans attendre : l’interruption
void IRAM_ATTR surAppui() {
compteurAppuis++; // aussi court et rapide que possible
}
void setup() {
attachInterrupt(digitalPinToInterrupt(BTN_PIN), surAppui, FALLING);
}
Le CPU suspend loop(), exécute la petite fonction, puis reprend exactement où il s’était arrêté.
IRAM_ATTR la place en RAM interne : sans ce mot-clé, la puce finit par planter.
Insister : tant que l’ISR s’exécute, tout le reste est suspendu, y compris les autres interruptions. Une ISR ne fait jamais de Serial.println(), jamais de delay(), jamais d’appel à une bibliothèque. Elle positionne un drapeau, et la loop() fait le travail.
Architecture d’un microcontrôleur GPIO et monde numérique
28
Du code à la puce
Compiler, flasher, exécuter
Le voyage complet
flowchart LR
A["Code source<br/>(.cpp)"] --> B["Compilateur<br/>(gcc-xtensa)"]
B --> C["Binaire<br/>(.bin)"]
C --> D["Flashage<br/>(USB / UART)"]
D --> E["Exécution<br/>ESP32-S3"]
Un clic sur Upload déclenche les quatre étapes, toujours dans cet ordre. Quand quelque chose échoue, la première question est : à quelle étape ?
Du matériel au logiciel
30
Élément
Rôle
Compilateur (gcc pour Xtensa)
Traduit le C++ en instructions machine
Core Arduino
Fournit pinMode(), digitalWrite(), analogRead()
Uploader (esptool)
Transfère le binaire vers la Flash, par USB
L’IDE ne fait qu’orchestrer ces trois outils. Arduino IDE ou PlatformIO, la chaîne reste la même : compiler, flasher, exécuter .
PlatformIO Arduino IDE
31
« Compiler » recouvre trois étapes
Préprocesseur : traite les #include et les #define, colle le contenu des bibliothèques
Compilation : chaque fichier C++ devient du code objet, séparément
Édition de liens : tous les objets sont assemblés en un binaire, en résolvant les références
Savoir les distinguer, c’est savoir lire une erreur. C’est la compétence la plus rentable du semestre.
Du matériel au logiciel
32
Lire une erreur
Message
Étape
Cause probable
expected ';' before ...
compilation
une faute de syntaxe, souvent une ligne avant
'x' was not declared
compilation
variable mal orthographiée, ou #include manquant
undefined reference to ...
édition de liens
bibliothèque absente de lib_deps
A fatal error occurred: Failed to connect
flashage
mauvais port, câble sans data, bouton BOOT
Corrigez la première erreur, pas les 40 suivantes.
Du matériel au logiciel
33
Au reset : la séquence de démarrage
ROM bootloader : gravé en usine, il lit les broches de strapping (dont GPIO0) pour choisir démarrage normal ou mode téléversement
Bootloader de second niveau : chargé depuis la Flash, il initialise horloge et mémoire, choisit la partition à lancer
Votre application : setup() une fois, puis loop() sans fin
C’est exactement ce que force le bouton BOOT maintenu au reset : il bloque l’étape 1 en mode téléversement.
Du matériel au logiciel
34
Dans l’ordre : vérifiez que le câble USB-C transporte des données (beaucoup de câbles ne font que charger), que le bon port est sélectionné, puis maintenez le bouton BOOT pendant les 2 premières secondes de l’upload, jusqu’à ce que Writing at... apparaisse.
Vérification de la toolchain
35
Tout un programme en deux fonctions
void setup () { // une seule fois, au démarrage
pinMode ( LED_PIN , OUTPUT );
Serial . begin ( 115200 );
}
void loop () { // en boucle, jusqu'à la coupure
digitalWrite ( LED_PIN , HIGH );
delay ( 500 );
digitalWrite ( LED_PIN , LOW );
delay ( 500 );
}
Pas de main() : le core Arduino l’écrit, et appelle setup() puis loop().
Du matériel au logiciel
36
Pas de système d’exploitation
Sur un ordinateur, votre programme est un processus parmi d’autres. Ici, il n’y a rien autour de lui :
pas de multitâche : loop() tourne seul
pas de sleep() : un delay() bloque tout , boutons compris
pas d’arrêt propre : couper le courant coupe le programme net
En contrepartie, le comportement est prévisible à la milliseconde près .
Du matériel au logiciel
37
Activité : trouvez le bug
En binôme 3 min Sans PC
void loop () {
digitalWrite ( LED , HIGH );
delay ( 500 );
digitalWrite ( LED , LOW );
delay ( 500 );
if ( digitalRead ( BOUTON ) == LOW ) {
tirer ();
}
}
Le joueur appuie sur le bouton. Que se passe-t-il ?
Réponse attendue : le bouton n’est lu qu’une fois par seconde, et seulement à l’instant précis où le programme atteint la ligne. Un appui de 200 ms a une chance sur cinq d’être vu. Enchaîner sur la slide suivante.
38
Correction : le bouton n’est presque jamais lu
Le programme passe 1 seconde sur 1 dans les delay(). Le digitalRead() n’est atteint qu’une fois par tour.
Un appui court de 200 ms : vu une fois sur cinq
Ajoutez un écran à rafraîchir : le jeu devient injouable
La solution n’est pas de raccourcir le delay(), c’est de ne jamais bloquer
Du matériel au logiciel
39
Ne jamais bloquer : regarder l’heure
unsigned long dernierClignotement = 0;
const unsigned long INTERVALLE = 500; // ms
int etatLed = LOW;
void loop() {
if (millis() - dernierClignotement >= INTERVALLE) {
dernierClignotement = millis();
etatLed = !etatLed;
digitalWrite(LED_PIN, etatLed);
}
}
On compare l’heure à une date mémorisée : rien n’est jamais figé.
Du matériel au logiciel
40
Pour une pause courte et unique (initialiser un composant, attendre au démarrage), delay() est parfaitement acceptable. C’est dans la loop(), quand plusieurs tâches doivent avancer en parallèle, qu’il faut l’éviter.
Du matériel au logiciel
41
Votre premier programme
Blink, ligne par ligne
Quatre lignes qui résument le cours
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // configure la broche : écriture registre
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // 3,3 V sur la broche
delay(500); // bloque le CPU : il n'y a pas d'OS
digitalWrite(LED_BUILTIN, LOW); // 0 V
delay(500);
}
Architecture, registres, GPIO et absence de système d’exploitation, réunis en quatre lignes. Compilé et flashé, ce code tourne tant que la carte est alimentée.
Vérification de la toolchain
43
Sur l’ESP32-S3-DevKitC-1, la LED intégrée est une RGB adressable (WS2812), pas une LED monochrome. Si digitalWrite(LED_BUILTIN, ...) ne produit rien, utilisez rgbLedWrite(RGB_BUILTIN, 40, 0, 0); puis rgbLedWrite(RGB_BUILTIN, 0, 0, 0); en gardant les delay(500).
Vérification de la toolchain ESP32-S3-DevKitC-1
44
[env:esp32-s3-devkitc-1]
platform = espressif32 ; la famille de puces
board = esp32-s3-devkitc-1 ; la carte exacte
framework = arduino ; le core utilisé
monitor_speed = 115200 ; la vitesse du moniteur série
lib_deps = ; les bibliothèques, téléchargées seules
bodmer/TFT_eSPI@^2.5.0
Tout le projet est décrit ici. C’est ce fichier, versionné dans votre repo, qui permet à quelqu’un d’autre de recompiler votre code à l’identique.
PlatformIO Installer PlatformIO
46
Action
Raccourci
Où
Compiler (Build )
Ctrl Alt B
icône ✓, barre bleue
Téléverser (Upload )
Ctrl Alt U
icône →, barre bleue
Moniteur série
Ctrl Alt S
icône prise, barre bleue
Compiler avant de téléverser fait gagner du temps : les erreurs de syntaxe sortent sans attendre le flashage.
Installer VSCode Installer PlatformIO
47
Déboguer : le moniteur série
void setup () {
Serial . begin ( 115200 );
}
void loop () {
Serial . printf ( "x=%d y=%d btn=%d \n " , x , y , btn );
}
Tant qu’il n’y a pas d’écran, c’est votre seul retour visuel. Afficher une variable au bon endroit résout la moitié des bugs.
Le port série sous VSCode
48
C’est presque toujours une vitesse qui ne correspond pas. Vérifiez que le moniteur série est réglé sur la même valeur que celle passée à Serial.begin(), en général 115200.
Le port série sous VSCode
49
À retenir
Un µC = CPU + Flash + RAM + périphériques, sur une seule puce
Percevoir, décider, agir : le « décider », c’est votre programme
Flash = le programme (persistant), RAM = les données (volatile)
Les périphériques se pilotent par des registres
Code → compilation → édition de liens → flashage → exécution
Pas d’OS : delay() bloque tout, millis() ne bloque rien
Tension logique : 3,3 V
Architecture d’un microcontrôleur Du matériel au logiciel
50
À faire de votre côté
Sur votre machine 30 min
Installer VSCode , puis l’extension PlatformIO
Laisser PlatformIO télécharger la plateforme espressif32 : c’est long, ne le faites pas au dernier moment
Parcourir le tutoriel de vérification de la toolchain pour savoir ce qui vous attend
Une chaîne de développement qui fonctionne avant de manipuler, c’est une séance entière de gagnée.
Installer VSCode Installer PlatformIO Vérification de la toolchain
51