Beginner7 min readESP32

Getting Started with the ESP32 in Arduino IDE

Install the ESP32 Arduino core, pick the right board and port, and upload a first Blink and Serial sketch, plus fixes for the upload errors almost everyone hits.

This guide takes you from a fresh Arduino IDE install to an ESP32 that blinks an LED and prints to the Serial Monitor. It is written for Arduino IDE 2.x and version 3.x of Espressif's ESP32 Arduino core, using a board built around the original ESP32 (an ESP32-WROOM-32 module). The steps are the same on Windows, macOS and Linux except for the USB driver.

What you need

  • An ESP32 development board, most likely Espressif's ESP32-DevKitC or one of the many "ESP32 DEVKIT V1" boards (the DOIT design and its clones).
  • A USB cable that carries data, not just power.
  • Arduino IDE 2.x from arduino.cc.
  • If your board has no LED you can control (the DevKitC doesn't): an LED, a 220–330 Ω resistor, a breadboard and two jumper wires.

Step 1: Add the ESP32 boards URL

  1. Open File → Preferences (on macOS: Arduino IDE → Settings).
  2. Find Additional boards manager URLs and paste: https://espressif.github.io/arduino-esp32/package_esp32_index.json If the field already holds a URL, click the button next to it and put this one on its own line.
  3. Click OK.

This tells the Boards Manager where Espressif publishes the ESP32 core.

Step 2: Install the ESP32 core

  1. Open Tools → Board → Boards Manager (or click the boards icon in the left sidebar).
  2. Search for esp32.
  3. Install esp32 by Espressif Systems, version 3.x.

Don't confuse it with Arduino ESP32 Boards by Arduino, which is for Arduino's own boards such as the Nano ESP32. The Espressif download is large (it includes compilers for the whole ESP32 family), so give it a few minutes.

Step 3: Install the USB-serial driver (if needed)

The original ESP32 has no USB hardware of its own. Your board has a separate USB-to-serial chip next to the USB connector, and your computer needs a driver for that chip. Read the marking on it:

  • CP2102 / CP2102N (Silicon Labs): use the CP210x driver from Silicon Labs.
  • CH340 (often CH340C or CH340G, made by WCH): use the CH340/CH341 driver from WCH. Some newer boards use WCH's CH9102 instead; its driver also comes from WCH.

What to do on each system:

  • Windows: plug the board in and open Device Manager → Ports (COM & LPT). If a new COM port appears (for example "Silicon Labs CP210x…" or "USB-SERIAL CH340"), you're done. If you see an unknown device instead, install the vendor driver.
  • macOS: open Tools → Port with the board unplugged, then again with it plugged in. A new entry, usually /dev/cu.usbserial-…, means it works. If nothing new appears, install the vendor driver.
  • Linux: the drivers are part of the kernel and the board shows up as /dev/ttyUSB0. If uploading fails with "Permission denied", add yourself to the dialout group (Debian and Ubuntu; some other distributions use a different group name), then log out and back in:
sudo usermod -a -G dialout $USER

Step 4: Select the board and port

  • Tools → Board → esp32 → ESP32 Dev Module. This generic definition works for both DevKitC and DEVKIT V1 boards with a WROOM-32 module. There is also a DOIT ESP32 DEVKIT V1 entry, which works for those boards too.
  • Tools → Port: pick the port that appeared when you plugged the board in.

Leave the other Tools settings at their defaults for now.

Step 5: Find your LED pin

The pin connected to the on-board LED is a property of the board, not of the ESP32 chip, so it differs between boards:

  • ESP32 DEVKIT V1 (DOIT) and most of its clones: a blue LED on GPIO2, lit when the pin is HIGH. The red LED next to it is the power indicator and can't be controlled.
  • Espressif ESP32-DevKitC: only a red power LED. There is no LED your code can control, so wire one up.
  • Any other board: check its schematic or product page. Don't guess.

To add an LED to a DevKitC, use GPIO4:

FromTo
GPIO4One leg of the 220–330 Ω resistor
Other leg of the resistorLED anode (the longer leg)
LED cathode (shorter leg, flat side of the rim)GND

The resistor limits the current. Without it, the LED pulls more current than the GPIO pin should supply, which can damage the LED, the pin, or both.

The sketch below sets the pin number itself instead of using LED_BUILTIN, because whether that constant exists, and which pin it names, depends on the board definition you selected.

Open a new sketch, replace everything in it with the code below, and set LED_PIN for your board.

// First ESP32 sketch: blink an LED and print to the Serial Monitor.
// Target: "ESP32 Dev Module", ESP32 Arduino core 3.x.
 
// Change this to match your board:
//   2 = ESP32 DEVKIT V1 (DOIT) and most clones (on-board blue LED)
//   4 = external LED wired as in the table above (e.g. on an ESP32-DevKitC)
const int LED_PIN = 2;
 
const unsigned long BLINK_INTERVAL_MS = 500;
 
unsigned long blinkCount = 0;
 
void setup() {
  Serial.begin(115200);
  delay(500);  // give the Serial Monitor a moment to catch up after reset
 
  pinMode(LED_PIN, OUTPUT);
 
  Serial.println();
  Serial.println("Hello from the ESP32!");
  Serial.print("Chip model: ");
  Serial.println(ESP.getChipModel());
  Serial.print("Chip revision: ");
  Serial.println(ESP.getChipRevision());
  Serial.print("CPU frequency (MHz): ");
  Serial.println(ESP.getCpuFreqMHz());
  Serial.print("Flash size (bytes): ");
  Serial.println(ESP.getFlashChipSize());
  Serial.print("Blinking the LED on GPIO ");
  Serial.println(LED_PIN);
}
 
void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(BLINK_INTERVAL_MS);
  digitalWrite(LED_PIN, LOW);
  delay(BLINK_INTERVAL_MS);
 
  blinkCount++;
  Serial.print("Blinks so far: ");
  Serial.println(blinkCount);
}

