Qu'est-ce que l'UART ? TX/RX, baud et liaison série avec Arduino
Qu'est-ce que l'UART ? TX/RX croisés, bauds, bits start et stop, relier deux Arduino, SoftwareSerial, niveaux 5V/3,3V, ESP32 Serial2 et UART du Pico.
La réponse courte à qu'est-ce que l'UART : l'UART (Universal Asynchronous Receiver-Transmitter) est le circuit de communication série qui permet à deux appareils d'échanger des données octet par octet avec seulement deux fils de données (TX et RX) et une masse (GND) commune. Chaque ligne que tu vois dans le moniteur série quand l'Arduino est branché à l'ordinateur arrive par l'UART. Des dizaines de modules, comme les récepteurs GPS, le module Bluetooth HC-05, le module Wi-Fi ESP-01, le module GSM SIM800L, les lecteurs d'empreintes et les lecteurs MP3, dialoguent aussi avec l'Arduino par UART.
Dans cet article, on explique pas à pas pourquoi l'UART n'a pas besoin de ligne d'horloge, ce qu'est le débit en bauds, comment un octet est encadré par des bits de start, de données et de stop, pourquoi TX et RX se croisent, comment faire dialoguer deux Arduino d'abord dans un sens puis dans les deux, les limites de SoftwareSerial, comment relier sans risque des cartes 5 V et 3,3 V, les trois UART de l'ESP32 et les broches UART du Raspberry Pi Pico. Dans la dernière partie, tu verras comment construire des paquets avec des caractères de début et de fin pour que les données ne se mélangent pas, ainsi que les erreurs les plus fréquentes.

