← Retour au chapitre

Étape 1 / 3

Exo 10 : Multitâche — millis() vs delay()

delay() = bloquer la route. millis() = rond-point. 2+ LEDs indépendantes.

Chapitres précédents non terminés
Pour un apprentissage optimal, termine d'abord : PWM : varier l'intensité

Le problème de delay()

Jusqu'ici, on a utilisé delay() pour créer des pauses. C'est simple et ça marche... mais delay() bloque TOUT le programme. Pendant qu'il attend, l'Arduino ne peut rien faire d'autre : pas lire un bouton, pas mettre à jour un afficheur, pas faire clignoter une seconde LED.

Analogie : delay() c'est comme bloquer une route entière pour faire un demi-tour. millis() c'est un rond-point : tout le monde continue à circuler.

Avec delay() — tout est bloqué
void loop() {
  digitalWrite(8, HIGH);
  delay(500);     // ⏸ TOUT est bloqué 500ms
  digitalWrite(8, LOW);
  delay(500);     // ⏸ Encore bloqué

  // La LED B ne peut PAS clignoter
  // à son propre rythme !
}

millis() : le chronomètre interne

La fonction millis() retourne le nombre de millisecondes écoulées depuis que l'Arduino a démarré. C'est un chronomètre qui tourne en permanence.

millis()

Retourne le temps écoulé

unsigned long

Type nécessaire (grand nombre)

~49 jours

Avant de revenir à 0 (overflow)

Le pattern magique : au lieu de bloquer avec delay(), on compare « maintenant » avec « la dernière fois qu'on a agi ». Si la différence dépasse notre intervalle, on agit et on note le nouveau « dernier moment ».

if (millis() - previousMillis >= interval) { ... }

Simulateur : delay() vs millis()

Compare les deux approches avec 2 LEDs. En mode delay(), les LEDs sont forcées de clignoter ensemble. Avec millis(), chacune a son propre rythme.

LED A (500ms)

LED B (300ms)

0.0s

Code : 2 LEDs indépendantes avec millis()

Chaque LED a son propre previousMillis, son propre interval et son propre state. Le loop() tourne à pleine vitesse et vérifie à chaque passage si c'est le moment de toggler.

unsigned long prevA = 0;
unsigned long prevB = 0;
const unsigned long intervalA = 500;  // LED A : 500ms
const unsigned long intervalB = 300;  // LED B : 300ms
bool stateA = LOW;
bool stateB = LOW;

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

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

  if (now - prevA >= intervalA) {
    prevA = now;
    stateA = !stateA;
    digitalWrite(8, stateA);
  }

  if (now - prevB >= intervalB) {
    prevB = now;
    stateB = !stateB;
    digitalWrite(9, stateB);
  }
}

Important : on utilise unsigned long pour stocker le temps. Un simple int déborderait au bout de 32 secondes ! unsigned long tient ~49 jours.

Pièges courants avec millis()

  • Utiliser int au lieu de unsigned long → ton timing plante au bout de 32 secondes (overflow du int 16 bits).
  • Oublier de mettre à jour previousMillis = now dans le if → la condition est toujours vraie et la LED clignote à fond.
  • Comparer avec == au lieu de >= → tu risques de rater le moment exact et la LED ne toggle jamais.

Schéma du circuit

Deux circuits LED indépendants : LED rouge sur D8, LED verte sur D9. Chacune a sa propre résistance 220Ω.

D8 → R 220Ω → LED rouge → GND | D9 → R 220Ω → LED verte → GND

D8220ΩD9220Ω

Montage pas à pas

LED rouge en colonne 10 (rangée c/d), résistance 220Ω verticale. Câble rouge du pin D8 vers colonne 11 (anode A). Cavalier GND.

++151015202530abcdeabcdefghijfghij151015202530++
100%

L'opérateur ! (NOT logique)

Pour inverser l'état d'une LED (allumée → éteinte, éteinte → allumée), on utilise ! (le NOT logique). C'est un raccourci élégant pour « l'inverse de ».

bool state = LOW;
state = !state; // LOW devient HIGH
state = !state; // HIGH redevient LOW

C'est équivalent à if (state == LOW) state = HIGH; else state = LOW; — mais en beaucoup plus court !

Exercice : complète le pattern millis()

Remplis les trous pour faire clignoter LED A indépendamment :

1. Quelle fonction retourne le temps en millisecondes ?

unsigned long now = ();

2. Avec quoi on compare « now » pour savoir si assez de temps s'est écoulé ?

if (now - >= intervalA) {

3. Comment inverser l'état de la LED ?

  stateA = ;

Défis bonus

🎵 Défi : 3 LEDs, 3 rythmes

Ajoute une 3e LED sur le pin ~10 avec un intervalle de 700ms. Les 3 LEDs doivent clignoter indépendamment.

⚡ Défi : Fade non-bloquant

Combine millis() et analogWrite() pour créer un effet respiration sans aucun delay(). La LED doit toujours pouvoir réagir à un bouton.

À retenir

  • delay() bloque tout le programme — rien d'autre ne peut s'exécuter pendant ce temps.
  • millis() retourne le temps écoulé depuis le démarrage, sans bloquer.
  • Le pattern if (millis() - prev >= interval) permet de vérifier si c'est le moment d'agir.
  • Chaque tâche indépendante a besoin de son propre previousMillis, interval et state.
  • Utiliser unsigned long pour stocker le temps (un int déborderait en 32s).

Valide cette étape quand tu as terminé la lecture et la manipulation.

Première étape du chapitre Exo 11 : Parle-moi — Serial Monitor →

Electro-Lab - support pédagogique Arduino (MVP).

IFOSUP Wavre - Cours Drones et Robotique.