Bases · 13 min de lecture

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.

Convertisseur USB-TTL CP2102
Convertisseur USB-TTL CP2102 : il transforme le port USB de l'ordinateur en UART avec des broches TX, RX et GND ; la puce USB de l'Arduino Uno fait le même travail.

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.

BitStartD0D1D2D3D4D5D6D7Stop
Lettre 'A' (0x41 = 0100 0001)0100000101
Niveau de la ligneLOWHIGHLOWLOWLOWLOWLOWHIGHLOWHIGH

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.

BaudsDurée d'un bitOctets max par seconde (8N1)Où l'utilise-t-on ?
9600104,2 µs960GPS NEO-6M, HC-05 en mode données, DFPlayer Mini, réglage classique du moniteur série
1920052,1 µs1920Certains capteurs et vieux modems
3840026,0 µs3840HC-05 en mode commandes AT
5760017,4 µs5760Anciens bootloaders Arduino, limite haute de SoftwareSerial
1152008,68 µs11520ESP32 et ESP-01, sortie de débogage rapide
1000000 et plus1 µs ou moins100 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éristiqueUARTI2CSPI
Fils2 (TX, RX) + GND2 (SDA, SCL) + GND4 (SCK, MOSI, MISO, CS) + GND
Ligne d'horlogeNon (asynchrone)OuiOui
Nombre d'appareils2 (point à point)Jusqu'à 127, par adresseAutant que de broches CS
Vitesse typique9600–115200 bauds100–400 kHz1–80 MHz
Deux sens en même tempsOui (full duplex)NonOui
Modules typiquesGPS, Bluetooth, GSM, ESP-01, empreinteOLED, LCD, RTC, BME280Carte 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 AFilArduino BRemarque
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—GNDMasse commune, obligatoire
5Vfacultatif5VSeulement si une seule carte est alimentée par USB
Sur l'Arduino Uno et le Nano, les broches de l'UART matériel D0 (RX) et D1 (TX) sont aussi reliées à la puce USB. Si tu téléverses un programme alors qu'un module est branché sur ces broches, le téléversement échoue avec l'erreur « not in sync », et dans le moniteur série les données du module se mélangent à celles de l'ordinateur. Débranche les fils de D0/D1 pendant le téléversement, ou utilise d'autres broches avec SoftwareSerial comme dans les exemples de cet article.

Faire dialoguer deux Arduino : dans un sens

Arduino Uno
Arduino Uno : comme son unique UART matériel (D0/D1) est réservé à l'USB, le plus simple est de relier deux Uno avec SoftwareSerial sur D10/D11.

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.

C++ (Arduino IDE)
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}
16
C++ (Arduino IDE)
1#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}
29

Deux 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.

C++ (Arduino IDE)
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}
15
C++ (Arduino IDE)
1#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}
54

L'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éristiqueUART matériel (Serial)SoftwareSerialAltSoftSerial
Broches sur l'UnoD0 (RX), D1 (TX), partagées avec l'USBPresque toutes (PCINT pour RX)Fixes : D8 (RX), D9 (TX)
Vitesse fiable maximale1–2 Mbauds57600 bauds (115200 limite)Stable à vitesse moyenne (9600–38400)
Charge processeurTrès faible (tampon matériel)Élevée, interruptions coupées à l'émissionMoyenne, utilise le Timer1
Émettre et recevoir en même tempsOuiNonOui
Plusieurs ports4 sur la MegaUn seul écoute à la foisUn seul port
ConflitsTéléversement et moniteur sérieBibliothèques sensibles au timing comme Servo, NeoPixelPWM sur D10 et Servo (Timer1)
Si tu utilises plusieurs modules UART (par exemple GPS + Bluetooth), préfère à l'Uno un Arduino Mega avec quatre UART matériels (Serial1 à Serial3 en plus de Serial) ou un ESP32 qui en a trois. Sur la Leonardo et la Pro Micro, l'USB est séparé, donc Serial1 sur D0/D1 est entièrement libre.

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.

