Using the Serial Monitor

Using the PlatformIO Serial Monitor for debugging ESP32 projects

The Serial Monitor is your primary debugging tool when working with an ESP32. It lets you see text output from your board and send commands back to it over USB. PlatformIO's Serial Monitor runs in the VS Code terminal and offers several useful features beyond what the Arduino IDE provides -- including monitor filters for timestamps, colorization, and log files.

The underlying serial communication is the same regardless of IDE. If you have not read the Arduino IDE Serial Monitor article, it covers the fundamentals of serial communication, USB-to-UART bridge chips, and driver installation in more detail. This article focuses on PlatformIO-specific workflow and features.

🔗How the ESP32 Talks to Your Computer

As a quick recap: the ESP32-WROOM-32 does not speak USB natively. Your dev board includes a USB-to-UART bridge chip -- typically a CP2102 or CH340 -- that translates between USB and UART serial. Your computer sees the ESP32 as a virtual serial port (COM3 on Windows, /dev/ttyUSB0 on Linux, /dev/cu.usbserial-0001 on macOS).

If the port does not appear, you likely need a driver. See the Arduino IDE Serial Monitor article for detailed driver installation instructions -- the same drivers work for both Arduino IDE and PlatformIO.

🔗Setting the Baud Rate

In PlatformIO, the Serial Monitor baud rate is configured in platformio.ini, not through a dropdown menu:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

The monitor_speed must match the value in your Serial.begin() call. For ESP32, 115200 is the standard.

Warning: If you see garbled characters like ?????? or random symbols in the Serial Monitor, the baud rate does not match. Check that monitor_speed in platformio.ini matches the Serial.begin() value in your code.

🔗Opening the Serial Monitor

There are three ways to open the PlatformIO Serial Monitor:

🔗1. Toolbar Button

Click the plug icon in the PlatformIO toolbar at the bottom of VS Code.

🔗2. Keyboard Shortcut

Press Ctrl+Alt+S (this is the default PlatformIO shortcut for "Monitor").

🔗3. Terminal Command

Open a VS Code terminal (`Ctrl+``) and run:

pio device monitor

This is the most flexible option because you can pass additional flags (covered below). It is also useful if you want to keep the monitor running in one terminal while using another terminal for other tasks.

All three methods open the Serial Monitor in a VS Code terminal tab. To close it, press Ctrl+C in the terminal or click the trash icon on the terminal tab.

🔗Serial Functions (Quick Reference)

The serial communication code is identical whether you use Arduino IDE or PlatformIO. Here is a quick reference:

FunctionWhat It DoesExample Output
Serial.print("text")Prints text, cursor stays on the same lineHello
Serial.println("text")Prints text followed by a newlineHello\n
Serial.print(42)Prints a number as text42
Serial.print(3.14, 2)Prints a float with 2 decimal places3.14
Serial.printf("Temp: %.1f C", t)Formatted output (like C printf)Temp: 23.5 C
Serial.available()Returns number of bytes waiting to be read--
Serial.readStringUntil('\n')Reads characters until a newline--

Note: Serial.printf() is available on ESP32 but is not part of standard Arduino. If you write code that needs to run on other Arduino boards (Uno, Nano, etc.), use Serial.print() and Serial.println() instead.

🔗A Basic Serial Example

#include <Arduino.h>

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("ESP32 is ready!");
}

void loop() {
  Serial.println("Hello from the loop!");
  delay(2000);
}

Upload this sketch and open the Serial Monitor. You should see:

ESP32 is ready!
Hello from the loop!
Hello from the loop!

🔗Sending Data to the ESP32

The PlatformIO Serial Monitor is interactive -- you can type text and press Enter to send it to the ESP32. Your sketch reads this input using Serial.available() and Serial.readStringUntil():

#include <Arduino.h>

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Type something and press Enter:");
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    input.trim();  // Remove trailing whitespace or carriage return

    Serial.print("You typed: ");
    Serial.println(input);
  }
}

Tip: By default, the PlatformIO Serial Monitor sends a newline (\n) when you press Enter. If readStringUntil('\n') seems to hang, check that you are pressing Enter after typing your input.

🔗PlatformIO Monitor Filters

This is where PlatformIO's Serial Monitor goes beyond the Arduino IDE. Monitor filters are processing layers that transform the serial output before displaying it. You can add them in platformio.ini or pass them as command-line flags.

🔗Adding Timestamps

The time filter prepends a timestamp to every line of output:

monitor_filters = time

Output becomes:

[2026-02-04 14:23:01] ESP32 is ready!
[2026-02-04 14:23:03] Hello from the loop!
[2026-02-04 14:23:05] Hello from the loop!

This is extremely useful for debugging timing-sensitive code or tracking how often events occur.

🔗Colorized Output

The colorize filter adds color to the terminal output, making it easier to scan visually:

monitor_filters = colorize

🔗Logging to a File

The log2file filter writes all serial output to a log file on your computer:

monitor_filters = log2file

Log files are saved to the project directory. This is valuable for long-running tests or when you need to analyze output after the fact.

🔗Combining Filters

You can stack multiple filters by listing them as a comma-separated list:

monitor_filters = time, colorize, log2file

🔗Using Filters from the Command Line

If you prefer not to change platformio.ini, pass filters directly when launching the monitor:

pio device monitor --filter time --filter colorize

This is handy for one-off debugging sessions where you want timestamps but do not want to commit the change to your project configuration.

🔗Available Filters

FilterEffect
defaultDefault behavior (no extra processing)
colorizeAdds color to output
debugShows raw bytes in hex alongside text
directNo processing at all (raw passthrough)
hexlifyDisplays all data as hexadecimal bytes
log2fileSaves output to a log file
nocontrolStrips control characters
printableShows only printable characters
timePrepends timestamp to each line
send_on_enterSends newline when Enter is pressed (default behavior)
esp32_exception_decoderDecodes ESP32 crash backtraces into readable function names

Tip: The esp32_exception_decoder filter is particularly valuable. When the ESP32 crashes, it prints a backtrace of hex addresses. This filter automatically decodes those addresses into function names and line numbers, saving you from running a separate decoder tool.

🔗Multiple Terminals in VS Code

One of VS Code's strengths is its multi-terminal support. You can have the Serial Monitor running in one terminal tab while using another terminal for other tasks -- running pio device list to check connected devices, editing platformio.ini, or even running a second monitor for a different board.

To open a new terminal: click the + icon in the terminal panel, or press Ctrl+Shift+`.

This is more flexible than the Arduino IDE, where the Serial Monitor is a single dedicated window.

🔗Practical Debugging Patterns

These patterns work the same in PlatformIO as in the Arduino IDE. The serial code does not change between IDEs.

int temperature = 24;
float humidity = 61.5;

Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");

Serial.printf("Humidity: %.1f%%\n", humidity);

🔗Mark Where Your Code Reaches

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("Starting setup...");

  // ... some initialization code ...
  Serial.println("WiFi initialized.");

  // ... more code ...
  Serial.println("Sensor initialized.");

  Serial.println("Setup complete!");
}

