ESP32 Getting Started: Your First Project in the Arduino IDE

The ESP32 gives you a dual-core 240MHz processor, Wi-Fi, and Bluetooth on a board that costs less than a sandwich. You can program it with the same Arduino IDE you already know. This guide takes you from a blank PC to a working Wi-Fi web server that switches an LED from your phone. It covers driver installs, board selection, pinout traps, and the errors that stop most first uploads.

Quick Takeaways

  • Install Arduino IDE 2.x, add the Espressif board URL, and install the esp32 by Espressif Systems package. You need no extra toolchain.
  • The ESP32 runs at 3.3V logic. GPIO pins are not 5V tolerant.
  • If upload fails with “Wrong boot mode,” hold the BOOT button while the IDE shows “Connecting…”.
  • Your first project is a Blink sketch. Your second is a Wi-Fi web server that toggles GPIO2.
Spec ESP32 (classic, WROOM-32)
CPU Dual-core Xtensa LX6, up to 240MHz
RAM 520KB SRAM
Flash 4MB typical (external)
Wireless 802.11 b/g/n Wi-Fi, Bluetooth 4.2 + BLE
Logic level 3.3V
GPIO Up to 34 usable pins (varies by board)
Interfaces I2C, SPI, UART, I2S, CAN, PWM

What You Need

Item Notes
ESP32 DevKit board ESP32-DevKitC, DOIT DevKit V1, or NodeMCU-32S all work
Data-capable USB cable Many cheap cables carry power only
LED + 220Ω resistor Optional if your board has an onboard LED
Breadboard + jumper wires For the external LED
Computer Windows, macOS, or Linux

Step 1: Install Arduino IDE and USB Drivers

Download Arduino IDE 2.x from arduino.cc and install it. Then check which USB-to-serial chip your board uses. Look at the small square IC near the USB port.

USB chip Driver needed? Typical boards
CP2102 / CP2104 (Silicon Labs) Yes on Windows/macOS: install the CP210x VCP driver DevKitC, many clones
CH340 / CH9102 (WCH) Yes on Windows/macOS: install the CH34x driver Budget clones
Native USB (ESP32-S3/C3) No S3, C3 boards with USB port

Plug in the board. Windows should list a new COM port in Device Manager. Linux shows /dev/ttyUSB0 or /dev/ttyACM0. On Linux, add your user to the serial group so the IDE can open the port:

sudo usermod -a -G dialout $USER   # Debian/Ubuntu; log out and back in afterward

Step 2: Add the ESP32 Board Package

The IDE does not ship with ESP32 support. Add Espressif’s package index.

  1. Open File → Preferences.
  2. Paste this URL into Additional boards manager URLs:
https://espressif.github.io/arduino-esp32/package_esp32_index.json
  1. Click OK.
  2. Open Tools → Board → Boards Manager (or press the board icon in the left sidebar).
  3. Search for esp32 and install esp32 by Espressif Systems.

The download is several hundred MB because it bundles compilers and tools. Let it finish. This guide targets the 3.x core. If you see older tutorials using ledcSetup(), they target the 2.x core. The 3.x API changed.

Step 3: Select Your Board and Port

Go to Tools → Board → esp32 and pick the entry that matches your hardware.

Your board Select this
Generic 30/38-pin DevKit (WROOM-32) ESP32 Dev Module
DOIT ESP32 DevKit V1 DOIT ESP32 DEVKIT V1
ESP32-S3 DevKit ESP32S3 Dev Module
ESP32-C3 DevKit ESP32C3 Dev Module
Not listed ESP32 Dev Module (safe default)

Then set Tools → Port to the new COM or tty port. Leave Upload Speed at 921600. Drop it to 115200 if uploads fail midway.

Pinout Configuration: Read This Before Wiring

Most first-project failures come from wrong pin choices, not code. Know these rules for the classic ESP32.

Pin group Rule
GPIO34–GPIO39 Input only. No output, no internal pull-ups
GPIO6–GPIO11 Connected to the onboard flash. Never use them
GPIO0, GPIO2, GPIO5, GPIO12, GPIO15 Strapping pins. Their level at reset sets the boot mode
ADC2 pins (GPIO0, 2, 4, 12–15, 25–27) Do not work while Wi-Fi is active. Use ADC1 (GPIO32–39) instead
GPIO21 / GPIO22 Default I2C SDA / SCL
GPIO23 / GPIO19 / GPIO18 Default SPI (VSPI) MOSI / MISO / SCLK
GPIO1 / GPIO3 UART0 TX / RX, used by the USB serial link

Each GPIO supplies at most about 12mA safely. The absolute maximum per pin is 40mA. Always use a 220Ω–330Ω series resistor with an LED.

Project 1: Blink an LED

Wiring

Many DevKit boards have an onboard LED on GPIO2. If yours does not, wire an external one:

  • GPIO2 → 220Ω resistor → LED anode (long leg)
  • LED cathode (short leg) → GND

Code

// Blink: toggles an LED on GPIO2 every 500 ms
#define LED_PIN 2            // GPIO2: onboard LED on most DevKit boards

