Upload / monitoring via USB (ESP32-S3)

Noob here, so sorry if it’s a naive question…

I am using:

This board has 2 USB-C sockets, meant for upload/monitoring:

  • 1 labeled UART1 (wich is shared with the UART2 plug, select by DIP switch)
  • 1 labeled USB

Using the UART1 plug, everything works fine, but, I need that UART2 socket for communication.

Using the USB port, I have following issues:

  • PIO uploads through COM4, but for monitoring, I can only choose COM3.
    Therefore, Serial moitor and ESP Decoder are not working.
  • I need to power cycle the board with BOOT pressed every time I want to upload and powercycle the board after every upload.
    The reset button does not do the trick, only pulling the plug works, which will chew up the plug in no time…

For using the USB port I added these to platformio.ini

  • -D ARDUINO_USB_MODE=1
  • -D ARDUINO_USB_CDC_ON_BOOT=1
  • -D CORE_DEBUG_LEVEL=1

So… it “kinda almost nearly works a little bit”, but does anyone know what I’m doing wrong here?

I tried so far:

  • specifying upload and monitor port
  • specifying USB mode 1 or 0
  • using older espressif32 platform

Check which COM port is the CDC serial port. After the sketch starts, open Device Manager. You should see a USB Serial (CDC) device. That is the port the Arduino Serial object uses. It may not be the same port used for uploading.

Thanks for the reply.

When I powercycle the board in BOOT mode, device manager shows 2 COM ports:

  • Intel(R) Active Management Technology - SOL (COM3)
  • USB Serial Device (COM4)

After uploading, it still shows the 2 ports, but the sketch doesn’t run.

If I powercycle it again, the sketch starts, and it shows only 1 port:

  • Intel(R) Active Management Technology - SOL (COM3)

It’s like the board is only visible to Windoze when it’s in BOOT mode… COM3 is also there when the board is unplugged… I do not really know what it’s representing… :thinking:

  1. The UART might appear under “Ports (COM & LPT)” in Device Manager. Please check there.
  2. COM3 is for SOL (Serial On LAN), so it is not directly relevant.

Also, with your current environment settings, Serial refers to the native USB port. If you want to output to UART0, please try using Serial0.
(Example)
Serial0.begin(115200);
Serial.println(“Hello,World”);

Alternatively, please remove:
-D ARDUINO_USB_CDC_ON_BOOT=1
Doing so should allow you to load the program via UART, eliminating the need to operate the Boot switch.
Then, by using the following example, “Hello, World” should be output via the USB port:
(Example)
USBSerial.begin(115200);
USBSerial.println(“Hello,World”);

Hi and thanks for suggestions.

  • In device manager, both, COM3 and COM4 (whenever it’s there) are in the ports section. I guess that’s kinda where ports belong :thinking:
  • No, I actually want to output to the USB port, as mentioned, if I connect via UART plug, everything works hunky dory. The problems arise when I try to connect to the USB socket.

To make it clear:

  • If I connect the board with the UART1 socket, windoze detects
    USB-Enhanced-SERIAL CH343 (COM5)
  • If I connect it with the USB socket, windoze doesn’t see anything.
  • If I connect it with the USB socket AND start it in BOOT mode, windoze detects
    USB Serial Device (COM4)

Sorry, I was editing my reply while you were sending your response.
Could you please try removing -D ARDUINO_USB_CDC_ON_BOOT=1?

Does the result remain the same even after executing USBSerial.begin()?

You might also find the following link helpful:

Removing -D ARDUINO_USB_CDC_ON_BOOT=1seems to make no difference, same behaviour.

I cannot execute USBSeial.begin() → identifier “USBSerial” is undefined

Am I missing a library here?

The thread you linked is “a step further”… he is only having issues with the init of his serial communication being slow as I understand.

I don’t expect the core of the problem to be in the sketch, since windoze never sees the board (except it’s powercycled into BOOT mode)…
I would rather expect the issue in platformio.ini or in some windoze settings/drivers…

I apologize for the inadequacy of my previous proposal, which led to an error.
My response was based on the environment I had tested previously.
Although I do not have the exact same device, I do have an N16R8 S3 board,
so I will verify the matter again using that.

I conducted the following tests on Windows 11 using a board equipped with the ESP32-S3-N16R8.
Please pay attention to the differences between my setup and yours. Note that in my configuration, the UART port is COM19.
It worked successfully.

  1. platforio.ini

[env:esp32-s3-devkitc1-n16r8]
platform = espressif32
board = esp32-s3-devkitc1-n16r8
framework = arduino
upload_port = COM19
monitor_port = COM3
build_flags =
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1

  1. main.cpp
#include <Arduino.h>
#define USBSerial Serial
#define UARTSerial Serial0

void setup()
{
USBSerial.begin(115200);
UARTSerial.begin(115200);
}

