ESP8266 and the Arduino IDE Part 5: adding wifiManager

ESP8266_Part_3_08A_1200

In the previous guides we connected the ESP8266 to a local network using hard coded credentials. It is fine for messing around with examples and when developing sketches but not very convenient or practicle for final projects.

What happens if you want to move the ESP8266 to another network or if you buy a new router? You need to change the sketch and re-upload. It would be better if we could pick the network to use at run time. This is exactly what WifiManager allows.

Previous posts:
Part 1: The Esp8266 and setting up the Arduino IDE
Part 2: Control an LED from a web page using Access Point Mode (AP)
Part 3: Control an LED from a web page using Access Station Mode (ST)
Part 4: mDNS

 

What is WifiManager?

WifiManager is a library that adds a connection page or connection portal to the ESP8266 sketch. This allows the ESP8266 to connect to any local network without the need to hard code the network credentials in to the sketch.

On first use, when using the library, the ESP8266 will start in AP mode and display a small connection/admin page that allows the user to select and connect to a local network. After the user has made a selection the ESP8266 will start Station Mode and try to connect to the selected network. If successful it will show the local network IP address. If the connection fails an error message is displayed. This means once you have connected to a network, you do not need to keep entering the details unless the network changes.

When a successful connection is made, the ESP8266 remembers the credentials and tries to connect to the same network next time. If it cannot connect, it uses AP mode to display the connection page again.

WifiManager uses both Access Point mode and Station Mode together. It uses AP mode for the connection page which is available under the ESP8266’s own network and at a known IP address (192.168.4.1) and then uses STA mode to connect to the local network.

 
The WifiManager library was originally released by Tzapu and while this is very good it does have a couple of short comings. It does not confirm when a connection has been made and it does not give you the new IP address the ESP8266 is using on the local network and of course, we need the IP address if we want to connect to it. Luckily Ken Taylor forked the WifiManager library and addressed these issues and this is the library I am using below.

Tzapu’s WifiManager is here.
Ken Taylor’s library is here.
Ryan Downing offers another variant called PersWiFiManager.

At the time of writing Ken Taylor’s library is not available through the Arduino library manger so you need to install the library the old fashioned way; download from Github, unzip and copy the folder to the Library folder inside the Arduino folder.

After installing the library restart the IDE and you should have a WifiManager entry under Examples. Open the ConfigOnStartup example. This is a basic sketch to show how things work.

ESP8266_Part_3_01_open_ConfigOnStartup

/*
This example will open a configuration portal for 60 seconds when first powered up. ConfigOnSwitch is a a bettter example for most situations but this has the advantage 
that no pins or buttons are required on the ESP8266 device at the cost of delaying 
the user sketch for the period that the configuration portal is open.
 
Also in this example a password is required to connect to the configuration portal 
network. This is inconvenient but means that only those who know the password or those 
already connected to the target WiFi network can access the configuration portal and 
the WiFi network credentials will be sent from the browser over an encrypted connection and
can not be read by observers.
 
*/
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
 
//needed for library
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h>          //https://github.com/kentaylor/WiFiManager
// Onboard LED I/O pin on NodeMCU board
const int PIN_LED = 2; // D4 on NodeMCU and WeMos. Controls the onboard LED.
 
void setup() {
  // put your setup code here, to run once:
  // initialize the LED digital pin as an output.
  pinMode(PIN_LED, OUTPUT);
 
  Serial.begin(115200);
  Serial.println("\n Starting");
  unsigned long startedAt = millis();
 
  WiFi.printDiag(Serial); //Remove this line if you do not want to see WiFi password printed
  Serial.println("Opening configuration portal");
  digitalWrite(PIN_LED, LOW); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.
  //Local intialization. Once its business is done, there is no need to keep it around
 
  WiFiManager wifiManager;  
  //sets timeout in seconds until configuration portal gets turned off.
  //If not specified device will remain in configuration mode until
  //switched off via webserver.
  if (WiFi.SSID()!="") wifiManager.setConfigPortalTimeout(60); //If no access point name has been previously entered disable timeout.
 
  //it starts an access point 
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.startConfigPortal("ESP8266","password"))  //Delete these two parameters if you do not want a WiFi password on your configuration access point
  {
     Serial.println("Not connected to WiFi but continuing anyway.");
  } 
  else 
  {
     //if you get here you have connected to the WiFi
     Serial.println("connected...yeey :)");
  }
      digitalWrite(PIN_LED, HIGH); // Turn led off as we are not in configuration mode.
      // For some unknown reason webserver can only be started once per boot up 
      // so webserver can not be used again in the sketch.
 
  Serial.print("After waiting ");
  int connRes = WiFi.waitForConnectResult();
  float waited = (millis()- startedAt);
  Serial.print(waited/1000);
  Serial.print(" secs in setup() connection result is ");
  Serial.println(connRes);
  if (WiFi.status()!=WL_CONNECTED)
  {
      Serial.println("failed to connect, finishing setup anyway");
  } 
  else
  {
    Serial.print("local ip: ");
    Serial.println(WiFi.localIP());
  }
}
 
 
void loop() {
 delay(10000);
  // put your main code here, to run repeatedly:
 
}

