ESP32 Complete Beginners Guide: Pinout, GPIO, WiFi and First Projects

!DOCTYPE html> ESP32 Complete Beginner's Guide: Pinout, WiFi, GPIO, and First Projects

ESP32 Complete Beginner's Guide: Pinout, WiFi, GPIO, and First Projects

Everything you need to go from unboxing an ESP32 to building WiFi-connected sensors, web servers, and MQTT IoT devices -- with complete, tested code for every example.

Why ESP32? ESP32 vs Arduino vs Raspberry Pi

FeatureESP32Arduino UnoRaspberry Pi 4
CPUDual-core 240 MHz16 MHz AVRQuad-core 1.8 GHz ARM
RAM520 KB SRAM2 KB SRAM4-8 GB
WiFi[YES] Built-in 2.4GHz[NO] (shield needed)[YES] Built-in
Bluetooth[YES] BLE + Classic[NO][YES] BLE
Power draw~240 mA active / 10 uA deep sleep~50 mA~3.4 W
OSFreeRTOS (bare-metal)NoneLinux
Cost~$4-8~$25~$55+
Best forIoT, sensors, battery projectsSimple real-time controlComplex software, vision

ESP32 Pinout Reference

ESP32 DevKit v1 (30-pin) -- Key Pins ?????????????????????????????????? GPIO 0 -- Boot mode select (pull HIGH for normal boot) GPIO 2 -- Onboard LED (active HIGH on most boards) GPIO 4 -- General purpose I/O GPIO 5 -- SPI SS / General purpose GPIO 12 -- JTAG TDI / ADC2_CH5 (avoid as OUTPUT on boot) GPIO 13 -- ADC2_CH4 / General purpose GPIO 14 -- ADC2_CH6 / General purpose GPIO 15 -- JTAG TDO / ADC2_CH3 GPIO 16 -- UART2 RX GPIO 17 -- UART2 TX GPIO 18 -- SPI CLK GPIO 19 -- SPI MISO GPIO 21 -- I2C SDA GPIO 22 -- I2C SCL GPIO 23 -- SPI MOSI GPIO 25 -- DAC1 / ADC2_CH8 GPIO 26 -- DAC2 / ADC2_CH9 GPIO 27 -- ADC2_CH7 GPIO 32 -- ADC1_CH4 (WiFi-safe ADC) GPIO 33 -- ADC1_CH5 (WiFi-safe ADC) GPIO 34 -- INPUT ONLY / ADC1_CH6 GPIO 35 -- INPUT ONLY / ADC1_CH7 GPIO 36 -- INPUT ONLY (VP) GPIO 39 -- INPUT ONLY (VN) ?????????????????????????????????? [WARN] ADC2 pins don't work reliably when WiFi is active -- use ADC1 (GPIO 32-39) [WARN] GPIO 6-11 are connected to internal flash -- never use them

Arduino IDE Setup

  1. Open Arduino IDE -> File -> Preferences
  2. Add to "Additional Boards Manager URLs":
    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  3. Go to Tools -> Board -> Boards Manager, search "esp32", install esp32 by Espressif Systems
  4. Select board: Tools -> Board -> ESP32 Arduino -> ESP32 Dev Module
  5. Set upload speed: Tools -> Upload Speed -> 921600
[WARN] Driver issue on Windows? Install the CP210x or CH340 USB-UART driver depending on your board's chip. Check the USB chip marking on the board.

GPIO: Digital I/O, PWM, ADC

Digital Output -- Blink LED

const int LED_PIN = 2;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  digitalWrite(LED_PIN, HIGH);
  Serial.println("LED ON");
  delay(1000);
  digitalWrite(LED_PIN, LOW);
  Serial.println("LED OFF");
  delay(1000);
}

Digital Input -- Button with Debounce

const int BTN_PIN = 14;
const int LED_PIN = 2;
unsigned long lastDebounce = 0;
const int DEBOUNCE_MS = 50;
int lastState = HIGH;
bool ledState = false;

void setup() {
  pinMode(BTN_PIN, INPUT_PULLUP);  // internal pull-up, button connects to GND
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  int reading = digitalRead(BTN_PIN);
  if (reading != lastState) {
    lastDebounce = millis();
  }
  if ((millis() - lastDebounce) > DEBOUNCE_MS) {
    if (reading == LOW) {          // button pressed (active LOW)
      ledState = !ledState;
      digitalWrite(LED_PIN, ledState);
      Serial.println(ledState ? "ON" : "OFF");
    }
  }
  lastState = reading;
}

PWM -- Fade LED / Control Servo

// ESP32 uses ledcWrite() -- NOT analogWrite()
const int LED_PIN   = 2;
const int PWM_CHAN  = 0;
const int PWM_FREQ  = 5000;   // Hz
const int PWM_RES   = 8;      // 8-bit = 0-255

void setup() {
  ledcSetup(PWM_CHAN, PWM_FREQ, PWM_RES);
  ledcAttachPin(LED_PIN, PWM_CHAN);
}

void loop() {
  for (int duty = 0; duty <= 255; duty++) {
    ledcWrite(PWM_CHAN, duty);
    delay(10);
  }
  for (int duty = 255; duty >= 0; duty--) {
    ledcWrite(PWM_CHAN, duty);
    delay(10);
  }
}

