Pourquoi delay() bloque les projets Arduino en classe (et comment enseigner millis() aux élèves)

L'utilisation de delay() met le microcontrôleur en veille, aveuglant les capteurs et bloquant les moteurs. Voici comment le modèle mental du chronomètre permet d'enseigner la temporisation non bloquante aux élèves de la Senior Phase.
La fonction delay() fait échouer les projets Arduino en classe car elle interrompt complètement le microcontrôleur. Pendant toute la durée de la pause, le processeur ne fait rien : il ne peut pas lire un capteur de contact, ne peut pas vérifier la mesure de distance d'un capteur à ultrasons et ne peut pas réagir à un bouton d'arrêt. Si un robot à roues avance au moment où il rencontre un délai de deux secondes, il foncera à l'aveugle dans un mur pendant deux secondes pleines avant d'exécuter l'instruction suivante.
Pour corriger cela avec des élèves de Grade 7 à 9, nul besoin d'enseigner le multithreading, les interruptions matérielles par timer ou les machines à états orientées objet. Il suffit d'un seul modèle mental, très concret : regarder sa montre plutôt que faire la sieste.
L'anatomie d'un bug classique en classe
Dans presque tous les programmes d'initiation à la robotique, la leçon 1 est le classique clignotement de LED :
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);Cela fonctionne, procure aux élèves une gratification immédiadte et pose une mine conceptuelle qui explose trois semaines plus tard. Lors de la leçon 4, lorsqu'on demande aux élèves de concevoir un passage piéton (faire clignoter un feu et détecter l'appui sur un bouton) ou un rover éviteur d'obstacles (faire tourner des moteurs et mesurer une distance), leur code s'effondre.
L'élève écrit une boucle qui vérifie le bouton-poussoir, active un buzzer et appelle delay(1000). Lorsqu'il appuie sur le bouton, la carte l'ignore la plupart du temps. Pourquoi ? Parce que le processeur était occupé à décompter des cycles d'horloge dans le vide pendant le délai. Le doigt a appuyé sur le bouton puis l'a relâché durant les 99 % du cycle de boucle où la puce était virtuellement endormie.
Sur un ATmega328P cadencé à 16 MHz, l'appel de delay(1000) gaspille 16 millions de cycles d'horloge à exécuter des instructions d'assembleur vides. Le robot n'exécute pas plusieurs tâches : il est figé.
Le modèle mental de la montre au poignet
Avant de montrer du code aux élèves, éloignez-les de leurs écrans pour une démonstration de cinq minutes. Demandez à un volontaire d'effectuer une tâche : « Tape dans tes mains toutes les trois secondes, mais si je fais tomber ce stylo, rattrape-le avant qu'il ne touche le sol. »
Demandez-lui d'abord de simuler delay() : expliquez-lui que pour compter trois secondes, il doit fermer les yeux et compter jusqu'à trois silencieusement dans sa tête. Lâchez le stylo à la deuxième seconde. Il échouera à coup sûr : ses capteurs étaient désactivés pendant qu'il comptait le temps.
Proposez-lui ensuite le modèle non bloquant : demandez-lui de garder les yeux grands ouverts, de regarder l'horloge murale de la classe (ou une montre numérique) et de ne pas quitter votre main des yeux. Il vérifie l'heure : si trois secondes se sont écoulées depuis son dernier applaudissement, il tape dans ses mains. Si le stylo tombe, il réagit instantanément.
Cela fait passer la notion de temporisation d'une action (« attendre deux secondes ») à une comparaison (« s'est-il écoulé assez de temps ? »).
Le schéma fondamental : trois questions
Une fois que les élèves ont compris le principe de l'horloge murale, introduisez millis(). Expliquez que millis() est simplement un chronomètre interne lancé à la milliseconde exacte où l'Arduino a été branché. Il ne s'arrête jamais et ne met jamais le code en pause.
Chaque événement non bloquant peut être ramené à trois questions simples au sein de la boucle principale :
- Quelle heure est-il en ce moment ? (Lire le chronomètre :
currentTime = millis()) - À quand remonte la dernière fois où j'ai fait cette action ? (Consulter la note enregistrée :
previousTime) - Le temps nécessaire s'est-il écoulé ? (Faire la soustraction :
currentTime - previousTime >= interval)
Si la réponse à la troisième question est oui, exécutez l'action et mettez la note à jour : appliquez previousTime = currentTime. Si la réponse est non, ignorez l'action et passez immédiatement à la suite. Comme la boucle s'exécute en une fraction de milliseconde, la carte est libre de lire les capteurs à ultrasons, de vérifier les interrupteurs de fin de course et d'interroger les suiveurs de ligne des milliers de fois par seconde.
Enseigner la syntaxe sans submerger les débutants
Pour les élèves de Grade 7 et 8, le code standard en C++ autour de unsigned long engendre souvent une surcharge cognitive. Dans les établissements qui appliquent le programme officiel de codage et robotique de la Senior Phase, les élèves travaillent généralement dans des environnements de programmation par blocs ou des éditeurs hybrides.
Si vous enseignez par blocs (comme dans les environnements Arduino basés sur Scratch), l'adaptation est directe : introduisez un bloc « chronomètre » et une variable nommée last_time_checked. Évitez complètement le bloc « attendre 1 seconde » dès que les entrées de base sont abordées.
Si vous enseignez le C++ Arduino textuel, ne parachutez pas l'exemple standard BlinkWithoutDelay sur leurs écrans sans étayage pédagogique. L'exemple officiel d'Arduino combine deux concepts distincts en même temps : la temporisation non bloquante et le basculement d'état (l'inversion d'une variable d'état de LED). C'est pour cela que les élèves s'y perdent.
Séparez la vérification temporelle de la logique. Utilisez plutôt cette progression :
- Démontrer l'échec : faites-leur exécuter un clignotement de LED avec
delay()tout en essayant de déclencher un bouton d'arrêt d'urgence. Observez leur frustration lorsque le bouton ne réagit pas. - Introduire la variable de temps : montrez-leur comment afficher
millis()dans le moniteur série pour qu'ils voient les chiffres défiler en continu. Cela démystifie la fonction : ce n'est qu'un compteur kilométrique du temps. - Écrire la structure temporelle : fournissez un modèle guidé où la logique de soustraction est isolée du comportement du robot.
| Approche | État du processeur | Réactivité des capteurs | Pertinence |
|---|---|---|---|
delay(1000) | Arrêté dans une boucle d'attente active | Totalement aveugle pendant la pause | Démonstrations à tâche unique, initiation en Grade 4–6 |
Comparaison avec millis() | En exécution libre à pleine cadence | Instantanée (interrogation inframilliseconde) | Robotique, rovers, systèmes interactifs |
Ancrer les acquis dans les projets de classe
Lorsque les élèves passent de rovers qui roulent à l'aveugle à des rovers qui interrogent leurs capteurs en continu, leur expérience de débogage change du tout au tout. Au lieu de se demander pourquoi un capteur de contact n'a pas arrêté un moteur à courant continu, ils peuvent suivre l'exécution du programme de manière limpide.
Si votre établissement structure une progression sur plusieurs trimestres allant de la logique par blocs vers la robotique physique, le fait de disposer de séquences pédagogiques structurées et de montages matériels éprouvés évite les tâtonnements. Notre équipe chez Sheen Robotics for Schools travaille aux côtés des enseignants pour aligner ces concepts de systèmes embarqués avec l'emploi du temps de la classe, afin que les élèves construisent des modèles mentaux fiables avant que de mauvaises habitudes de code ne s'installent.
Dès lors qu'un élève comprend qu'un ordinateur ne doit jamais rester les yeux fermés à compter les secondes, il franchit le cap : il ne se contente plus d'exécuter des scripts, il commence à concevoir des logiciels réactifs et adaptés au monde réel.



