Qué es UART: conexión TX/RX, baudios y comunicación serie Arduino
Qué es UART y cómo funciona: TX/RX cruzados, baudios, bits de inicio y parada, unir dos Arduino, SoftwareSerial, 5V y 3,3V, ESP32 Serial2 y UART de la Pico.
La respuesta corta a qué es UART: UART (Universal Asynchronous Receiver-Transmitter) es el hardware de comunicación serie que permite a dos dispositivos intercambiar datos byte a byte con solo dos cables de datos (TX y RX) y una masa (GND) común. Cada línea que ves en el Monitor Serie con el Arduino conectado al ordenador llega por UART. Decenas de módulos, como receptores GPS, el módulo Bluetooth HC-05, el Wi-Fi ESP-01, el GSM SIM800L, lectores de huellas y reproductores MP3, también hablan con el Arduino por UART.
En este artículo explicamos paso a paso por qué UART no necesita línea de reloj, qué es la velocidad en baudios, cómo se enmarca un byte con bits de inicio, datos y parada, por qué TX y RX se cruzan, cómo comunicar dos Arduino primero en un sentido y luego en ambos, los límites de SoftwareSerial, cómo conectar con seguridad placas de 5 V y 3,3 V, los tres UART del ESP32 y los pines UART de la Raspberry Pi Pico. En la última sección verás cómo crear paquetes con caracteres de inicio y fin para que los datos no se mezclen, y los errores más habituales.

¿Qué es UART y cómo funciona?
La palabra «asíncrono» del nombre es la clave: en I2C y SPI se envía una señal de reloj junto con los datos, mientras que UART no tiene línea de reloj. En su lugar, ambos lados acuerdan antes una velocidad, llamada velocidad en baudios. En reposo la línea está en HIGH (1). Para enviar un byte, el emisor pone la línea en LOW durante un bit; es el bit de inicio (start), que dice al receptor «empieza a contar». Después van los 8 bits de datos, empezando por el menos significativo (LSB), puede venir un bit de paridad opcional y al final la línea se mantiene en HIGH al menos un bit; es el bit de parada (stop). El ajuste por defecto del Arduino es 8N1: 8 bits de datos, sin paridad, 1 bit de parada.
| Bit | Inicio | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | Parada |
|---|---|---|---|---|---|---|---|---|---|---|
| Letra 'A' (0x41 = 0100 0001) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| Nivel de la línea | LOW | HIGH | LOW | LOW | LOW | LOW | LOW | HIGH | LOW | HIGH |
Cada bit dura 1 / baudios segundos. A 9600 baudios un bit dura 104,2 microsegundos; como en una trama 8N1 cada byte ocupa 10 bits (inicio + 8 datos + parada), se pueden enviar como máximo 960 bytes por segundo. Tras detectar el flanco de bajada del bit de inicio, el receptor lee la línea en el centro de cada bit. Aunque los relojes de ambos lados difieran un poco, los datos se leen bien mientras el error acumulado en 10 bits no supere medio bit; por eso el error total de baudios debe quedar por debajo del 2–3 % aproximadamente. Con su cristal de 16 MHz, el Arduino Uno no genera 115200 baudios exactos y la velocidad real difiere un 2,1 %; aun así funciona porque está dentro del límite.
| Baudios | Duración del bit | Bytes por segundo máx. (8N1) | ¿Dónde se usa? |
|---|---|---|---|
| 9600 | 104,2 µs | 960 | GPS NEO-6M, HC-05 en modo datos, DFPlayer Mini, ajuste clásico del Monitor Serie |
| 19200 | 52,1 µs | 1920 | Algunos sensores y módems antiguos |
| 38400 | 26,0 µs | 3840 | HC-05 en modo de comandos AT |
| 57600 | 17,4 µs | 5760 | Bootloaders antiguos de Arduino, límite superior de SoftwareSerial |
| 115200 | 8,68 µs | 11520 | ESP32 y ESP-01, salida de depuración rápida |
| 1000000 o más | 1 µs o menos | 100 000+ | Enlaces cortos entre placas, registro rápido de datos |
Diferencias entre UART, I2C y SPI
Los tres métodos de comunicación serie más usados en Arduino son UART, I2C y SPI. UART funciona solo entre dos dispositivos, y los dos pueden hablar cuando quieran (full duplex). I2C reúne decenas de dispositivos con direcciones en los mismos dos cables; SPI es mucho más rápido con cuatro cables pero necesita un pin de selección por dispositivo. Para más detalles, mira los artículos Qué es I2C y Qué es SPI.
| Característica | UART | I2C | SPI |
|---|---|---|---|
| Cables | 2 (TX, RX) + GND | 2 (SDA, SCL) + GND | 4 (SCK, MOSI, MISO, CS) + GND |
| Línea de reloj | No (asíncrono) | Sí | Sí |
| Número de dispositivos | 2 (punto a punto) | Hasta 127, por dirección | Tantos como pines CS |
| Velocidad típica | 9600–115200 baudios | 100–400 kHz | 1–80 MHz |
| Ambos sentidos a la vez | Sí (full duplex) | No | Sí |
| Módulos típicos | GPS, Bluetooth, GSM, ESP-01, huella | OLED, LCD, RTC, BME280 | Tarjeta SD, RFID, TFT, LoRa |
TX y RX cruzados y masa común
La regla de oro del cableado UART: el pin TX (transmitir) de un dispositivo va al pin RX (recibir) del otro, es decir, los cables se cruzan. Piénsalo como boca y oído: donde uno habla, el otro tiene que escuchar. Si unes TX con TX, dos salidas quedan conectadas entre sí y no pasa ningún dato. El tercer cable, GND, da a ambas placas la misma referencia de tensión; sin él, «HIGH» y «LOW» pierden sentido y los datos se convierten en caracteres sin sentido. Aunque las placas se alimenten de fuentes distintas, las masas deben estar unidas.
| Arduino A | Cable | Arduino B | Nota |
|---|---|---|---|
| TX (D11, SoftwareSerial) | → | RX (D10, SoftwareSerial) | Lo que envía A llega a B |
| RX (D10, SoftwareSerial) | ← | TX (D11, SoftwareSerial) | La respuesta de B llega a A |
| GND | — | GND | Masa común, obligatoria |
| 5V | opcional | 5V | Solo si una sola placa se alimenta por USB |
Comunicar dos Arduino: en un sentido