void loop()
{
USBSerial.println(“Hello,World - Serial(USB) -”);
UARTSerial.println("Hello,World - Serial0(UART) - ");
delay(1000);
}


  1. Connecting the PC and device
    Connect using USB cables as follows:
    (1) UART: COM19
    (2) USB: COM3

  2. Build and Upload
    Run the “Upload” task.

  3. Starting the program
    Press the device’s reset button once.

  4. Partial execution log (Tera Term 5 log) UART(COM19)
    [2026-07-09 11:32:50.552] ESP-ROM:esp32s3-20210327
    [2026-07-09 11:32:50.552] Build:Mar 27 2021
    [2026-07-09 11:32:50.552] rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)
    [2026-07-09 11:32:50.565] SPIWP:0xee
    [2026-07-09 11:32:50.565] mode:DIO, clock div:1
    [2026-07-09 11:32:50.565] load:0x3fce2820,len:0x1150
    [2026-07-09 11:32:50.569] load:0x403c8700,len:0x4
    [2026-07-09 11:32:50.569] load:0x403c8704,len:0xc24
    [2026-07-09 11:32:50.569] load:0x403cb700,len:0x30b4
    [2026-07-09 11:32:50.569] entry 0x403c88b8
    [2026-07-09 11:32:50.660] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:51.665] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:52.665] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:53.663] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:54.662] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:55.662] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:56.663] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:57.664] Hello,World - Serial0(UART) -
    [2026-07-09 11:32:58.664] Hello,World - Serial0(UART) -

7. Partial execution log (Tera Term 5 log) USB(COM3)

[2026-07-09 11:32:51.662] Hello,World - Serial(USB) -
[2026-07-09 11:32:51.662] Hello,World - Serial(USB) -
[2026-07-09 11:32:52.650] Hello,World - Serial(USB) -
[2026-07-09 11:32:53.647] Hello,World - Serial(USB) -
[2026-07-09 11:32:54.662] Hello,World - Serial(USB) -
[2026-07-09 11:32:55.662] Hello,World - Serial(USB) -
[2026-07-09 11:32:56.647] Hello,World - Serial(USB) -
[2026-07-09 11:32:57.648] Hello,World - Serial(USB) -
[2026-07-09 11:32:58.648] Hello,World - Serial(USB) -

Thanks, unfortunately, the only reason for me to want to use the USB interface is to have the UART free for another purpose. If I use the UART socket, anyhow everything works just fine.

The main problem is:
When using the USB socket, Windows can only detect the board in bootloader mode.
If I get this solved, I think the other issues disappear.

I see threads about very similar problems on ESP32 S2, S3 and C3. Apparently only with PIO.
There is lots of questions, but I can’t seem to find any answer to it.

I start thinking I’ll just use UART for upload/monitoring and will communicate with the other ESP32 with ESPNOW or I2C…

The code I provided loads and connects to the PC in exactly the same way on both Windows 11 and Ubuntu 24.04.4 (though the port definitions differ). Therefore, I believe that if the program loads successfully, the device itself should function correctly.

Since Windows recognizes the USB connection in boot mode as COM4, ​​there are no driver issues. The problem likely lies in the device initialization not being performed correctly.

I had assumed that simply swapping COM19 for COM5 (UART) and COM3 for COM4 (USB) would make it work; am I correct in understanding that this did not succeed?

If you haven’t given up on resolving this issue yet, could you please share your current platformio.ini and setup() code (specifically the version that fails to connect to the PC’s USB port)?

This community has many talented members who can offer suggestions from a variety of perspectives.

You are likely to receive even better answers than I could provide.

Just to confirm, which of the numbered items in the table corresponds to the work you would like done?

Again, thanks a lot for all time you’re putting into this.

Regarding your sample code:

I plugged in both cables while holding the boot switch, in order to get a port number for the USB.

  • After uploading, nothing happens (it’s in boot mode)
  • Hitting the reset button: nothing happens (I think it remains in boot mode)
  • Disconnecting both cables and reconnecting them:
    It works, I get both serial outputs.

What completely puzzles me:
Now I can:

  • unplug both cables
  • plug in only USB (Windoze recognizes it)
  • change upload COM4 & monitor port to COM4
  • Everything works I can upload, I can monitor. No need to put board into boot mode.

So that’s it… all problems solved….. except:

I do the same with my project, and it doesn’t work :thinking: :persevering_face: :astonished_face:

I have identical platformio.ini

I do the same steps:

  • Start board in boot mode with both cables plugged in
  • upload COM5 monitor COM4
  • unplug both cables
  • plug in only USB….
    ONLY NOW, Windoze doesn’t detect it…


My platformio.ini and setup method:

platformio.ini:

[env:esp32dev]
platform = espressif32 ;https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
;platform = espressif32@6.9.0
board = esp32-s3-devkitc-1
framework = arduino

board_build.arduino.memory_type = qio_opi
board_upload.flash_size = 8MB  
board_build.partitions = default_8MB.csv

upload_port= COM5
monitor_port=COM4

build_flags = 
    -D ESP_PANEL_BOARD_DEFAULT_USE_SUPPORTED=1
    -D BOARD_WAVESHARE_ESP32_S3_TOUCH_LCD_7

    -D ARDUINO_USB_MODE=1
	-D ARDUINO_USB_CDC_ON_BOOT=1 
    -D CORE_DEBUG_LEVEL=1

