1 ยท ESP32 Quick Reference
30-pin DevKitC Power Pins
| Pin | Label | Notes |
| 1, 2 | 3V3 | 3.3 V regulated output, max 1200 mA total (board + peripherals) |
| 3, 4, 5, 8, 9, 28, 29, 30 | GND | Ground, all connected together |
| 7 | 5V | 5 V input (via USB or VIN) or output when USB powered |
| 6 | VIN | 6โ20 V raw input, feeds the onboard regulator to 3.3 V |
Key GPIO Restrictions
| GPIOs | Restriction |
| 6, 7, 8, 9, 10, 11 | Flash pins. Connected to the onboard SPI flash. Do not use as general I/O. |
| 34, 35, 36, 39 | Input-only. No digitalWrite(), no INPUT_PULLUP (external pull-up needed). |
| 0, 2, 4, 12โ15, 25โ27 | ADC2 channels. analogRead() fails when Wi-Fi is active. Use ADC1 (GPIO 32โ39) with Wi-Fi. |
| 2 | Strapping pin. High = boot from flash. Bootloader prints to this pin. |
| 12 | Strapping pin. Affects flash voltage at boot. Avoid high at startup. |
| 15 | Strapping pin. Controls JTAG at boot. |
IยฒC & SPI Bus Defaults
| Bus | Default Pins | Notes |
| IยฒC SDA | GPIO 21 | Changeable with Wire.begin(SDA, SCL) |
| IยฒC SCL | GPIO 22 | |
| SPI MOSI | GPIO 23 | Used by SD card, displays, etc. |
| SPI MISO | GPIO 19 | |
| SPI SCK | GPIO 18 | |
| SPI SS | GPIO 5 | Chip select, active low |
2 ยท GPIO & Digital I/O
pinMode(pin, INPUT / OUTPUT / INPUT_PULLUP);
digitalRead(pin); // returns HIGH or LOW
digitalWrite(pin, HIGH / LOW);
| Function | What it does | Where to put it |
pinMode(pin, OUTPUT) | Configures the pin to drive a load | setup() once |
pinMode(pin, INPUT_PULLUP) | Enables the internal 45 kΩ pull-up | setup() once |
digitalRead(pin) | Returns HIGH (≥1.7 V) or LOW | loop() |
digitalWrite(pin, HIGH) | Drives the pin to 3.3 V | loop() |
INPUT_PULLUP: The button reads LOW when pressed, HIGH when released. Wiring the switch between the GPIO and GND (no external resistor) is the standard pattern.
3 ยท Analog (ADC)
int value = analogRead(pin); // 0โ4095 (12-bit)
float voltage = value * 3.3 / 4095.0;
// Note: analogRead on ADC2 (GPIO 0,2,4,12-15,25-27) fails when Wi-Fi is active
| ADC | GPIO Pins | Safe with Wi-Fi? |
| ADC1 | 32, 33, 34, 35, 36, 39 | Yes |
| ADC2 | 0, 2, 4, 12, 13, 14, 15, 25, 26, 27 | No |
ADC2 + Wi-Fi: When the Wi-Fi radio is active, ADC2 returns 0 regardless of the actual voltage. Use ADC1 pins (GPIO 32โ39) for any analog reading that will run alongside Wi-Fi.
4 ยท PWM (LED Control)
ledcAttach(pin, freq, resolution); // ESP32 core 3.x API
ledcWrite(pin, duty); // duty: 0 to 2^resolution - 1
// Example: ledcAttach(4, 5000, 8); ledcWrite(4, 128); // 50% duty
| Parameter | What it controls | Typical value |
freq | PWM frequency in Hz | 5000 (LED), 50 (servo) |
resolution | Bit resolution (1โ16) | 8 (0โ255), 10 (0โ1023), 12 (0โ4095) |
duty | Duty cycle value | 0 = off, 2res−1 = full on |
Built-in tone(): ESP32 Core 3.x includes tone(pin, frequency, duration) and noTone(pin) natively. No external library needed.
5 ยท Serial Communication
Serial.begin(115200);
Serial.println("Hello");
Serial.printf("Value: %d\n", value);
| Method | Output |
Serial.print("A") | Prints without newline |
Serial.println("A") | Prints with \r\n |
Serial.printf("x=%d\n", x) | Formatted output (like C printf) |
Serial.println(value) | Prints an integer in decimal |
Baud rate: Always 115200. Set the Serial Monitor to match. USB CDC on the ESP32 auto-resets, so you may see a brief garbage burst at power-on.
6 ยท Wi-Fi (Station Mode)
#include <WiFi.h>
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
| Function | Returns |
WiFi.begin(ssid, pass) | Starts connection (returns wl_status_t) |
WiFi.status() | WL_CONNECTED, WL_IDLE, WL_DISCONNECTED, etc. |
WiFi.localIP() | The assigned IP address (e.g. 192.168.1.42) |
WiFi.SSID() | Name of the connected network |
WiFi.RSSI() | Signal strength in dBm (closer to 0 = stronger) |
7 ยท Common Sensor APIs
// DHT11 Temperature & Humidity
#include <DHT.h>
DHT dht(pin, DHT11);
dht.begin();
float t = dht.readTemperature(); // Celsius
float h = dht.readHumidity();
// PIR Motion
int motion = digitalRead(pin); // HIGH = motion detected
// Potentiometer
int pot = analogRead(pin); // 0โ4095
| Sensor | Library | Key functions | Output |
| DHT11 | DHT by Adafruit | readTemperature(), readHumidity() | Floats (ยฐC, %RH). Returns NaN on read failure. |
| HC-SR501 PIR | None (digital) | digitalRead() | HIGH when motion, LOW otherwise |
| 10 kΩ Pot | None (analog) | analogRead() | 0โ4095 |
8 ยท Web Server (AsyncWebServer)
#include <ESP Async WebServer.h>
AsyncWebServer server(80);
server.on("/", HTTP_GET, [](AsyncWebServerRequest *req){
req->send(200, "text/html", "<h1>Hello</h1>");
});
server.begin();
| Method | Use case |
server.on(path, method, handler) | Register a route handler |
req->send(code, type, body) | Send a response |
server.on("/led", HTTP_GET, ...) | Handle GET requests with query params |
server.on("/led", HTTP_POST, ...) | Handle POST from forms or AJAX |
Libraries needed: Install both
ESP Async WebServer and
AsyncTCP via the Arduino Library Manager. See
Project 5 for a complete example.
9 ยท MQTT (Ubidots)
#include <UbidotsEsp32Mqtt.h>
Ubidots ubidots(TOKEN);
ubidots.connectToWifi(ssid, pass);
ubidots.setCallback(callback);
ubidots.setup();
ubidots.reconnect();
// In loop():
ubidots.add("variable", value);
ubidots.publish("device-label");
ubidots.loop();
| Step | Function | Notes |
| 1. Connect | connectToWifi() | Blocks until connected |
| 2. Callback | setCallback() | Called when a subscribed variable changes |
| 3. Setup | setup() | Connects to Ubidots MQTT broker |
| 4. Reconnect | reconnect() | Re-subscribes to variables |
| 5. Publish | add() + publish() | Send data in every loop iteration |
| 6. Keep alive | loop() | Must be called frequently |
10 ยท ESP32 Core 3.x Migration Notes
PWM API (most common break)
| Core 2.x (old) | Core 3.x (current) |
| Setup | ledcSetup(channel, freq, resolution) | ledcAttach(pin, freq, resolution) |
| Attach | ledcAttachPin(pin, channel) | Merged into ledcAttach() |
| Write | ledcWrite(channel, duty) | ledcWrite(pin, duty) |
Migration: Core 3.x assigns channels automatically per pin. The old channel-based approach no longer compiles. Every PWM project in this kit uses the 3.x API.
Other Changes
| Area | Change |
analogSetAttenuation() | Now takes an enum (ADC_11db), not an integer. Default is 11 dB (full 0โ3.3 V range). |
tone() / noTone() | Built-in. No library needed. Signature: tone(pin, freq, duration). |
ledcSetup() | Removed entirely. Use ledcAttach() instead. |
ledcAttachPin() | Removed entirely. Use ledcAttach() instead. |
analogReadResolution() | 12 bits is the default. No need to call analogReadResolution(12). |