ADC -- Read Analog Sensor (Use ADC1 with WiFi!)

const int SENSOR_PIN = 34;  // ADC1 -- works with WiFi active

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);          // 12-bit = 0-4095 (default)
  analogSetAttenuation(ADC_11db);    // full 0-3.3V range
}

void loop() {
  int raw = analogRead(SENSOR_PIN);
  float voltage = raw * (3.3 / 4095.0);
  Serial.printf("Raw: %d  Voltage: %.3f V\n", raw, voltage);
  delay(500);
}

WiFi: Station and Access Point Mode

Station Mode -- Connect to Router

#include <WiFi.h>

const char* SSID     = "YourWiFiName";
const char* PASSWORD = "YourPassword";

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PASSWORD);

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected! IP: " + WiFi.localIP().toString());
  Serial.printf("RSSI: %d dBm\n", WiFi.RSSI());
}

Built-in Web Server -- Control GPIO from Browser

#include <WiFi.h>
#include <WebServer.h>

const char* SSID = "YourSSID";
const char* PASS = "YourPassword";
const int LED    = 2;

WebServer server(80);

void handleRoot() {
  String html = R"(
    <!DOCTYPE html><html><head>
      <meta name='viewport' content='width=device-width,initial-scale=1'>
      <style>body{font-family:sans-serif;text-align:center;padding:40px}
        .btn{padding:20px 40px;font-size:20px;border:none;border-radius:8px;cursor:pointer}
        .on{background:#27ae60;color:white} .off{background:#e74c3c;color:white}</style>
    </head><body>
      <h2>ESP32 GPIO Control</h2>
      <a href='/on'><button class='btn on'>LED ON</button></a>
      <a href='/off'><button class='btn off'>LED OFF</button></a>
    </body></html>)";
  server.send(200, "text/html", html);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.println("IP: " + WiFi.localIP().toString());

  server.on("/",    handleRoot);
  server.on("/on",  []() { digitalWrite(LED, HIGH); server.sendHeader("Location","/"); server.send(302); });
  server.on("/off", []() { digitalWrite(LED, LOW);  server.sendHeader("Location","/"); server.send(302); });
  server.begin();
}

void loop() {
  server.handleClient();
}

MQTT IoT Sensor Node

// Required libraries: PubSubClient, DHT sensor library
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

#define DHTPIN  4
#define DHTTYPE DHT22

const char* SSID        = "YourSSID";
const char* PASS        = "YourPassword";
const char* MQTT_BROKER = "192.168.1.100";
const int   MQTT_PORT   = 1883;
const char* TOPIC_TEMP  = "home/sensor/temperature";
const char* TOPIC_HUM   = "home/sensor/humidity";

DHT dht(DHTPIN, DHTTYPE);
WiFiClient espClient;
PubSubClient mqtt(espClient);

void connectMQTT() {
  while (!mqtt.connected()) {
    Serial.print("Connecting MQTT...");
    if (mqtt.connect("ESP32Sensor")) {
      Serial.println("connected");
    } else {
      Serial.printf("failed (rc=%d), retry in 5s\n", mqtt.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(SSID, PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(MQTT_BROKER, MQTT_PORT);
}

void loop() {
  if (!mqtt.connected()) connectMQTT();
  mqtt.loop();

  float temp = dht.readTemperature();
  float hum  = dht.readHumidity();

  if (!isnan(temp) && !isnan(hum)) {
    char buf[10];
    snprintf(buf, sizeof(buf), "%.1f", temp);
    mqtt.publish(TOPIC_TEMP, buf, true);   // retained message
    snprintf(buf, sizeof(buf), "%.1f", hum);
    mqtt.publish(TOPIC_HUM, buf, true);
    Serial.printf("Published -- Temp: %.1f degreesC  Humidity: %.1f%%\n", temp, hum);
  }
  delay(30000);  // publish every 30 seconds
}

Deep Sleep for Battery Projects

// Deep sleep draws only ~10 uA -- extends battery life from days to months
#include <esp_sleep.h>

#define uS_TO_S 1000000ULL
#define SLEEP_SECONDS 300       // wake every 5 minutes

RTC_DATA_ATTR int bootCount = 0;  // persists across deep sleep

void setup() {
  Serial.begin(115200);
  bootCount++;
  Serial.printf("Boot #%d\n", bootCount);

  // --- Do your work here (read sensor, send MQTT, etc.) ---
  readAndPublishSensor();
  // --------------------------------------------------------

  Serial.println("Going to deep sleep for 5 minutes...");
  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * uS_TO_S);
  esp_deep_sleep_start();   // execution stops here; setup() runs again on wake
}
[YES] Power tip: For battery-powered sensors, budget your wake time. A DHT22 read + WiFi connect + MQTT publish + disconnect typically takes 3-5 seconds at ~180 mA. Then 5 minutes at 10 uA deep sleep. Average current: ~0.5 mA -- a 2000 mAh battery lasts ~167 days.

Key Takeaways: Never use ADC2 pins when WiFi is active -- they share the radio hardware. Use ledcWrite() for PWM, not analogWrite(). Design battery projects around deep sleep -- it's transformative. MQTT over WiFi is the standard protocol for ESP32 IoT sensor nodes.

ESP32IoTArduinoWiFiMQTTGPIOEmbedded

Post a Comment

0 Comments