void setup() {
  pinMode(LED_PIN, OUTPUT);  // configure GPIO2 as a push-pull output
}

void loop() {
  digitalWrite(LED_PIN, HIGH);  // drive pin to 3.3V, LED on
  delay(500);                   // wait 500 ms
  digitalWrite(LED_PIN, LOW);   // drive pin to 0V, LED off
  delay(500);
}

Upload

  1. Click the Verify (checkmark) button to compile. The first build takes a minute or two.
  2. Click Upload (right arrow).
  3. When the console shows Connecting........, press and hold BOOT if it stalls. Release it once the upload begins.
  4. The LED should blink twice per second.

If it works, your toolchain, drivers, and board are all good.

Project 2: Wi-Fi Web Server to Control the LED

Now use the feature that sets the ESP32 apart from an Arduino Uno. This sketch connects to your 2.4GHz network and hosts a page with ON and OFF buttons. The ESP32 does not support 5GHz Wi-Fi.

Circuit

Reuse the Blink wiring: GPIO2 → 220Ω → LED → GND.

Code

// ESP32 Wi-Fi LED controller using the built-in WebServer library
#include <WiFi.h>
#include <WebServer.h>

const char* WIFI_SSID = "YOUR_SSID";      // 2.4 GHz network name
const char* WIFI_PASS = "YOUR_PASSWORD";  // network password

#define LED_PIN 2
WebServer server(80);                     // HTTP server on TCP port 80
bool ledState = false;

// Build the HTML page; the button label reflects the current state
String buildPage() {
  String html = "<!DOCTYPE html><html><head>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
  html += "<title>ESP32 LED</title></head><body style='font-family:sans-serif;text-align:center'>";
  html += "<h1>ESP32 LED Control</h1>";
  html += "<p>LED is <b>" + String(ledState ? "ON" : "OFF") + "</b></p>";
  html += ledState ? "<a href='/off'><button>Turn OFF</button></a>"
                   : "<a href='/on'><button>Turn ON</button></a>";
  html += "</body></html>";
  return html;
}

void handleRoot() { server.send(200, "text/html", buildPage()); }

void handleOn() {
  ledState = true;
  digitalWrite(LED_PIN, HIGH);
  server.sendHeader("Location", "/");     // redirect back to the main page
  server.send(303);
}

void handleOff() {
  ledState = false;
  digitalWrite(LED_PIN, LOW);
  server.sendHeader("Location", "/");
  server.send(303);
}

void setup() {
  Serial.begin(115200);                   // UART0 at 115200 baud for debug output
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  WiFi.mode(WIFI_STA);                    // station mode: join an existing network
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) { // wait for the DHCP lease
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());         // open this address in your browser

  server.on("/", handleRoot);             // register URL handlers
  server.on("/on", handleOn);
  server.on("/off", handleOff);
  server.begin();
}

void loop() {
  server.handleClient();                  // process incoming HTTP requests
}

Run It

  1. Replace YOUR_SSID and YOUR_PASSWORD with your network credentials.
  2. Upload the sketch.
  3. Open Tools → Serial Monitor and set the baud rate to 115200.
  4. Press the EN (reset) button on the board.
  5. Wait for the printed IP address, such as 192.168.1.57.
  6. Enter that address in a browser on the same network. Tap the button and watch the LED respond.

How the Code Works

  • WiFi.mode(WIFI_STA) makes the chip a client. Use WIFI_AP if you want the board to create its own network.
  • server.on() maps a URL path to a handler function. This is lightweight routing.
  • The 303 redirect stops the browser from re-sending /on when you refresh the page.
  • server.handleClient() must run often. Avoid long delay() calls in loop(), or the page will feel unresponsive.

ESP32 vs. ESP8266 vs. Arduino Uno

Feature ESP32 ESP8266 Arduino Uno
CPU Dual-core 240MHz Single-core 80/160MHz 16MHz AVR
SRAM 520KB ~80KB 2KB
Wi-Fi Yes (2.4GHz) Yes (2.4GHz) No
Bluetooth Yes (Classic + BLE) No No
Logic level 3.3V 3.3V 5V
ADC 12-bit, up to 18 channels 10-bit, 1 channel 10-bit, 6 channels
Typical price Low Lowest Moderate
Best for IoT, BLE, multitasking Simple Wi-Fi projects Beginner logic, 5V shields

Common Upload and Boot Errors

Symptom Likely cause Fix
No COM port appears Charge-only cable or missing driver Swap the cable. Install CP210x or CH34x driver
Failed to connect to ESP32: Wrong boot mode Chip is not in download mode Hold BOOT during “Connecting…”. Release after upload starts
A fatal error occurred: Timed out waiting for packet header Weak USB power or wrong port Use a rear PC port. Try a shorter cable. Re-select the port
Upload stalls at a percentage Upload speed too high Set Upload Speed to 115200
Brownout detector was triggered loop Supply sags under Wi-Fi load Use a 5V/1A+ supply. Add a 100µF capacitor across 3V3 and GND
Garbled Serial Monitor text Baud rate mismatch Match the monitor to Serial.begin(115200)
Wi-Fi never connects 5GHz network or wrong credentials Use a 2.4GHz SSID. Re-check the password
ets_main.c reboot loop on boot A strapping pin is held at the wrong level Disconnect wiring from GPIO0, 2, 12, 15 and retry

