Configuring ESP8266 Wi-Fi Network Connection Through A Web Page

İbrahim Gündüz
8 min readSep 10, 2023

--

ESP8266 is one of the popular Wi-Fi chips with microcontroller capability. In this article, we will touch on a couple of items that are possible to do with ESP8266 and finally, we will see how to configure a WI-FI network connection through a web page working on the chip by bringing all those together.

Table of contents:

Creating A WI-FI Access Point

ESP8266 can operate in station and access point modes. As we need to access a web page to be running on ESP8266, we will see how to run the chip in access point mode first.

In order to configure the WI-FI, we import the ESP8266WiFi library.

#include <ESP8266WiFi.h>

Next, we define an SSID and a password for the Wi-Fi network we’re going to create.

const char *AP_SSID="MyDevice";
const char *AP_PASSWORD="123456789";

And finally, it’s time to start our mini access point.

void setup() {
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID, AP_PASSWORD);
}

Let’s compile the code below and upload it to the development board (In my case, I used a NodeMCU board with an EP8266 chip)

#include <ESP8266WiFi.h>

const char *AP_SSID="MyDevice";
const char *AP_PASSWORD="123456789";

void setup() {
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID, AP_PASSWORD);
}

void loop() {}

As you can see from the following picture, the access point name appears on the list.

Enter the password that we defined in the code to authenticate the network.

And, that’s it! ESP8266Wifi library handles the rest of the network configuration and allows assigning a dynamic IP to the connected client.

