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 = 115200The 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 thatmonitor_speedinplatformio.inimatches theSerial.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 monitorThis 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:
| Function | What It Does | Example Output |
|---|---|---|
Serial.print("text") | Prints text, cursor stays on the same line | Hello |
Serial.println("text") | Prints text followed by a newline | Hello\n |
Serial.print(42) | Prints a number as text | 42 |
Serial.print(3.14, 2) | Prints a float with 2 decimal places | 3.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.), useSerial.print()andSerial.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. IfreadStringUntil('\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 = timeOutput 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 = log2fileLog 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 colorizeThis 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
| Filter | Effect |
|---|---|
default | Default behavior (no extra processing) |
colorize | Adds color to output |
debug | Shows raw bytes in hex alongside text |
direct | No processing at all (raw passthrough) |
hexlify | Displays all data as hexadecimal bytes |
log2file | Saves output to a log file |
nocontrol | Strips control characters |
printable | Shows only printable characters |
time | Prepends timestamp to each line |
send_on_enter | Sends newline when Enter is pressed (default behavior) |
esp32_exception_decoder | Decodes ESP32 crash backtraces into readable function names |
Tip: The
esp32_exception_decoderfilter 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.
🔗Print Variable Values
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.
🔗Print Timing Information
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
| Problem | Likely Cause | Solution |
|---|---|---|
| No port appears | Missing driver or bad cable | Install CP2102/CH340 driver; try a different USB cable (some are charge-only) |
| Garbled output | Baud rate mismatch | Set monitor_speed = 115200 in platformio.ini to match Serial.begin() |
| Messages cut off at start | Missing delay after begin | Add delay(1000) after Serial.begin() |
| "Port busy" when uploading | Serial Monitor still open | PlatformIO usually auto-closes the monitor for uploads; if not, press Ctrl+C to close it manually |
| Monitor opens but shows nothing | Sketch not printing, or wrong port | Press 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 group | Run sudo usermod -a -G dialout $USER and log out/back in |
| Random reboot messages on connect | ESP32 boot log | Normal -- the ESP32 prints boot info at 115200 baud on every reset |
| Two monitors cannot open at once | Port already in use | Close 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:
| Aspect | Arduino IDE | PlatformIO |
|---|---|---|
| Monitor location | Dedicated panel or window | VS Code terminal tab |
| Baud rate | Dropdown in Serial Monitor | monitor_speed in platformio.ini |
| Timestamps | Not built-in | monitor_filters = time |
| Log to file | Not built-in | monitor_filters = log2file |
| Crash decoding | Requires separate tool | monitor_filters = esp32_exception_decoder |
| Serial Plotter | Built-in graphing tool | Not built-in (use Teleplot extension or export data) |
| Multiple monitors | One at a time | Multiple 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.