Qu'est-ce que l'UART et comment fonctionne-t-il ?
Le mot « asynchrone » dans le nom est essentiel : en I2C et en SPI, un signal d'horloge accompagne les données, alors que l'UART n'a pas de ligne d'horloge. À la place, les deux côtés se mettent d'accord à l'avance sur une vitesse, le débit en bauds. Au repos, la ligne reste à HIGH (1). Pour envoyer un octet, l'émetteur met la ligne à LOW pendant la durée d'un bit : c'est le bit de start, qui dit au récepteur « commence à compter ». Viennent ensuite les 8 bits de données, en commençant par le bit de poids faible (LSB), éventuellement un bit de parité, et enfin la ligne reste à HIGH au moins un bit : c'est le bit de stop. Le réglage par défaut de l'Arduino est 8N1 : 8 bits de données, pas de parité, 1 bit de stop.
| Bit | Start | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | Stop |
|---|---|---|---|---|---|---|---|---|---|---|
| Lettre 'A' (0x41 = 0100 0001) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| Niveau de la ligne | LOW | HIGH | LOW | LOW | LOW | LOW | LOW | HIGH | LOW | HIGH |
Chaque bit dure 1 / débit secondes. À 9600 bauds, un bit dure 104,2 microsecondes ; comme une trame 8N1 compte 10 bits par octet (start + 8 données + stop), on peut envoyer au maximum 960 octets par seconde. Après avoir détecté le front descendant du bit de start, le récepteur lit la ligne au milieu de chaque bit. Même si les deux horloges diffèrent un peu, les données sont lues correctement tant que l'erreur cumulée sur 10 bits reste inférieure à un demi-bit ; c'est pourquoi l'erreur totale de débit doit rester sous 2 à 3 % environ. Avec son quartz de 16 MHz, l'Arduino Uno ne produit pas exactement 115200 bauds et la vitesse réelle s'écarte d'environ 2,1 % ; ça fonctionne quand même, car c'est dans la limite.
| Bauds | Durée d'un bit | Octets max par seconde (8N1) | Où l'utilise-t-on ? |
|---|---|---|---|
| 9600 | 104,2 µs | 960 | GPS NEO-6M, HC-05 en mode données, DFPlayer Mini, réglage classique du moniteur série |
| 19200 | 52,1 µs | 1920 | Certains capteurs et vieux modems |
| 38400 | 26,0 µs | 3840 | HC-05 en mode commandes AT |
| 57600 | 17,4 µs | 5760 | Anciens bootloaders Arduino, limite haute de SoftwareSerial |
| 115200 | 8,68 µs | 11520 | ESP32 et ESP-01, sortie de débogage rapide |
| 1000000 et plus | 1 µs ou moins | 100 000+ | Liaisons courtes entre cartes, enregistrement rapide |
UART, I2C et SPI : les différences
Les trois méthodes de communication série les plus courantes sur Arduino sont l'UART, l'I2C et le SPI. L'UART ne fonctionne qu'entre deux appareils, et chacun peut parler quand il veut (full duplex). L'I2C réunit des dizaines d'appareils avec des adresses sur les deux mêmes fils ; le SPI est bien plus rapide avec quatre fils mais demande une broche de sélection par appareil. Pour les détails, lis les articles Qu'est-ce que l'I2C et Qu'est-ce que le bus SPI.
| Caractéristique | UART | I2C | SPI |
|---|---|---|---|
| Fils | 2 (TX, RX) + GND | 2 (SDA, SCL) + GND | 4 (SCK, MOSI, MISO, CS) + GND |
| Ligne d'horloge | Non (asynchrone) | Oui | Oui |
| Nombre d'appareils | 2 (point à point) | Jusqu'à 127, par adresse | Autant que de broches CS |
| Vitesse typique | 9600–115200 bauds | 100–400 kHz | 1–80 MHz |
| Deux sens en même temps | Oui (full duplex) | Non | Oui |
| Modules typiques | GPS, Bluetooth, GSM, ESP-01, empreinte | OLED, LCD, RTC, BME280 | Carte SD, RFID, TFT, LoRa |
TX et RX croisés, masse commune
La règle d'or du câblage UART : la broche TX (émission) d'un appareil va sur la broche RX (réception) de l'autre, les fils se croisent donc. Pense à une bouche et une oreille : là où l'un parle, l'autre doit écouter. Si tu relies TX à TX, deux sorties se retrouvent face à face et aucune donnée ne passe. Le troisième fil, GND, donne aux deux cartes la même référence de tension ; sans lui, « HIGH » et « LOW » n'ont plus de sens et les données deviennent des caractères incohérents. Même si les cartes sont alimentées par des sources différentes, leurs masses doivent être reliées.
| Arduino A | Fil | Arduino B | Remarque |
|---|---|---|---|
| TX (D11, SoftwareSerial) | → | RX (D10, SoftwareSerial) | Ce qu'envoie A arrive à B |
| RX (D10, SoftwareSerial) | ← | TX (D11, SoftwareSerial) | La réponse de B arrive à A |
| GND | — | GND | Masse commune, obligatoire |
| 5V | facultatif | 5V | Seulement si une seule carte est alimentée par USB |
Faire dialoguer deux Arduino : dans un sens

