44 Wi-Fi Implementation: ESP32 Basics
Sensor Squad: ESP32 Wi-Fi Basics
Sammy the Sensor was learning to connect to Wi-Fi for the very first time, and Max the Microcontroller was his teacher!
“There are THREE ways to use Wi-Fi,” Max explained. “Station Mode is like being a student joining a classroom – you connect to an existing Wi-Fi network (the router is the teacher). Access Point Mode is like BEING the teacher – you create your own Wi-Fi network and other devices connect to you! And scanning is like peeking into every classroom to see what is available.”
“Why would I want to BE a Wi-Fi network?” asked Sammy. Max replied: “Imagine you are a brand-new smart light bulb with no screen or keyboard. How does your owner tell you the home Wi-Fi password? You create a temporary AP called ‘SmartBulb-Setup,’ the owner connects their phone to it, types the real Wi-Fi password into a web page, and then you switch to Station Mode!”
Bella the Battery added a warning: “NEVER put the Wi-Fi password directly in your code! If someone reads your code on GitHub, they get your password. Use SmartConfig or SoftAP provisioning to send credentials SEPARATELY from the firmware.”
44.1 Learning Objectives
By the end of this chapter, you will be able to:
- Construct ESP32 Station Mode firmware that connects to existing Wi-Fi networks with timeout handling and auto-reconnect logic
- Design Access Point configurations that create device-hosted Wi-Fi hotspots for provisioning and local control
- Evaluate Wi-Fi scan results by interpreting RSSI, channel overlap, and security protocol data to select optimal networks
- Diagnose connection failures using Wi-Fi status codes and implement exponential-backoff reconnection strategies
- Contrast provisioning methods (SmartConfig, SoftAP captive portal, BLE) and justify which approach fits a given deployment scenario
For Beginners: Getting Started with ESP32 Wi-Fi
What is this chapter? Practical ESP32 Wi-Fi programming including station mode, access point mode, and network scanning.
When to use:
- When building your first Wi-Fi-connected IoT device
- When you need to configure Wi-Fi on ESP32/ESP8266
- Before implementing more complex Wi-Fi applications
Key Topics:
| Topic | Application |
|---|---|
| Station Mode | Connect device to existing network |
| AP Mode | Create device hotspot |
| Network Scanning | Discover available networks |
| SmartConfig | Provision credentials wirelessly |
Prerequisites:
- Wi-Fi fundamentals knowledge
- Basic C/C++ programming
- Understanding of TCP/IP basics
44.2 Prerequisites
Before diving into this chapter, you should be familiar with:
- Wi-Fi Fundamentals and Standards: Understanding Wi-Fi standards, frequency bands, and basic Wi-Fi characteristics
- Wi-Fi Architecture and Mesh: Knowledge of infrastructure mode, Wi-Fi Direct, and mesh networking
- C/C++ Programming: Basic programming skills for ESP32 code examples
Key Concepts
- ESP32 Wi-Fi Architecture: Dual-core MCU with integrated 802.11b/g/n radio, TCP/IP stack, TLS library, and MQTT client
- Station Mode (STA): ESP32 connects to an existing Wi-Fi network as a client device; the standard mode for IoT sensors
- Access Point Mode (AP): ESP32 creates its own Wi-Fi hotspot; used for provisioning or direct device-to-device communication
- STA+AP Mode: Simultaneous station and access point; ESP32 connects to router while hosting a configuration portal
- ESP-IDF Wi-Fi API: Event-based Wi-Fi management API; esp_wifi_init(), esp_wifi_start(), WiFiEventGroup for synchronization
- DHCP Client: Automatic IP address assignment from router; alternatively use static IP for faster connection and deterministic addressing
- Wi-Fi Security: WPA2-PSK (TKIP/CCMP) and WPA3-SAE; never use open or WEP networks for production IoT devices
- NVS (Non-Volatile Storage): Flash-based key-value store for persisting Wi-Fi credentials and device configuration across reboots
44.3 Hands-on: ESP32 Wi-Fi Configuration
44.3.1 Basic Wi-Fi Connection
// ESP32 Wi-Fi Station Mode - Basic Connection
#include <Wi-Fi.h>
// Wi-Fi credentials
const char* ssid = "YourNetworkSSID";
const char* password = "YourPassword";
void setup() {
Serial.begin(115200);
delay(1000);
// Connect to Wi-Fi
Serial.println("Connecting to Wi-Fi...");
Wi-Fi.mode(WIFI_STA); // Station mode
Wi-Fi.begin(ssid, password);
// Wait for connection
int attempts = 0;
while (Wi-Fi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (Wi-Fi.status() == WL_CONNECTED) {
Serial.println("\nWi-Fi connected!");
Serial.print("IP address: ");
Serial.println(Wi-Fi.localIP());
Serial.print("MAC address: ");
Serial.println(Wi-Fi.macAddress());
Serial.print("Signal strength (RSSI): ");
Serial.print(Wi-Fi.RSSI());
Serial.println(" dBm");
} else {
Serial.println("\nFailed to connect to Wi-Fi");
}
}
void loop() {
// Check Wi-Fi connection status
if (Wi-Fi.status() != WL_CONNECTED) {
Serial.println("Wi-Fi disconnected! Reconnecting...");
Wi-Fi.reconnect();
}
delay(10000);
}
Security Note
These examples inline SSID/password for clarity. For production IoT, avoid hardcoding credentials: use a provisioning flow (BLE/SoftAP/SmartConfig as appropriate) and store credentials in NVS protected by flash encryption/secure boot where supported. See Wi-Fi Security and Provisioning.
Putting Numbers to It
RSSI signal quality interpretation:
Convert RSSI (dBm) to quality percentage for UI visualization:
\[\text{Quality} = \begin{cases} 100\% & \text{RSSI} \geq -50\ \text{dBm} \\ 2 \times (\text{RSSI} + 100) & -100 \leq \text{RSSI} < -50 \\ 0\% & \text{RSSI} < -100\ \text{dBm} \end{cases}\]
Examples:
- RSSI = -45 dBm: \(Q = 100\%\) (Excellent)
- RSSI = -60 dBm: \(Q = 2 \times (-60 + 100) = 80\%\) (Good)
- RSSI = -75 dBm: \(Q = 2 \times (-75 + 100) = 50\%\) (Fair)
- RSSI = -90 dBm: \(Q = 2 \times (-90 + 100) = 20\%\) (Poor)
- RSSI = -105 dBm: \(Q = 0\%\) (Critical)
Putting Numbers to It (continued)
Distance estimation (2.4 GHz, free space):
Using FSPL formula: \[d = 10^{\frac{\text{FSPL} + 147.55 - 20\log_{10}(f)}{20}}\]
For \(f = 2400\) MHz, TX power +17 dBm, RX antenna gain 2 dBi:
- RSSI -60 dBm: \(\text{FSPL} = 17 + 2 - (-60) = 79\ \text{dB}\) → \(d \approx 15\ \text{m}\)
- RSSI -75 dBm: \(\text{FSPL} = 94\ \text{dB}\) → \(d \approx 50\ \text{m}\)
Interactive Simulator: ESP32 Wi-Fi Connection
Try it yourself! See how ESP32 connects to Wi-Fi networks and retrieves network information.
What This Simulates: An ESP32 connecting to a Wi-Fi network in Station (STA) mode, displaying connection status, IP address, and signal strength.
How to Use:
- Click Start Simulation
- Watch the Serial Monitor show connection progress
- Observe the Wi-Fi connection status LEDs
- See the IP address assignment (DHCP)
- Monitor signal strength (RSSI) readings
- Try modifying credentials to see connection failures
44.3.2 Wi-Fi with Auto-Reconnect
// ESP32 Wi-Fi with Automatic Reconnection
#include <Wi-Fi.h>
const char* ssid = "YourSSID";
const char* password = "YourPassword";
void connectWiFi() {
if (Wi-Fi.status() != WL_CONNECTED) {
Serial.print("Connecting to Wi-Fi");
Wi-Fi.begin(ssid, password);
int timeout = 0;
while (Wi-Fi.status() != WL_CONNECTED && timeout < 30) {
delay(500);
Serial.print(".");
timeout++;
}
if (Wi-Fi.status() == WL_CONNECTED) {
Serial.println("\nConnected!");
Serial.println("IP: " + Wi-Fi.localIP().toString());
} else {
Serial.println("\nConnection failed!");
}
}
}
void setup() {
Serial.begin(115200);
// Configure Wi-Fi for low power
Wi-Fi.mode(WIFI_STA);
Wi-Fi.setAutoReconnect(true);
Wi-Fi.persistent(false); // Don't save Wi-Fi config to flash
connectWiFi();
}
void loop() {
// Your IoT logic here
// Periodic connection check
static unsigned long lastCheckMs = 0;
if (millis() - lastCheckMs >= 30000) { // Every 30 seconds
lastCheckMs = millis();
if (Wi-Fi.status() != WL_CONNECTED) {
connectWiFi();
}
}
}44.3.3 Wi-Fi Scanning (Find Available Networks)
// ESP32 Wi-Fi Network Scanner
#include <Wi-Fi.h>
void setup() {
Serial.begin(115200);
Wi-Fi.mode(WIFI_STA);
Wi-Fi.disconnect();
delay(100);
Serial.println("Scanning Wi-Fi networks...");
}
void loop() {
int n = Wi-Fi.scanNetworks();
Serial.println("\n=== Wi-Fi Scan Results ===");
if (n == 0) {
Serial.println("No networks found");
} else {
Serial.printf("Found %d networks:\n", n);
for (int i = 0; i < n; i++) {
Serial.printf("%2d: %-32s ", i + 1, Wi-Fi.SSID(i).c_str());
Serial.printf("(%3d dBm) ", Wi-Fi.RSSI(i));
Serial.printf("CH:%2d ", Wi-Fi.channel(i));
// Security type
switch (Wi-Fi.encryptionType(i)) {
case WIFI_AUTH_OPEN:
Serial.print("[OPEN]");
break;
case WIFI_AUTH_WEP:
Serial.print("[WEP]");
break;
case WIFI_AUTH_WPA_PSK:
Serial.print("[WPA]");
break;
case WIFI_AUTH_WPA2_PSK:
Serial.print("[WPA2]");
break;
case WIFI_AUTH_WPA_WPA2_PSK:
Serial.print("[WPA/WPA2]");
break;
#ifdef WIFI_AUTH_WPA2_WPA3_PSK
case WIFI_AUTH_WPA2_WPA3_PSK:
Serial.print("[WPA2/WPA3]");
break;
#endif
#ifdef WIFI_AUTH_WPA3_PSK
case WIFI_AUTH_WPA3_PSK:
Serial.print("[WPA3]");
break;
#endif
case WIFI_AUTH_WPA2_ENTERPRISE:
Serial.print("[WPA2-ENT]");
break;
default:
Serial.print("[UNKNOWN]");
}
Serial.println();
}
}
delay(10000); // Scan every 10 seconds
}
Interactive Simulator: Wi-Fi Network Scanner
Try it yourself! See how ESP32 scans and discovers available Wi-Fi networks.
What This Simulates: An ESP32 performing Wi-Fi network scans to discover nearby access points, displaying SSID, signal strength, channel, and security type.
How to Use:
- Click Start Simulation
- Watch the Serial Monitor show discovered networks
- Observe network details: SSID, RSSI (dBm), channel, security
- See how scan results update periodically
- Notice different security protocols (OPEN, WPA2, etc.)
44.3.4 ESP32 as Access Point (Soft AP)
// ESP32 as Wi-Fi Access Point
#include <Wi-Fi.h>
const char* ap_ssid = "ESP32-IoT-AP";
const char* ap_password = "12345678"; // Min 8 characters
void setup() {
Serial.begin(115200);
// Configure Access Point
Wi-Fi.softAP(ap_ssid, ap_password);
IPAddress IP = Wi-Fi.softAPIP();
Serial.println("Access Point Started");
Serial.print("AP IP address: ");
Serial.println(IP);
Serial.print("AP SSID: ");
Serial.println(ap_ssid);
// Optional: Configure AP with more parameters
// Wi-Fi.softAP(ssid, password, channel, hidden, max_connections)
// Wi-Fi.softAP(ap_ssid, ap_password, 6, false, 4);
}
void loop() {
// Check connected clients
Serial.printf("Connected stations: %d\n", Wi-Fi.softAPgetStationNum());
delay(5000);
}
Interactive Simulator: ESP32 Access Point Mode
Try it yourself! See how ESP32 creates its own Wi-Fi network that other devices can connect to.
What This Simulates: An ESP32 running as a Wi-Fi Access Point (Soft AP), allowing other devices to connect and displaying the number of connected clients.
How to Use:
- Click Start Simulation
- Watch the Serial Monitor show AP configuration
- See the AP IP address (typically 192.168.4.1)
- Observe connected station count updates
- Notice the ESP32 becomes a Wi-Fi router!
44.3.5 Wi-Fi Provisioning (SmartConfig)
// ESP32 Wi-Fi Provisioning with SmartConfig
#include <Wi-Fi.h>
void setup() {
Serial.begin(115200);
Wi-Fi.mode(WIFI_STA);
// Start SmartConfig
Serial.println("Starting SmartConfig...");
Serial.println("Use a SmartConfig-compatible app to provide Wi-Fi credentials");
Wi-Fi.beginSmartConfig();
// Wait for SmartConfig completion
while (!Wi-Fi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("\nSmartConfig received!");
Serial.println("Connecting to Wi-Fi...");
// Wait for Wi-Fi connection
while (Wi-Fi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi Connected!");
Serial.print("IP Address: ");
Serial.println(Wi-Fi.localIP());
// Save credentials (optional)
Serial.println("SSID: " + Wi-Fi.SSID());
}
void loop() {
// Your application code
}44.4 Raspberry Pi Wi-Fi Configuration
For a quick overview, see Wi-Fi Fundamentals and Standards. Below are CLI-first options commonly used in IoT deployments.
44.4.1 Option A: NetworkManager (nmcli)
sudo nmcli dev wifi list
sudo nmcli dev wifi connect "<SSID>" password "<PASSWORD>" ifname wlan0
ip -br a show wlan0
ping -c 3 1.1.1.144.4.2 Option B: wpa_supplicant (legacy / minimal images)
Edit /etc/wpa_supplicant/wpa_supplicant.conf:
country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="YourNetworkSSID"
psk="YourPassword"
}WPA2-Enterprise (example; validate server certificates):
network={
ssid="Enterprise-Wi-Fi"
key_mgmt=WPA-EAP
eap=PEAP
identity="username"
password="password"
ca_cert="/etc/ssl/certs/your_ca.pem"
phase2="auth=MSCHAPV2"
}Apply and verify:
sudo wpa_cli -i wlan0 reconfigure
sudo systemctl restart dhcpcd || true
ip -br a show wlan0
iw dev wlan0 link44.4.3 Python Wi-Fi Client (MQTT over Wi-Fi)
# Python Wi-Fi-enabled MQTT IoT Sensor
import paho.mqtt.client as mqtt
import time
import random
# MQTT Configuration
MQTT_BROKER = "192.168.1.100" # Local broker or cloud
MQTT_PORT = 1883
MQTT_TOPIC = "home/sensors/temperature"
# Callback signature for paho-mqtt 2.0+
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code == 0:
print("Connected to MQTT broker via Wi-Fi")
else:
print(f"Connection failed with reason code {reason_code}")
def on_publish(client, userdata, mid):
print(f"Message {mid} published")
# Create MQTT client (paho-mqtt 2.0+ API)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="RaspberryPi-Sensor")
client.on_connect = on_connect
client.on_publish = on_publish
# Connect to broker
try:
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
while True:
# Simulate sensor reading
temperature = round(20 + random.uniform(-5, 5), 2)
# Publish to MQTT
result = client.publish(MQTT_TOPIC, str(temperature))
print(f"Published temperature: {temperature}C (QoS: {result.rc})")
time.sleep(10) # Publish every 10 seconds
except KeyboardInterrupt:
print("\nDisconnecting...")
client.loop_stop()
client.disconnect()
Common Mistake: Hardcoding Wi-Fi Credentials in Production Firmware
The Mistake: A company ships 10,000 smart light bulbs with Wi-Fi credentials hardcoded in the firmware:
const char* ssid = "CompanyTestNetwork";
const char* password = "DevTeam2024!";Six months later, the source code leaks on GitHub during a repository cleanup. Now every customer’s home Wi-Fi password is exposed if they connected their devices to the same network name.
Why This Is Catastrophic:
- Single Password for All Customers: Every device shipped uses identical credentials burned into firmware
- Password Extraction: Firmware can be dumped from any device using SPI flash readers or UART debugging
- Reverse Engineering: Compiled binaries can be analyzed to extract string constants
- Code Leaks: GitHub, GitLab, or internal repository accidents expose credentials permanently
- No Update Path: Changing hardcoded credentials requires firmware update to all 10,000 devices
Real-World Attack Scenario:
- Attacker buys one smart bulb ($20) and extracts firmware using ESP32 flash dumper
- String search finds
const char* ssid = "SmartHome-2024"and password - Attacker now has credentials for thousands of homes that used default network name
- Wardriving campaign identifies homes with the compromised SSID
- Attacker gains network access to steal data, launch attacks, pivot to other devices
The Correct Approach: Never Hardcode Credentials
44.4.4 Method 1: SmartConfig (ESP Touch)
Device creates temporary AP, user sends credentials via smartphone app:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
// No hardcoded credentials
WiFi.mode(WIFI_STA);
WiFi.beginSmartConfig();
Serial.println("Waiting for SmartConfig...");
Serial.println("1. Download ESP Touch app on smartphone");
Serial.println("2. Connect phone to your home Wi-Fi");
Serial.println("3. Open app and enter Wi-Fi password");
Serial.println("4. Device receives credentials securely");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("\nSmartConfig complete!");
Serial.println("Credentials saved to NVS (encrypted storage)");
// Credentials persist across reboots in NVS
WiFi.begin(); // Uses stored credentials
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.print("Connected to: ");
Serial.println(WiFi.SSID());
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}Advantages:
- Zero credentials in source code
- Works with any Wi-Fi network
- Stored in NVS (Non-Volatile Storage) - persists across power cycles
- Each device gets unique network credentials
44.4.5 Method 2: SoftAP Provisioning (Captive Portal)
Device creates temporary hotspot, user configures via web interface. On first boot, ESP32 creates a SmartBulb-Setup AP with a captive portal. Users enter their Wi-Fi credentials through a web form, which are saved to NVS flash for future reconnection.
Expand Full SoftAP Provisioning Code (~86 lines)
#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>
WebServer server(80);
Preferences prefs;
const char* ap_ssid = "SmartBulb-Setup"; // This is safe - temporary AP name
void handleRoot() {
String html = R"(
<!DOCTYPE html>
<html>
<head><title>Wi-Fi Setup</title></head>
<body>
<h1>Smart Bulb Configuration</h1>
<form method='POST' action='/save'>
<label>Your Wi-Fi Network:</label><br>
<input type='text' name='ssid' required><br><br>
<label>Wi-Fi Password:</label><br>
<input type='password' name='password' required><br><br>
<input type='submit' value='Connect'>
</form>
</body>
</html>
)";
server.send(200, "text/html", html);
}
void handleSave() {
String ssid = server.arg("ssid");
String password = server.arg("password");
// Save to encrypted NVS (NOT to source code)
prefs.begin("wifi", false);
prefs.putString("ssid", ssid);
prefs.putString("password", password);
prefs.end();
server.send(200, "text/html", "<h1>Saved! Rebooting...</h1>");
delay(2000);
ESP.restart();
}
void setup() {
Serial.begin(115200);
prefs.begin("wifi", true); // Read-only
String saved_ssid = prefs.getString("ssid", "");
if (saved_ssid == "") {
// First boot - start provisioning AP
WiFi.softAP(ap_ssid);
Serial.println("Provisioning mode - Connect to 'SmartBulb-Setup'");
Serial.print("Open http://");
Serial.println(WiFi.softAPIP());
server.on("/", handleRoot);
server.on("/save", HTTP_POST, handleSave);
server.begin();
while (true) {
server.handleClient();
}
} else {
// Normal operation - connect with stored credentials
WiFi.begin(saved_ssid.c_str(), prefs.getString("password", "").c_str());
prefs.end();
int timeout = 0;
while (WiFi.status() != WL_CONNECTED && timeout < 20) {
delay(500);
timeout++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected!");
} else {
Serial.println("Failed - restarting provisioning");
prefs.begin("wifi", false);
prefs.clear(); // Clear bad credentials
prefs.end();
ESP.restart();
}
}
}Provisioning Flow:
- First Boot: Device creates
SmartBulb-SetupWi-Fi hotspot (no password for setup) - User Connection: Customer connects phone to
SmartBulb-Setup(IP: 192.168.4.1) - Web Configuration: Opens
http://192.168.4.1, enters home Wi-Fi credentials - Credential Storage: ESP32 saves to encrypted NVS (never in source code)
- Normal Operation: Device reboots, connects to home network using stored credentials
44.4.6 Method 3: BLE Provisioning (ESP-IDF)
For devices without web interface, use Bluetooth Low Energy:
#include <WiFiProv.h>
const char* service_name = "PROV_DEVICE";
const char* pop = "abcd1234"; // Proof of possession (shown on device)
void setup() {
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM,
WIFI_PROV_SECURITY_1, pop, service_name);
Serial.println("BLE provisioning started");
Serial.println("1. Download ESP BLE Provisioning app");
Serial.println("2. Scan for 'PROV_DEVICE'");
Serial.println("3. Enter POP code: abcd1234");
Serial.println("4. Select your Wi-Fi network and enter password");
}Security Best Practices:
| Practice | Why It Matters |
|---|---|
| Never Hardcode Credentials | Source code leaks expose all devices |
| Use NVS Encryption | Flash encryption prevents credential extraction |
| Rotate Provisioning Passwords | Unique POP codes per device (print on label) |
| Timeout Provisioning Mode | Auto-exit after 10 minutes to prevent rogue provisioning |
| HTTPS for Web Provisioning | Self-signed certs better than plain HTTP |
| Secure Boot | Prevents unsigned firmware from reading NVS |
Production Deployment Checklist:
Key Insight: Hardcoded credentials are the #1 IoT security vulnerability. The solution is provisioning - every device gets unique credentials from its owner during setup, never from the factory. This eliminates the “one firmware dump compromises all devices” attack vector. The provisioning flow adds 2-3 minutes to customer setup time but provides permanent security. For 10,000-device deployments, this is mandatory, not optional.
Try It Yourself: SmartConfig Provisioning
Goal: Configure Wi-Fi credentials on an ESP32 without hardcoding them in firmware.
Materials Needed:
- ESP32 development board
- Smartphone with ESP Touch app (Android/iOS)
- Arduino IDE with ESP32 board support
Exercise Steps:
Upload SmartConfig Sketch - Load the SmartConfig example from Arduino IDE (
File → Examples → WiFi → WiFiSmartConfig) and upload to ESP32.Enter SmartConfig Mode - Reset the ESP32. The serial monitor should show “Waiting for SmartConfig” (blue LED may blink).
Install ESP Touch App - Download “ESP Touch” or “EspTouch” from your phone’s app store (official Espressif app).
Send Credentials - Open the app, enter your Wi-Fi SSID and password, tap “Confirm”. The app broadcasts encrypted UDP packets containing your credentials.
Observe Connection - The ESP32 should connect within 30-60 seconds. Serial monitor shows “WiFi Connected!” and the device’s assigned IP address.
Verify Persistence - Reset the ESP32. It should reconnect automatically using stored credentials from NVS flash.
Expected Observations:
- First boot: Enters SmartConfig mode (credentials not found in NVS)
- After provisioning: Credentials saved to flash, automatic reconnection on reboot
- Factory reset: Clears NVS, returns to SmartConfig mode
What to Explore:
- How does the app encode credentials in UDP packets?
- What happens if you provision with the wrong password?
- Can you provision multiple ESP32s simultaneously?
Extension: Implement a “factory reset” button that clears NVS credentials when pressed during boot.
Concept Relationships
| Concept | Relates To | Why It Matters |
|---|---|---|
| Station (STA) Mode | Client mode, Connects to existing AP | Standard mode for IoT devices joining home/office networks |
| Access Point (AP) Mode | Server mode, Creates own network | Enables device configuration and local control without router |
| SmartConfig Provisioning | Wireless configuration, Eliminates hardcoded credentials | Securely transfers Wi-Fi credentials from smartphone to device |
| Network Scanning | Site surveys, SSID discovery, Channel analysis | Identifies available networks and signal strength |
| NVS (Non-Volatile Storage) | Credential persistence, Flash storage | Remembers Wi-Fi credentials across reboots |
44.5 See Also
- Wi-Fi Hands-On Labs - Wokwi weather station tutorial
- Wi-Fi Impl Comprehensive Lab - Production patterns
- Wi-Fi Security and Provisioning - WPA3 and secure setup
- ESP32 Programming - ESP32 development guide
Common Pitfalls
1. Not Waiting for IP Address Before Attempting Network Operations
After Wi-Fi connection, the ESP32 receives an IP address via DHCP which takes 100-500 ms. Attempting to make network requests immediately after the “connected” event (before IP assignment) fails silently. Always wait for the WIFI_EVENT_STA_GOT_IP event before starting network communication.
2. Using the Arduino wifi.begin() Blocking Pattern in Production
Arduino’s WiFi.begin() pattern blocks the main loop and ignores events. In ESP-IDF and advanced Arduino development, use the event-driven pattern with proper event groups. Blocking patterns prevent handling other tasks during connection and make reconnection logic fragile.
3. Forgetting to Handle Wi-Fi Disconnection Events
Many ESP32 examples never disconnect. Production devices must handle WIFI_EVENT_STA_DISCONNECTED gracefully — pausing network operations, triggering reconnection with backoff, and buffering sensor data during disconnection. Missing disconnection handling causes the device to hang silently after any Wi-Fi interruption.
4. Ignoring Flash Memory Wear From Frequent NVS Writes
Writing Wi-Fi credentials or connection state to NVS on every connect/disconnect cycle causes excessive flash wear. NVS uses wear leveling but has finite write cycles (~100,000 per page). Write credentials once during provisioning; use RAM variables for transient state during normal operation.
44.6 Summary
This chapter covered the fundamentals of ESP32 Wi-Fi implementation:
- Station Mode Configuration: Connecting ESP32 to existing Wi-Fi networks with connection handling, timeout management, and auto-reconnect logic
- Access Point Mode: Creating ESP32-hosted Wi-Fi networks for device configuration, local control, and mesh networking
- Network Scanning: Discovering available networks with SSID, RSSI, channel, and security information for network selection and site surveys
- SmartConfig Provisioning: Wirelessly configuring Wi-Fi credentials without hardcoding them in firmware
- Raspberry Pi Configuration: Using nmcli and wpa_supplicant for Linux-based IoT Wi-Fi setup
44.7 Knowledge Check
44.8 What’s Next
| If you want to… | Read this |
|---|---|
| Implement HTTP and WebSocket on ESP32 | Wi-Fi HTTP & WebSocket |
| Optimize Wi-Fi power on ESP32 | Wi-Fi Power Optimization |
| Work through comprehensive lab exercises | Wi-Fi Comprehensive Lab |
| Secure your Wi-Fi IoT device | Wi-Fi Security and Provisioning |
| Learn all Wi-Fi IoT implementations | Wi-Fi for IoT: Implementations |