Index des chapitres Chapitre précédent Chapitre suivant

Chapitre 2 — Inputs digitaux

Du bouton poussoir au jeu Simon Says : apprendre à lire des signaux digitaux.

Le contexte

La phase 1 était unidirectionnelle : l'ESP32 envoyait des commandes. Maintenant, il doit écouter. Un bouton poussoir, c'est le capteur le plus simple — il dit ON ou OFF. Mais transformer ce signal brut en interaction fiable, c'est plus subtil qu'on pense.


Exercice 2.1 — Lire un bouton

Premier circuit avec un input : le bouton sur GPIO 21 avec INPUT_PULLUP.

Bouton + LED + buzzer branchés
Le bouton rejoint le circuit — LED, buzzer et bouton ensemble

Ce que j'ai appris :


Exercice 2.2 — Toggle et détection de front

Le problème : si on fait if (bouton == LOW) { toggle LED }, ça toggle des centaines de fois par seconde tant qu'on tient le bouton. La loop tourne trop vite !

La solution — détection de front descendant :

On compare l'état actuel avec l'état précédent. On ne réagit qu'au MOMENT où le bouton passe de HIGH à LOW.

bool appui = (etatActuel == LOW && etatPrecedent == HIGH);

Le deuxième piège — le rebond (bounce) :

Un bouton physique ne fait pas un contact propre. Quand on appuie, le signal "rebondit" entre HIGH et LOW pendant quelques millisecondes. Solution : ignorer tout changement pendant 50ms après un appui.

if (millis() - dernierChangement < 50) return;

Exercice 2.3 — Sélecteur de modes avec millis()

Combinaison de la machine à états (phase 1) avec le bouton (phase 2). Chaque appui passe au mode suivant :

OFF → FIXE → CLIGNOTANT → SOS → RESPIRE → OFF
Setup modes LED avec bouton
Le setup avec bouton, LED et buzzer — prêt pour le sélecteur de modes

Le grand changement — millis() au lieu de delay() :

delay() bloque tout. Impossible de lire le bouton pendant un delay(500). millis() résout tout : on regarde l'heure au lieu de fermer les yeux.

// delay() = fermer les yeux et compter
delay(500);

// millis() = regarder sa montre
if (millis() - dernierTick >= 500) {
  dernierTick = millis();
  // faire quelque chose
}

Le crash LEDC : Premier crash sérieux ! "Guru Meditation Error: Interrupt wdt timeout on CPU1". La cause : mélanger analogWrite() et digitalWrite() sur le même pin crée un conflit dans le périphérique LEDC de l'ESP32.

La règle : Sur ESP32, choisir UN mode par pin — soit analogWrite(), soit digitalWrite(). Ne jamais mélanger.


Exercice 2.4 — Simon Says : le boss de fin

Le jeu de mémoire classique, adapté pour un seul bouton + buzzer + LED.

Comment ça marche :

Machine à états avec branches :

ATTENTE → SHOW_SEQUENCE → SHOW_SYMBOLE → PAUSE_SYMBOLE
                                                 ↓
                   WAIT_INPUT → CHECK_INPUT
                                     ↓         ↓
                           ROUND_OK   GAME_OVER

Ce que j'ai appris :


Récapitulatif Phase 2

Concept Exercice Application robot soccer
digitalRead / INPUT_PULLUP 2.1 Lire des capteurs binaires
Détection de front / debounce 2.2 Réagir aux changements de capteurs
millis() non-bloquant 2.3 Multitâche (capteurs + moteurs)
Tableaux / random / timeout 2.4 Trajectoires, imprévisibilité

Temps total : ~2 heures

Difficulté : Moyenne (le debounce et millis() demandent de la réflexion)

Bug mémorable : Le crash LEDC — ne jamais mélanger analogWrite et digitalWrite sur ESP32 !

digitalRead debounce millis() analogWrite random tableaux

← Chapitre précédent

Prochain chapitre → Les inputs analogiques — le robot commence à percevoir le monde réel.