Dans le premier exemple, la carte A envoie dix fois par seconde à la carte B la valeur d'un potentiomètre branché sur A0, et la carte B règle avec elle la luminosité de la LED sur D9. Les deux cartes utilisent SoftwareSerial sur D10 (RX) et D11 (TX), ce qui laisse libres la liaison USB et le moniteur série. Comme les valeurs sont envoyées avec println(), chaque nombre se termine par les caractères « \r\n » (fin de ligne) ; le récepteur sait ainsi que le nombre est complet. Câblage : D11 de A vers D10 de B, D10 de A vers D11 de B, masses reliées.
1#include <SoftwareSerial.h>
2
3SoftwareSerial link(10, 11); // RX = 10, TX = 11 (diğer karta / to the other board)
4
5void setup() {
6 Serial.begin(9600); // USB: bilgisayar / computer
7 link.begin(9600); // iki tarafta aynı baud / same baud on both sides
8}
9
10void loop() {
11 int deger = analogRead(A0); // potansiyometre 0-1023 / potentiometer 0-1023
12 link.println(deger); // ör. "512\r\n" / e.g. "512\r\n"
13 Serial.println(deger);
14 delay(100); // saniyede 10 ölçüm / 10 readings per second
15}
161#include <SoftwareSerial.h>
2
3SoftwareSerial link(10, 11); // RX = 10, TX = 11
4const int LED_PIN = 9; // PWM pini / PWM pin
5
6char tampon[8]; // en fazla 7 karakter + '\0' / up to 7 chars + '\0'
7byte konum = 0;
8
9void setup() {
10 Serial.begin(9600);
11 link.begin(9600);
12 pinMode(LED_PIN, OUTPUT);
13}
14
15void loop() {
16 while (link.available()) { // gelen her baytı oku / read every incoming byte
17 char c = link.read();
18 if (c == '\n') { // satır bitti / line complete
19 tampon[konum] = '\0';
20 int deger = atoi(tampon);
21 analogWrite(LED_PIN, map(deger, 0, 1023, 0, 255));
22 Serial.println(deger);
23 konum = 0;
24 } else if (c != '\r' && konum < sizeof(tampon) - 1) {
25 tampon[konum++] = c; // satıra ekle / append to the line
26 }
27 }
28}
29Deux points comptent dans le code récepteur. D'abord, les données n'arrivent jamais « d'un bloc » : « 512 » arrive en trois octets séparés, à environ 1 milliseconde d'intervalle. C'est pourquoi on accumule les octets dans un tampon et on les convertit en nombre à l'arrivée de la fin de ligne. Ensuite, le code n'attend jamais : des fonctions comme readString() ou parseInt() attendent 1 seconde par défaut quand rien n'arrive et ralentissent ton programme. Lire les octets au fur et à mesure est la méthode la plus fiable et la plus rapide. On limite aussi la taille du tampon pour qu'une donnée corrompue ne soit pas écrite hors du tableau.
Communication dans les deux sens : commande et réponse
Les vrais projets demandent souvent un échange dans les deux sens : une carte envoie une commande, l'autre l'exécute et répond. Dans l'exemple ci-dessous, la carte A sert de passerelle : elle transmet à B chaque caractère tapé dans le moniteur série et affiche chaque caractère venant de B. La carte B comprend les commandes « LED ON », « LED OFF » et « DURUM? » (état), répond à chacune et prévient aussi d'elle-même quand on appuie sur le bouton de D2. N'oublie pas de régler la fin de ligne du moniteur série sur Nouvelle ligne (Newline) ; c'est grâce à ce caractère que B sait que la commande est terminée.
1#include <SoftwareSerial.h>
2
3SoftwareSerial link(10, 11); // RX = 10, TX = 11
4
5void setup() {
6 Serial.begin(9600);
7 link.begin(9600);
8 Serial.println("Komut yaz / type a command: LED ON, LED OFF, DURUM?");
9}
10
11void loop() {
12 if (Serial.available()) link.write(Serial.read()); // bilgisayar -> B kartı / computer -> board B
13 if (link.available()) Serial.write(link.read()); // B kartı -> bilgisayar / board B -> computer
14}
151#include <SoftwareSerial.h>
2
3SoftwareSerial link(10, 11); // RX = 10, TX = 11
4const int LED_PIN = 13; // kart üstündeki LED / on-board LED
5const int BUTON_PIN = 2; // buton GND'ye / button to GND
6
7String satir = "";
8int oncekiButon = HIGH;
9
10void komutCalistir(String k) {
11 k.trim(); // \r ve boşlukları at / strip \r and spaces
12 if (k == "LED ON") {
13 digitalWrite(LED_PIN, HIGH);
14 link.println("OK LED=1");
15 } else if (k == "LED OFF") {
16 digitalWrite(LED_PIN, LOW);
17 link.println("OK LED=0");
18 } else if (k == "DURUM?") { // durum sorgusu / status query
19 link.print("LED=");
20 link.print(digitalRead(LED_PIN));
21 link.print(" BUTON=");
22 link.println(digitalRead(BUTON_PIN) == LOW ? 1 : 0);
23 } else {
24 link.print("HATA / unknown: ");
25 link.println(k);
26 }
27}
28
29void setup() {
30 link.begin(9600);
31 pinMode(LED_PIN, OUTPUT);
32 pinMode(BUTON_PIN, INPUT_PULLUP);
33 satir.reserve(32);
34}
35
36void loop() {
37 while (link.available()) {
38 char c = link.read();
39 if (c == '\n') {
40 komutCalistir(satir);
41 satir = "";
42 } else if (satir.length() < 31) {
43 satir += c;
44 }
45 }
46
47 int buton = digitalRead(BUTON_PIN); // değişince kendiliğinden bildir / report changes unprompted
48 if (buton != oncekiButon) {
49 oncekiButon = buton;
50 link.println(buton == LOW ? "BUTON BASILDI / pressed" : "BUTON BIRAKILDI / released");
51 delay(20); // basit debounce / simple debounce
52 }
53}
54L'appel trim() sur la carte B supprime le caractère \r qui arrive quand le moniteur série est réglé sur « Les deux, NL et CR », ainsi que les espaces superflus ; les commandes sont donc reconnues avec les deux réglages. Utiliser reserve(32) sur l'objet String évite une nouvelle allocation mémoire à chaque caractère ajouté et limite la fragmentation des 2 Ko de RAM de l'Uno. Cette structure sert aussi de base pour piloter l'Arduino depuis un programme Python sur l'ordinateur ; détails dans l'article communication série Arduino et Python.
Les limites de SoftwareSerial
SoftwareSerial imite un UART par logiciel au lieu du matériel : le processeur chronomètre lui-même chaque bit. C'est très pratique, mais il y a un prix. Pendant l'émission, les interruptions sont coupées pendant tout l'octet ; à 9600 bauds, cela fait environ 1 milliseconde par octet, pendant laquelle millis() peut dériver, les impulsions d'un servo peuvent trembler et des données arrivant sur un autre port série peuvent se perdre. Un seul port SoftwareSerial peut écouter à la fois ; si tu en ouvres un second, tu choisis lequel écoute avec listen(). Sur des cartes comme la Mega et la Leonardo, seules certaines broches capables d'interruption peuvent servir de RX.
| Caractéristique | UART matériel (Serial) | SoftwareSerial | AltSoftSerial |
|---|---|---|---|
| Broches sur l'Uno | D0 (RX), D1 (TX), partagées avec l'USB | Presque toutes (PCINT pour RX) | Fixes : D8 (RX), D9 (TX) |
| Vitesse fiable maximale | 1–2 Mbauds | 57600 bauds (115200 limite) | Stable à vitesse moyenne (9600–38400) |
| Charge processeur | Très faible (tampon matériel) | Élevée, interruptions coupées à l'émission | Moyenne, utilise le Timer1 |
| Émettre et recevoir en même temps | Oui | Non | Oui |
| Plusieurs ports | 4 sur la Mega | Un seul écoute à la fois | Un seul port |
| Conflits | Téléversement et moniteur série | Bibliothèques sensibles au timing comme Servo, NeoPixel | PWM sur D10 et Servo (Timer1) |
Adapter les niveaux 5V et 3,3V
En UART, le niveau « HIGH » correspond à la tension de fonctionnement de la carte : 5 V sur l'Arduino Uno, 3,3 V sur l'ESP32, le Raspberry Pi Pico, l'ESP-01 et la plupart des modules récents. Relier directement une sortie TX en 5 V à une entrée RX en 3,3 V met l'entrée en surtension et abîme la broche, à la longue ou tout de suite ; ni l'ESP32 ni le Pico à RP2040 ne tolèrent le 5 V. Dans l'autre sens, ça passe en général : l'Uno considère comme HIGH tout ce qui dépasse 3,0 V, il peut donc lire un TX en 3,3 V, mais comme c'est proche de la limite, un convertisseur de niveau est plus sûr sur de longs fils.
| Liaison | Ce qu'il faut | Exemple |
|---|---|---|
| TX de l'Uno (5 V) → RX de l'ESP32 / du Pico (3,3 V) | Pont diviseur ou convertisseur de niveau | 1 kΩ en série + 2 kΩ vers GND : 5 × 2/3 ≈ 3,3 V |
| TX de l'ESP32 / du Pico (3,3 V) → RX de l'Uno (5 V) | En direct le plus souvent | L'Uno considère HIGH au-dessus de 3,0 V |
| TX de l'Uno → RX du HC-05 | Pont diviseur conseillé | Le RX du HC-05 fonctionne en niveau 3,3 V |
| TX de l'Uno → RX du SIM800L | Pont diviseur | Le niveau de signal du SIM800L est d'environ 2,8 V |
| Deux cartes en 5 V ou deux en 3,3 V | En direct | Uno ↔ Nano, ESP32 ↔ Pico |
UART sur l'ESP32 : Serial, Serial1 et Serial2
L'ESP32 possède trois UART matériels, et le meilleur, c'est que grâce à sa matrice GPIO, les broches UART peuvent être déplacées sur presque n'importe quelle broche. L'UART0 (Serial) est relié à la puce USB-série et sert au moniteur série. L'UART2 (Serial2) est par défaut sur GPIO 16 (RX) et 17 (TX). Les anciennes broches par défaut de l'UART1 (GPIO 9 et 10) sont reliées à la mémoire flash de la carte et inutilisables directement ; démarre donc toujours Serial1 en précisant les broches : begin(baud, SERIAL_8N1, RX, TX). Le code ci-dessous crée une passerelle dans les deux sens entre le moniteur série et un appareil branché sur l'UART2 (un GPS, un autre Arduino, un capteur) ; idéal pour lire les phrases NMEA d'un module GPS.
| UART | Nom Arduino | RX / TX par défaut | Remarque |
|---|---|---|---|
| UART0 | Serial | GPIO 3 / GPIO 1 | Relié à la puce USB-série, téléversement et moniteur série |
| UART1 | Serial1 | GPIO 9 / GPIO 10 (flash, à éviter) | Indique d'autres broches dans begin(), par ex. 25 / 26 |
| UART2 | Serial2 | GPIO 16 / GPIO 17 | Sur les cartes WROVER, 16/17 servent à la PSRAM : choisis d'autres broches |
1// ESP32: UART0 = Serial (USB), UART2 = Serial2 (GPIO 16/17)
2const int RXD2 = 16; // karşı cihazın TX'i buraya / the other device's TX goes here
3const int TXD2 = 17; // karşı cihazın RX'ine / to the other device's RX
4
5void setup() {
6 Serial.begin(115200); // USB Seri Monitör / USB Serial Monitor
7 Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2); // baud, çerçeve, RX, TX / baud, frame, RX, TX
8 // UART1'i de istediğin pinlere taşıyabilirsin / UART1 can be moved to any free pins:
9 // Serial1.begin(115200, SERIAL_8N1, 25, 26);
10 Serial.println("UART2 hazir / ready");
11}
12
13void loop() {
14 while (Serial2.available()) Serial.write(Serial2.read()); // UART2 -> USB
15 while (Serial.available()) Serial2.write(Serial.read()); // USB -> UART2
16}
17Les UART de l'ESP32 montent jusqu'à 5 Mbauds et chacun a son tampon matériel ; le tampon de réception par défaut fait 256 octets et peut être agrandi avant begin() avec un appel comme Serial2.setRxBufferSize(1024). C'est utile avec les modules GPS qui envoient des dizaines de phrases par seconde ou les modules GSM aux longues réponses. Comme les broches de l'ESP32 sont en 3,3 V, n'oublie pas le pont diviseur de la partie précédente si tu le relies à un Arduino 5 V. Le brochage de l'ESP32 est visible dans l'outil Pinout.
Broches UART du Raspberry Pi Pico et MicroPython
Le Raspberry Pi Pico possède deux UART matériels (uart0 et uart1), chacun pouvant être routé sur plusieurs paires de broches. En MicroPython, le REPL et les sorties de print() passent par un port série virtuel séparé sur l'USB, donc l'UART0 est entièrement libre ; pas besoin de débrancher des fils pour téléverser comme sur Arduino. Les broches du Pico sont en 3,3 V et ne tolèrent pas le 5 V sur le Pico à RP2040. Le code ci-dessous fait sur le Pico ce que faisait la carte B sur Arduino : il lit des lignes sur l'UART0, allume ou éteint la LED intégrée avec « LED ON » et « LED OFF » et répond. Pour le faire dialoguer avec le code passerelle de l'Uno, n'oublie pas un pont diviseur sur le TX de l'Uno.
| UART | Broches TX | Broches RX | Exemple MicroPython |
|---|---|---|---|
| uart0 | GP0, GP12, GP16 | GP1, GP13, GP17 | UART(0, 9600, tx=Pin(0), rx=Pin(1)) |
| uart1 | GP4, GP8 | GP5, GP9 | UART(1, 9600, tx=Pin(4), rx=Pin(5)) |
1from machine import UART, Pin
2import time
3
4uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) # UART0: GP0 = TX, GP1 = RX
5led = Pin("LED", Pin.OUT) # Pico ve Pico W dahili LED / on-board LED
6
7tampon = b""
8while True:
9 if uart.any():
10 tampon += uart.read() # gelen baytlar / incoming bytes
11 while b"\n" in tampon: # her tam satırı işle / handle each full line
12 satir, tampon = tampon.split(b"\n", 1)
13 try:
14 komut = satir.decode().strip()
15 except UnicodeError:
16 continue # bozuk bayt: atla / corrupt byte: skip
17 if komut == "LED ON":
18 led.on()
19 uart.write("OK LED=1\n")
20 elif komut == "LED OFF":
21 led.off()
22 uart.write("OK LED=0\n")
23 else:
24 uart.write("HATA / unknown: " + komut + "\n")
25 if len(tampon) > 64: # satır sonu hiç gelmezse taşmayı önle / avoid overflow
26 tampon = b""
27 time.sleep_ms(5)
28Mise en paquets : caractères de début et de fin
L'UART est un flux d'octets ; il ne sait pas où commence ni où finit quoi que ce soit. Quand l'émetteur écrit « 23.5,48,812 », le récepteur a pu commencer à écouter au milieu, un octet a pu se perdre à cause du bruit, ou deux mesures peuvent se coller. La solution consiste à mettre les données en paquet : si chaque paquet commence par « < » et finit par « > », le récepteur ignore tout jusqu'au premier « < », traite le paquet à l'arrivée du « > » et jette les demi-paquets intermédiaires. Côté émetteur, il suffit d'écrire les valeurs entre Serial.print('<'), des virgules et Serial.print('>'). Tu peux tester tout de suite le récepteur ci-dessous en tapant <23.5,48,812> dans le moniteur série.
1// Paket biçimi / packet format: <sicaklik,nem,isik> ör. / e.g. <23.5,48,812>
2const byte MAKS = 32;
3char tampon[MAKS];
4byte konum = 0;
5bool paketIcinde = false; // '<' görüldü mü? / have we seen '<'?
6
7void paketiIsle(char* p) {
8 char* parca = strtok(p, ","); // ilk alan / first field
9 if (!parca) return;
10 float sicaklik = atof(parca);
11 parca = strtok(NULL, ",");
12 if (!parca) return; // eksik alan: paketi at / missing field: drop
13 int nem = atoi(parca);
14 parca = strtok(NULL, ",");
15 if (!parca) return;
16 int isik = atoi(parca);
17
18 Serial.print("Sicaklik / temp: ");
19 Serial.print(sicaklik, 1);
20 Serial.print(" Nem / humidity: ");
21 Serial.print(nem);
22 Serial.print(" Isik / light: ");
23 Serial.println(isik);
24}
25
26void setup() {
27 Serial.begin(9600); // Seri Monitör'den <23.5,48,812> yazarak dene / test from the Serial Monitor
28}
29
30void loop() {
31 while (Serial.available()) {
32 char c = Serial.read();
33 if (c == '<') { // yeni paket başladı / a new packet starts
34 paketIcinde = true;
35 konum = 0;
36 } else if (c == '>' && paketIcinde) { // paket bitti / packet complete
37 tampon[konum] = '\0';
38 paketIcinde = false;
39 paketiIsle(tampon);
40 } else if (paketIcinde) {
41 if (konum < MAKS - 1) tampon[konum++] = c;
42 else paketIcinde = false; // çok uzun, bozuk: at / too long, corrupt: drop
43 } // paket dışındaki baytlar yok sayılır / bytes outside packets are ignored
44 }
45}
46| Méthode | Exemple | Avantage | Inconvénient |
|---|---|---|---|
| Texte avec fin de ligne | 512\n | Le plus simple, lisible dans le moniteur série | En milieu de ligne, on ne sait pas où ça commence |
| Caractères de début et de fin | <23.5,48,812> | Se resynchronise tout seul | Impossible d'utiliser < et > dans les données |
| Texte avec somme de contrôle (comme NMEA) | $GPGGA,...*47 | Détecte les paquets corrompus | Un peu plus de calcul et de code |
| Paquet binaire | 0xAA, longueur, données, CRC | Le plus court et le plus rapide | Difficile à lire et à déboguer |
Dans un environnement perturbé ou avec de longs fils, tu peux aller plus loin et ajouter une somme de contrôle (checksum) au paquet. Le format NMEA des modules GPS en est un bon exemple : on fait le XOR de tous les caractères entre « $ » et « * » et on écrit le résultat à la fin sous forme de nombre hexadécimal à deux chiffres. Le récepteur refait le calcul et rejette le paquet si le résultat ne correspond pas. Tu évites ainsi des erreurs sournoises, comme un « 812 » corrompu traité comme « 872 ».
Idées de projets avec l'UART
- Pilotage au téléphone : le HC-05 est en fait un UART sans fil ; commande une LED, un relais ou une voiture robot depuis ton téléphone avec le HC-05.
- Enregistreur GPS : décode les phrases NMEA qu'un GPS NEO-6M envoie par UART et écris la position sur une carte SD.
- Système à deux cartes : relie par UART un Uno qui lit les capteurs à un ESP32 qui envoie les données sur internet en Wi-Fi.
- Alarme SMS : envoie des commandes AT à un SIM800L par UART et reçois un SMS quand une porte s'ouvre.
- Tableau de bord sur PC : envoie des commandes à l'Arduino depuis une application de bureau en Python et trace les données des capteurs.
- Lecteur MP3 : choisis des morceaux, règle le volume et joue des messages vocaux par UART avec un DFPlayer Mini.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| Caractères incohérents dans le moniteur série | Débits différents | Choisis le même débit dans le code et le moniteur série |
| Aucune donnée | TX relié à TX, RX à RX | Croise les fils : TX → RX, RX → TX |
| Caractères corrompus au hasard | GND non relié | Relie les masses des deux cartes |
| Téléversement impossible (not in sync) | Module branché sur D0/D1 | Débranche les fils pendant le téléversement ou utilise SoftwareSerial |
| Commandes non reconnues | Fin de ligne \r\n ou absente | Règle le moniteur sur Nouvelle ligne et nettoie le texte avec trim() |
| La fin des longs messages disparaît | Tampon de 64 octets débordé | Évite delay(), lis les données au fil de l'eau, baisse le débit |
| La broche RX de l'ESP32 ne marche pas ou est abîmée | TX 5 V branché en direct | Ajoute un pont diviseur ou un convertisseur de niveau |
| SoftwareSerial plante à 115200 | Le timing logiciel ne suit pas | Passe à 57600 ou moins, ou à un UART matériel |
L'UART est la première méthode de communication à apprendre en électronique : deux fils, une masse commune et le même débit suffisent, et bien installé, il fonctionne des années sans souci. Une fois le câblage croisé, l'adaptation de niveaux et la mise en paquets maîtrisés, tu peux utiliser facilement des dizaines de modules, du GPS au GSM. Dans l'application BlueGrays, tu trouveras des projets de communication unidirectionnelle et bidirectionnelle entre deux Arduino, d'allumage d'une LED depuis le téléphone en Bluetooth et de voiture pilotée en Bluetooth, pas à pas avec schéma et code.
Questions fréquentes
Que signifie UART et à quoi ça sert ?
UART signifie Universal Asynchronous Receiver-Transmitter, soit émetteur-récepteur asynchrone universel. Il permet à deux appareils d'échanger des données octet par octet sans ligne d'horloge, avec seulement les fils TX et RX et un débit convenu à l'avance. Le moniteur série de l'Arduino et les modules GPS, Bluetooth et GSM utilisent l'UART.
Comment brancher TX et RX ?
La broche TX d'un appareil va sur la broche RX de l'autre, et sa broche RX sur le TX de l'autre : la liaison est croisée. Il faut aussi relier les broches GND des deux appareils. Relier TX à TX bloque complètement les données.
Qu'est-ce que le débit en bauds et lequel choisir ?
Le débit en bauds est le nombre de bits envoyés par seconde et doit être identique des deux côtés. Les valeurs les plus courantes avec les modules Arduino sont 9600 et 115200 ; 9600 est la valeur par défaut de la plupart des modules GPS et Bluetooth, 115200 est préféré pour l'ESP32 et les sorties rapides. Commence avec le débit par défaut indiqué par le module.
UART et port série, c'est la même chose ?
Dans l'usage courant, les deux termes sont souvent employés l'un pour l'autre. L'UART est le circuit qui sérialise les données ; le port série est la connexion COM ou /dev/tty de l'ordinateur. Le RS-232 et le RS-485 sont des normes qui utilisent d'autres niveaux de tension pour transporter les signaux UART plus loin.
Comment utiliser plusieurs UART sur Arduino ?
L'Uno n'a qu'un UART matériel, partagé avec l'USB ; pour d'autres ports on utilise SoftwareSerial, mais un seul peut écouter à la fois. L'Arduino Mega possède trois UART matériels supplémentaires (Serial1, Serial2 et Serial3), l'ESP32 trois au total et le Raspberry Pi Pico deux.
Quelle longueur maximale pour un câble UART ?
Un UART en niveaux TTL (3,3 V ou 5 V) fonctionne de façon fiable jusqu'à quelques mètres à bas débit, et la distance diminue quand la vitesse augmente. Pour aller plus loin, les transceivers RS-485 (comme le MAX485) atteignent des centaines de mètres, et le RS-232 environ 15 mètres.
Projets à réaliser après cet article
Voir tous les projets
Communication unidirectionnelle entre 2 Arduino
Tu fais discuter deux Arduino par un seul fil : appuie sur le bouton de l'un et la LED de l'autre s'allume, appuie encore et elle s'éteint. La carte qui envoie signale l'appui par un court message, et

