Setting up the Arduino IDE for ESP32-S2, S3 and C6
Setting up the Arduino IDE for ESP32 work
A step by step guide to installing the Arduino IDE, adding ESP32 board support, and getting a first sketch onto an ESP32-S2, ESP32-S3 or ESP32-C6.
If you have never used the Arduino IDE before, the process looks more complicated than it really is. There are three parts to it: install the IDE, install the ESP32 board support package, then pick the right board and port. Most of the trouble people run into happens in the last part, so the board settings are covered in detail further down.
This guide assumes you are using Arduino IDE 2, which is the current version and the one you should be using for ESP32 work. The older 1.8.x IDE still works but the board manager is slower and the editor is far less useful.
What you need before you start
- A Windows, macOS or Linux machine with a few gigabytes free. The ESP32 core and its toolchains are a large download.
- A USB cable that carries data. This catches people out constantly. Plenty of USB-C cables supplied with phones and battery packs are charge only, and the board will simply never appear.
- An ESP32 board. The instructions below cover the S2, S3 and C6 variants.
- A reasonable internet connection for the initial download.
Step 1: Install the Arduino IDE
Go to arduino.cc/en/software and download the current release for your operating system. The site will offer you a donation page first. You can skip that and go straight to the download.
- Windows: take the installer rather than the ZIP. Accept the driver prompts if any appear during installation.
- macOS: open the disk image and drag the application into Applications. On first launch you may need to approve it under Privacy and Security.
- Linux: the AppImage is the least trouble. Mark it executable and run it. You will also need to add yourself to the dialout group, which is covered under drivers below.

Figure 1: The download page on arduino.cc
Launch the IDE once installation has finished. It will create a sketchbook folder in your documents area and a hidden settings folder. It is worth knowing where the settings folder is, because if the board support ever gets into a mess the quickest fix is to delete part of it and start again:
- Windows:
%LOCALAPPDATA%\Arduino15 - macOS:
~/Library/Arduino15 - Linux:
~/.arduino15
Step 2: Install the ESP32 core
Open the boards manager. It is the second icon down in the left hand toolbar, or Tools > Board > Boards Manager. Type esp32 into the search box and give it a moment to load the list.
Older guides, including plenty that are still near the top of the search results, tell you to paste a custom URL into Preferences before you can do this. On current versions of the IDE that is often not necessary, so try the search first and see what comes back. If the Espressif package is listed, carry straight on. If it is not, there is a short detour below that will sort it out.
You will most likely see two entries, and it matters which one you pick:
- Arduino ESP32 Boards, by Arduino. This package only contains the Arduino Nano ESP32. It will not give you the S2, S3 or C6 development module entries. Unless you own a Nano ESP32, this is not the one you want.
- esp32, by Espressif Systems. This is the one you need. Choose the latest 3.x release from the version drop down and click Install.
The download is several hundred megabytes once the compiler toolchains are included, so give it time. The progress bar sits still for long stretches while it unpacks. Do not close the IDE partway through. If it fails halfway, run it again rather than assuming it worked.

Figure 2: Two packages, similar names. You want esp32 by Espressif Systems.
If the Espressif package does not appear
Point the IDE at Espressif's own package index by hand. It does no harm to do this even if the package was already showing, so if you would rather set it up once and not think about it again, go ahead.
Go to File > Preferences, or on macOS Arduino IDE > Settings. Find the field labelled Additional boards manager URLs and add this:
https://espressif.github.io/arduino-esp32/package_esp32_index.json
If you already have other URLs in there, for ATtiny or ESP8266 support for example, click the small icon at the right hand end of the field to open a larger box and put each URL on its own line. Click OK, then restart the IDE, because it only fetches a newly added index when it starts up. Search the boards manager for esp32 again and the Espressif entry will be there.

Figure 3: The additional boards manager URLs field in Preferences
Important for C6 users: ESP32-C6 support only exists in core version 3.0.0 and later. If you are running an older 2.x core the C6 will not appear in the board list at all. The S2 and S3 are supported in both, but there is no good reason to stay on 2.x now.
Step 3: USB drivers, or the lack of them
Whether you need a driver depends entirely on how the board connects to your computer, not on which chip it uses.
Boards with native USB
The S2, S3 and C6 all have a USB peripheral built into the silicon. If the USB socket on your board goes directly to the chip, no driver is needed on Windows 10 or 11, macOS or any current Linux distribution. The board turns up as a standard serial device on its own.
Boards with a USB to serial bridge
Many development boards fit a separate bridge chip so that uploads work the traditional way. If your board has one of these, install the matching driver:
- CP2102 or CP2102N: the Silicon Labs CP210x VCP driver.
- CH340 or CH9102: the WCH driver.
- FTDI: the FTDI VCP driver, although Windows usually supplies this already.
Some S3 boards have two USB sockets, one wired to the bridge and one wired to the chip. They behave differently and produce different port names. Make a note of which socket you plugged into, because it matters when you get to the board settings.
Linux permissions
On Linux the port will exist but you will not be able to open it until your user is in the dialout group:
sudo usermod -a -G dialout $USER
Log out and back in for that to take effect. On some distributions the group is called uucp instead.
Step 4: Select your board
Go to Tools > Board > esp32 and you will be presented with a very long list. If your board has a specific entry by name, use it, because the manufacturer has already set the flash size, PSRAM and pin definitions for you. If it does not, use the generic development module entry:
- ESP32-S2: ESP32S2 Dev Module
- ESP32-S3: ESP32S3 Dev Module
- ESP32-C6: ESP32C6 Dev Module
The list is long enough that scrolling is painful. In Arduino IDE 2 you can use the board selector drop down at the top of the window and type into it instead, which is far quicker.

