Getting started with the ESP32
The ESP32 from Espressif is a low-cost microcontroller with Wi-Fi and Bluetooth built in, and it can be programmed with the same Arduino functions as an Uno. It is also less forgiving: 3.3 V logic, pins with special jobs and a few that can only be inputs. This guide covers what you need to know before the first sketch, then gets one running.
What the ESP32 is
The original ESP32 is a system on a chip with a dual-core 32-bit Xtensa processor running at up to 240 MHz, 520 KB of SRAM, 2.4 GHz Wi-Fi (802.11 b/g/n) and Bluetooth 4.2 (Classic and Low Energy). Most people meet it on a module such as the ESP32-WROOM-32, which adds 4 MB of flash and an antenna, mounted on a development board such as the ESP32-DevKitC or the many DevKit V1 boards with a USB-to-serial chip and a voltage regulator.
The name now covers a family: the ESP32-S3 (with USB and vector instructions for machine learning), the RISC-V based ESP32-C3 and C6, and others. This guide is about the original ESP32 on a WROOM-32 module; the newer chips differ in pins and peripherals.
The pins: what to use and what to avoid
- Logic is 3.3 V. A HIGH output is about 3.3 V, and inputs should not see more than that: treat the pins as not 5 V tolerant and level-shift 5 V signals.
- GPIO 34, 35, 36 and 39 (the ones the WROOM-32 brings out from the 34 to 39 group) are inputs only, with no internal pull-up or pull-down. They are good analogue inputs; they cannot drive an LED, and INPUT_PULLUP does nothing on them.
- GPIO 6 to 11 connect to the module’s flash memory. Do not use them.
- GPIO 0, 2, 5, 12 and 15 are strapping pins, read at reset to choose the boot mode. They can be used, but a part that pulls one the wrong way can stop the board starting or uploading. GPIO 12 is the one most likely to cause trouble.
- ADC2 pins (including 0, 2, 4, 12 to 15 and 25 to 27) cannot be read while Wi-Fi is on. For analogue inputs in a Wi-Fi project, use ADC1: GPIO 32 to 39.
- analogRead returns 0 to 4095 (12 bits). The ESP32’s ADC is not perfectly linear, especially near 0 V and the top of its range, so calibrate if you need accurate volts.
Install the Arduino-ESP32 core
- Install the Arduino IDE from arduino.cc.
- Open File, Preferences (Arduino IDE, Settings on macOS) and paste https://espressif.github.io/arduino-esp32/package_esp32_index.json into Additional boards manager URLs.
- Open Tools, Board, Boards Manager, search for esp32 and install esp32 by Espressif Systems.
- Choose your board under Tools, Board, esp32: ESP32 Dev Module works for most WROOM-32 development boards.
- Connect the board. If no port appears, install the driver for its USB-to-serial chip (often a Silicon Labs CP210x or a WCH CH340).
- Choose the port under Tools, Port. If an upload stalls at Connecting, hold the board’s BOOT button until it starts.
A first sketch: blink
Many DevKit V1 boards have a blue LED on GPIO 2. Espressif’s own ESP32-DevKitC has only a power LED, so on that board wire an LED and a resistor from GPIO 2 to GND. At 3.3 V a red LED with a 220 Ω resistor draws about (3.3 − 2.0) ÷ 220 = 5.9 mA. Note that the ESP32 serial port is usually opened at 115200 baud.
const int ledPin = 2; // the on-board LED on many ESP32 DevKit V1 boards
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH);
Serial.println("LED on");
delay(500);
digitalWrite(ledPin, LOW);
Serial.println("LED off");
delay(500);
}
A button and a potentiometer
GPIO 4 has an internal pull-up, so a button from GPIO 4 to GND reads LOW when pressed. GPIO 34 is input-only and on ADC1, which makes it a good place for a potentiometer wiper (ends on 3V3 and GND, never 5 V).
const int buttonPin = 4; // internal pull-up available
const int ledPin = 2;
const int potPin = 34; // ADC1, input only
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}
void loop() {
if (digitalRead(buttonPin) == LOW) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
int raw = analogRead(potPin); // 0 to 4095
Serial.print("Potentiometer: ");
Serial.println(raw);
delay(200);
}
ESP32 or Arduino Uno?
Start on the Uno if you are new and your parts are 5 V modules; move to the ESP32 when a project needs Wi-Fi, Bluetooth or more memory. The code you learn carries over almost unchanged.
| Arduino Uno R3 | ESP32 on a WROOM-32 | |
|---|---|---|
| Processor | ATmega328P, 8-bit AVR, 16 MHz | Dual-core 32-bit Xtensa, up to 240 MHz |
| Memory | 32 KB flash, 2 KB SRAM, 1 KB EEPROM | 4 MB flash (module), 520 KB SRAM |
| Logic level | 5 V | 3.3 V, not 5 V tolerant |
| Analogue inputs | 6, 10-bit (0 to 1023) | Up to 18 channels, 12-bit (0 to 4095); ADC2 unavailable with Wi-Fi |
| PWM | Pins 3, 5, 6, 9, 10, 11 | Most output pins, through the LEDC peripheral |
| Wireless | None | Wi-Fi 802.11 b/g/n, Bluetooth 4.2 Classic and LE |
| Pins to be careful with | D0 and D1 (USB serial) | Flash pins 6 to 11, strapping pins, input-only 34 to 39 |
| Best for | Learning, 5 V sensors and shields, simple timing | Connected projects, more memory and speed |
Power and wiring tips
- Power the board from USB or 5 V on its VIN or 5V pin; the on-board regulator makes 3.3 V. Never put 5 V on a 3V3 pin.
- Wi-Fi transmission draws current in bursts of a few hundred milliamps. A weak USB port or long thin cable can make the board reset (a brown-out); a better supply fixes it.
- Share ground between the ESP32 and every module it talks to.
- Check that 5 V sensors are actually 3.3 V compatible, or use a level shifter or a divider on their outputs.
Try it in Simscuit first
Simscuit simulates an ESP32 DevKit V1 with the WROOM-32 pin rules: GPIO 34, 35, 36 and 39 are inputs only, analogRead is 12-bit, the logic level is 3.3 V and the LED is on GPIO 2. Both sketches above run on it, so you can check the wiring and the logic before the board arrives. The ESP32-S3, Nano ESP32, XIAO ESP32C3 and NodeMCU ESP8266 are simulated too, among about 20 boards.
The limits are plain: Simscuit does not simulate Wi-Fi or Bluetooth, and it runs sketches in its own Arduino interpreter rather than on an emulated Xtensa core, so FreeRTOS tasks, interrupts and Wi-Fi libraries need real hardware or a firmware-level simulator.
Sources
Pin rules from Espressif’s documentation, checked 6 November 2026.
Questions
Can I use 5 V sensors with an ESP32?
Power them from 5 V if they need it, but do not feed their 5 V outputs straight into an ESP32 pin. Use a level shifter, a resistor divider, or a 3.3 V version of the sensor.
Why does INPUT_PULLUP not work on GPIO 34?
GPIO 34 to 39 on the ESP32 are input-only and have no internal pull-up or pull-down. Add an external resistor, or use another pin such as GPIO 4.