Entrées et sorties numériques
Une carte Arduino communique avec le monde extérieur via ses broches (pins). Chaque broche peut être configurée en entrée ou en sortie, et elle ne connaît que deux états : HIGH (5 V) ou LOW (0 V). C'est le principe du numérique.
1. pinMode — configurer une broche
Avant d'utiliser une broche, tu dois lui dire ce qu'elle est.
C'est le rôle de pinMode(), appelée dans setup().
// Syntaxe
pinMode(numéroBroche, mode);
// Les trois modes disponibles
pinMode(13, OUTPUT); // broche en sortie (LED, relais…)
pinMode(2, INPUT); // broche en entrée (bouton avec résistance externe)
pinMode(2, INPUT_PULLUP); // entrée avec résistance pull-up interne (plus simple)
OUTPUT — la broche pilote une charge (LED, relais, buzzer).
INPUT — la broche écoute un signal extérieur.
INPUT_PULLUP — entrée avec résistance pull-up interne (~50 kΩ). La logique est inversée : LOW = bouton pressé.
2. Sortie numérique : allumer une LED
digitalWrite(broche, valeur) place la broche à HIGH (5 V) ou LOW (0 V).
C'est la manière la plus simple de contrôler une LED.
Toujours mettre une résistance en série avec une LED. Sans elle, la LED tire un courant excessif et brûle — et peut endommager la broche Arduino. Pour une LED standard alimentée en 5 V, utilise une résistance de 220 Ω à 470 Ω. Calcul : R = (Valim − Vf) / If → (5 − 2) / 0,02 = 150 Ω minimum. En pratique, 220 Ω est une valeur sûre et courante.
// LED sur la broche 13 (avec résistance 220 Ω en série)
const int PIN_LED = 13;
void setup() {
pinMode(PIN_LED, OUTPUT);
}
void loop() {
digitalWrite(PIN_LED, HIGH); // LED allumée
delay(1000); // attendre 1 seconde
digitalWrite(PIN_LED, LOW); // LED éteinte
delay(1000); // attendre 1 seconde
}
Ce programme fait clignoter la LED intégrée (broche 13 sur l'Arduino Uno).
delay(1000) bloque l'exécution pendant 1000 ms (1 seconde).
On verra plus loin pourquoi c'est une mauvaise habitude à long terme.
3. Entrée numérique : lire un bouton
digitalRead(broche) renvoie HIGH (1) ou LOW (0)
selon l'état de la broche. On l'utilise typiquement avec un bouton-poussoir.
const int PIN_BTN = 2;
const int PIN_LED = 13;
void setup() {
pinMode(PIN_BTN, INPUT_PULLUP); // pull-up interne activé
pinMode(PIN_LED, OUTPUT);
}
void loop() {
int etat = digitalRead(PIN_BTN);
if (etat == LOW) { // LOW = bouton pressé (logique inversée)
digitalWrite(PIN_LED, HIGH);
} else {
digitalWrite(PIN_LED, LOW);
}
}
Montage : une patte du bouton sur la broche 2, l'autre patte sur GND.
Avec INPUT_PULLUP, pas besoin de résistance externe.
4. Résistances pull-up et pull-down
Quand un bouton est ouvert, la broche d'entrée n'est connectée à rien. Elle "flotte" et capte des parasites électriques : son état est aléatoire. Une résistance pull-up ou pull-down force un état stable par défaut.
// PULL-DOWN (résistance externe vers GND)
// 5V ── Bouton ── Broche ── R (10 kΩ) ── GND
// État par défaut : LOW | Bouton pressé : HIGH
// PULL-UP (résistance externe vers 5V)
// 5V ── R (10 kΩ) ── Broche ── Bouton ── GND
// État par défaut : HIGH | Bouton pressé : LOW
// PULL-UP INTERNE Arduino (pas de résistance externe)
pinMode(broche, INPUT_PULLUP);
// Même logique : défaut HIGH, pressé LOW
La résistance interne de l'Arduino (~50 kΩ) est suffisante pour la plupart des boutons. Elle simplifie le montage : un seul fil relie le bouton à la broche, l'autre patte va au GND.
Règle pratique : utilise toujours INPUT_PULLUP pour les boutons.
Tu n'as besoin d'une résistance externe pull-down (10 kΩ vers GND) que si tu as absolument
besoin de la logique "HIGH = pressé", par exemple pour être compatible avec d'autres composants.
5. Le rebond (debounce)
Quand tu appuies sur un bouton mécanique, les contacts rebondissent pendant quelques millisecondes avant de se stabiliser. L'Arduino est si rapide qu'il détecte des dizaines de pressions là où il n'y en a eu qu'une.
La solution logicielle classique : ignorer les changements d'état pendant un délai de stabilisation
(~20 ms) grâce à millis().
const int PIN_BTN = 2;
const int PIN_LED = 13;
const unsigned long DELAI_DEBOUNCE = 20; // ms
int etatPrecedent = HIGH;
int etatLED = LOW;
unsigned long dernierChangement = 0;
void setup() {
pinMode(PIN_BTN, INPUT_PULLUP);
pinMode(PIN_LED, OUTPUT);
}
void loop() {
int lecture = digitalRead(PIN_BTN);
// Si l'état a changé, mémoriser le moment
if (lecture != etatPrecedent) {
dernierChangement = millis();
}
// Si l'état est stable depuis DELAI_DEBOUNCE ms, le prendre en compte
if ((millis() - dernierChangement) > DELAI_DEBOUNCE) {
if (lecture == LOW) { // bouton pressé, stable
etatLED = !etatLED; // basculer la LED
digitalWrite(PIN_LED, etatLED);
}
}
etatPrecedent = lecture;
}
Chaque fois que le bouton change d'état, on note le timestamp avec millis().
On ne prend la décision que si l'état est resté stable 20 ms — suffisant pour ignorer les rebonds.
6. Plusieurs LEDs : séquence et feux de circulation
On peut contrôler autant de LEDs que de broches disponibles. Exemple classique : simuler des feux de circulation (rouge → orange → vert).
// Feux de circulation — broche 9 = rouge, 10 = orange, 11 = vert
const int ROUGE = 9;
const int ORANGE = 10;
const int VERT = 11;
void setup() {
pinMode(ROUGE, OUTPUT);
pinMode(ORANGE, OUTPUT);
pinMode(VERT, OUTPUT);
}
void allumerSeul(int broche) {
digitalWrite(ROUGE, LOW);
digitalWrite(ORANGE, LOW);
digitalWrite(VERT, LOW);
digitalWrite(broche, HIGH);
}
void loop() {
allumerSeul(ROUGE); delay(3000); // rouge 3 s
allumerSeul(ORANGE); delay(1000); // orange 1 s
allumerSeul(VERT); delay(3000); // vert 3 s
}
La fonction allumerSeul() éteint toutes les LEDs puis allume la bonne.
Ce schéma fonctionne bien ici car on n'a qu'une tâche à gérer.
Dès qu'il y en a plusieurs, delay() devient un problème.
7. millis() vs delay() : le multi-tâche sans blocage
delay(n) bloque tout le programme pendant n millisecondes.
Pendant ce temps, l'Arduino ne peut rien faire d'autre — ni lire un bouton, ni envoyer des données.
millis() renvoie le nombre de millisecondes écoulées depuis le démarrage (type unsigned long).
Il n'arrête rien : il permet de mesurer le temps sans bloquer.
// Blink sans delay() — pattern non-bloquant
const int PIN_LED = 13;
const unsigned long INTERVALLE = 500; // ms entre chaque bascule
unsigned long dernierBlink = 0;
int etatLED = LOW;
void setup() {
pinMode(PIN_LED, OUTPUT);
}
void loop() {
unsigned long maintenant = millis();
if (maintenant - dernierBlink >= INTERVALLE) {
dernierBlink = maintenant;
etatLED = !etatLED; // basculer
digitalWrite(PIN_LED, etatLED);
}
// Ici on peut faire autre chose pendant que la LED clignote !
// Par exemple lire un bouton, envoyer une donnée série, etc.
}
Attention au débordement de millis() : après environ 49 jours, le compteur revient à 0.
Le calcul maintenant - dernierBlink reste correct même lors du débordement,
tant que les deux variables sont de type unsigned long — ne jamais utiliser int pour stocker une valeur de millis().
Le principe : à chaque tour de loop(), on vérifie si assez de temps s'est écoulé.
Si oui, on agit et on met à jour le timestamp. Sinon, on continue.
La boucle tourne des milliers de fois par seconde, parfaitement disponible pour d'autres tâches.
pinMode(broche, OUTPUT / INPUT / INPUT_PULLUP)configure la broche danssetup().digitalWrite(broche, HIGH/LOW)pilote une sortie numérique.digitalRead(broche)lit une entrée numérique (0 ou 1).- Toujours une résistance de 220–470 Ω en série avec une LED pour limiter le courant.
INPUT_PULLUPactive la résistance interne : logique inversée (LOW = pressé).- Le rebond mécanique s'élimine en filtrant les changements d'état sur ~20 ms avec
millis(). millis()est non-bloquant ;delay()bloque tout — préférermillis()dès qu'on gère plusieurs choses à la fois.