Cos'è la UART? Collegamento TX/RX, baud e seriale con Arduino
Cos'è la UART e come funziona: TX/RX incrociati, baud, bit di start e stop, due Arduino, SoftwareSerial, livelli 5V e 3,3V, ESP32 Serial2 e UART del Pico.
La risposta breve a cos'è la UART: la UART (Universal Asynchronous Receiver-Transmitter) è l'hardware di comunicazione seriale che permette a due dispositivi di scambiarsi dati byte per byte con soli due fili di dati (TX e RX) più una massa (GND) comune. Ogni riga che vedi nel Monitor seriale con l'Arduino collegato al computer arriva tramite UART. Decine di moduli, come ricevitori GPS, il modulo Bluetooth HC-05, il Wi-Fi ESP-01, il GSM SIM800L, i lettori di impronte e i lettori MP3, parlano con Arduino via UART.
In questo articolo spieghiamo passo passo perché la UART non ha bisogno di una linea di clock, cosa sono i baud, come un byte viene incorniciato da bit di start, dati e stop, perché TX e RX si incrociano, come far comunicare due Arduino prima in un verso e poi in entrambi, i limiti di SoftwareSerial, come collegare in sicurezza schede a 5 V e 3,3 V, le tre UART dell'ESP32 e i pin UART del Raspberry Pi Pico. Nell'ultima sezione vedrai come creare pacchetti con caratteri di inizio e fine per non mescolare i dati, e gli errori più comuni.

Cos'è la UART e come funziona?
La parola «asincrona» nel nome è il punto chiave: in I2C e SPI insieme ai dati viaggia un segnale di clock, mentre la UART non ha linea di clock. Al suo posto i due lati si accordano prima su una velocità, chiamata baud rate. A riposo la linea resta HIGH (1). Per inviare un byte il trasmettitore porta la linea a LOW per la durata di un bit: è il bit di start, che dice al ricevitore «inizia a contare». Seguono gli 8 bit di dati, a partire dal meno significativo (LSB), un eventuale bit di parità e infine la linea resta HIGH per almeno un bit: è il bit di stop. L'impostazione predefinita di Arduino è 8N1: 8 bit di dati, nessuna parità, 1 bit di stop.
| Bit | Start | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | Stop |
|---|---|---|---|---|---|---|---|---|---|---|
| Lettera 'A' (0x41 = 0100 0001) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| Livello della linea | LOW | HIGH | LOW | LOW | LOW | LOW | LOW | HIGH | LOW | HIGH |
Ogni bit dura 1 / baud secondi. A 9600 baud un bit dura 104,2 microsecondi; poiché in un frame 8N1 ogni byte occupa 10 bit (start + 8 dati + stop), si possono inviare al massimo 960 byte al secondo. Dopo aver rilevato il fronte di discesa del bit di start, il ricevitore legge la linea al centro di ogni bit. Anche se i due clock differiscono un po', i dati vengono letti correttamente finché l'errore accumulato su 10 bit resta sotto mezzo bit; per questo l'errore totale di baud deve restare sotto il 2–3% circa. Con il suo quarzo da 16 MHz l'Arduino Uno non genera esattamente 115200 baud e la velocità reale si discosta di circa il 2,1%; funziona comunque perché è entro il limite.
| Baud | Durata del bit | Byte al secondo max (8N1) | Dove si usa? |
|---|---|---|---|
| 9600 | 104,2 µs | 960 | GPS NEO-6M, HC-05 in modalità dati, DFPlayer Mini, impostazione classica del Monitor seriale |
| 19200 | 52,1 µs | 1920 | Alcuni sensori e vecchi modem |
| 38400 | 26,0 µs | 3840 | HC-05 in modalità comandi AT |
| 57600 | 17,4 µs | 5760 | Vecchi bootloader Arduino, limite superiore per SoftwareSerial |
| 115200 | 8,68 µs | 11520 | ESP32 ed ESP-01, output di debug veloce |
| 1000000 e oltre | 1 µs o meno | 100.000+ | Collegamenti corti tra schede, data logging veloce |
Differenze tra UART, I2C e SPI
I tre metodi di comunicazione seriale più usati con Arduino sono UART, I2C e SPI. La UART funziona solo tra due dispositivi, ed entrambi possono parlare quando vogliono (full duplex). L'I2C raccoglie decine di dispositivi con indirizzi sugli stessi due fili; l'SPI è molto più veloce con quattro fili ma richiede un pin di selezione per ogni dispositivo. Per i dettagli leggi gli articoli Cos'è l'I2C e Cos'è SPI.
| Caratteristica | UART | I2C | SPI |
|---|---|---|---|
| Fili | 2 (TX, RX) + GND | 2 (SDA, SCL) + GND | 4 (SCK, MOSI, MISO, CS) + GND |
| Linea di clock | No (asincrona) | Sì | Sì |
| Numero di dispositivi | 2 (punto-punto) | Fino a 127, tramite indirizzo | Tanti quanti i pin CS |
| Velocità tipica | 9600–115200 baud | 100–400 kHz | 1–80 MHz |
| Entrambi i versi insieme | Sì (full duplex) | No | Sì |
| Moduli tipici | GPS, Bluetooth, GSM, ESP-01, impronte | OLED, LCD, RTC, BME280 | Scheda SD, RFID, TFT, LoRa |
TX e RX incrociati e massa comune
La regola d'oro del cablaggio UART: il pin TX (trasmissione) di un dispositivo va al pin RX (ricezione) dell'altro, quindi i fili si incrociano. Pensa a bocca e orecchio: dove uno parla, l'altro deve ascoltare. Se colleghi TX con TX, due uscite si ritrovano unite e non passa alcun dato. Il terzo filo, GND, dà alle due schede lo stesso riferimento di tensione; senza di esso «HIGH» e «LOW» perdono significato e arrivano solo caratteri senza senso. Anche se le schede sono alimentate da fonti diverse, le masse vanno collegate.
| Arduino A | Filo | Arduino B | Nota |
|---|---|---|---|
| TX (D11, SoftwareSerial) | → | RX (D10, SoftwareSerial) | Ciò che invia A arriva a B |
| RX (D10, SoftwareSerial) | ← | TX (D11, SoftwareSerial) | La risposta di B arriva ad A |
| GND | — | GND | Massa comune, obbligatoria |
| 5V | facoltativo | 5V | Solo se una sola scheda è alimentata via USB |
Far comunicare due Arduino: in un verso

