Hello! Welcome back to our course on C++ for the ESP32.
In the last lesson, you successfully created and configured a new C++ project from scratch. You now have a compiled firmware file (cpp_project.bin) ready to go. This lesson closes the loop on the basic development cycle by focusing on the final, most rewarding steps: getting your code onto the hardware and seeing it run.
We will cover how to flash your ESP32 program (transferring the binary from your PC to the chip's memory) and then monitor its serial output to see the results. This is the fundamental process you'll use every time you upload and test new code.
1. The Hardware Connection: How Your PC Talks to the ESP32
Before we issue any commands, it's helpful to understand what's happening at the hardware level. Your computer's USB port doesn't speak the same electrical language as the ESP32's core processor. A special chip on your development board acts as a translator.
DevCon23 - ESP-IDF Getting Started (Beginners Guide to Key Concepts and Resources)
This official video from Espressif provides an excellent conceptual overview of the flashing process and the hardware involved. Given your engineering background, you'll appreciate this look under the hood.
Watch from 8:32 to 9:38. Focus on the explanation of the ESP32 module, the external flash chip, and the crucial role of the 'UART to USB' bridge. This bridge is what makes communication and programming over a standard USB cable possible.
As the video explains, your PC sends the compiled program through the USB cable to this USB-to-UART bridge. The bridge then converts the signals and forwards them to the ESP32, which writes the data to its flash memory chip. This same bridge is used in reverse to send output from the ESP32 back to your PC, which we'll use for monitoring.
2. Identifying Your ESP32's Serial Port
To flash the device, you must tell the idf.py tool which port the ESP32 is connected to. The name for this port differs by operating system.
Establish Serial Connection with ESP32
The official documentation provides clear, step-by-step instructions for finding the serial port name on all major operating systems.
Read the sections 'Check Port on Windows' and 'Check Port on Linux and macOS'. Follow the instructions for your operating system. A simple trick is to check the list of ports, then unplug and replug your device to see which port name disappears and reappears.
- On Windows, you'll look in the Device Manager for a "USB Serial Port" listed under "Ports (COM & LPT)". The name will be something like
COM3orCOM5. - On Linux, the port will typically be
/dev/ttyUSB0. - On macOS, it will be something like
/dev/cu.usbserial-XXXXXXXX.
A Common Issue on Linux: If you're using Linux, you might encounter a "Permission denied" error when you try to flash. This is because your user account doesn't have the necessary rights to access the serial port hardware.
Establish Serial Connection with ESP32
This is a frequent stumbling block for Linux users. The fix is simple and only needs to be done once.
Read the section 'Adding User to dialout or uucp on Linux'. Run the command provided for your distribution to add your user to the correct group. You will need to log out and log back in for the change to take effect.
3. Flashing Your Program
With the port identified, you can now flash the project you built in the previous lesson. The command for this is idf.py flash.
Build the Project - Flash onto the Device
The ESP-IDF documentation explains the flash command and its options. This is your primary reference for the flashing process.
Read the section 'Flash onto the Device'. Pay close attention to the command structure: idf.py -p PORT flash. Replace PORT with the name you found in the previous step.
To flash your board, follow these steps:
- Make sure your ESP32 board is connected to your computer.
- Open the ESP-IDF terminal in VS Code.
- Navigate to your
cpp_projectdirectory. - Run the command, replacing
YOUR_PORT_NAMEwith your actual port (e.g.,COM5or/dev/ttyUSB0):
Note: If you omit theidf.py -p YOUR_PORT_NAME flash-p PORTargument,idf.pywill try to find the port automatically, which often works.
You will see output showing the esptool.py utility connecting to your board, writing the bootloader, partition table, and finally your application binary to the flash memory.
4. Monitoring Serial Output
After flashing is complete, the ESP32 reboots and starts running your app_main function. To see the std::cout messages from your program, you need to open a serial monitor.
Build the Project - Monitor the Output
The same documentation page also covers the monitor command.
Read the section 'Monitor the Output'. Note the command idf.py -p PORT monitor and, crucially, the shortcut Ctrl+] to exit the monitor. Many developers get stuck in the monitor window the first time!
Run this command in your terminal:
idf.py -p YOUR_PORT_NAME monitor
You will first see a block of boot-up messages from the ESP-IDF, followed by the output from your program: Hello from C++! Count: 0, Hello from C++! Count: 1, and so on.
DevCon23 - ESP-IDF Getting Started (Beginners Guide to Key Concepts and Resources)
This video helps decipher the initial burst of text you see when the monitor starts. Understanding this boot log is useful for debugging.
Watch from 10:21 to 11:27. The video breaks down the boot process: the first stage bootloader loads the second stage bootloader, which then finds and loads your application from the partition table before finally calling app_main. This context is very helpful for understanding what the device is doing.
Test your understanding!
You've successfully flashed your project. You then run idf.py monitor and see a stream of garbled, unreadable characters instead of the boot log and "Hello World" message. Based on the documentation you've reviewed, what is a likely cause and how would you fix it?
Show answer
The most likely cause is a mismatch between the crystal frequency your board uses (e.g., 26 MHz) and the default frequency ESP-IDF is configured for (usually 40 MHz).
To fix this, you would:
- Exit the monitor with
Ctrl+]. - Run
idf.py menuconfig. - Navigate to
Component config->Hardware Settings->Main XTAL Config. - Change the
Main XTAL frequencyto the correct value for your board. - Save the configuration and exit
menuconfig. - Build and flash the project again.
5. The Efficient Workflow: Flash and Monitor
Constantly running flash and then monitor as separate commands is inefficient. The ESP-IDF provides a convenient way to combine them.
The command idf.py flash monitor will build (if needed), flash, and then immediately start monitoring. This is the command you will likely use most often during development.

To try it, make a small change to the std::cout line in your main.cpp, save the file, and then run:
idf.py -p YOUR_PORT_NAME flash monitor
You'll see the project rebuild due to your change, flash the new binary, and then show you the updated output. Remember to use Ctrl+] to exit when you're done.
Conclusion
Congratulations! You have now mastered the complete basic workflow for ESP32 development with the ESP-IDF: creating, configuring, building, flashing, and monitoring a C++ application.
Here are the key takeaways from this lesson:
- A USB-to-UART bridge on your development board is what enables programming and communication over a single USB cable.
- You must identify your ESP32's serial port (
COMxon Windows,/dev/ttyUSBxon Linux) to communicate with it. idf.py -p <PORT> flashcompiles and uploads your program to the ESP32's flash memory.idf.py -p <PORT> monitorshows you the live serial output from your running application.idf.py flash monitoris the combined command for an efficient development cycle.
In our next lesson, we will build directly on what you've just learned. We will explore the ESP32's powerful logging framework, moving beyond simple std::cout to produce structured, color-coded debug messages with different severity levels. This will give you a professional-grade tool for debugging your future applications.