Communication bidirectionnelle entre 2 Arduino
Deux Arduino reliés par des fils se parlent : appuie sur le bouton de l'un et la lumière de l'autre s'allume, appuie encore et elle s'éteint. Les deux cartes ont le même programme, donc chacune envoie

Contrôler une LED depuis un téléphone via Bluetooth
Une petite répétition pour allumer et éteindre les lumières de ta chambre depuis ton téléphone. Le module Bluetooth transmet à l'Arduino les lettres envoyées par ton téléphone ; une lettre allume la L

Voiture contrôlée par Bluetooth avec L298N
Transforme ton téléphone en télécommande et pilote ta propre voiture robot. L'Arduino reçoit, via un module Bluetooth, les ordres d'une appli de télécommande sur ton téléphone et fait tourner les roue

Clavier pour développeur Python
Si tu en as assez de taper sans cesse les mêmes structures quand tu codes, ce petit clavier est fait pour toi. L'Arduino Leonardo se branche à l'ordinateur comme un vrai clavier, et chaque touche du c

HC-SR04 Mesure de la distance (affichage en série)
Le capteur HC-SR04 fonctionne comme une chauve-souris qui trouve son chemin dans le noir : il envoie un son que tu ne peux pas entendre, écoute l'écho et mesure à quelle distance se trouve l'objet dev

Température et humidité avec DHT11
Quelle température fait-il dans ta chambre, et l'air est-il humide ou sec ? Le capteur DHT11 mesure la température et l'humidité, et l'Arduino affiche les valeurs sur un écran LCD à deux lignes, mises

Mesure de l'intensité lumineuse avec le module LDR ESP32
Suivi en temps réel sur le moniteur série de la valeur brute de l'ADC du module LDR et du pourcentage relatif de luminosité calculé à partir de références dans l'obscurité et à la lumière. Ce pourcentage n'est pas une mesure en lux. Permet de comprendre le principe de calibrage du module. Il est préférable de réaliser cet exercice avant le projet 10, car il sert à déterminer la valeur seuil.
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 200 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

