L’UART est la liaison série asynchrone point à point qui fait dialoguer l’ESP32 avec un autre appareil — module GPS, lecteur RFID, seconde carte — sur deux fils (TX et RX) plus une masse commune. À ne pas confondre avec le moniteur série : celui-ci occupe l’UART0 pour parler au PC via l’USB, tandis qu’ici on utilise un second port matériel pour parler à un composant. L’ESP32 en possède trois (UART0, UART1, UART2) et, contrairement à l’Arduino, ses broches sont remappables : inutile de recourir à SoftwareSerial.
À quoi ça sert ?
Beaucoup de modules ne parlent qu’en série. L’UART matériel de l’ESP32 les prend en charge sans occuper le moniteur :
Recevoir un flux. Un module GPS crache en continu des trames NMEA. On les lit sur un port dédié pendant que le moniteur reste libre pour le débogage.
Piloter un module. Un lecteur RFID, un modem, un afficheur série reçoivent leurs commandes par TX et répondent par RX.
Relier deux cartes. Deux ESP32 (ou un ESP32 et un Arduino) échangent des données par une liaison série directe, une fois les niveaux de tension adaptés.
Le principe du protocole (trame, bit de start, débit) est décrit dans la notion transverse UART. Cette fiche montre comment le câbler et le coder sur ESP32.
Procédure pas à pas
Quatre temps : choisir un port libre, l’initialiser, câbler, échanger.
1. Choisir un port libre
Serial (UART0) est réservé au moniteur et au journal de boot : on ne s’en sert pas pour un module, sinon les deux flux se mélangent. On prend donc Serial2 (ou Serial1). Par défaut, Serial2 est câblé sur GPIO16 (RX2) et GPIO17 (TX2).
2. Initialiser la liaison
Serial2.begin() accepte le débit, le format de trame, puis les broches RX puis TX :
const int RX2 = 16; // l'ESP32 reçoit iciconst int TX2 = 17; // l'ESP32 émet iciSerial2.begin(9600, SERIAL_8N1, RX2, TX2);
Le débit (9600, 115200…) doit être identique des deux côtés. Il est imposé par la datasheet du module. SERIAL_8N1 est le format le plus courant (8 bits de données, pas de parité, 1 bit de stop).
3. Câbler : TX vers RX, croisé
La règle d’or de l’UART : ce qu’une carte émet (TX), l’autre le reçoit (RX). Les deux fils se croisent, et les masses doivent être reliées.
Warning
Les broches de l’ESP32 sont en 3,3 V. Un module qui émet en 5 V sur la ligne RX de l’ESP32 peut détruire la broche. Vérifier la tension de sortie du module. Au-delà de 3,3 V, intercaler une adaptation de niveau (voir niveaux de tension).
4. Échanger
Les fonctions sont celles du moniteur, appliquées à Serial2 :
Serial2.available() — nombre d’octets reçus en attente ;
Serial2.read() — lit un octet ;
Serial2.write() / Serial2.print() — émet.
Exemple — Un pont entre le module et le moniteur
Cas concret : on relaie dans les deux sens ce qui passe sur Serial2 (le module) et sur Serial (le moniteur, donc le PC). On voit au moniteur ce que le module envoie, et on peut lui répondre en tapant au clavier : idéal pour tester un module série inconnu.
const int RX2 = 16; // reçoit du module (relié au TX du module)const int TX2 = 17; // émet vers le module (relié au RX du module)void setup() { Serial.begin(115200); // UART0 : vers le PC Serial2.begin(9600, SERIAL_8N1, RX2, TX2); // UART2 : vers le module Serial.println("Pont serie : moniteur <-> module (UART2)");}void loop() { // module -> PC : tout octet reçu sur UART2 est renvoyé au moniteur while (Serial2.available() > 0) { Serial.write(Serial2.read()); } // PC -> module : tout ce qu'on tape au moniteur part sur UART2 while (Serial.available() > 0) { Serial2.write(Serial.read()); }}
Chaque whilevide la file d’un côté avant de passer à l’autre, sans jamais bloquer : la boucle reste réactive dans les deux sens. Ouvrir le moniteur à 115200 (le débit du PC, indépendant des 9600 du module) : les trames du module défilent, et le texte tapé au clavier lui parvient.
Au moniteur ouvert à 115200, avec un module qui répond aux commandes AT :
Pont serie : moniteur <-> module (UART2)
AT
OK
+DATA:23.4,48
+DATA:23.5,48
+DATA:23.5,47
Seule la première ligne vient du sketch. Les suivantes sont relayées telles quelles : AT est parti du clavier vers le module, tout le reste est ce que le module a répondu. Un module muet ne produit rien après la première ligne : c’est le symptôme à reconnaître.
Pièges
TX branché sur TX. Le piège n°1 : rien ne circule. TX émet, RX écoute : les deux fils se croisent (TX d’un côté sur RX de l’autre).
Masse non reliée. Sans masse commune, les niveaux logiques n’ont pas de référence : réception erratique ou nulle. Toujours relier les GND.
Signal 5 V sur une broche ESP32. Un module 5 V (certains GPS, cartes Arduino) grille la broche RX de l’ESP32 en 3,3 V. Adapter le niveau.
Utiliser Serial pour le module. Brancher un module sur UART0 mélange son flux avec le moniteur et perturbe le téléversement. Réserver UART0 au PC, prendre Serial1/Serial2 pour les modules.
GPIO16/17 sur une carte WROVER. Sur les modules WROVER (8 Mo de PSRAM), GPIO16 et GPIO17 sont pris par la PSRAM et indisponibles : remapper Serial2 sur d’autres broches (Serial2.begin(9600, SERIAL_8N1, 25, 26)). Les cartes WROOM n’ont pas cette contrainte.
Débits désaccordés.Serial2.begin(9600…) face à un module en 115200 donne du charabia. Le débit vient de la datasheet du module, pas d’une supposition.
Exercices
Exercice 1 — Compter les lignes reçues
Un module envoie du texte ligne par ligne sur Serial2. Comptez les lignes reçues et affichez le total au moniteur à chaque nouvelle ligne. Indice : lire une ligne complète, pas un octet.
Corrigé
On lit la ligne entière avec readStringUntil('\n'), on incrémente un compteur, on renvoie au moniteur.
const int RX2 = 16;const int TX2 = 17;unsigned long lignes = 0;void setup() { Serial.begin(115200); Serial2.begin(9600, SERIAL_8N1, RX2, TX2);}void loop() { if (Serial2.available() > 0) { String ligne = Serial2.readStringUntil('\n'); // jusqu'au saut de ligne ligne.trim(); // retire espaces et \r if (ligne.length() > 0) { lignes++; Serial.print("Ligne "); Serial.print(lignes); Serial.print(" : "); Serial.println(ligne); } }}
readStringUntil('\n') agrège les octets jusqu’au saut de ligne, plus pratique que read() octet par octet pour du texte structuré.
Exercice 2 — Deux modules en même temps
Faites dialoguer l’ESP32 avec deux modules série simultanément (par exemple un GPS et un afficheur), chacun sur son propre UART, sans toucher au moniteur. Quelles broches choisir ?
Corrigé
On garde UART0 pour le moniteur, et on utilise Serial1 et Serial2 sur des broches libres distinctes.
Les trois UART matériels de l’ESP32 travaillent en parallèle. Serial1doit être remappé (ses broches par défaut servent la Flash). On choisit deux GPIO libres.
Cas particulier — UART1 et les liaisons longues
UART1 est disponible mais ses broches par défaut sont câblées sur la Flash interne : il faut toujours lui préciser des broches libres (Serial1.begin(baud, SERIAL_8N1, rx, tx)).
Sur les variantes à USB natif (C3, S3, C6…), Serial peut être l’USB Serial/JTAG, et le nombre d’UART matériels disponibles diffère. Se reporter au brochage de la carte via configurer les GPIO.
Pour une liaison longue ou en milieu bruité (plusieurs mètres, moteurs à proximité), l’UART simple ne suffit plus : on passe à une couche différentielle type RS-485, dont le principe est évoqué dans bus de communication.
Raccrochage projet
Preuve de concept — dès qu’un module série entre dans le projet (GPS, télémètre, modem), le port dédié le fait parler sans perturber le débogage.
Intégration et tests — relier deux sous-systèmes par une liaison série est un grand classique de l’assemblage. Le pont de l’exemple sert à vérifier chaque sens isolément.