If you’ve ever built an IoT project with an ESP32, you know the pain of changing your home Wi-Fi or hotspot SSID: every time you switch networks, you have to open Arduino IDE, edit the code, and re-upload it.
That process is slow and frustrating—especially when your ESP32 is already mounted inside a project enclosure.
This tutorial fixes that forever. You’ll learn how to create a dynamic Wi-Fi configuration portal and web dashboard so that users can connect the ESP32 to any network—without re-flashing the firmware.
By the end of this guide, you’ll have:
- A smart Wi-Fi Manager built on ESP32
- A Captive Portal that appears automatically (just like public Wi-Fi)
- A Web Dashboard to view and modify saved SSID/password
- EEPROM-based storage so credentials persist after power cycles
- Zero dependence on Arduino IDE after deployment 🚀
🧠 How It Works
- Startup check:
When the ESP32 powers up, it looks for stored SSID/password in EEPROM or flash memory. - If valid credentials found:
It auto-connects to that network and prints the IP address. - If no credentials or connection fails:
It launches a Wi-Fi Access Point (AP) mode, hosting a small web server. - User connects to that AP (e.g.,
ESP32_Setup) and opens192.168.4.1.
The page lets you type a new SSID and password. - ESP32 saves the data locally, reboots, and connects to the new Wi-Fi—without re-uploading code.
- You can also revisit the dashboard anytime to change credentials manually.
⚙️ Hardware & Software Requirements
Hardware:
- ESP32 Dev Module
- Micro-USB Cable
- Breadboard (optional)
- Power Supply (5 V 2 A recommended)
Software:
- Arduino IDE (2.2 or later)
- ESP32 Board Package
- Libraries:
WiFi.hWebServer.hEEPROM.h
🧩 Circuit Connections
This project doesn’t require external components, but if you want to test visual feedback, connect:
- An LED to GPIO 2 (with 220 Ω resistor) → shows Wi-Fi status
- Optional push-button to GPIO 0 → factory-reset credentials
ESP32 GPIO2 → LED → 220Ω → GND
ESP32 GPIO0 → Push Button → GND
That’s all you need for the hardware setup.
💻 Arduino IDE Setup
- Install the ESP32 board package from the Board Manager.
- Choose your board:
Tools > Board > ESP32 Dev Module. - Set upload speed to 921600 and Flash size to 4 MB.
- Select your COM port.
🔧 Code Structure Overview
Before writing the full sketch, let’s understand the structure:
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#define LED_PIN 2
WebServer server(80);
String ssid, password;
void setup() {
Serial.begin(115200);
EEPROM.begin(512);
pinMode(LED_PIN, OUTPUT);
// Load stored credentials
ssid = readString(0);
password = readString(50);
if (connectWiFi()) {
Serial.println("Connected to WiFi!");
} else {
startAPMode();
}
}
void loop() {
server.handleClient();
}
This skeleton shows three major functions you’ll implement later:
connectWiFi()→ tries saved SSID/passwordstartAPMode()→ starts captive portalreadString()/writeString()→ EEPROM helpers
🧠 EEPROM Memory Concept
The ESP32’s flash can emulate EEPROM. We’ll store:
- SSID (0–49 bytes)
- Password (50–99 bytes)
EEPROM ensures that even if the ESP32 reboots or loses power, credentials remain safe.
🌐 User Experience Preview
Here’s how your final setup will behave:
| Step | Action | What Happens |
|---|---|---|
| 1 | Power on ESP32 | Tries to connect using saved Wi-Fi |
| 2 | If fail | Creates AP “ESP32_Setup” |
| 3 | User connects & opens 192.168.4.1 | Sees web form |
| 4 | User enters SSID + Password | ESP32 saves and reboots |
| 5 | ESP32 connects to new Wi-Fi | Displays IP on Serial Monitor |
| 6 | Dashboard available at new IP | View/change Wi-Fi any time |
🧭 Next Up
In Part 2, we’ll write the complete code for the Wi-Fi Manager Portal, including:
- HTML form for credentials
- WebServer handling
- EEPROM storage and retrieval
- Automatic connection logic
Now that you understand the concept, let’s dive into the complete working code that lets your ESP32 switch Wi-Fi networks anytime — without re-uploading the sketch.
This part covers:
✅ Captive Portal setup
✅ Web form for Wi-Fi credentials
✅ EEPROM storage
✅ Auto reconnect and reboot sequence
💻 Complete Arduino Code
Copy and paste this code into your Arduino IDE 👇
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#define EEPROM_SIZE 200
#define LED_PIN 2
WebServer server(80);
String ssid;
String password;
// --------- Function to Read String from EEPROM ----------
String readStringFromEEPROM(int startAddr) {
String data = "";
char c;
for (int i = startAddr; i < startAddr + 50; i++) {
c = EEPROM.read(i);
if (c == '\0') break;
data += c;
}
return data;
}
// --------- Function to Write String to EEPROM ----------
void writeStringToEEPROM(int startAddr, String data) {
for (int i = 0; i < 50; i++) {
if (i < data.length()) EEPROM.write(startAddr + i, data[i]);
else EEPROM.write(startAddr + i, '\0');
}
EEPROM.commit();
}
// --------- WiFi Connection Function ----------
bool connectWiFi() {
if (ssid == "" || password == "") return false;
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid.c_str(), password.c_str());
int retry = 0;
while (WiFi.status() != WL_CONNECTED && retry < 20) {
delay(500);
Serial.print(".");
retry++;
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.println("✅ Connected to WiFi!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
digitalWrite(LED_PIN, HIGH);
return true;
} else {
Serial.println("❌ Connection Failed!");
return false;
}
}
// --------- Captive Portal Web Form ----------
void handleRoot() {
String html = "<html><head><title>ESP32 WiFi Manager</title></head><body>";
html += "<h2>WiFi Configuration Portal</h2>";
html += "<form action='/save' method='POST'>";
html += "SSID:<br><input type='text' name='ssid'><br>";
html += "Password:<br><input type='password' name='pass'><br><br>";
html += "<input type='submit' value='Save'>";
html += "</form></body></html>";
server.send(200, "text/html", html);
}
// --------- Save Credentials ----------
void handleSave() {
String newSSID = server.arg("ssid");
String newPass = server.arg("pass");
if (newSSID.length() > 0 && newPass.length() > 0) {
writeStringToEEPROM(0, newSSID);
writeStringToEEPROM(50, newPass);
server.send(200, "text/html", "<h3>✅ Saved! Rebooting...</h3>");
delay(2000);
ESP.restart();
} else {
server.send(200, "text/html", "<h3>❌ Invalid Input! Try Again.</h3>");
}
}
// --------- Start AP Mode for WiFi Config ----------
void startAPMode() {
Serial.println("🔄 Starting Access Point...");
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP32_Setup", "12345678");
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
server.on("/", handleRoot);
server.on("/save", handleSave);
server.begin();
digitalWrite(LED_PIN, LOW);
Serial.println("🌐 Web Portal Ready. Connect to 'ESP32_Setup' and open 192.168.4.1");
}
// --------- Setup ----------
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
EEPROM.begin(EEPROM_SIZE);
ssid = readStringFromEEPROM(0);
password = readStringFromEEPROM(50);
Serial.println("Stored SSID: " + ssid);
Serial.println("Stored Password: " + password);
if (!connectWiFi()) {
startAPMode();
}
}
// --------- Loop ----------
void loop() {
server.handleClient();
}
🔍 Code Explanation
Let’s break down the main parts of this sketch:
🧠 EEPROM Functions
We use two functions:
readStringFromEEPROM()→ retrieves SSID and password from memory.writeStringToEEPROM()→ saves new credentials permanently.
EEPROM is initialized with EEPROM.begin(200) to allocate 200 bytes.
🌐 WebServer & Captive Portal
We use the WebServer library to host a small HTML page.
When the user connects to ESP32_Setup, they can open 192.168.4.1 and see a simple Wi-Fi setup page.
Once they hit Save, credentials are stored and the ESP restarts.
🔁 Smart Boot Logic
On startup:
- If saved SSID/password exist → try connecting.
- If connection fails → create a new Access Point (
ESP32_Setup).
This ensures your ESP32 never gets stuck offline.
💡 LED Indicator
You can connect an LED to GPIO 2:
- ON = Connected to Wi-Fi
- OFF = Access Point mode
It’s optional but helpful for debugging.
📶 How the Captive Portal Works
When the ESP32 fails to connect to Wi-Fi, it automatically enters AP mode:
- Creates a local network
ESP32_Setup - Assigns itself an IP
192.168.4.1 - Hosts the configuration page
You can connect your mobile or laptop to that Wi-Fi and open the portal.
Now that your ESP32 can save and switch Wi-Fi credentials dynamically, it’s time to add a Web Dashboard to manage, monitor, and reset the connection directly from a browser.
In this part, you’ll learn how to:
✅ Build a modern dashboard to show Wi-Fi details
✅ Add Reset/Erase buttons for saved credentials
✅ Display current connection strength (RSSI)
✅ Host the dashboard directly from ESP32’s flash memory
💻 Dashboard Overview
Your dashboard will include:
- Wi-Fi Network Name
- Signal Strength
- Connection Status (Connected / Disconnected)
- Local IP Address
- “Change Wi-Fi” Button to launch Captive Portal again
- “Erase Credentials” Button to delete stored SSID and password
When accessed through a browser, it will look something like this 👇
--------------------------------------------
🌐 ESP32 WiFi Manager Dashboard
--------------------------------------------
📡 Network: My_Home_WiFi
📶 Signal: -45 dBm
✅ Status: Connected
💻 IP: 192.168.0.112
[Change Wi-Fi] [Erase Credentials]
--------------------------------------------
🧠 Adding the Dashboard Page in Code
We’ll extend our previous sketch and add new routes for:
/dashboard→ main page showing Wi-Fi info/reset→ to clear saved credentials
Here’s the updated code section 👇
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#define EEPROM_SIZE 200
#define LED_PIN 2
WebServer server(80);
String ssid, password;
// Function Declarations
String readStringFromEEPROM(int startAddr);
void writeStringToEEPROM(int startAddr, String data);
bool connectWiFi();
void startAPMode();
// ----------- NEW FUNCTION: Erase Credentials -----------
void eraseCredentials() {
for (int i = 0; i < 100; i++) EEPROM.write(i, '\0');
EEPROM.commit();
server.send(200, "text/html", "<h3>🧹 Credentials Erased! Rebooting...</h3>");
delay(2000);
ESP.restart();
}
// ----------- NEW FUNCTION: Show Dashboard -----------
void handleDashboard() {
String html = "<html><head><title>ESP32 WiFi Dashboard</title>";
html += "<style>body{font-family:Arial;text-align:center;background:#101010;color:#00FF99;}</style></head><body>";
html += "<h2>🌐 ESP32 Wi-Fi Manager Dashboard</h2>";
if (WiFi.status() == WL_CONNECTED) {
html += "<p><b>Network:</b> " + WiFi.SSID() + "</p>";
html += "<p><b>IP Address:</b> " + WiFi.localIP().toString() + "</p>";
html += "<p><b>Signal Strength:</b> " + String(WiFi.RSSI()) + " dBm</p>";
html += "<p><b>Status:</b> ✅ Connected</p>";
} else {
html += "<p><b>Status:</b> ❌ Disconnected</p>";
}
html += "<br><button onclick=\"location.href='/'\">Change Wi-Fi</button>";
html += "<button onclick=\"location.href='/reset'\">Erase Credentials</button>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// ----------- Handle Root Page (WiFi Setup) -----------
void handleRoot() {
String html = "<html><head><title>WiFi Setup</title></head><body>";
html += "<h2>ESP32 WiFi Setup</h2>";
html += "<form action='/save' method='POST'>";
html += "SSID:<br><input type='text' name='ssid'><br>";
html += "Password:<br><input type='password' name='pass'><br><br>";
html += "<input type='submit' value='Save Wi-Fi'>";
html += "</form>";
html += "<br><a href='/dashboard'>Go to Dashboard</a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// ----------- Update AP Mode -----------
void startAPMode() {
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP32_Setup", "12345678");
IPAddress IP = WiFi.softAPIP();
Serial.print("Access Point started at: ");
Serial.println(IP);
server.on("/", handleRoot);
server.on("/save", handleSave);
server.on("/dashboard", handleDashboard);
server.on("/reset", eraseCredentials);
server.begin();
Serial.println("🌐 Configuration Portal is active!");
}
💡 What’s New in This Part
🖥️ 1. Dashboard Page
The /dashboard route displays real-time network data (SSID, RSSI, IP).
It uses WiFi.RSSI() to show signal strength.
🧹 2. Erase Credentials
/reset clears all stored SSID and password values in EEPROM.
After reboot, ESP32 starts in Access Point mode again — ready for new Wi-Fi credentials.
🔄 3. Navigation Links
The dashboard links back to the setup page, so users can easily switch between pages without code re-uploading.
📲 How to Test the Dashboard
- Upload the full code to your ESP32.
- Connect to your configured Wi-Fi or to the
ESP32_Setupaccess point. - Open your browser and enter the device IP (e.g.
192.168.4.1or assigned IP). - You’ll see the dashboard interface with connection details.
- Try clicking:
- Change Wi-Fi: Opens setup form.
- Erase Credentials: Clears memory and reboots ESP32.
✅ Result: A fully functional Web Dashboard + Wi-Fi Manager inside your ESP32!
🧠 Next Up
In Part 4, we’ll:
- Discuss real-world use cases
- Add OTA updates for firmware upgrades
- Share troubleshooting tips
- Explore advanced automation use
🌍 1. Real-World Applications
This dynamic Wi-Fi Manager system isn’t just a cool experiment — it’s used in many commercial and professional IoT devices. Here are some examples:
🏠 Smart Home Devices
You can integrate this code into:
- Smart plugs or lights
- Smart switches and fans
- IoT-enabled sensors (temperature, water level, etc.)
When a user installs your device, they simply connect to the ESP32 setup network and configure Wi-Fi — just like setting up a smart bulb!
🏢 Industrial IoT Systems
Industries often move devices between different Wi-Fi networks.
This system allows technicians to update network credentials without using a laptop or programming cable — saving massive setup time.
🚜 Remote Agricultural Monitoring
For ESP32-based soil sensors, weather stations, or irrigation controllers — being able to change Wi-Fi remotely helps when relocating devices or updating access points.
🚀 DIY & Learning Projects
Students and developers can integrate this same logic into their prototypes — giving them professional-grade configuration capability like real IoT appliances.
⚙️ 2. Adding OTA (Over-the-Air) Updates
You can expand your project to allow firmware updates over Wi-Fi without connecting ESP32 to a PC.
Here’s a quick snippet to enable OTA:
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#include <ESPmDNS.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
void setup() {
Serial.begin(115200);
EEPROM.begin(200);
pinMode(2, OUTPUT);
// Connect to stored WiFi
ssid = readStringFromEEPROM(0);
password = readStringFromEEPROM(50);
WiFi.begin(ssid.c_str(), password.c_str());
// OTA Setup
ArduinoOTA.onStart([]() { Serial.println("Start updating..."); });
ArduinoOTA.onEnd([]() { Serial.println("\nUpdate Complete!"); });
ArduinoOTA.begin();
}
void loop() {
ArduinoOTA.handle(); // Keep OTA listening
}
✅ With this feature, you can upload new firmware via Wi-Fi, directly from the Arduino IDE or your web dashboard — no USB cable needed!
📡 3. Improving Security
While this project is easy to use, real IoT applications should have:
- Password protection for setup and dashboard pages
- HTTPS/TLS encryption (possible via ESP32 SSL libraries)
- Token-based authentication with Firebase or MQTT brokers
- Hidden AP credentials to prevent unauthorized access
Adding a login page to your portal (using HTML + JavaScript) is highly recommended for production devices.
💾 4. Expanding Storage (Preferences Library)
Instead of EEPROM, you can use the Preferences library — a modern alternative that allows saving data as key-value pairs, and offers more stability.
Example:
#include <Preferences.h>
Preferences preferences;
preferences.begin("wifi", false);
preferences.putString("ssid", "MyWiFi");
preferences.putString("pass", "12345678");
preferences.end();
This is safer for long-term projects, as EEPROM has limited write cycles.
🧠 5. Troubleshooting Common Issues
Let’s go over a few common problems and how to fix them:
| Issue | Possible Cause | Solution |
|---|---|---|
| ESP32 not connecting to Wi-Fi | Incorrect SSID or password | Double-check your credentials and case sensitivity |
| Web portal not loading | Wrong IP address | Try 192.168.4.1 or check the Serial Monitor |
| Wi-Fi not reconnecting after power loss | EEPROM not initialized correctly | Ensure EEPROM.begin(200) is called in setup |
| Captive portal doesn’t appear | DNS not redirecting | Open browser manually and enter 192.168.4.1 |
| Device reboots repeatedly | Memory overflow or bad save | Clear EEPROM using /reset route |
💡 Tip: Always test using your mobile hotspot before deploying in routers with firewalls or MAC filters.
🧩 6. Future Upgrades
Once you’re comfortable with the basics, you can expand this project into a complete IoT configuration suite. Here are a few upgrade ideas:
🔗 A. Firebase Integration
Add Firebase database code so that your ESP32 automatically uploads Wi-Fi status and sensor data to the cloud.
📱 B. Mobile-Friendly Dashboard
Design a responsive HTML page using Bootstrap or TailwindCSS for a better mobile experience.
🔔 C. Real-Time Monitoring
Include sensor data (like temperature, humidity, or relay status) in your web dashboard — updating in real time using AJAX.
⚡ D. Multi-Device Configuration
Store multiple Wi-Fi networks in memory and let ESP32 automatically switch between them if one fails.
🧭 E. MQTT Compatibility
Use MQTT for fast, lightweight data transfer between your ESP32 and a cloud broker (like HiveMQ or Adafruit IO).
🎯 7. Key Highlights Recap
| Feature | Description |
|---|---|
| Wi-Fi Manager | Change network anytime without re-uploading code |
| Web Dashboard | Manage connections and view signal status |
| EEPROM Storage | Saves credentials permanently |
| Captive Portal | Easy setup via mobile or laptop |
| OTA Update | Upload new code wirelessly |
| Reset Function | Erase stored data anytime |
🏁 8. Final Thoughts
With this project, you’ve turned your ESP32 into a professional-grade IoT device that’s flexible, portable, and user-friendly.
No more hardcoding SSIDs, no more manual reprogramming — just connect, configure, and control.
This setup is the foundation of every real-world IoT product, whether it’s:
- A smart home automation system,
- A remote weather station,
- Or an industrial monitoring unit.
You’ve built something that’s not only educational but deployable.
So go ahead — integrate it into your next IoT project, add your own dashboard styling, and make your ESP32 truly smart!
🎥 Full Tutorial: Watch the complete working video and demo on YaranaIoT Guru YouTube Channel for live setup, troubleshooting, and dashboard walkthroughs.
📞 Contact YaranaIoT Guru Empowering IoT Innovation | ESP32 | Home Automation | Smart Solutions | 50K+ Community
We’d love to hear from you! Whether it’s IoT project queries, collaborations, tech support, custom PCB design, bulk orders, corporate training, college workshops, or freelance development — we’re just one message away.
✉️ Email (Official)
For detailed inquiries, project support, business collaboration, sponsorships, or documentation: 📩 contact@yaranaiotguru.in 📧 Alternate: support@yaranaiotguru.in ⏳ Response: Within 24 hours (Mon–Sat) 💡 Best for attachments (code, schematics, logs, etc.)
📱 Phone / WhatsApp (24×7 Support)
Instant live help, troubleshooting, project consultation, or order updates: 📞 +91 70527 22734 💬 WhatsApp: Chat Now ⏰ Call Hours: Mon–Sat, 10 AM – 7 PM IST 🚀 Emergency? WhatsApp anytime — reply within 1 hour
🌐 Official Website
Tutorials, code, PDFs, schematics, blogs, free tools & online store: 🔗 www.yaranaiotguru.in 🛒 Shop: yaranaiotguru.in/shop (ESP32 DevKits, Sensors, Relays, Custom PCBs, Project Kits)
▶️ YouTube Channel
Step-by-step IoT builds, live coding, ESP32, Blynk, Node-RED, MQTT, Home Assistant & more: 🔗 Yarana IoT Guru 📺 1,200+ Videos | 52K+ Subs | 5.5M+ Views | 4.8★ Rating 🎥 New Video Every Week — 🔔 Subscribe & Turn On Notifications
🛠 GitHub (100% Open Source)
All codes, Arduino sketches, PlatformIO projects, Node-RED flows, MQTT configs & docs: 🔗 github.com/YaranaIotGuru ⭐ 50+ Repos | 10K+ Stars & Forks
🔥 Top Projects:
- ESP32 WebSocket Real-Time Dashboard
- Smart Home with Blynk & Alexa
- IoT Irrigation System with Soil Moisture
- MQTT + Node-RED + MySQL Logging
- OLED Weather Station with API
Daily reels, quick tips, live builds, student showcases & giveaways: 🔗 @YaranaIoTGuru 📱 10K+ Followers | Reels | Stories | Live Sessions
💼 LinkedIn (Professional Network)
B2B, IoT consulting, training, hiring & partnerships: 🔗 Yarana IoT Guru
🤝 Services Offered:
- Custom IoT Product Development
- Embedded Systems Training
- College Workshops & FDPs
- PCB Design & Prototyping
🐦 Twitter / X
Real-time updates, polls, project launches & community Q&A: 🔗 @YaranaIoTGuru 📢 Follow for instant alerts
🛠 Hackster.io (Project Showcases)
In-depth write-ups, circuits, BOM, code & ratings: 🔗 hackster.io/yaranaiotguru 🏆 50+ Projects | 100K+ Views | Top 5% Creator
📝 Instructables (DIY Guides)
Beginner-friendly step-by-step guides with templates & troubleshooting: 🔗 instructables.com/member/YaranaIoTGuru
🛠 Featured Guides:
- Automatic Plant Watering System
- Voice-Controlled Home Appliances
- WiFi-enabled Temperature Monitor
📚 Medium Blog
Deep-dive articles, trends, tutorials & career tips in embedded systems: 🔗 medium.com/@yaranaiotguru ✍️ 50+ Articles | 15K+ Readers
🛒 Online Store & Kits
Ready-to-use IoT kits, custom PCBs, sensors & merch: 🔗 yaranaiotguru.in/shop 📦 Free Shipping in India above ₹999 💳 Payment: UPI, Card, Wallet, COD
🌟 Community Platforms
| Platform | Link | Purpose |
|---|---|---|
| Telegram Channel | t.me/YaranaIoTGuru | Project files, PDFs, updates |
| Telegram Group | t.me/YaranaIoTCommunity | Peer support, doubts |
| Discord Server | discord.gg/yarana-iot | Live voice help, coding rooms |
| WhatsApp Community | Join Here | Announcements & polls |
🏢 Office & Studio Address
Yarana Studio & Software (Yarana IoT Guru HQ) 📍 Near Rookh Baba Mandir, Umariya Badal Urf Gainda, Allahabad (Prayagraj), Uttar Pradesh – 212507, India ⭐ Google Rating: 5.0 ★ (100+ Reviews)
🕒 Opening Hours: Mon–Sat: 10:00 AM – 5:00 PM Sunday: Closed
🌐 Associated Website: yaranawebtech.in 🗺️ View on Google Maps: Search “Yarana Studio & Software” 📌 Walk-ins welcome | Appointment recommended for project discussions