LiaisonCe qu'il fautExemple
TX de l'Uno (5 V) → RX de l'ESP32 / du Pico (3,3 V)Pont diviseur ou convertisseur de niveau1 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 souventL'Uno considère HIGH au-dessus de 3,0 V
TX de l'Uno → RX du HC-05Pont diviseur conseilléLe RX du HC-05 fonctionne en niveau 3,3 V
TX de l'Uno → RX du SIM800LPont diviseurLe niveau de signal du SIM800L est d'environ 2,8 V
Deux cartes en 5 V ou deux en 3,3 VEn directUno ↔ Nano, ESP32 ↔ Pico
Un pont diviseur ne convient qu'aux signaux à sens unique et de vitesse faible à moyenne (par exemple jusqu'à 115200 bauds). Pour les lignes bidirectionnelles ou très rapides, utilise un convertisseur de niveau logique bidirectionnel à base de BSS138. Tu peux calculer les résistances avec le calculateur de pont diviseur ; les convertisseurs de niveau sont détaillés dans l'article convertisseur de niveau logique.

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.

UARTNom ArduinoRX / TX par défautRemarque
UART0SerialGPIO 3 / GPIO 1Relié à la puce USB-série, téléversement et moniteur série
UART1Serial1GPIO 9 / GPIO 10 (flash, à éviter)Indique d'autres broches dans begin(), par ex. 25 / 26
UART2Serial2GPIO 16 / GPIO 17Sur les cartes WROVER, 16/17 servent à la PSRAM : choisis d'autres broches
C++ (Arduino IDE)
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}
17

Les 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.

UARTBroches TXBroches RXExemple MicroPython
uart0GP0, GP12, GP16GP1, GP13, GP17UART(0, 9600, tx=Pin(0), rx=Pin(1))
uart1GP4, GP8GP5, GP9UART(1, 9600, tx=Pin(4), rx=Pin(5))
MicroPython
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)
28

Mise 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.

C++ (Arduino IDE)
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éthodeExempleAvantageInconvénient
Texte avec fin de ligne512\nLe plus simple, lisible dans le moniteur sérieEn 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 seulImpossible d'utiliser < et > dans les données
Texte avec somme de contrôle (comme NMEA)$GPGGA,...*47Détecte les paquets corrompusUn peu plus de calcul et de code
Paquet binaire0xAA, longueur, données, CRCLe plus court et le plus rapideDifficile à 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 ».

L'émetteur ne doit pas aller plus vite que le récepteur ne peut traiter. Le tampon de réception matériel de l'Arduino Uno ne fait que 64 octets ; si tu utilises de longs delay() dans loop(), les octets qui arrivent sont perdus dès que le tampon est plein. Côté récepteur, utilise millis() au lieu de delay() et teste Serial.available() à chaque tour de boucle.

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ômeCause probableSolution
Caractères incohérents dans le moniteur sérieDébits différentsChoisis le même débit dans le code et le moniteur série
Aucune donnéeTX relié à TX, RX à RXCroise les fils : TX → RX, RX → TX
Caractères corrompus au hasardGND non reliéRelie les masses des deux cartes
Téléversement impossible (not in sync)Module branché sur D0/D1Débranche les fils pendant le téléversement ou utilise SoftwareSerial
Commandes non reconnuesFin de ligne \r\n ou absenteRègle le moniteur sur Nouvelle ligne et nettoie le texte avec trim()
La fin des longs messages disparaîtTampon 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éeTX 5 V branché en directAjoute un pont diviseur ou un convertisseur de niveau
SoftwareSerial plante à 115200Le timing logiciel ne suit pasPasse à 57600 ou moins, ou à un UART matériel
Si un module UART ne répond pas, branche-le d'abord directement à l'ordinateur avec un convertisseur USB-TTL et envoie-lui des commandes depuis un terminal série. S'il fonctionne là, le problème vient du code Arduino ou du câblage ; s'il ne marche pas non plus, vérifie le débit, l'alimentation et le module lui-même.

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.

Voir tous les projets
Communication unidirectionnelle entre 2 Arduino
#57Intermédiaire
Premium

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

4.4(37)
50
Communication bidirectionnelle entre 2 Arduino
#58Intermédiaire
Premium

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

4.5(20)
26
Contrôler une LED depuis un téléphone via Bluetooth
#34Débutant
Premium

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

4.8(68)
89
Voiture contrôlée par Bluetooth avec L298N
#80Avancé
Premium

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

5.0(38)
65
Clavier pour développeur Python
#66Intermédiaire
Premium

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

4.6(35)
45
HC-SR04 Mesure de la distance (affichage en série)
#27Débutant

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

4.6(46)
71
Température et humidité avec DHT11
#55Intermédiaire

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

4.7(47)
73
Mesure de l'intensité lumineuse avec le module LDR ESP32
#113Débutant

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.

4.6(36)
55