If your board crashes or hangs, the last message you see tells you where the problem is.

void loop() {
  unsigned long start = millis();

  // ... do some work ...

  unsigned long elapsed = millis() - start;
  Serial.printf("Loop took %lu ms\n", elapsed);
}

With PlatformIO's time filter enabled, you get both the wall-clock time and the elapsed time in a single view -- useful for correlating events with real-world timing.

🔗A Note on Hardware Debugging

PlatformIO supports JTAG hardware debugging for ESP32 -- you can set breakpoints, step through code, and inspect variables in real time, just like debugging a desktop application. This requires a JTAG adapter (such as an ESP-Prog board) and some additional configuration.

Hardware debugging is beyond the scope of this getting-started guide, but it is worth knowing about. For most ESP32 projects, serial println debugging is perfectly sufficient. When you outgrow it, PlatformIO's debugging support is there.

🔗Common Issues

ProblemLikely CauseSolution
No port appearsMissing driver or bad cableInstall CP2102/CH340 driver; try a different USB cable (some are charge-only)
Garbled outputBaud rate mismatchSet monitor_speed = 115200 in platformio.ini to match Serial.begin()
Messages cut off at startMissing delay after beginAdd delay(1000) after Serial.begin()
"Port busy" when uploadingSerial Monitor still openPlatformIO usually auto-closes the monitor for uploads; if not, press Ctrl+C to close it manually
Monitor opens but shows nothingSketch not printing, or wrong portPress EN (reset) on the board; check monitor_port in platformio.ini if you have multiple serial devices
"Access denied" on port (Linux)User not in dialout groupRun sudo usermod -a -G dialout $USER and log out/back in
Random reboot messages on connectESP32 boot logNormal -- the ESP32 prints boot info at 115200 baud on every reset
Two monitors cannot open at oncePort already in useClose the first Serial Monitor before opening another for the same port

🔗Arduino IDE vs. PlatformIO: What Changed?

The serial communication code is identical whether you use Arduino IDE or PlatformIO. Only the monitoring tool differs:

AspectArduino IDEPlatformIO
Monitor locationDedicated panel or windowVS Code terminal tab
Baud rateDropdown in Serial Monitormonitor_speed in platformio.ini
TimestampsNot built-inmonitor_filters = time
Log to fileNot built-inmonitor_filters = log2file
Crash decodingRequires separate toolmonitor_filters = esp32_exception_decoder
Serial PlotterBuilt-in graphing toolNot built-in (use Teleplot extension or export data)
Multiple monitorsOne at a timeMultiple terminal tabs

Note about Serial Plotter: The Arduino IDE has a built-in Serial Plotter for graphing numeric data. PlatformIO does not include one by default, but you can install the Teleplot VS Code extension for similar functionality, or pipe your serial data to a file and plot it with other tools.

🔗What's Next?

You now have a solid debugging workflow in PlatformIO. Between serial print statements and monitor filters, you can diagnose most issues quickly. The fundamentals -- Serial.begin(), Serial.print(), and Serial.println() -- will appear in nearly every project on this site.

From here, continue to the Digital vs. Analog guide to learn about reading sensors and creating smooth analog outputs like dimming an LED.