lib_extra_dirs = lib
monitor_speed = 115200
test_ignore = test_disabled
monitor_filters = esp32_exception_decoder
build_type = debug

setup:

void setup()
{
    USBSerial.begin(115200);
    UARTSerial.begin(115200);

    Board *board = new Board();
    board->init();

    #if LVGL_PORT_AVOID_TEARING_MODE
    auto lcd = board->getLCD();
    // When avoid tearing function is enabled, the frame buffer number should be set in the board driver
    lcd->configFrameBufferNumber(LVGL_PORT_DISP_BUFFER_NUM);

#if ESP_PANEL_DRIVERS_BUS_ENABLE_RGB && CONFIG_IDF_TARGET_ESP32S3
    auto lcd_bus = lcd->getBus();
    /**
     * As the anti-tearing feature typically consumes more PSRAM bandwidth, for the ESP32-S3, we need to utilize the
     * "bounce buffer" functionality to enhance the RGB data bandwidth.
     * This feature will consume `bounce_buffer_size * bytes_per_pixel * 2` of SRAM memory.
     */
    if (lcd_bus->getBasicAttributes().type == ESP_PANEL_BUS_TYPE_RGB) {
        static_cast<BusRGB *>(lcd_bus)->configRGB_BounceBufferSize(lcd->getFrameWidth() * 10);
    }
#endif

#endif
    assert(board->begin());

    //Serial.println("Initializing LVGL");
    lvgl_port_init(board->getLCD(), board->getTouch());
    lvgl_port_lock(-1); //mutex
    lvgl_styles();
    lvgl_mainScreen();
    lv_scr_load(scrMain);
    lvgl_port_unlock();
}


Your last question, (the table), I cannot really follow..

I want:

  • No cable on the UART socket, as this will be used otherwise
  • Upload AND monitoring through the USB port
  • Board being recognized by windoze without being in boot mode

All of it works with your sketch, but not with mine, and I couldn’t figure why…

It seems you have put a lot of effort into this, so I would first like to say, “Great job.”
Since you confirmed that the sample code I provided works, you should be able to identify the problematic area by carefully comparing it with your own code.

There are many community members with far more knowledge in this field than I have, so I expect you will receive even more helpful advice soon.
That said, since we have come this far together, let me offer two additional suggestions.

1.platformio.ini
Your device is equipped with PSRAM (8MB), so
please select “ESP32-S3-DEVKITC-1-N8R8” as the board,
or try adding the following build option:
-D BOARD_HAS_PSRAM=1
This is because LVGL requires a significant amount of RAM, yet the board JSON file for
“ESP32-S3-DEVKITC-1” does not include a PSRAM definition.

If the above does not resolve the issue, why not try the following?
2. setup()
Try pausing execution immediately after initializing the serial ports to see what happens.
Specifically, add the following code after USBSerial.begin(115200); and UARTSerial.begin(115200); :
while(1)
{
USBSerial.println(“USBSerial”);
UARTSerial.println(“UARTSerial”);
delay(1000);
}
This essentially reproduces the state of the sample code.
If you get output via both UART and USB—just like with the sample code—
then the problem likely lies somewhere in the subsequent code.
If you do not get the same output as the sample code,
it suggests there is an issue with your platformio.ini settings.

By gradually moving this while() loop further down through your code,
you should be able to pinpoint exactly where the problem is occurring.

ESP32-S3-DEVKITC-1-N8R8 gives “unknown board” error

-D BOARD HAS PSRAM=1 does not resolve the issue… board still not seen by windoze…

I see what it’s doing, but do not really understand why that should help here… I’m also too tired now… bedtime here… I’ll look into it 2morrow.

Thanx so much :star_struck:

I am sorry for giving bad information. The platformio.ini setting must be as shown below:

board = esp32-s3-devkitc1-n8r8

If you specify the board this way, there is no need to include -D BOARD HAS PSRAM=1.

However, if you have a specific reason for needing to keep the board set as esp32-s3-devkitc-1, then you should use -D BOARD HAS PSRAM=1.

Alternatively—though it requires a bit more effort—you can create a new project from scratch and select the board from the drop-down list (please refer to the screenshot). This ensures the board is selected correctly.
Note, however, that with this method, you will need to manually copy over any work you have already completed in the current project.

I could kinda track down where this behaviour originates.

If I remove everthing LVGL, it’s still the same.

If then I remove in setup (and all subsequent references):

Board *board = new Board();
board->init();

Everything works.
But unfortunately this is needed for the LVGL port… :confused:

These 2 lines refer to esp_panel_board.hpp (part of ESP32_Display_Panel), and is somehow defining board and display. Unfortunately for me it’s “written in klingonian”. way above my paygrade…

So the culprit is ESP32_Display_Panel, respectively it’s configuration.

1 Like

I’m glad to hear you’ve managed to make some progress.
However, unfortunately, I have absolutely no experience with this particular device, so I don’t think I can offer any insightful advice.
Please hang in there and keep at it.