Configurer les GPIO (General Purpose Input/Output) de l’ESP32, c’est choisir quelles broches lire ou piloter, et comment. C’est le geste de base de toute interaction avec le monde physique — lire un bouton, allumer une LED, mesurer une tension, commander un actionneur. L’ESP32 offre beaucoup de broches, mais toutes ne se valent pas : certaines sont réservées, d’autres ont des contraintes au démarrage. Savoir lesquelles utiliser évite la majorité des montages qui « ne marchent pas sans raison ». Le concept général de broche d’entrée/sortie est traité dans GPIO. Cette fiche en donne l’incarnation ESP32.

À quoi ça sert ?

Sur l’ESP32, bien choisir et configurer ses broches conditionne trois choses :

  • Que le montage fonctionne tout court. Brancher un bouton sur une broche réservée à la Flash, ou attendre une résistance de tirage interne sur une broche qui n’en a pas, produit un comportement erratique impossible à déboguer au logiciel.
  • Que la carte démarre. Quelques broches (strapping pins) sont lues au reset pour choisir le mode de boot. Un montage qui les force peut empêcher le démarrage.
  • Que la mesure soit lisible. Les entrées analogiques ont des contraintes propres (plage, conflit avec le Wi-Fi) qu’il faut connaître avant de croire un relevé.

Les broches de l’ESP32

L’ESP32 d’origine expose des GPIO numérotées (GPIO0 à GPIO39, avec des trous : 20, 24 et 28 à 31 ne sortent pas du boîtier). On les désigne par leur numéro, pas par une position de carte. Quelques catégories à connaître :

  • Broches polyvalentes — la majorité : entrée, sortie, tirage interne, PWM. À privilégier.
  • Broches d’entrée seule — GPIO34, 35, 36, 39 : lecture uniquement, pas de sortie, pas de résistance de tirage interne. Parfaites pour un capteur analogique, à proscrire pour piloter quoi que ce soit ou pour un bouton sans tirage externe.
  • Broches de la Flash — GPIO6 à GPIO11 : utilisées par la mémoire Flash de la carte. Ne pas y toucher, sous peine de planter la puce.
  • Broches série — GPIO1 (TX) et GPIO3 (RX) : c’est l’UART0 du moniteur série. Les laisser libres tant qu’on l’utilise.
  • Strapping pins — GPIO0, 2, 5, 12, 15 : lues au reset pour le mode de boot. Utilisables, mais avec précaution (voir Pièges).

Brochage de l'ESP32 par catégorie : broches polyvalentes, entrée seule (GPIO34/35/36/39), broches Flash (GPIO6-11), série (GPIO1/3) et strapping (GPIO0/2/5/12/15)|640

Warning

L’ESP32 est en 3,3 V et ne tolère pas le 5 V. Appliquer 5 V sur une entrée peut détruire la broche. Tout signal 5 V (capteur, module) passe par une adaptation de niveau (voir niveaux de tension). C’est la différence la plus piégeuse avec l’Arduino.

Configurer une broche numérique

Comme partout, deux temps : déclarer le sens dans setup(), puis lire ou écrire dans loop().

const int LED = 16;       // sortie
const int BOUTON = 4;     // entrée
 
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BOUTON, INPUT_PULLUP);  // tirage interne activé
}
 
void loop() {
  bool appuye = (digitalRead(BOUTON) == LOW);  // PULLUP : LOW quand appuyé
  digitalWrite(LED, appuye ? HIGH : LOW);
}

pinMode accepte INPUT, OUTPUT, INPUT_PULLUP et, spécificité ESP32 absente de l’Arduino AVR, INPUT_PULLDOWN (tirage interne vers la masse). Le tirage interne évite l’entrée flottante : une broche en INPUT nu capte le bruit ambiant et lit n’importe quoi. Rappel : les broches GPIO34-39 n’ont aucun tirage interne. Un bouton sur l’une d’elles exige une résistance externe.

Câblage sur ESP32 : LED avec résistance 220 Ω sur GPIO16, bouton entre GPIO4 et GND lu en INPUT_PULLUP|600

Tip

Constantes en const, pas en #define. Déclarer const int LED = 16; est typé et lisible. Le compilateur vérifie l’usage. On réserve #define à ce que const ne sait pas faire (compilation conditionnelle, macros).

Lire une entrée analogique

analogRead(broche) renvoie la tension de la broche sur une échelle 12 bits : 0 à 4095 (et non 10 bits / 0-1023 comme l’Arduino Uno). Le principe de la conversion analogique-numérique est transverse (voir ADC). Deux contraintes ESP32 majeures :

  • La conversion naïve ment en haut de plage. L’atténuation vaut déjà 11 dB par défaut : la pleine plage 0-3,3 V est couverte sans rien régler. En revanche la réponse de l’ADC n’est pas linéaire près du haut de l’échelle, et un calcul brut * 3.3 / 4095 en hérite. Pour une tension juste, utiliser analogReadMilliVolts(broche), qui s’appuie sur les données de calibration gravées dans la puce. (analogSetAttenuation() sert à réduire la plage pour gagner en finesse sur un capteur de faible tension, pas à l’étendre.)
  • Conflit ADC2 / Wi-Fi. Les broches du convertisseur ADC2 (GPIO0, 2, 4, 12-15, 25-27) sont inutilisables dès que le Wi-Fi est actif. Pour une mesure analogique sur un projet connecté, utiliser ADC1 : GPIO32 à GPIO39.