The Wifi Manger requires 2 other libraries, DNSServer and ESP8266WebServer

#include <DNSServer.h>
#include <ESP8266WebServer.h>

These are included in the ESP8266 core and therefore you should already have them installed.

Compile and upload this sketch to the ESP8266.

The first time the sketch runs there is no saved network so it will start its own network called what ever name is specified in the startConfigPortal statement. In this case it is “ESP8266″ with a password of “password”.

wifiManager.startConfigPortal("ESP8266","password"))

Using a wifi device, scan for networks and you should see ESP8266 listed. Select it and enter the password “password” to connect.
ESP8266_Part_3_02A_1200

Using your web browser of choice, go to 192.168.4.1 and you should get the WifiManger main page. Click the “Configuration” button and you should see a list of available networks. Select one, enter the password and click “save” to connect.
ESP8266_Part_3_05A_1200

After the ESP8266 has connected to the local network the main connection page is updated. You can also click the “Information” link to get additional information.
Here I have connected to JAMguest.
ESP8266_Part_3_08A_1200

In use I find the library not quite 100% reliable and have had some connections issues after joining the local network. Sometimes my wifi device (mobile phone) will lose the connection to the ESP8266 and jump back to my home network. However, this is not a big problem since it is a one time operation. After the the network credentials have been entered they are stored and ESP8266 will auto-connect.

ConfigOnStartup is the most basic of the examples, other examples include ConfigOnSwitch and ConfigOnDoubleReset.

ConfigOnSwitch relies on a switch connected to the ESP8266. When the switch is closed on boot up the configuration page is shown. ConfigOnDoubleReset is a little smarter. This uses resets to determine if the configuration page should be displayed. If the ESp8266 is reset twice within a given time it triggers AP mode and the configuration page.

 

Using WifiManager in our own sketches

The next step is to add the WifiManager library to the ESP8266_LED_Control_05_Station_Mode_with_mDNS sketch. To do this we simply replace the code that is responcible for connecting to the local wifi network with the new wifiManager commands. The new lines required are:

#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> 
...
...
 
WiFiManager wifiManager;
wifiManager.autoConnect("ESP8266","password");

When added to the previous sketch it gives us:

/*
 * Sketch: ESP8266_LED_Control_06_Station_Mode_with_mDNS_and_wifiManager
 * Control an LED from a web browser
 * Intended to be run on an ESP8266
 */
 
#include <ESP8266WiFi.h>
//#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>   
 
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
 
// change these values to match your network
char ssid[] = "MyNetwork_SSID";       //  your network SSID (name)
char pass[] = "Newtwork_Password";    // your network password
 
WiFiServer server(80);
 
String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
String html_1 = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1.0'/><meta charset='utf-8'><style>body {font-size:140%;} #main {display: table; margin: auto;  padding: 0 10px 0 10px; } h2,{text-align:center; } .button { padding:10px 10px 10px 10px; width:100%;  background-color: #4CAF50; font-size: 120%;}</style><title>LED Control</title></head><body><div id='main'><h2>LED Control</h2>";
String html_2 = "";
String html_4 = "</div></body></html>";
 