Nel primo esempio la scheda A invia dieci volte al secondo alla scheda B il valore di un potenziometro su A0, e la scheda B regola di conseguenza la luminosità del LED su D9. Entrambe le schede usano SoftwareSerial su D10 (RX) e D11 (TX), così la connessione USB e il Monitor seriale restano liberi. Poiché i valori vengono inviati con println(), ogni numero termina con i caratteri «\r\n» (fine riga); il ricevitore capisce così che il numero è completo. Collegamento: D11 di A al D10 di B, D10 di A al D11 di B, masse unite.
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}
29Nel codice del ricevitore ci sono due cose da notare. Primo, i dati non arrivano mai «in un pezzo solo»: «512» arriva come tre byte separati, a circa 1 millisecondo l'uno dall'altro. Per questo raccogliamo i byte in un buffer e li convertiamo in numero quando arriva il fine riga. Secondo, il codice non aspetta mai: funzioni come readString() o parseInt() aspettano per impostazione predefinita 1 secondo quando non arrivano dati e rallentano il programma. Leggere i byte man mano che arrivano è il metodo più affidabile e veloce. Limitiamo anche la dimensione del buffer così che un dato corrotto non venga scritto oltre la fine dell'array.
Comunicazione nei due versi: comando e risposta
Nei progetti reali serve quasi sempre un dialogo nei due versi: una scheda invia un comando, l'altra lo esegue e risponde. Nell'esempio qui sotto la scheda A fa da ponte: inoltra a B ogni carattere che scrivi nel Monitor seriale e stampa ogni carattere che arriva da B. La scheda B capisce i comandi «LED ON», «LED OFF» e «DURUM?» (stato), risponde a ciascuno e avvisa anche da sola quando si preme il pulsante su D2. Non dimenticare di impostare il fine riga del Monitor seriale su A capo (NL) (Newline); B riconosce così la fine del comando.
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}
54La chiamata trim() sulla scheda B elimina il carattere \r che arriva quando il Monitor seriale è impostato su «Entrambi (NL & CR)», insieme agli spazi in eccesso, così i comandi vengono riconosciuti con entrambe le impostazioni. Usare reserve(32) per l'oggetto String evita di riallocare memoria a ogni carattere aggiunto e riduce la frammentazione dei 2 KB di RAM dell'Uno. Questa struttura è anche la base per far dialogare Arduino con un programma Python sul computer; dettagli nell'articolo comunicazione seriale tra Arduino e Python.
I limiti di SoftwareSerial
SoftwareSerial imita una UART via software invece che in hardware: è il processore stesso a temporizzare ogni bit. È molto comodo, ma ha un costo. Durante la trasmissione gli interrupt vengono disabilitati per tutto il byte; a 9600 baud significa circa 1 millisecondo per byte, durante il quale millis() può slittare, gli impulsi di un servo possono tremolare e i dati in arrivo su un'altra seriale possono andare persi. Può ascoltare una sola porta SoftwareSerial alla volta; se ne apri una seconda, scegli quale ascolta con listen(). Su schede come Mega e Leonardo si possono usare come RX solo alcuni pin con supporto agli interrupt.
| Caratteristica | UART hardware (Serial) | SoftwareSerial | AltSoftSerial |
|---|---|---|---|
| Pin sull'Uno | D0 (RX), D1 (TX), condivisi con l'USB | Quasi ogni pin (PCINT per RX) | Fissi: D8 (RX), D9 (TX) |
| Velocità affidabile massima | 1–2 Mbaud | 57600 baud (115200 al limite) | Stabile a velocità medie (9600–38400) |
| Carico sulla CPU | Bassissimo (buffer hardware) | Alto, interrupt spenti in trasmissione | Medio, usa il Timer1 |
| Trasmettere e ricevere insieme | Sì | No | Sì |
| Più porte | 4 sulla Mega | Ne ascolta una sola alla volta | Una sola porta |
| Conflitti | Caricamento e Monitor seriale | Librerie sensibili ai tempi come Servo e NeoPixel | PWM su D10 e Servo (Timer1) |
Adattare i livelli 5V e 3,3V
Nella UART il livello «HIGH» è la tensione di lavoro della scheda: 5 V sull'Arduino Uno, 3,3 V su ESP32, Raspberry Pi Pico, ESP-01 e la maggior parte dei moduli recenti. Collegare direttamente un'uscita TX a 5 V a un ingresso RX a 3,3 V espone l'ingresso a sovratensione e danneggia il pin, col tempo o subito; né l'ESP32 né il Pico con RP2040 tollerano i 5 V. Nel verso opposto di solito va bene: l'Uno considera HIGH da 3,0 V in su, quindi legge un TX a 3,3 V, ma essendo vicino al limite, con cavi lunghi un convertitore di livello è più robusto.
| Collegamento | Cosa serve | Esempio |
|---|---|---|
| TX dell'Uno (5 V) → RX di ESP32 / Pico (3,3 V) | Partitore di tensione o convertitore di livello | 1 kΩ in serie + 2 kΩ verso GND: 5 × 2/3 ≈ 3,3 V |
| TX di ESP32 / Pico (3,3 V) → RX dell'Uno (5 V) | Di solito diretto | L'Uno considera HIGH sopra i 3,0 V |
| TX dell'Uno → RX dell'HC-05 | Partitore consigliato | L'RX dell'HC-05 lavora a livello 3,3 V |
| TX dell'Uno → RX del SIM800L | Partitore di tensione | Il livello di segnale del SIM800L è di circa 2,8 V |
| Entrambe le schede a 5 V o entrambe a 3,3 V | Diretto | Uno ↔ Nano, ESP32 ↔ Pico |
UART dell'ESP32: Serial, Serial1 e Serial2
L'ESP32 ha tre UART hardware e il bello è che, grazie alla matrice GPIO, i pin UART si possono spostare su quasi qualsiasi pin. La UART0 (Serial) è collegata al chip USB-seriale e serve per il Monitor seriale. La UART2 (Serial2) è per impostazione predefinita su GPIO 16 (RX) e 17 (TX). I vecchi pin predefiniti della UART1 (GPIO 9 e 10) sono collegati alla memoria flash della scheda e non si possono usare direttamente, quindi avvia sempre Serial1 indicando i pin: begin(baud, SERIAL_8N1, RX, TX). Il codice qui sotto crea un ponte nei due versi tra il Monitor seriale e un dispositivo collegato alla UART2 (un GPS, un altro Arduino, un sensore); è ideale per vedere le frasi NMEA di un modulo GPS.
| UART | Nome in Arduino | RX / TX predefiniti | Nota |
|---|---|---|---|
| UART0 | Serial | GPIO 3 / GPIO 1 | Collegata al chip USB-seriale, caricamento e Monitor seriale |
| UART1 | Serial1 | GPIO 9 / GPIO 10 (flash, non usare) | Indica altri pin in begin(), ad es. 25 / 26 |
| UART2 | Serial2 | GPIO 16 / GPIO 17 | Sulle schede WROVER 16/17 sono usati dalla PSRAM, scegli altri pin |
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}
17Le UART dell'ESP32 arrivano fino a 5 Mbaud e ognuna ha il suo buffer hardware; il buffer di ricezione predefinito è di 256 byte e si può ingrandire prima di begin() con una chiamata come Serial2.setRxBufferSize(1024). È importante con i moduli GPS che inviano decine di frasi al secondo o con i moduli GSM dalle risposte lunghe. Poiché i pin dell'ESP32 sono a 3,3 V, non dimenticare il partitore della sezione precedente quando lo colleghi a un Arduino a 5 V. La piedinatura dell'ESP32 è visibile nello strumento Pinout.
Pin UART del Raspberry Pi Pico e MicroPython
Il Raspberry Pi Pico ha due UART hardware (uart0 e uart1), ognuna instradabile su diverse coppie di pin. In MicroPython il REPL e l'output di print() passano da una porta seriale virtuale separata sull'USB, quindi la UART0 è completamente libera; non serve scollegare fili durante il caricamento come su Arduino. I pin del Pico sono a 3,3 V e sul Pico con RP2040 non tollerano i 5 V. Il codice qui sotto fa sul Pico quello che faceva la scheda B su Arduino: legge righe dalla UART0, accende o spegne il LED integrato con «LED ON» e «LED OFF» e risponde. Se vuoi farlo dialogare con lo sketch ponte dell'Uno, ricorda un partitore di tensione sul TX dell'Uno.
| UART | Pin TX | Pin RX | Esempio 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)
28Pacchetti di dati: carattere di inizio e di fine
La UART è un flusso di byte; non sa dove qualcosa inizia o finisce. Quando il trasmettitore scrive «23.5,48,812», il ricevitore potrebbe aver iniziato ad ascoltare a metà, un byte potrebbe essersi perso per un disturbo o due misure potrebbero unirsi. La soluzione è trasformare i dati in un pacchetto: se ogni pacchetto inizia con «<» e finisce con «>», il ricevitore ignora tutto fino al primo «<», elabora il pacchetto all'arrivo di «>» e scarta i mezzi pacchetti intermedi. Il trasmettitore deve solo scrivere i valori tra Serial.print('<'), virgole e Serial.print('>'). Puoi provare subito il ricevitore qui sotto scrivendo <23.5,48,812> nel Monitor seriale.
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| Metodo | Esempio | Pro | Contro |
|---|---|---|---|
| Testo con fine riga | 512\n | Il più semplice, leggibile nel Monitor seriale | A metà riga non si sa dove inizia |
| Carattere di inizio e fine | <23.5,48,812> | Si risincronizza da solo | Non si possono usare < e > nei dati |
| Testo con checksum (come NMEA) | $GPGGA,...*47 | Rileva i pacchetti corrotti | Un po' più di calcoli e codice |
| Pacchetto binario | 0xAA, lunghezza, dati, CRC | Il più corto e veloce | Difficile da leggere e da debuggare |
In ambienti disturbati o con cavi lunghi puoi fare un passo in più e aggiungere al pacchetto un checksum. Il formato NMEA dei moduli GPS ne è un buon esempio: si fa lo XOR di tutti i caratteri tra «$» e «*» e il risultato si scrive in fondo come numero esadecimale a due cifre. Il ricevitore rifà lo stesso calcolo e scarta il pacchetto se non coincide. Così eviti errori subdoli, come un «812» corrotto elaborato come «872».
Idee di progetto con la UART
- Controllo dal telefono: l'HC-05 è in realtà una UART senza fili; comanda un LED, un relè o un'auto robot dallo smartphone con l'HC-05.
- Registro GPS: interpreta le frasi NMEA che un GPS NEO-6M invia via UART e salva la posizione su una scheda SD.
- Sistema a due schede: collega via UART un Uno che legge i sensori a un ESP32 che invia i dati su internet via Wi-Fi.
- Allarme via SMS: invia comandi AT a un SIM800L via UART e ricevi un SMS quando si apre una porta.
- Pannello di controllo sul PC: invia comandi ad Arduino da un'applicazione desktop in Python e traccia i grafici dei dati dei sensori.
- Lettore MP3: scegli i brani, regola il volume e riproduci messaggi vocali via UART con un DFPlayer Mini.
Errori comuni e soluzioni
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| Caratteri senza senso nel Monitor seriale | Velocità diverse | Usa gli stessi baud nel codice e nel Monitor seriale |
| Non arriva nessun dato | TX collegato a TX, RX a RX | Incrocia i fili: TX → RX, RX → TX |
| Caratteri corrotti a caso | GND non collegato | Unisci le masse delle due schede |
| Il caricamento fallisce (not in sync) | Modulo collegato a D0/D1 | Scollega i fili durante il caricamento o usa SoftwareSerial |
| I comandi non vengono riconosciuti | Fine riga \r\n o assente | Imposta il Monitor seriale su A capo (NL) e pulisci il testo con trim() |
| La fine dei messaggi lunghi si perde | Buffer da 64 byte traboccato | Niente delay(), leggi i dati appena arrivano, abbassa la velocità |
| Il pin RX dell'ESP32 non funziona o si è danneggiato | TX a 5 V collegato direttamente | Aggiungi un partitore o un convertitore di livello |
| SoftwareSerial sbaglia a 115200 | La temporizzazione software non regge | Usa 57600 o meno, oppure passa a una UART hardware |
La UART è il primo metodo di comunicazione da imparare in elettronica: bastano due fili, una massa comune e la stessa velocità, e se montata bene funziona per anni senza problemi. Quando avrai preso confidenza con il collegamento incrociato, l'adattamento dei livelli e i pacchetti, potrai usare con facilità decine di moduli, dal GPS al GSM. Nell'app BlueGrays trovi progetti di comunicazione monodirezionale e bidirezionale tra due Arduino, di accensione di un LED dal telefono via Bluetooth e di un'auto comandata via Bluetooth, passo passo con schema e codice.
Domande frequenti
Cosa significa UART e a cosa serve?
UART significa Universal Asynchronous Receiver-Transmitter, cioè ricevitore-trasmettitore asincrono universale. Permette a due dispositivi di scambiarsi dati byte per byte senza linea di clock, solo con i fili TX e RX e una velocità concordata prima. Il Monitor seriale di Arduino e i moduli GPS, Bluetooth e GSM usano la UART.
Come si collegano TX e RX?
Il pin TX di un dispositivo va al pin RX dell'altro, e il suo RX al TX dell'altro: il collegamento è incrociato. Inoltre i pin GND dei due dispositivi devono essere uniti. Collegare TX con TX blocca completamente i dati.
Cos'è il baud rate e quale scegliere?
Il baud rate è il numero di bit inviati al secondo e deve essere uguale sui due lati. I valori più comuni con i moduli Arduino sono 9600 e 115200; 9600 è il valore predefinito della maggior parte dei moduli GPS e Bluetooth, 115200 si preferisce per l'ESP32 e per output veloci. Parti dalla velocità predefinita indicata dal modulo.
UART e porta seriale sono la stessa cosa?
Nell'uso quotidiano spesso sì. La UART è l'unità hardware che serializza i dati; la porta seriale è il collegamento COM o /dev/tty del computer. RS-232 e RS-485 sono standard che usano altri livelli di tensione per portare i segnali UART a distanze maggiori.
Come si usano più UART su Arduino?
L'Uno ha una sola UART hardware condivisa con l'USB; per altre porte si usa SoftwareSerial, ma ne può ascoltare una sola alla volta. L'Arduino Mega ha tre UART hardware in più (Serial1, Serial2 e Serial3), l'ESP32 tre in totale e il Raspberry Pi Pico due.
Quanto può essere lungo un cavo UART?
Una UART a livelli TTL (3,3 V o 5 V) funziona in modo affidabile fino a pochi metri a bassa velocità, e la distanza si accorcia aumentando i baud. Per distanze maggiori i transceiver RS-485 (come il MAX485) arrivano a centinaia di metri, l'RS-232 a circa 15 metri.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
Comunicazione unidirezionale tra 2 Arduino
Fai parlare due Arduino con un solo filo: premi il pulsante sull'uno e il LED dell'altro si accende, premi di nuovo e si spegne. La scheda che invia segnala la pressione con un breve messaggio, e quel