Click Upload (the right-arrow button). The IDE compiles the sketch, which takes a while the first time, then the output panel shows Connecting…, a series of Writing at 0x… lines with percentages, and finally a message that it is hard-resetting the board. The LED should start blinking.

Step 7: Open the Serial Monitor at 115200

Open Tools → Serial Monitor and set the baud rate dropdown to 115200. It has to match the number in Serial.begin(115200). If the two differ, you get a stream of garbage characters instead of text.

Press the EN (sometimes labelled RST) button on the board to restart it. First you'll see a few lines from the chip's built-in boot ROM, starting with rst: and boot:. On the original ESP32 these are also sent at 115200 baud, so they're readable too. After that come the chip details and the blink counter from the sketch.

Troubleshooting

"Failed to connect to ESP32: Timed out waiting for packet header"

To accept a new program, the ESP32 has to restart with GPIO0 held LOW, which puts it into its serial bootloader ("download mode"). Dev boards normally do this for you: the USB-serial chip's DTR and RTS lines drive the EN and GPIO0 pins through a small circuit. When that timing doesn't work on a particular board, cable, or OS and driver combination, the chip never enters the bootloader and the upload tool gives up.

Tip

Manual download mode: click Upload. When Connecting… appears, press and hold the BOOT button (sometimes labelled IO0). Release it once the Writing at … percentages start. When the upload finishes, press EN to run your sketch.

If you need the BOOT button every time, lowering Tools → Upload Speed to 115200 sometimes helps. A 10 µF capacitor between EN and GND is a widely used fix for boards with marginal auto-reset timing. Also unplug anything wired to GPIO0, GPIO2 or GPIO12: these pins decide how the chip boots, and an external circuit pulling them the wrong way can block uploads (see the GPIO pin guide).

No port appears

  • Charge-only cable. Many USB cables, especially ones bundled with power banks and gadgets, contain only the power wires. The board's power LED lights up, but the computer never sees a device. Try a cable you know transfers data.
  • Missing driver. See Step 3.
  • Port or hub. Try another USB port, and avoid unpowered hubs.
  • Ubuntu and CH340 boards: if the port appears for a second and then vanishes, the brltty braille-display service may be claiming the adapter. Removing that package (if you don't use a braille display) fixes it.

"Brownout detector was triggered" or constant reboots

The supply voltage dipped below what the chip needs. This often happens when Wi-Fi starts, because the radio draws current in bursts. Try a different cable (thin, long cables drop more voltage), a different USB port, or a powered hub.

Check LED_PIN against Step 5. A DevKitC has no controllable LED, and an external LED wired backwards won't light. Press EN once after uploading in case the board didn't reset.

Next steps

Stuck on a step?

Describe your board and what you see; the assistant has this page as context.

Ask the assistant

Keep going