En el primer ejemplo, la placa A envía diez veces por segundo a la placa B el valor de un potenciómetro en A0, y la placa B ajusta con él el brillo del LED en D9. Ambas placas usan SoftwareSerial en D10 (RX) y D11 (TX), así la conexión USB y el Monitor Serie quedan libres. Como los valores se envían con println(), cada número termina con los caracteres «\r\n» (fin de línea); el receptor sabe que el número está completo al verlos. Conexión: D11 de A a D10 de B, D10 de A a D11 de B y las masas juntas.
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}
29Hay dos cosas a tener en cuenta en el código receptor. Primero, los datos nunca llegan «de una pieza»: «512» llega como tres bytes separados, con aproximadamente 1 milisegundo entre ellos. Por eso juntamos los bytes en un búfer y los convertimos en número cuando llega el fin de línea. Segundo, el código nunca espera: funciones como readString() o parseInt() esperan 1 segundo por defecto cuando no llegan datos y ralentizan tu programa. Leer los bytes según llegan es la forma más fiable y rápida. Además limitamos el tamaño del búfer para que un dato corrupto no se escriba fuera del array.
Comunicación en ambos sentidos: comando y respuesta
En los proyectos reales suele hacer falta una conversación en ambos sentidos: una placa envía un comando y la otra lo ejecuta y responde. En el ejemplo de abajo la placa A funciona como puente: reenvía a B cada carácter que escribes en el Monitor Serie y muestra cada carácter que llega de B. La placa B entiende los comandos «LED ON», «LED OFF» y «DURUM?» (estado), responde a cada uno y además avisa por sí sola cuando se pulsa el botón de D2. No olvides poner el fin de línea del Monitor Serie en Nueva línea (Newline); B sabe así que el comando ha terminado.
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 llamada trim() en la placa B elimina el carácter \r que llega cuando el Monitor Serie está en «Ambos NL y CR», además de los espacios sobrantes, de modo que los comandos se reconocen con cualquiera de los dos ajustes. Usar reserve(32) con el objeto String evita que la memoria se reasigne cada vez que se añade un carácter y reduce la fragmentación de los 2 KB de RAM del Uno. Esta estructura es también la base para hablar con el Arduino desde un programa en Python en el ordenador; detalles en el artículo comunicación serie entre Arduino y Python.
Los límites de SoftwareSerial
SoftwareSerial imita un UART por software en lugar de por hardware: el propio procesador mide el tiempo de cada bit. Es muy práctico, pero tiene un precio. Al transmitir, las interrupciones se desactivan durante todo el byte; a 9600 baudios eso es aproximadamente 1 milisegundo por byte, y mientras tanto millis() puede desviarse, los pulsos de un servo pueden temblar y se pueden perder datos que llegan por otro puerto serie. Solo un puerto SoftwareSerial puede escuchar a la vez; si abres un segundo, eliges cuál escucha con listen(). En placas como la Mega y la Leonardo solo pueden usarse como RX ciertos pines con interrupción.
| Característica | UART por hardware (Serial) | SoftwareSerial | AltSoftSerial |
|---|---|---|---|
| Pines en el Uno | D0 (RX), D1 (TX), compartidos con USB | Casi cualquier pin (PCINT para RX) | Fijos: D8 (RX), D9 (TX) |
| Velocidad fiable máxima | 1–2 Mbaudios | 57600 baudios (115200 al límite) | Estable a velocidades medias (9600–38400) |
| Carga de CPU | Muy baja (búfer por hardware) | Alta, interrupciones apagadas al enviar | Media, usa el Timer1 |
| Enviar y recibir a la vez | Sí | No | Sí |
| Varios puertos | 4 en la Mega | Solo uno escucha a la vez | Un solo puerto |
| Conflictos | Carga del código y Monitor Serie | Librerías sensibles al tiempo como Servo y NeoPixel | PWM en D10 y Servo (Timer1) |
Niveles de 5V y 3,3V
En UART, el nivel «HIGH» es la tensión de trabajo de la placa: 5 V en el Arduino Uno y 3,3 V en el ESP32, la Raspberry Pi Pico, el ESP-01 y la mayoría de módulos modernos. Conectar directamente una salida TX de 5 V a una entrada RX de 3,3 V somete la entrada a sobretensión y daña el pin, con el tiempo o al momento; ni el ESP32 ni la Pico con RP2040 toleran 5 V. El sentido contrario suele ir bien: el Uno considera HIGH a partir de 3,0 V, así que puede leer un TX de 3,3 V, aunque al estar cerca del límite un conversor de nivel es más robusto con cables largos.
| Conexión | Qué hace falta | Ejemplo |
|---|---|---|
| TX del Uno (5 V) → RX de ESP32 / Pico (3,3 V) | Divisor de tensión o conversor de nivel | 1 kΩ en serie + 2 kΩ a GND: 5 × 2/3 ≈ 3,3 V |
| TX de ESP32 / Pico (3,3 V) → RX del Uno (5 V) | Normalmente directo | El Uno considera HIGH por encima de 3,0 V |
| TX del Uno → RX del HC-05 | Se recomienda divisor | El RX del HC-05 trabaja a nivel de 3,3 V |
| TX del Uno → RX del SIM800L | Divisor de tensión | El nivel de señal del SIM800L ronda los 2,8 V |
| Las dos placas a 5 V o las dos a 3,3 V | Directo | Uno ↔ Nano, ESP32 ↔ Pico |
UART en el ESP32: Serial, Serial1 y Serial2
El ESP32 tiene tres UART por hardware y lo mejor es que, gracias a su matriz GPIO, los pines UART se pueden llevar a casi cualquier pin. UART0 (Serial) está conectado al chip USB-serie y se usa para el Monitor Serie. UART2 (Serial2) está por defecto en GPIO 16 (RX) y 17 (TX). Los antiguos pines por defecto de UART1 (GPIO 9 y 10) están conectados a la memoria flash de la placa y no se pueden usar directamente, así que inicia siempre Serial1 indicando pines: begin(baudios, SERIAL_8N1, RX, TX). El código de abajo crea un puente en ambos sentidos entre el Monitor Serie y un dispositivo conectado a UART2 (un GPS, otro Arduino, un sensor); es ideal para ver las frases NMEA de un módulo GPS.
| UART | Nombre en Arduino | RX / TX por defecto | Nota |
|---|---|---|---|
| UART0 | Serial | GPIO 3 / GPIO 1 | Conectado al chip USB-serie, carga y Monitor Serie |
| UART1 | Serial1 | GPIO 9 / GPIO 10 (flash, no usar) | Indica otros pines en begin(), p. ej. 25 / 26 |
| UART2 | Serial2 | GPIO 16 / GPIO 17 | En placas WROVER 16/17 los usa la PSRAM, elige otros pines |
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}
17Los UART del ESP32 llegan hasta 5 Mbaudios y cada uno tiene su búfer por hardware; el búfer de recepción por defecto es de 256 bytes y se puede ampliar antes de begin() con una llamada como Serial2.setRxBufferSize(1024). Esto importa con módulos GPS que envían decenas de frases por segundo o módulos GSM con respuestas largas. Como los pines del ESP32 son de 3,3 V, no olvides el divisor de la sección anterior al conectarlo a un Arduino de 5 V. Puedes ver los pines del ESP32 en la herramienta Pinout.
Pines UART de la Raspberry Pi Pico y MicroPython
La Raspberry Pi Pico tiene dos UART por hardware (uart0 y uart1) y cada uno puede llevarse a varios pares de pines. En MicroPython, el REPL y la salida de print() van por un puerto serie virtual aparte en el USB, así que UART0 queda totalmente libre; no hace falta desconectar cables al subir código como en Arduino. Los pines de la Pico son de 3,3 V y en la Pico con RP2040 no toleran 5 V. El código de abajo hace en la Pico lo mismo que la placa B en Arduino: lee líneas de UART0, enciende o apaga el LED integrado con «LED ON» y «LED OFF» y responde. Si quieres que hable con el código puente del Uno, no olvides un divisor de tensión en el TX del Uno.
| UART | Pines TX | Pines RX | Ejemplo en 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)
28Empaquetar datos: carácter de inicio y de fin
UART es un flujo de bytes; no sabe dónde empieza ni dónde acaba nada. Cuando el emisor escribe «23.5,48,812», puede que el receptor haya empezado a escuchar a mitad, que un byte se haya perdido por ruido o que dos lecturas se junten. La solución es convertir los datos en un paquete: si cada paquete empieza con «<» y termina con «>», el receptor ignora todo hasta el primer «<», procesa el paquete cuando llega «>» y descarta los medios paquetes intermedios. El emisor solo tiene que escribir los valores entre Serial.print('<'), comas y Serial.print('>'). Puedes probar ya mismo el receptor de abajo escribiendo <23.5,48,812> en el Monitor Serie.
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étodo | Ejemplo | Ventaja | Inconveniente |
|---|---|---|---|
| Texto con fin de línea | 512\n | El más simple, legible en el Monitor Serie | A media línea no se sabe dónde empieza |
| Carácter de inicio y fin | <23.5,48,812> | Se recupera solo si pierde la sincronía | No se pueden usar < y > dentro de los datos |
| Texto con suma de control (como NMEA) | $GPGGA,...*47 | Detecta paquetes corruptos | Algo más de cálculo y código |
| Paquete binario | 0xAA, longitud, datos, CRC | El más corto y rápido | Difícil de leer y depurar |
En entornos con ruido o con cables largos puedes ir un paso más allá y añadir una suma de control (checksum) al paquete. El formato NMEA de los módulos GPS es un buen ejemplo: se hace el XOR de todos los caracteres entre «$» y «*» y el resultado se escribe al final como un número hexadecimal de dos cifras. El receptor hace el mismo cálculo y descarta el paquete si no coincide. Así evitas errores traicioneros, como que un «812» corrupto se procese como «872».
Ideas de proyectos con UART
- Control desde el móvil: el HC-05 es en realidad un UART inalámbrico; controla un LED, un relé o un coche robot desde el móvil con el HC-05.
- Registro GPS: interpreta las frases NMEA que un GPS NEO-6M envía por UART y guarda la posición en una tarjeta SD.
- Sistema de dos placas: une por UART un Uno que lee los sensores con un ESP32 que envía los datos a internet por Wi-Fi.
- Alarma por SMS: envía comandos AT a un SIM800L por UART y recibe un SMS cuando se abra una puerta.
- Panel de control en el ordenador: envía comandos al Arduino desde una aplicación de escritorio en Python y dibuja gráficas con los datos de los sensores.
- Reproductor MP3: elige canciones, ajusta el volumen y reproduce avisos de voz por UART con un DFPlayer Mini.
Errores frecuentes y soluciones
| Síntoma | Causa probable | Solución |
|---|---|---|
| Caracteres sin sentido en el Monitor Serie | Velocidades distintas | Usa los mismos baudios en el código y en el Monitor Serie |
| No llega ningún dato | TX unido a TX y RX a RX | Cruza los cables: TX → RX, RX → TX |
| Caracteres corruptos al azar | GND sin conectar | Une las masas de las dos placas |
| La carga falla (not in sync) | Hay un módulo en D0/D1 | Desconecta los cables al subir o usa SoftwareSerial |
| No se reconocen los comandos | El fin de línea es \r\n o no hay | Pon el Monitor Serie en Nueva línea y limpia el texto con trim() |
| Se pierde el final de los mensajes largos | Se desbordó el búfer de 64 bytes | No uses delay(), lee los datos según llegan, baja la velocidad |
| El RX del ESP32 no funciona o se dañó | Se conectó un TX de 5 V directamente | Añade un divisor de tensión o un conversor de nivel |
| SoftwareSerial falla a 115200 | La temporización por software no llega | Usa 57600 o menos, o pasa a un UART por hardware |
UART es el primer método de comunicación que conviene aprender en electrónica: bastan dos cables, una masa común y la misma velocidad, y bien montado funciona años sin problemas. Cuando domines el cableado cruzado, los niveles de tensión y el empaquetado, podrás usar con soltura decenas de módulos, del GPS al GSM. En la app BlueGrays encontrarás proyectos de comunicación en un sentido y en ambos entre dos Arduino, encender un LED desde el móvil por Bluetooth y un coche controlado por Bluetooth, paso a paso con esquema y código.
Preguntas frecuentes
¿Qué significa UART y para qué sirve?
UART significa Universal Asynchronous Receiver-Transmitter, es decir, receptor-transmisor asíncrono universal. Permite que dos dispositivos intercambien datos byte a byte sin línea de reloj, solo con los cables TX y RX y una velocidad acordada de antemano. El Monitor Serie de Arduino y los módulos GPS, Bluetooth y GSM usan UART.
¿Cómo se conectan TX y RX?
El pin TX de un dispositivo va al pin RX del otro, y su RX al TX del otro, así que la conexión es cruzada. Además, los pines GND de los dos dispositivos deben estar unidos. Conectar TX con TX bloquea por completo los datos.
¿Qué son los baudios y cuál elijo?
La velocidad en baudios es el número de bits enviados por segundo y debe ser igual en ambos lados. Los valores más comunes con módulos Arduino son 9600 y 115200; 9600 es el valor por defecto de la mayoría de módulos GPS y Bluetooth, y 115200 se prefiere para el ESP32 y salidas rápidas. Empieza con la velocidad por defecto que indique el módulo.
¿UART y puerto serie son lo mismo?
En el uso diario suelen significar lo mismo. UART es la unidad de hardware que serializa los datos; el puerto serie es la conexión COM o /dev/tty del ordenador. RS-232 y RS-485 son estándares que usan otros niveles de tensión para llevar las señales UART a más distancia.
¿Cómo uso varios UART en Arduino?
El Uno tiene un solo UART por hardware compartido con el USB; para más puertos se usa SoftwareSerial, pero solo uno puede escuchar a la vez. El Arduino Mega tiene tres UART por hardware extra (Serial1, Serial2 y Serial3), el ESP32 tres en total y la Raspberry Pi Pico dos.
¿Qué longitud puede tener un cable UART?
UART con niveles TTL de 3,3 V o 5 V funciona de forma fiable hasta unos pocos metros a baja velocidad, y la distancia se acorta al subir los baudios. Para distancias mayores, los transceptores RS-485 (como el MAX485) llegan a cientos de metros, y RS-232 a unos 15 metros.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Comunicación unidireccional entre 2 Arduino
Haces que dos Arduino hablen por un solo cable: pulsas el botón de uno y se enciende el LED del otro, vuelves a pulsar y se apaga. La placa que envía avisa del botón con un mensaje corto, y la que rec