Practical Next Steps

Once Blink and the web server run, pick a small build that adds one new skill each time.

Project New skill Key parts
Temperature/humidity monitor Read an I2C sensor and serve JSON BME280 on GPIO21/22
Wi-Fi relay switch Switch mains loads safely 5V relay module with optocoupler, external supply
BLE beacon Use Bluetooth Low Energy Built-in radio, BLEDevice library
Touch-controlled light Use capacitive touch pins touchRead(T0) on GPIO4
Deep-sleep sensor node Cut power use to ~10µA esp_deep_sleep_start(), RTC wake timer

Follow these habits from the start:

  • Keep Wi-Fi credentials in a separate secrets.h file and exclude it from version control.
  • Use the ADC1 pins for analog reads whenever Wi-Fi is on.
  • Add a level shifter between the ESP32 and any 5V sensor output.
  • Print debug messages with Serial.println() early. They save hours later.

FAQ

Is the ESP32 compatible with the Arduino IDE?

Yes. The esp32 by Espressif Systems board package adds full support to Arduino IDE 1.8.x and 2.x. You use standard functions like digitalWrite() and Serial.begin(), plus ESP32-specific libraries for Wi-Fi and Bluetooth.

Why won’t my ESP32 upload code?

The usual causes are a charge-only USB cable, a missing CP210x or CH340 driver, or the chip not entering download mode. Use a data cable, install the driver, and hold the BOOT button while the IDE shows “Connecting…”. Lowering Upload Speed to 115200 fixes many stalls.

Can I power the ESP32 with 5V?

Yes, through the VIN or 5V pin or the USB port. The onboard regulator drops it to 3.3V. The GPIO pins are 3.3V only. Connecting a 5V signal directly to a GPIO can damage the chip, so use a level shifter or a voltage divider.

Which ESP32 board should a beginner buy?

Buy a 30-pin or 38-pin ESP32 DevKit with a WROOM-32 module and a CP2102 USB chip. It has the most tutorials and library support. It also fits a standard breadboard. Choose the ESP32-S3 if you need native USB or more RAM, and the ESP32-C3 if you want a cheap RISC-V board.

Hot this week

Your First Arduino Program: Blink an LED

Learn how to blink an LED with Arduino: wiring, resistor math, and copy-paste code for the Uno. Build your first circuit in 10 minutes. Start now.

Logic Analyzers Explained: See Digital Signals Clearly

Learn how a logic analyzer works, how to choose one, and how to decode I2C, SPI, and UART. Read the guide and debug your circuits faster.

Oscilloscopes for Beginners: What to Buy and How to Use One

New to oscilloscopes? Compare the best beginner scopes, learn the controls, and take your first measurement in 10 minutes. Start debugging today.

Raspberry Pi vs Arduino vs ESP32: Choosing the Right Platform

Compare Raspberry Pi, Arduino, and ESP32 on specs, power draw, price, and use cases. Find the right board for your build and start today.

Build a Weather Station: Sensors, Logging, and Dashboards

Build an ESP32 weather station with a BME280, MQTT logging to InfluxDB, and a Grafana dashboard. Wiring, code, and calibration tips. Start building.

Topics

Your First Arduino Program: Blink an LED

Learn how to blink an LED with Arduino: wiring, resistor math, and copy-paste code for the Uno. Build your first circuit in 10 minutes. Start now.

Logic Analyzers Explained: See Digital Signals Clearly

Learn how a logic analyzer works, how to choose one, and how to decode I2C, SPI, and UART. Read the guide and debug your circuits faster.

Oscilloscopes for Beginners: What to Buy and How to Use One

New to oscilloscopes? Compare the best beginner scopes, learn the controls, and take your first measurement in 10 minutes. Start debugging today.

Raspberry Pi vs Arduino vs ESP32: Choosing the Right Platform

Compare Raspberry Pi, Arduino, and ESP32 on specs, power draw, price, and use cases. Find the right board for your build and start today.

Build a Weather Station: Sensors, Logging, and Dashboards

Build an ESP32 weather station with a BME280, MQTT logging to InfluxDB, and a Grafana dashboard. Wiring, code, and calibration tips. Start building.

Arduino IDE 2 Setup: Install, Configure, and Upload Your First Sketch

Install Arduino IDE 2, add board cores, select the port, and upload Blink in minutes. Follow this step-by-step setup guide and flash your first board.

Desoldering Done Right: Braid, Pumps, and Hot Air

This guide covers solder braid, solder suckers, and hot air rework, with temperatures, technique, and a decision table. Read now.

Subqueries vs CTEs: Writing Cleaner SQL

Compare SQL CTEs and subqueries with code, performance notes, and a decision table. Learn when each wins, then refactor your queries today.

Related Articles

Popular Categories