Figure 4: Choosing the correct development module
Step 5: The board options that actually matter
Once a board is selected the Tools menu fills up with options. Most of them can be left alone. These are the ones that will cause you grief if they are wrong.
| Setting | ESP32-S2 | ESP32-S3 | ESP32-C6 |
|---|---|---|---|
| USB CDC On Boot | Enabled | Enabled | Enabled |
| USB Mode | Not offered | Hardware CDC and JTAG | Not offered |
| Flash Size | Match the module | Match the module | Match the module |
| PSRAM | Enabled only if fitted | QSPI or OPI, as fitted | Not supported |
| CPU Frequency | 240 MHz | 240 MHz | 160 MHz |
| Partition Scheme | Default to start | Default to start | Default to start |
| Upload Speed | 921600, drop if unreliable | 921600, drop if unreliable | 921600, drop if unreliable |
| Core Debug Level | None | None | None |
USB CDC On Boot
This is the single most common cause of "my sketch uploads but the serial monitor shows nothing". On a board using native USB, the serial port you are talking to is created by the sketch itself. If USB CDC On Boot is disabled, Serial is routed to the hardware UART pins instead of the USB socket, and you will see nothing at all on screen. Set it to Enabled.
If your board uses a separate USB to serial bridge chip, leave it disabled, because in that case Serial going to the UART pins is exactly what you want.
Flash size and partition scheme
Set the flash size to match the module, not to the largest value in the list. If you tell the IDE you have 16MB and the module only has 4MB, the upload may appear to succeed and then the board will boot loop or lose its stored settings.
The default partition scheme is fine until your compiled sketch exceeds the application partition. When the IDE starts complaining that the sketch is too big, switch to one of the larger app schemes. If you intend to do over the air updates you need a scheme with two app partitions, since OTA writes the new image into the spare one before switching over.
PSRAM
Only enable PSRAM if the module physically has it. Enabling it on a module without it will produce boot failures or a stream of errors on the serial output. On the S3 you also have to choose between QSPI and OPI, and getting that wrong causes the same symptoms. Check the module part number if you are unsure. The C6 has no PSRAM support at all, so the option does not appear.

Figure 5: The board options under the Tools menu
Step 6: Find the port
Plug the board in and look under Tools > Port. On Windows you will get a COM number. On macOS you will see something beginning /dev/cu.usbmodem for native USB or /dev/cu.usbserial for a bridge chip. On Linux it will be /dev/ttyACM0 or /dev/ttyUSB0.
If nothing appears, work through it in this order:
- Try a different cable. This solves the problem more often than anything else.
- Try a different USB socket, preferably one directly on the machine rather than through a hub.
- Check whether the board has a bridge chip that needs a driver.
- On Windows, open Device Manager and look for an unknown device appearing and disappearing as you plug the board in.
There is one behaviour with native USB that surprises everybody the first time. The port belongs to the running sketch, so it vanishes on reset and reappears a second or two later. If you upload a sketch that crashes early, the port may vanish permanently until you force the board into download mode.
Step 7: Forcing download mode
If the upload fails with a message about failing to connect, you need to put the chip into its bootloader manually. The sequence is always the same:
- Hold down the BOOT button (sometimes marked IO0).
- Press and release the RESET button (sometimes marked EN or RST).
- Release BOOT.
The board is now sitting in its ROM bootloader, waiting. On a native USB board it will enumerate as a different serial port at this point, so go back into Tools > Port and select the new one before you upload. Once the upload finishes, press RESET on its own to run the sketch, and the original port will come back.
Notes by chip
S2: the most likely of the three to need the manual button sequence. Get into the habit of doing it as a matter of course and you will save yourself a lot of muttering.
S3: usually resets itself into download mode automatically over native USB, but not always, particularly if the previous sketch disabled USB or crashed in setup.
C6: generally well behaved. If it does refuse, the same button sequence applies.