Comunicación bidireccional entre 2 Arduino
Dos Arduino se conectan con cables y hablan entre sí: pulsas el botón de uno y se enciende la luz del otro, lo pulsas otra vez y se apaga. Las dos placas llevan el mismo programa, así que cada una env

Controlar un LED desde el móvil por Bluetooth
Un pequeño ensayo para encender y apagar las luces de tu habitación desde el móvil. El módulo Bluetooth pasa al Arduino las letras que envías desde el teléfono; una letra enciende el LED rojo, otra en

Coche controlado por Bluetooth con L298N
Convierte tu móvil en un mando y conduce tu propio coche robot. El Arduino recibe por un módulo Bluetooth las órdenes de una app de control remoto en el móvil y mueve las ruedas con un controlador de

Teclado para desarrolladores de Python
Si te cansa escribir los mismos patrones una y otra vez mientras programas, este pequeño teclado está hecho para ti. El Arduino Leonardo se conecta al ordenador como si fuera un teclado, y cada tecla

HC-SR04 Medición de distancia (pantalla en serie)
El sensor HC-SR04 funciona igual que un murciélago que se orienta en la oscuridad: emite un sonido que no puedes oír, escucha el eco y mide a qué distancia está el objeto que tiene delante. El Arduino

Temperatura y humedad con DHT11
¿Qué temperatura hace en tu habitación, y el aire está húmedo o seco? El sensor DHT11 mide la temperatura y la humedad, y el Arduino escribe los valores en una pantalla LCD de dos líneas, actualizándo

Lectura de la intensidad luminosa con el módulo LDR del ESP32
Visualización en tiempo real en el monitor serie del valor bruto del ADC del módulo LDR y del porcentaje relativo de luz calculado a partir de referencias de oscuridad y claridad. Este porcentaje no es una medición en lux. Explica el funcionamiento de la calibración del módulo. Es recomendable realizarlo antes del Proyecto 10, ya que se utiliza para determinar el valor umbral.
Más artículos
App BlueGrays
Monta este circuito paso a paso en tu teléfono
Esquema, código y lista de piezas en una sola pantalla. Más de 200 proyectos de Arduino, ESP32 y Pico listos para montar.
Escanea con tu teléfono
Apunta la cámara al código y se abrirá la tienda de apps de tu teléfono.
o ábrela en la tienda