String request = "";
int LED_Pin = D1;
 
 
void setup() 
{
      pinMode(LED_Pin, OUTPUT); 
 
      Serial.begin(115200);
      delay(500);
      Serial.println(F("Serial started at 115200"));
      Serial.println();
 
      // We start by connecting to a WiFi network
      //Serial.print(F("Connecting to "));  Serial.println(ssid);
      //WiFi.begin(ssid, pass);
 
      //while (WiFi.status() != WL_CONNECTED) 
      //{
      //    Serial.print(".");    delay(500);
      //}
      //Serial.println("");
      //Serial.println(F("[CONNECTED]"));
      //Serial.print("[IP ");              
      //Serial.print(WiFi.localIP()); 
      //Serial.println("]");
 
     // WiFiManager
      WiFiManager wifiManager;
      wifiManager.autoConnect("ESP8266","password");
 
 
      // or use this for auto generated name ESP + ChipID
      //wifiManager.autoConnect();
 
      // if you get here you have connected to the WiFi
      Serial.println("Connected.");
 
 
      if (!MDNS.begin("esp8266"))   {  Serial.println("Error setting up MDNS responder!");  }
      else                          {  Serial.println("mDNS responder started");  }
 
      // start a server
      server.begin();
      Serial.println("Server started");
 
} // void setup()
 
 
 
void loop() 
{
 
    // Check if a client has connected
    WiFiClient client = server.available();
    //if (!client)  {  return;  }
 
    if (client)
    {
          // Read the first line of the request
          request = client.readStringUntil('\r');
 
          Serial.println("request:");
          Serial.println(request);
 
          if       ( request.indexOf("LEDON") > 0 )  { digitalWrite(LED_Pin, HIGH);  }
          else if  ( request.indexOf("LEDOFF") > 0 ) { digitalWrite(LED_Pin, LOW);   }
 
 
          // Get the LED pin status and create the LED status message
          if (digitalRead(LED_Pin) == HIGH) 
          {
              // the LED is on so the button needs to say turn it off
             html_2 = "<form id='F1' action='LEDOFF'><input class='button' type='submit' value='Turn off the LED' ></form><br>";
          }
          else                              
          {
              // the LED is off so the button needs to say turn it on
              html_2 = "<form id='F1' action='LEDON'><input class='button' type='submit' value='Turn on the LED' ></form><br>";
          }
 
 
          client.flush();
 
          client.print( header );
          client.print( html_1 );    
          client.print( html_2 );
          client.print( html_4);
 
          delay(5);
 
         // The client will actually be disconnected when the function returns and 'client' object is detroyed
 
    }
 
 
} // void loop()

I have commented out rather than deleted the lines that are no longer required. This allows you see exactly what code the wifiManager replaces. Because I already have mDNS, which uses the ESP8266mDNS.h library the DNSServer.h library is not needed and also commented out.

Upload the sketch and give it a go.
Connect your mobile device to the ESP8266 network. SSID is “ESP8266″ and the password is “password”.
ESP8266_wifiManager_001

After you have connected, open a browser and go to 192.168.4.1. You should see the connection portal. Select your network and enter the password. Wait a few seconds and then cick the link on the final page.
ESP8266_wifiManager_002

If the connection is successful the main page should now show the details for the network.
ESP8266_wifiManager_003
Here you can see the ESP8266 is connected to JAMnet_2.4GHz and has an IP address of 192.168.2.107.

If you now go to 192.168.2.107 you will find you still have the connection portal not the LED control webpage. The portal is still active.
To stop the wifiManager portal click “Exit Portal”. When the portal closes so does the ESP8266 AP. Connect to your regular wifi network and try 192.168.2.107 again. You should not get the LED Control page.
ESP8266_wifiManager_004

Since I am using an Android device I have to use the IP address. On a PC I can use either the IP address or the url esp8266.local.
ESP8266_wifiManager_005

And that’s all there is to it.

To erase the saved connection details, use resetSettings() just after you initialize the wifimanager library.

     // WiFiManager
      WiFiManager wifiManager;
 
      wifiManager.resetSettings();
      wifiManager.autoConnect("ESP8266","password");

 

Downloads

Arduino sketch: ESP8266_LED_Control_06_Station_Mode_with_mDNS_and_wifiManager

 
We now have a fairly nice website with a very handy connection portal. One this you will notice though, the webpage refreshes every time the button is clicked. We see what we can do about this is the next part using AJAX and javascript. Coming sometime soonish.

 
 

Leave a Reply

Your email address will not be published. Required fields are marked *


3 + = six

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>