%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085'}}}%%
flowchart LR
subgraph ESP32["ESP32 DevKit"]
V33["3.3V"]
G4["GPIO 4"]
GND["GND"]
G2["GPIO 2<br/>(Built-in LED)"]
end
subgraph DHT["DHT22 Sensor"]
VCC["VCC"]
DATA["Data"]
NC["NC"]
DGND["GND"]
end
V33 -.->|"Power"| VCC
G4 -.->|"Data Signal"| DATA
GND -.->|"Ground"| DGND
style ESP32 fill:#2C3E50,stroke:#16A085,stroke-width:2px,color:#fff
style DHT fill:#16A085,stroke:#2C3E50,stroke-width:2px,color:#fff
838 Wi-Fi Hands-On Labs and Exercises
838.1 Learning Objectives
By completing these hands-on labs, you will be able to:
- Configure ESP32 Wi-Fi in Station (STA) mode
- Read digital sensor data using the DHT protocol
- Create an HTTP web server on embedded hardware
- Serve dynamic HTML content with live sensor readings
- Analyze Wi-Fi channel congestion and optimize deployments
- Calculate power consumption for battery-powered Wi-Fi devices
- Design Wi-Fi network infrastructure for IoT applications
838.2 Hands-On Lab: Wi-Fi Weather Station
This interactive lab uses the Wokwi ESP32 simulator to build a complete Wi-Fi weather station. You will connect an ESP32 to Wi-Fi, read temperature and humidity data from a DHT22 sensor, and serve the readings through a simple web server.
838.2.1 Prerequisites
- Basic understanding of Arduino/C++ syntax
- Familiarity with Wi-Fi concepts from previous chapters
- No physical hardware required (browser-based simulation)
838.2.2 About Wokwi
Wokwi is a free online simulator for Arduino, ESP32, and other microcontrollers. It allows you to build and test IoT projects entirely in your browser without purchasing hardware.
838.2.3 Launch the Simulator
Launch the simulator below to get started. The default project includes an ESP32 - you will add components and code as you progress.
- Click on the ESP32 to see available pins
- Use the + button to add components (search for “DHT22”)
- Connect wires by clicking on pins
- The Serial Monitor shows debug output
- Press the green Play button to run your code
838.2.4 Step 1: Set Up the Circuit
- Add a DHT22 sensor: Click the + button and search for “DHT22”
- Wire the DHT22 to ESP32:
- DHT22 VCC (pin 1) -> ESP32 3.3V
- DHT22 Data (pin 2) -> ESP32 GPIO 4
- DHT22 GND (pin 4) -> ESP32 GND
- Optional: Add an LED on GPIO 2 for status indication
838.2.5 Step 2: Copy the Weather Station Code
Copy this code into the Wokwi code editor:
// Wi-Fi Weather Station Lab
// Reads DHT22 temperature/humidity and serves data via web server
#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"
// ========== CONFIGURATION ==========
// Note: In Wokwi simulator, use these credentials:
const char* ssid = "Wokwi-GUEST";
const char* password = ""; // Leave empty for Wokwi
// DHT Sensor Configuration
#define DHTPIN 4 // GPIO pin connected to DHT22 data pin
#define DHTTYPE DHT22 // DHT22 (AM2302)
#define LED_PIN 2 // Built-in LED for status
// ========== GLOBAL OBJECTS ==========
DHT dht(DHTPIN, DHTTYPE);
WebServer server(80);
// Sensor readings (global for access in handlers)
float temperature = 0.0;
float humidity = 0.0;
unsigned long lastReadTime = 0;
const unsigned long READ_INTERVAL = 2000; // Read every 2 seconds
// ========== WEB PAGE HTML ==========
String getHTML() {
String html = "<!DOCTYPE html><html><head>";
html += "<meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<meta http-equiv='refresh' content='5'>"; // Auto-refresh every 5s
html += "<title>ESP32 Weather Station</title>";
html += "<style>";
html += "body { font-family: Arial, sans-serif; background: #1a1a2e; color: #eee; ";
html += "display: flex; justify-content: center; align-items: center; ";
html += "min-height: 100vh; margin: 0; }";
html += ".container { text-align: center; background: #16213e; ";
html += "padding: 40px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); }";
html += "h1 { color: #e94560; margin-bottom: 30px; }";
html += ".reading { background: #0f3460; padding: 20px; margin: 15px; ";
html += "border-radius: 15px; display: inline-block; min-width: 150px; }";
html += ".value { font-size: 48px; font-weight: bold; color: #00fff5; }";
html += ".label { font-size: 14px; color: #aaa; margin-top: 10px; }";
html += ".unit { font-size: 24px; color: #e94560; }";
html += ".status { margin-top: 20px; font-size: 12px; color: #666; }";
html += "</style></head><body>";
html += "<div class='container'>";
html += "<h1>ESP32 Weather Station</h1>";
html += "<div class='reading'>";
html += "<div class='value'>" + String(temperature, 1) + "<span class='unit'>C</span></div>";
html += "<div class='label'>Temperature</div>";
html += "</div>";
html += "<div class='reading'>";
html += "<div class='value'>" + String(humidity, 1) + "<span class='unit'>%</span></div>";
html += "<div class='label'>Humidity</div>";
html += "</div>";
html += "<div class='status'>Auto-refreshes every 5 seconds</div>";
html += "</div></body></html>";
return html;
}
// ========== REQUEST HANDLERS ==========
void handleRoot() {
digitalWrite(LED_PIN, HIGH); // Blink LED on request
server.send(200, "text/html", getHTML());
delay(50);
digitalWrite(LED_PIN, LOW);
}
void handleJSON() {
// API endpoint for JSON data
String json = "{";
json += "\"temperature\":" + String(temperature, 2) + ",";
json += "\"humidity\":" + String(humidity, 2) + ",";
json += "\"unit\":\"celsius\",";
json += "\"timestamp\":" + String(millis());
json += "}";
server.send(200, "application/json", json);
}
void handleNotFound() {
server.send(404, "text/plain", "404: Not Found");
}
// ========== SENSOR READING ==========
void readSensor() {
if (millis() - lastReadTime >= READ_INTERVAL) {
float h = dht.readHumidity();
float t = dht.readTemperature();
// Check if readings are valid
if (!isnan(h) && !isnan(t)) {
humidity = h;
temperature = t;
Serial.printf("Temperature: %.1f C, Humidity: %.1f%%\n", t, h);
} else {
Serial.println("Failed to read from DHT sensor!");
}
lastReadTime = millis();
}
}
// ========== SETUP ==========
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.println("\n========================================");
Serial.println(" ESP32 Wi-Fi Weather Station Lab");
Serial.println("========================================\n");
// Initialize DHT sensor
dht.begin();
Serial.println("[OK] DHT22 sensor initialized");
// Connect to Wi-Fi
Serial.printf("[..] Connecting to %s", ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 30) {
delay(500);
Serial.print(".");
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Blink while connecting
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n[OK] Wi-Fi connected!");
Serial.print("[OK] IP Address: ");
Serial.println(WiFi.localIP());
digitalWrite(LED_PIN, HIGH); // Solid LED when connected
} else {
Serial.println("\n[!!] Wi-Fi connection failed!");
return;
}
// Set up web server routes
server.on("/", handleRoot);
server.on("/api/data", handleJSON);
server.onNotFound(handleNotFound);
// Start server
server.begin();
Serial.println("[OK] HTTP server started on port 80");
Serial.println("\n========================================");
Serial.printf(" Open: http://%s/\n", WiFi.localIP().toString().c_str());
Serial.println(" API: /api/data (JSON format)");
Serial.println("========================================\n");
}
// ========== MAIN LOOP ==========
void loop() {
server.handleClient(); // Handle incoming HTTP requests
readSensor(); // Read sensor at intervals
}838.2.6 Step 3: Configure the Wokwi Project
In Wokwi, configure the diagram.json file:
{
"version": 1,
"author": "IoT Class Lab",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 0, "left": 0, "attrs": {} },
{ "type": "wokwi-dht22", "id": "dht1", "top": -50, "left": 150, "attrs": {} }
],
"connections": [
[ "esp:TX0", "$serialMonitor:RX", "", [] ],
[ "esp:RX0", "$serialMonitor:TX", "", [] ],
[ "dht1:VCC", "esp:3V3", "red", [] ],
[ "dht1:SDA", "esp:D4", "green", [] ],
[ "dht1:GND", "esp:GND.1", "black", [] ]
],
"dependencies": {}
}838.2.7 Step 4: Run and Test
- Click the Play button to start the simulation
- Watch the Serial Monitor for connection status
- Once connected, Wokwi provides a simulated IP address
- Click the IP address link to open the web page
- Observe temperature and humidity readings updating
838.2.8 Understanding the Code
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085'}}}%%
flowchart LR
subgraph SENSOR["Sensing Layer"]
DHT["DHT22<br/>Temp + Humidity"]
end
subgraph MCU["Processing Layer"]
ESP["ESP32<br/>Read sensor<br/>Run web server<br/>Handle requests"]
end
subgraph NETWORK["Network Layer"]
WIFI["Wi-Fi<br/>802.11 b/g/n"]
HTTP["HTTP Server<br/>Port 80"]
end
subgraph CLIENT["Presentation Layer"]
BROWSER["Web Browser<br/>HTML + CSS"]
API["JSON API<br/>/api/data"]
end
DHT -->|"Digital Signal"| ESP
ESP -->|"Connect"| WIFI
WIFI -->|"TCP/IP"| HTTP
HTTP -->|"GET /"| BROWSER
HTTP -->|"GET /api/data"| API
style DHT fill:#16A085,stroke:#2C3E50,stroke-width:2px,color:#fff
style ESP fill:#2C3E50,stroke:#16A085,stroke-width:2px,color:#fff
style WIFI fill:#E67E22,stroke:#2C3E50,stroke-width:2px,color:#fff
Key Components:
| Component | Purpose |
|---|---|
WiFi.h |
ESP32 Wi-Fi library for network connectivity |
WebServer.h |
Creates HTTP server to handle requests |
DHT.h |
Library to read DHT22 temperature/humidity sensor |
WiFi.begin() |
Initiates connection to Wi-Fi network |
server.on() |
Registers URL routes and handler functions |
server.handleClient() |
Processes incoming HTTP requests |
838.2.9 Challenge Exercises
The DHT library can calculate the “feels like” temperature. Modify the code to:
- Calculate heat index using
dht.computeHeatIndex(temperature, humidity, false) - Display heat index on the web page alongside temperature
- Add a warning message if heat index exceeds 32C
Hint: Add a new variable heatIndex and update both readSensor() and getHTML().
Create a simple history feature:
- Store the last 10 temperature readings in an array
- Create a new endpoint
/api/historythat returns all readings as JSON - Add a simple bar chart to the HTML using CSS
Hint: Use a circular buffer array and update it each read cycle.
Implement an alert system:
- Define HIGH_TEMP and LOW_TEMP thresholds
- Change the web page background color based on temperature:
- Blue if below LOW_TEMP
- Green if normal
- Red if above HIGH_TEMP
- Blink the LED when temperature is outside normal range
Hint: Pass a “status” parameter to the HTML generation function.
Expand the weather station:
- Add a second DHT22 sensor on a different GPIO pin
- Read both sensors and display indoor/outdoor readings
- Calculate the difference between the two
- Add a
/api/compareendpoint with both readings
Hint: Create a second DHT object with a different pin number.
Add professional IoT features:
- Enable mDNS so the device is accessible at
weather.local - Add Over-The-Air (OTA) update capability
- Create a
/settingspage to configure the device name
Hint: Include ESPmDNS.h and ArduinoOTA.h libraries.
838.2.10 Troubleshooting Guide
| Problem | Possible Cause | Solution |
|---|---|---|
| “Failed to read from DHT sensor!” | Incorrect wiring | Check GPIO 4 connection to DHT22 data pin |
| Wi-Fi won’t connect | Wrong credentials | Use “Wokwi-GUEST” with empty password |
| Web page not loading | Server not started | Check Serial Monitor for IP address |
| Readings show NaN | Sensor initialization failed | Ensure dht.begin() is called in setup |
| Page loads but shows 0.0 | First reading not complete | Wait 2+ seconds after boot |
838.3 Exercise 1: Wi-Fi Channel Analysis
Objective: Analyze 2.4 GHz and 5 GHz channel congestion to optimize IoT device placement
Tasks:
- Scan 2.4 GHz Spectrum (simulated or real):
- Use Wi-Fi analyzer app (Wi-Fi Analyzer for Android, NetSpot for PC/Mac)
- Identify all access points on channels 1, 6, 11
- Measure signal strength (RSSI) for each AP
- Calculate channel utilization percentage
- Identify Overlapping Channels:
- Determine which APs cause interference
- Find the least congested channel
- Calculate expected throughput reduction from overlapping APs
- Compare 2.4 GHz vs 5 GHz:
- Scan 5 GHz channels
- Count total APs on each band
- Recommend band selection for IoT devices
- Design Channel Plan:
- For a building with 3 Wi-Fi APs, assign non-overlapping channels
- Account for neighboring networks
- Minimize interference for IoT sensors
838.4 Exercise 2: Wi-Fi Security Audit
Objective: Audit a Wi-Fi network for security vulnerabilities
Tasks:
- Identify Security Weaknesses:
- Scan for WEP/WPA networks (outdated encryption)
- Find APs with default SSIDs
- Detect open networks
- Identify WPS-enabled networks
- Test WPA2/WPA3 Configuration:
- Verify encryption method (CCMP vs TKIP)
- Check if WPA2-Enterprise is available
- Test guest network isolation
- IoT Device Security Assessment:
- Inventory all IoT devices on network
- Identify devices using weak passwords
- Check for HTTP admin panels
- Scan for outdated firmware
- Create Security Improvement Plan:
- Upgrade to WPA3 if supported
- Disable WPS
- Create separate IoT VLAN
838.5 Exercise 3: Wi-Fi Power Consumption Measurement
Objective: Measure and optimize Wi-Fi power consumption for battery-powered IoT sensors
Scenario: ESP32-based temperature sensor sending data every 10 minutes
Tasks:
- Measure Current Draw (use multimeter or power analyzer):
- Wi-Fi connection establishment
- Active transmission
- Wi-Fi modem sleep
- Deep sleep
- Calculate Battery Life:
- Battery: 2x AA (3000 mAh)
- Operating voltage: 3.3V
- Daily cycles: 144 (every 10 minutes)
- Optimize for 1-Year Battery Life:
- Option A: Wi-Fi 4 with standard sleep
- Option B: Wi-Fi 6 with TWT
- Option C: Reduce transmission frequency
Expected Outcome:
Power Consumption Measurement:
====================================
ESP32 Wi-Fi Power States:
1. Deep Sleep: 10 uA
2. Wi-Fi Connecting: 160 mA for 2s
3. Transmitting Data: 120 mA for 1s
4. Wi-Fi Modem Sleep: 15 mA
Daily Power Budget (144 cycles):
====================================
Deep Sleep (23h 48m):
- 23.8h x 0.010 mA = 0.238 mAh
Wi-Fi Connection (144 x 2s):
- 288s x 160 mA / 3600 = 12.8 mAh
Data Transmission (144 x 1s):
- 144s x 120 mA / 3600 = 4.8 mAh
Total Daily: 17.84 mAh/day
Battery Life: 3000 mAh / 17.84 = 168 days
Optimization Strategy:
====================================
Option A: Wi-Fi 4 (current) -> 168 days
Option B: Wi-Fi 6 + TWT -> ~300 days
Option C: 30-minute intervals -> 456 days
Recommended: Option C + Option B
- 30-minute transmission + Wi-Fi 6 TWT
- New daily budget: 6.5 mAh/day
- Battery life: 461 days (1.26 years)
838.6 Exercise 4: Wi-Fi Network Capacity Planning
Objective: Design Wi-Fi infrastructure for a 200-device IoT deployment
Scenario: Office building (2,000 sqm) deploying: - 100x Occupancy sensors (low bandwidth, 2.4 GHz) - 50x Smart lights (medium bandwidth, 2.4 GHz) - 30x Environmental sensors (low bandwidth, 2.4 GHz) - 20x Security cameras (high bandwidth, 5 GHz)
Tasks:
- Calculate Bandwidth Requirements:
- Occupancy sensors: 100 bytes every 5 minutes
- Smart lights: 200 bytes on state change
- Environmental sensors: 500 bytes every 10 minutes
- Cameras: 2 Mbps continuous
- Determine AP Count and Placement:
- Consumer AP capacity: 30-50 devices
- Enterprise AP capacity: 200-500 devices
- Coverage area per AP
- Design VLAN Segmentation:
- VLAN 10: Corporate laptops/phones
- VLAN 20: IoT sensors
- VLAN 30: Security cameras
- VLAN 40: Guest network
- Calculate Total Cost:
- Access points (enterprise-grade)
- PoE switches for AP power
- Controller software
838.7 Lab Summary
In these labs, you practiced:
- Connecting an ESP32 to a Wi-Fi network
- Reading temperature and humidity from a DHT22 sensor
- Creating an HTTP web server on embedded hardware
- Building a responsive web interface with auto-refresh
- Implementing a JSON API endpoint for data integration
- Analyzing Wi-Fi channel congestion
- Planning power budgets for battery-powered devices
- Designing network infrastructure for IoT
838.8 What’s Next
Apply your Wi-Fi knowledge by exploring:
- Wi-Fi Architecture and Mesh - Network topologies and mesh implementations
- Wi-Fi Security - WPA3 and secure provisioning
- MQTT Protocol - IoT messaging over Wi-Fi
- Wi-Fi Overview - Introduction and basics
- Wi-Fi Standards Evolution - 802.11 generations
- Wi-Fi Frequency Bands - Channel planning
- Wi-Fi Power Consumption - Battery optimization
- Wi-Fi Deployment Planning - Capacity and case studies