Meet the ESP32
The ESP32 is where beginner electronics becomes IoT. It has GPIO like Arduino, but also Wi-Fi, Bluetooth, more processing power, and enough memory to run connected device projects.
By the end of this course, learners build a connected smart room monitor that reads temperature, humidity, light, and motion, publishes sensor readings over MQTT, serves a local dashboard, and can trigger alerts through an HTTP webhook.
Microcontroller side
The ESP32 can read pins, control LEDs, handle buttons, read sensors, and run fast loops just like an Arduino-style board.
Network side
It can join Wi-Fi, serve a web page, send HTTP requests, publish MQTT messages, and act like a tiny connected product.
| Item | Use |
|---|---|
| ESP32 DevKit board | Main controller for the course. |
| Micro USB or USB-C cable | Power and programming connection. Make sure it supports data, not just charging. |
| Breadboard + jumper wires | Prototyping sensor and LED circuits. |
| DHT22 or DHT11 | Temperature and humidity readings. |
| PIR motion sensor | Room movement detection for the capstone. |
| LEDs + 220Ω/330Ω resistors | Visible status indicators. |
Setup & First Upload
Install ESP32 board support, select the right board and port, then upload a first sketch to prove the toolchain works before adding hardware complexity.
- Install Arduino IDE.
- Add the ESP32 board package through Boards Manager.
- Connect the ESP32 with a data-capable USB cable.
- Select a matching ESP32 Dev Module board.
- Select the serial port that appears after plugging in the board.
- Upload a simple Blink sketch.
const int ledPin = 2; // many ESP32 boards have onboard LED on GPIO 2
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
}
Upload Blink, change the delay from 500ms to 100ms, upload again, and confirm the device changes behavior. This proves the board, cable, driver, IDE, and upload process are working.
GPIO on the ESP32
The ESP32 has many pins, but not every pin is safe for every purpose. Learners practice LEDs, buttons, pull-ups, and safe pin selection.
- Use common safe GPIO pins such as 2, 4, 5, 18, 19, 21, 22, 23, 25, 26, 27, 32, and 33 for beginner projects.
- Avoid changing boot-strapping pins until you understand their startup behavior.
- Remember that input-only pins exist on some ESP32 boards.
- Keep all signal wiring at 3.3V logic.
const int buttonPin = 27;
const int ledPin = 2;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}
void loop() {
bool pressed = digitalRead(buttonPin) == LOW;
digitalWrite(ledPin, pressed ? HIGH : LOW);
}
- Wire a button from GPIO 27 to GND.
- Use INPUT_PULLUP.
- Light the onboard LED while the button is pressed.
- Print the state to Serial for debugging.
Wi-Fi Fundamentals
A connected device must join a network reliably. This module covers SSID, password, station mode, IP addresses, connection status, and basic troubleshooting.
Most beginner ESP32 projects use station mode, meaning the ESP32 joins an existing Wi-Fi network like a laptop or phone. Once connected, it receives an IP address and can communicate on the local network or internet.
#include <WiFi.h>
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected. IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {}
Web Server Dashboard
The ESP32 can host a tiny web server. Learners create a browser dashboard that shows device state and controls an LED from any phone or laptop on the same network.
When the ESP32 runs a web server, it listens for browser requests. A phone opens the ESP32 IP address, the ESP32 sends HTML back, and button links can trigger GPIO actions.
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";
const int ledPin = 2;
WebServer server(80);
bool ledOn = false;
void handleHome() {
String page = "<h1>ESP32 Dashboard</h1>";
page += "<p>LED: " + String(ledOn ? "ON" : "OFF") + "</p>";
page += "<a href='/toggle'>Toggle LED</a>";
server.send(200, "text/html", page);
}
void handleToggle() {
ledOn = !ledOn;
digitalWrite(ledPin, ledOn ? HIGH : LOW);
server.sendHeader("Location", "/");
server.send(303);
}
void setup() {
pinMode(ledPin, OUTPUT);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(300);
server.on("/", handleHome);
server.on("/toggle", handleToggle);
server.begin();
}
void loop() {
server.handleClient();
}
Connect the ESP32 to Wi-Fi, open the printed IP address on a phone, and toggle the LED from the dashboard.
Sensors & Data
An IoT device becomes useful when it collects real measurements. This module reads temperature, humidity, light, and motion, then formats clean data for dashboards and messages.
- Read the sensor.
- Validate the reading.
- Store it in variables.
- Print it for debugging.
- Display or publish it.
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
float tempC = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(tempC) || isnan(humidity)) {
Serial.println("Sensor read failed");
return;
}
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Humidity: ");
Serial.println(humidity);
delay(2000);
}
Read a DHT sensor, print values to Serial, then add the readings to the web dashboard from Module 05.
MQTT Messaging
MQTT is one of the most common IoT messaging patterns. Devices publish messages to topics, and dashboards or services subscribe to receive them.
Publisher
The ESP32 sends a message such as temperature data to a named topic.
Subscriber
A dashboard, server, or another device listens to the topic and reacts when a message arrives.
| Topic | Purpose |
|---|---|
| home/room1/temperature | Temperature readings |
| home/room1/humidity | Humidity readings |
| home/room1/motion | Motion status |
| home/room1/status | Device online/offline heartbeat |
#include <WiFi.h>
#include <PubSubClient.h>
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
void publishReading(float tempC) {
char payload[16];
dtostrf(tempC, 4, 1, payload);
mqtt.publish("home/room1/temperature", payload);
}
Run a local MQTT broker, connect the ESP32, publish temperature readings every few seconds, and view messages from a desktop MQTT client.
HTTP APIs & Webhooks
HTTP lets the ESP32 talk to web services. Learners send data to an API endpoint and trigger a webhook-style alert when a sensor crosses a threshold.
| Protocol | Best For |
|---|---|
| MQTT | Continuous small messages between devices and dashboards. |
| HTTP | Calling web APIs, sending form-like data, triggering webhook endpoints. |
#include <HTTPClient.h>
void sendWebhook(String message) {
HTTPClient http;
http.begin("https://example.com/webhook");
http.addHeader("Content-Type", "application/json");
String body = "{\"message\":\"" + message + "\"}";
int code = http.POST(body);
Serial.print("HTTP status: ");
Serial.println(code);
http.end();
}
When the PIR sensor detects motion, send a webhook message. Add cooldown logic so the ESP32 does not spam repeated alerts.
Bluetooth & Power
Not every connected device needs Wi-Fi all the time. This module introduces Bluetooth use cases and power-aware design for battery-powered projects.
Bluetooth use cases
Local phone control, setup mode, short-range device configuration, and simple nearby interactions.
Power awareness
Reduce radio time, avoid unnecessary delays, dim indicators, and use deep sleep for periodic sensor projects.
- Does the device need to be always-on?
- Can it wake, read, publish, then sleep?
- How often does the sensor actually need to report?
- Are LEDs wasting power?
- Is Wi-Fi required, or is Bluetooth enough?
#define SECONDS_TO_SLEEP 60
void setup() {
Serial.begin(115200);
Serial.println("Read sensor, publish data, then sleep...");
esp_sleep_enable_timer_wakeup(SECONDS_TO_SLEEP * 1000000ULL);
esp_deep_sleep_start();
}
void loop() {}
Build a sketch that wakes, prints a sensor reading, waits briefly, and enters deep sleep. Discuss how this changes battery life compared to always-on Wi-Fi.
Capstone: Smart Room Monitor
Learners combine everything from the course into one product-style build: sensing, dashboard, MQTT publishing, motion alerts, status LED, and deployment notes.
- Read temperature and humidity from a DHT sensor.
- Read motion from a PIR sensor.
- Show current readings on a local ESP32 web dashboard.
- Publish readings to MQTT topics every fixed interval.
- Send an HTTP webhook alert when motion is detected.
- Use a status LED pattern for booting, connected, error, and alert states.
- Document wiring, setup steps, screenshots, and troubleshooting notes.
ESP32
├── inputs
│ ├── DHT22 temperature/humidity
│ └── PIR motion sensor
├── outputs
│ └── status LED
├── local dashboard
│ └── WebServer on port 80
├── MQTT publisher
│ ├── home/room1/temperature
│ ├── home/room1/humidity
│ └── home/room1/motion
└── HTTP alert
└── webhook on motion event- README with parts list and wiring table.
- Screenshot of local dashboard.
- Photo of the breadboard build.
- Short demo video or GIF.
- Known issues and future improvements.
- Clean code with credentials removed.