esp32 esp8266 serial uart

ESP32 Serial Monitor Prints Garbage? Baud Mismatch and the 74880 Trap

Why an ESP32 or ESP8266 serial monitor shows garbled characters: baud mismatches, ROM messages at 74880, and the wiring, ground and logic-level problems behind them.

· Mohammed Aquib Ansari

You open the serial monitor and get a burst of question marks, boxes and random accented letters. The firmware might be fine. Almost always, the two ends of the wire disagree about timing.

A UART has no clock line. Sender and receiver each agree to sample the line at a fixed rate, the baud rate, and if those rates differ the receiver chops the bit stream at the wrong points. It still produces bytes, just the wrong ones. Most of them aren’t printable or valid UTF-8, and that’s the garbage.

Cause 1: the monitor’s baud rate isn’t the sketch’s

Serial.begin(115200) means the monitor must be set to 115200. This is the obvious one, but it bites when you:

  • copy a sketch that uses Serial.begin(9600) while your monitor remembers 115200;
  • use PlatformIO without setting monitor_speed in platformio.ini (it defaults to 9600);
  • swap between projects that use different rates.

The tell is that everything is garbage, all the time. Change the monitor’s rate, not the code, and see if it clears.

Cause 2: the first lines are garbage and then it’s fine

This one confuses people because the baud rate is right for the sketch. You see a line or two of junk after every reset, then clean output.

That junk is the chip’s ROM bootloader, which prints its reset reason before your code starts, at a rate it chooses:

ChipROM boot message baud
ESP826674880
ESP32, S2, S3, C3, C6115200
ESP32-C2 with a 26 MHz crystal74880

Where does 74880 come from? The ESP8266 ROM was written for a 40 MHz crystal but the chip usually runs from 26 MHz, so its intended 115200 comes out as 115200 × 26 / 40 = 74880. Arduino’s ESP8266 core uses a 115200 sketch rate, so the ROM lines are always at the “wrong” speed.

On a classic ESP32 the ROM already prints at 115200, so if your sketch also uses 115200, the boot lines are readable. If your sketch uses anything else, the boot lines are garbled instead.

Should you care? Usually not. But those lines are exactly what you need when a board is boot-looping, because they say why it reset. On an ESP8266, set the monitor to 74880 and press reset. You’ll get readable lines like:

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

On ESP8266, rst cause:2 is a reset from the EN pin and boot mode:(3,…) means boot from flash. A watchdog reset or an exception shows up here too.

There’s a neat trick on the ESP8266: call Serial.begin(74880) in your sketch, and both the ROM messages and your own output become readable at one setting.

Cause 3: the right baud rate but a different frame

Baud rate isn’t the only setting. Data bits, parity and stop bits (8N1 is the near-universal default) also have to match. GPS modules, RS-485 sensors and some industrial devices use 7E1 or 8E1. Get it wrong and you’ll see mostly right text with a few wrong characters, especially on symbols. In the browser monitor these sit under “Line settings”, and the port is reopened when you change them.

Cause 4: it’s electrical, not a setting

If you’re wiring a separate USB-UART adapter or a second board to the ESP32, as opposed to using the dev board’s own USB port, garbage can be a hardware problem:

  • No common ground. TX and RX alone aren’t enough. The adapter’s GND must connect to the ESP32’s GND, or the receiver has no reference for what “high” means. This produces garbage that changes every time you touch the wires.
  • TX to TX. It’s TX → RX and RX → TX. With TX to TX you usually get nothing rather than garbage, but it’s worth a check.
  • 5 V logic into a 3.3 V chip. A 5 V Arduino’s TX feeding an ESP32 RX needs a level shifter or at least a voltage divider. Without one you risk the pin, and often get corrupted bytes.
  • Long or unshielded wires at high baud. 921600 baud over 50 cm of jumper wire is optimistic. Drop to 115200.
  • RS-485 or RS-232 devices. These use different voltage levels and need a transceiver (MAX485, MAX3232). Wired straight to a GPIO, they produce nonsense or damage.

Cause 5: two things printing at once

If the output is mostly readable but lines are spliced into each other, two tasks are writing to Serial at the same time, or an ISR is printing. That’s interleaving, not a baud problem. Guard the shared port with a mutex, or print from one task.

Working through it quickly

Here’s the order I check things in:

  1. Is everything garbage? Change the monitor’s baud rate to match Serial.begin().
  2. Only the first lines after reset? That’s the ROM. Ignore it, or read it at 74880 (ESP8266) or 115200 (ESP32).
  3. A few characters wrong per line? Check data bits and parity.
  4. Garbage that changes when you touch the wires? Ground, wiring and voltage levels.

I do this in the browser serial monitor because switching baud rate reopens the port immediately, and the hex view shows the raw bytes. A consistent 0xFF or 0x00 pattern points to wiring, while varied bytes point to timing.

If you’re flashing at the same time, the ESP32 flasher streams the boot log after writing, at 115200 or 74880. It flags a log that is mostly unprintable characters as a baud mismatch.