Comunicazione bidirezionale tra 2 Arduino
Due Arduino collegati con dei fili parlano tra loro: premi il pulsante di uno e si accende la luce dell'altro, premilo di nuovo e si spegne. Entrambe le schede hanno lo stesso programma, quindi ognuna

Controllare un LED dal telefono tramite Bluetooth
Una piccola prova per accendere e spegnere le luci della tua stanza dal telefono. Il modulo Bluetooth passa all'Arduino le lettere che invii dal telefono; una lettera accende il LED rosso, un'altra qu

Auto controllata via Bluetooth con L298N
Trasforma il telefono in un telecomando e guida la tua auto robot. L'Arduino riceve tramite un modulo Bluetooth i comandi di un'app di controllo remoto sul telefono e fa girare le ruote con un driver

Tastiera per sviluppatori Python
Se sei stanco di scrivere sempre gli stessi schemi mentre programmi, questa piccola tastiera fa per te. L'Arduino Leonardo si collega al computer proprio come una tastiera, e ogni tasto del tastierino

HC-SR04 Misura della distanza (display seriale)
Il sensore HC-SR04 funziona come un pipistrello che trova la strada al buio: manda un suono che non puoi sentire, ne ascolta l'eco e misura quanto è lontano l'oggetto davanti a sé. L'Arduino scrive qu

Temperatura e umidità con DHT11
Quanti gradi ci sono nella tua stanza, e l'aria è umida o secca? Il sensore DHT11 misura temperatura e umidità, e l'Arduino scrive i valori su uno schermo LCD a due righe, aggiornandoli ogni paio di s

Lettura dell'intensità luminosa con il modulo LDR ESP32
Monitoraggio in tempo reale sul Serial Monitor del valore grezzo dell'ADC del modulo LDR e della percentuale relativa di luce calcolata dai valori di riferimento al buio e alla luce. Questa percentuale non è una misurazione in lux. Spiega il principio di calibrazione del modulo. È consigliabile eseguirlo prima del Progetto 10, poiché serve a determinare il valore di soglia.
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 200 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