const int POTAR = 34;  // ADC1, compatible Wi-Fi, entrée seule
 
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  int brut = analogRead(POTAR);              // 0..4095, valeur crue
  int mV = analogReadMilliVolts(POTAR);      // tension calibrée, en millivolts
 
  Serial.print(brut);
  Serial.print("  ->  ");
  Serial.print(mV / 1000.0, 2);              // la même, en volts
  Serial.println(" V");
  delay(200);
}

Câblage du potentiomètre sur ESP32 : les deux extrémités entre 3V3 et GND, le curseur sur GPIO34|600

Commander en PWM (intensité, vitesse)

L’ESP32 n’a pas d’analogWrite historique : la modulation de largeur d’impulsion passe par le périphérique LEDC. Avec le cœur 3.x, on attache une broche à une fréquence et une résolution, puis on écrit un rapport cyclique :

const int LED = 16;
 
void setup() {
  ledcAttach(LED, 5000, 8);   // 5 kHz, résolution 8 bits (0..255)
}
 
void loop() {
  for (int duty = 0; duty <= 255; duty++) {
    ledcWrite(LED, duty);     // fondu progressif
    delay(5);
  }
}

Câblage : c’est la même LED sur GPIO16 qu’à la section numérique (voir son montage plus haut).

Warning

L’API LEDC a changé au cœur 3.0. Le code ci-dessus (ledcAttach(broche, freq, bits) + ledcWrite(broche, duty)) suppose un cœur ≥ 3.0. Sur un cœur 2.x, l’API était ledcSetup(canal, freq, bits) + ledcAttachPin(broche, canal) + ledcWrite(canal, duty). Si ledcAttach est introuvable, c’est une question de version (voir prise en main, étape 2).

Le concept de PWM lui-même (rapport cyclique, fréquence) est transverse (voir PWM).

Pièges

Broche d’entrée seule utilisée en sortie. GPIO34-39 ne peuvent pas piloter une LED ni fournir de tirage interne. Symptôme : pinMode(34, OUTPUT) sans effet, ou un bouton qui lit n’importe quoi. Les réserver aux capteurs en lecture.

Entrée flottante. Un bouton sur une broche INPUT sans tirage (ni interne ni externe) lit aléatoirement HIGH/LOW. Utiliser INPUT_PULLUP (ou INPUT_PULLDOWN), et sur GPIO34-39 une résistance externe obligatoire.

ADC2 + Wi-Fi. Une mesure analogique qui devient nulle ou figée dès qu’on active le Wi-Fi : la broche est sur ADC2. Migrer le capteur sur ADC1 (GPIO32-39).

Strapping pin contrainte au boot. Un montage qui force GPIO0, 2, 5, 12 ou 15 à un niveau au reset peut empêcher le démarrage (GPIO0 à LOW = mode bootloader ; GPIO12 à HIGH = mauvaise tension Flash). Éviter de les câbler en tirage permanent, ou choisir d’autres broches.

Toucher aux broches Flash 6-11. Les câbler plante la puce. Ne jamais les utiliser comme GPIO.

Croire l’échelle Arduino. analogRead rend 0-4095 (12 bits), pas 0-1023. Une formule de conversion copiée d’un code Uno donne des valeurs fausses d’un facteur 4.

Exercices

Exercice 1 — Bouton anti-rebond, une action par appui

Un bouton sur GPIO4 (en INPUT_PULLUP) doit basculer une LED (GPIO16) à chaque appui : un appui = un changement d’état, pas un clignotement tant qu’on tient le bouton. Quel est le bon motif ?

Exercice 2 — Gradateur piloté au potentiomètre

Un potentiomètre sur GPIO34 (ADC1) doit régler l’intensité d’une LED sur GPIO16 en PWM. Reliez la lecture 0-4095 au rapport cyclique 0-255.

Raccrochage projet

  • Étape 4 de la phase de preuve de concept — dès qu’on branche le premier capteur ou actionneur sur la carte cible, le choix des broches (entrée seule, ADC1 vs ADC2, strapping) conditionne la fiabilité du prototype. Un câblage choisi à la légère se paie en bugs intermittents.
  • Étape 2 de la phase d’intégration et tests — valider une pièce électronique isolée passe par la lecture de ses entrées/sorties, donc par des GPIO correctement configurées et des niveaux de tension respectés.

Fixer une fois pour toutes une carte de ses broches sûres (ADC1 pour les capteurs, broches polyvalentes pour les actionneurs, strapping évitées) évite de redécouvrir les contraintes à chaque montage.

Aller plus loin

  • GPIO — le concept général d’entrée/sortie numérique (transverse).
  • PWM — la modulation de largeur d’impulsion en détail (transverse).
  • Référence GPIO de l’Arduino-ESP32 — fonctions et contraintes par variante.
  • Sortie analogique vraie (DAC) sur GPIO25/26 de l’ESP32 d’origine : dacWrite(broche, valeur) — absente des C3/S3.

Voir aussi