How to Set Up WiFi on ESP32 with Access Point Mode and Web Server

Protonest IoT
5 min readJul 10, 2024

--

In this tutorial, we’ll guide you through creating an ESP32 project that allows users to configure WiFi settings via a web interface in Access Point (AP) mode.

Users can input their WiFi credentials, which will be saved on the ESP32 and used for subsequent connections. The system also includes a physical button to switch back to AP mode for reconfiguration if needed.

Components Needed

Step-by-Step Guide

Setting Up the Hardware

Make the circuit as follows,

Code

Create a file named ‘WiFiRebooter.ino’ with the following content,

#include <WiFi.h>
#include <WiFiClient.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <DNSServer.h>

const char* AP_SSID = "ESP32-AP";
const char* AP_PASSWORD = "12345678";
const int APButtonPin = 5;
const int statusLedPin = 2;
const int connStatusLedPin = 4;

AsyncWebServer server(80);
DNSServer dnsServer;

bool apMode = false;
bool apModeTrigger = false;

String ssid, pass;

void IRAM_ATTR handleButtonPress() {
apModeTrigger = true;
}

void setup() {
Serial.begin(115200);

pinMode(APButtonPin, INPUT_PULLUP);
pinMode(statusLedPin, OUTPUT);
pinMode(connStatusLedPin, OUTPUT);

attachInterrupt(digitalPinToInterrupt(APButtonPin), handleButtonPress, FALLING);

if (!SPIFFS.begin(true)) {
Serial.println("SPIFFS Mount Failed");
return;
}

ssid = readFile("/ssid.txt");
pass = readFile("/pass.txt");

if (ssid == "" || pass == "") {
startAPMode();
} else {
connectToWiFi();
}
}

void loop() {
if (apModeTrigger) {
detachInterrupt(APButtonPin); // Detach interrupt to avoid multiple triggers
Serial.println("AP Mode Triggered by Button Press");
startAPMode();
apModeTrigger = false;
attachInterrupt(digitalPinToInterrupt(APButtonPin), handleButtonPress, FALLING);
}
}

void connectToWiFi() {
WiFi.begin(ssid.c_str(), pass.c_str());

unsigned long startAttemptTime = millis();

while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
digitalWrite(connStatusLedPin, millis() % 1000 < 500 ? HIGH : LOW);
delay(100);
}

if (WiFi.status() == WL_CONNECTED) {
digitalWrite(connStatusLedPin, HIGH);
Serial.println("Connected to WiFi");
startWebServer();
} else {
Serial.println("Failed to connect to WiFi, starting AP mode");
startAPMode();
}
}

void startAPMode() {
apMode = true;
WiFi.softAP(AP_SSID, AP_PASSWORD);

dnsServer.start(53, "*", WiFi.softAPIP());

digitalWrite(statusLedPin, HIGH); // Turn on status LED in AP mode

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});

server.on("/", HTTP_POST, [](AsyncWebServerRequest *request){
int params = request->params();
for (int i = 0; i < params; i++) {
AsyncWebParameter* p = request->getParam(i);
if (p->name() == "ssid") {
ssid = p->value();
}
if (p->name() == "pass") {
pass = p->value();
}
}
saveCredentials();
request->send(200, "text/plain", "Credentials saved. Restarting...");
delay(3000);
ESP.restart();
});

server.begin();
Serial.println("AP Mode Started");
Serial.print("AP SSID: ");
Serial.println(AP_SSID);
Serial.print("AP IP Address: ");
Serial.println(WiFi.softAPIP());
}

void startWebServer() {
digitalWrite(statusLedPin, LOW); // Turn off status LED when in station mode

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
server.begin();
Serial.println("Web Server Started in Station Mode");
Serial.print("ESP32 IP Address: ");
Serial.println(WiFi.localIP());
}

String readFile(const char* path) {
File file = SPIFFS.open(path);
if (!file || file.isDirectory()) {
return String();
}
String content = file.readString();
file.close();
return content;
}

void saveCredentials() {
writeFile("/ssid.txt", ssid.c_str());
writeFile("/pass.txt", pass.c_str());
}

void writeFile(const char* path, const char* message) {
File file = SPIFFS.open(path, FILE_WRITE);
if (!file) {
return;
}
file.print(message);
file.close();
}

Creating the HTML Interface

Create a file named ‘index.html’ in a folder named ‘data’ (if using Arduino IDE). This HTML file will be served by the ESP32 when in AP mode.

<!DOCTYPE html>
<html>
<head>
<title>ESP32 WiFi Configuration</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background-color: #fff;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 10px;
text-align: center;
width: 300px;
}
h2 {
color: #333;
}
label {
display: block;
margin: 10px 0 5px;
color: #555;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 10px;
margin: 5px 0 20px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}
input[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
input[type="submit"]:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h2>ESP32 WiFi Configuration</h2>
<form action="/" method="POST">
<label for="ssid">SSID:</label>
<input type="text" id="ssid" name="ssid" required>
<label for="pass">Password:</label>
<input type="password" id="pass" name="pass" required>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>

How the file system should look,

Uploading Files to SPIFFS

Using Arduino IDE

Installing the Libraries

  1. Download the Required Libraries
  • Download the following libraries from Google Drive:

Libraries for running the code

2. Add Libraries to the Arduino IDE

  • Extract the downloaded ZIP files.
  • Copy the extracted folders to your Arduino libraries folder. This is usually located at ‘Documents/Arduino/libraries’

Uploading the Code

Note: Use 2.0.15 version for esp32 borad

After uploading the spiffs, you need to upload the code using the upload button on the Arduino IDE.

  • Initial Setup: When the ESP32 starts for the first time, it will enter AP mode if it doesn’t find the ‘ssid.txt’ and ‘pass.txt’ files.
  • Connect to AP: Connect to the “ESP32-AP” network using the password “12345678”.
  • Enter Credentials: Open a browser and navigate to ‘192.168.4.1’. You will see the enhanced web page for inputting the Wi-Fi SSID and password.
  • Save Credentials: Enter your Wi-Fi credentials and submit the form. The ESP32 will save these credentials and restart, attempting to connect to the specified network.
  • Switch to AP Mode on Demand: Press the button connected to GPIO 5 to switch back to AP mode. The serial monitor will show “AP Mode Triggered by Button Press” and display the AP SSID and IP address.

With this setup, the ESP32 can be easily configured to connect to different Wi-Fi networks without hardcoding the credentials.

The AP mode provides a convenient way to input and save new credentials through a web interface, making the device more flexible and user-friendly.

Contact us for any consultations or projects related to IoT

Email: udara@protonest.co

Protonest for more details.

Protonest specializes in transforming IoT ideas into reality. We offer prototyping services from concept to completion. Our commitment ensures that your visionary IoT concepts become tangible, innovative, and advanced prototypes.

Our Website: https://www.protonest.co/

If you enjoyed this article and would like to show some support, consider buying me a coffee on Ko-Fi.

Your support not only helps me keep creating content like this but also fuels me! ☕️📚

Thank you for being an amazing reader!

Here’s my Ko-Fi link: https://ko-fi.com/udarakumarasena

Cheers!

--

--

Protonest IoT
Protonest IoT

Written by Protonest IoT

We make your IoT ideas a reality

Responses (1)