You can also manually configure the access point`s network as follows

void setup() {
IPAddress localIp(192, 168, 20, 1);
IPAddress gatewayIp(0, 0, 0, 0);
IPAddress netmask(255, 255, 255, 0);

WiFi.mode(WIFI_AP);
WiFi.softAPConfig(localIp, gatewayIp, netmask);
WiFi.softAP(AP_SSID, AP_PASSWORD);
}

<< Back to top

Connecting A Wi-Fi Network

We can connect to a Wi-Fi network by using the same library. Let’s start by defining the network credentials we’ll connect.

const char * WIFI_SSID = "YourRouterSsid";
const char * WIFI_PASSWORD = "YourWifiPassword";

Connect to the specified network.

WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

As it’s a process that is not immediately happening, we should keep it waiting until connected.

while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

And finally, maybe it’s good to print some information at the end.

  if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected.");
Serial.println(WiFi.localIP());
} else {
Serial.println("Not connected.");
}

Let’s compile the code below and upload it to the development board.

#include <Arduino.h>
#include <ESP8266WiFi.h>

const char * WIFI_SSID = "YourRouterSsid";
const char * WIFI_PASSWORD = "YourWifiPassword";

void setup() {
Serial.begin(9600);
Serial.println("Connecting...");

WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

// Wait until connected
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected.");
Serial.println(WiFi.localIP());
} else {
Serial.println("Not connected.");
}
}

void loop() {}

As you can see from the following picture, it connected to the network and obtained a new IP address from the DHCP service existing on the router.

<< Back to top

Creating A Web Server

We can easily create a simple web server that handles just GET/POST requests by using ESP8266WebServer library.

Let’s take the following example:

// ...
#include <ESP8266WebServer.h>
// ...
ESP8266WebServer webServer(80);

void setup() {
// ...
webServer.on("/", handleRequest);
webServer.begin();
}

void loop() {
webServer.handleClient();
}

void handleRequest() {
webServer.send(200, "text/html", "Hello World!");
}

As you can see from the code above, the web server starts listening to the port 80 defined while creating the class instance by calling the begin method. It handles the incoming requests by the handleClient() function called inside the loop method and, it calls the assigned request handler function accordingly with the request path.

The chip can operate the same logic for both access point and station modes.

Let’s compile the code below and upload it to the development board.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char *AP_SSID="MyDevice";
const char *AP_PASSWORD="123456789";

void handleRequest();

ESP8266WebServer webServer(80);

void setup() {
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID, AP_PASSWORD);

webServer.on("/", handleRequest);
webServer.begin();
}

void loop() {
webServer.handleClient();
}

void handleRequest() {
webServer.send(200, "text/html", "Hello World!");
}

After the uploading is complete, connect the access point named MyDevice and navigate http://192.168.4.1/ url from the browser.

<< Back to top

Storing And Reading Data From The Flash Memory

Finally, we reached the last topic that we’re going to learn before putting everything together.

It’s possible to save some data on the chip although power cuts. You can use EEPROM library to write or read data from the flash memory. EEPROM emulates an EEPROM by using a part of the flash memory from the microcontroller.

Let’s take a look at the code example below:

#include <Arduino.h>
#include <EEPROM.h>

struct WifiCredentials {
char ssid[30];
char password[30];
}

wifiCredentials = {};

void setup() {
Serial.begin(9600);
delay(2000);

strncpy(wifiCredentials.ssid, "MyDevice", sizeof(wifiCredentials.ssid));
strncpy(wifiCredentials.password, "123456789", sizeof(wifiCredentials.password));

// write the wifiCredentials variable content on the EPROM address 0.
EEPROM.begin(sizeof(wifiCredentials));
EEPROM.put(0, wifiCredentials);
EEPROM.commit();

// Read data from the EPROM address 0 into wifiCredentials variable.
EEPROM.get(0, wifiCredentials);
Serial.println(wifiCredentials.ssid);
}

void loop() {}

There are a few points to mention regarding the code above.

You need to call EEPROM.begin(n) before any reading or writing operation. (n) is the number of bytes to be used from the memory.

EEPROM does not store the data permanently before calling EEPROM.commit().

<< Back to top

Setting Up Wi-Fi Network Through A Web Page on ESP8266

Although the code looks like a little bit large, simply it performs the following operations

  • Reads the stored credentials from EEPROM
  • Tries to connect to Wi-Fi if credentials exist
  • It starts the wifi in access point mode if the previously started connection has failed or no stored credentials exist.

Let’s compile the code below and upload it to the development board.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <Arduino.h>

#define AP_SSID "MyDevice"
#define AP_PASSWORD "123456789"
#define WEB_SERVER_PORT 80
#define MAX_CONNECTION_RETRY 30

struct WiFiCredentials
{
char ssid[30];
char password[30];
} wiFiCredentials = {};

void connectToWiFi(WiFiCredentials wiFiCredentials);
void setupAccessPoint();
void handleRequest();

ESP8266WebServer server(WEB_SERVER_PORT);

void setup()
{
Serial.begin(9600);
delay(2000);

EEPROM.begin(sizeof(wiFiCredentials));

EEPROM.get(0, wiFiCredentials);

if (wiFiCredentials.ssid[0] != '\0')
{
connectToWiFi(wiFiCredentials);
}

if (WiFi.status() != WL_CONNECTED)
{
setupAccessPoint();
}
}

void loop() {
server.handleClient();
}

void connectToWiFi(WiFiCredentials wiFiCredentials)
{
Serial.println("Connecting...");
WiFi.mode(WIFI_STA);
WiFi.begin(wiFiCredentials.ssid, wiFiCredentials.password);

int unsigned retry = 0;

while (WiFi.status() != WL_CONNECTED)
{
delay(500);

if (retry++ > MAX_CONNECTION_RETRY) {
break;
}
}

if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected!");
Serial.println(WiFi.localIP());
} else {
Serial.println("Failed to connect!");
}
}

void setupAccessPoint()
{
Serial.println("Starting Access Point");
WiFi.mode(WIFI_AP);
WiFi.softAP(AP_SSID, AP_PASSWORD);

server.on("/", handleRequest);
server.begin();
}

void handleRequest()
{
if (server.method() == HTTP_POST) {
strncpy(wiFiCredentials.ssid, server.arg("ssid").c_str(), sizeof(wiFiCredentials.ssid));
strncpy(wiFiCredentials.password, server.arg("password").c_str(), sizeof(wiFiCredentials.password));

wiFiCredentials.ssid[server.arg("ssid").length()] = wiFiCredentials.password[server.arg("password").length()] = 0;

EEPROM.put(0, wiFiCredentials);
EEPROM.commit();

const char * content = "<html><head> <link rel=\"stylesheet\" href=\"https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css\"> <style>body{background: #eee !important;}.wrapper{margin-top: 80px; margin-bottom: 80px;}.form-signin, .result-message{max-width: 380px; padding: 15px 35px 45px; margin: 0 auto; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.1);}.form-signin .form-signin-heading{margin-bottom: 30px;}.form-signin .form-control{position: relative; font-size: 16px; height: auto; padding: 10px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}.form-signin .form-control:focus{z-index: 2;}.form-signin input[type=text]{margin-bottom: -1px; border-bottom-left-radius: 0; border-bottom-right-radius: 0;}.form-signin input[type=password]{margin-bottom: 20px; border-top-left-radius: 0; border-top-right-radius: 0;}.result-message{text-align: center;}</style></head><body> <div class=\"wrapper\"> <div class=\"result-message\"> The Wi-Fi credentials have been stored. <br/> Please reboot the device! </div></div></body></html> ";
server.send(200, "text/html", content);
} else {
const char * formHtml = "<html><head> <link rel=\"stylesheet\" href=\"https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css\"> <style>body{background: #eee !important;}.wrapper{margin-top: 80px; margin-bottom: 80px;}.form-signin{max-width: 380px; padding: 15px 35px 45px; margin: 0 auto; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.1);}.form-signin .form-signin-heading{margin-bottom: 30px;}.form-signin .form-control{position: relative; font-size: 16px; height: auto; padding: 10px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}.form-signin .form-control:focus{z-index: 2;}.form-signin input[type=text]{margin-bottom: -1px; border-bottom-left-radius: 0; border-bottom-right-radius: 0;}.form-signin input[type=password]{margin-bottom: 20px; border-top-left-radius: 0; border-top-right-radius: 0;}</style></head><body> <div class=\"wrapper\"> <form class=\"form-signin\" method=\"POST\"> <h2 class=\"form-signin-heading\">Connect To Wi-Fi</h2> <input type=\"text\" class=\"form-control\" name=\"ssid\" placeholder=\"SSID\" required=\"\" autofocus=\"\"/> <input type=\"password\" class=\"form-control\" name=\"password\" placeholder=\"Password\" required=\"\"/> <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Save</button> </form> </div></body></html> ";
server.send(200, "text/html", formHtml);
}
}

Open the Wi-Fi network list from your computer, find the access point named MyDevice, and connect to it.

Navigate to http://192.168.4.1 from your browser and save your Wi-Fi network credentials.

After saving your credentials, your board will be ready to connect to the Wi-Fi network. All you have to do is reset the board after seeing the following page.

You can also check the debug information from the serial monitor to make sure the board is connected to the Wi-Fi network smoothly.

That’s it. You can see a short demo in the video below:

Hope you enjoyed reading. Please write your thoughts or questions down in the comments below.

Thanks for reading!

<< Back to top

Credits:

--

--