Figure 6: BOOT and RESET buttons - On the mercury the POWER button is RESET, and the BUTTON is the BOOT button for example.
Step 8: A first sketch to prove the toolchain
Resist the urge to start with blink. On many S3 and C6 development boards the onboard LED is an addressable RGB type rather than a plain one, so a standard blink sketch does nothing at all and you are left wondering whether the upload worked. Print something over serial instead, since that tells you the chip really is running your code and confirms the board settings at the same time.
void setup() {
Serial.begin(115200);
delay(2000); // lets the USB serial port enumerate before we print
Serial.println();
Serial.println("ESP32 is alive");
Serial.print("Chip model : ");
Serial.println(ESP.getChipModel());
Serial.print("Cores : ");
Serial.println(ESP.getChipCores());
Serial.print("Flash bytes : ");
Serial.println(ESP.getFlashChipSize());
Serial.print("Free heap : ");
Serial.println(ESP.getFreeHeap());
}
void loop() {
Serial.print("uptime ms: ");
Serial.println(millis());
delay(1000);
}
Click the arrow to upload, then open the Serial Monitor with the magnifying glass icon at the top right and set the baud rate to 115200. You should see the chip report itself. If the model line says ESP32-S3 and you selected an S3 board, everything from the IDE down to the silicon is talking properly.
The two second delay at the start is there deliberately. With native USB the host takes a moment to open the port after reset, and anything printed before that is lost. Do not replace it with a bare while (!Serial); loop, because on a board running from a battery with no computer attached that will hang forever. If you want to wait properly, put a timeout on it:
while (!Serial && millis() < 3000) {
delay(10);
}
Step 9: Installing libraries
Most sensors and peripherals need a library. Use the library manager, which is the books icon in the left hand toolbar, or Sketch > Include Library > Manage Libraries. Search, choose, install, and the IDE will offer to bring in any dependencies as well. Say yes to those.
For a library supplied as a ZIP file, use Sketch > Include Library > Add .ZIP Library. It gets unpacked into the libraries folder inside your sketchbook, and you can also just drop a folder in there by hand if you prefer. Restart the IDE afterwards if a manually added library does not show up.
One thing worth watching: not every Arduino library works on the ESP32, and of those that do, not all of them work on all three chips. Anything that pokes at AVR registers directly, or assumes the older ESP32 classic peripheral set, may fail to compile on the C6 in particular because it is a RISC-V part rather than Xtensa. If a library refuses to build, check its issue tracker before assuming your setup is broken.
Keeping your versions under control
This part gets skipped by nearly everyone and then causes trouble six months later. The core version you build against affects timing, peripheral behaviour and occasionally the meaning of an API call. A project that built and flew perfectly last season can behave differently after an update.
Two habits are worth forming:
- Write down the core version and the library versions you used, alongside the code. A comment at the top of the main sketch file is enough.
- Do not update the core in the middle of a project unless you have a reason. Finish, verify, then update, then re-verify before you rely on it again.
The boards manager lets you pick any published version from the drop down, not just the newest, so going back is straightforward if an update breaks something.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| No port appears at all | Charge only cable, missing bridge driver, or a hub in the way. Try a known good cable first. |
| Failed to connect, or a timeout waiting for a packet header | The chip is not in download mode. Use the BOOT and RESET sequence, then re-select the port that appears. |
| Upload succeeds but the serial monitor is blank | USB CDC On Boot is disabled, or the baud rate is wrong, or you printed before the port opened. |
| Continuous reboots with a rst reason printed at 115200 | Usually PSRAM enabled when there is none fitted, the wrong PSRAM mode on an S3, or a wrong flash size. |
| Brownout detector was triggered | Insufficient supply current, often during Wi-Fi transmit. Use a better supply or a shorter cable. |
| Sketch too big | Change to a partition scheme with a larger app area. |
| The port disappears the moment the sketch starts | The sketch is crashing during setup. Force download mode and upload something known good. |
| Only the Nano ESP32 shows in the board list | You installed Arduino ESP32 Boards rather than esp32 by Espressif Systems. Install the Espressif package as well. |
| Board does not appear in the list | Core too old, particularly for the C6. Update to 3.x or later. |
| Compile errors straight after installing the core | Interrupted download. Remove the esp32 package in the boards manager and install it again. |
Where to go next
Once you have serial output working you have the hard part behind you. Everything after that is just code. The examples that come with the core are a good place to start, and they are all under File > Examples once an ESP32 board is selected. Only the examples relevant to the chip you have chosen will be shown, which is useful in itself when you are trying to work out what a particular part can do.
If something in this guide does not match what you are seeing, the board settings are the first place to look. Nine times out of ten it is USB CDC On Boot, the flash size, or the PSRAM setting.


