02 October 2018

Robust ESP8266 network connects

While building small devices with the ESP8266 chip I made some experiences with the stability of implementations which I would like to share here.

The examples you can find on the Internet often don't go into these problems in detail, but you can also find tips and tricks on these topics.

Connecting to the Network, too simple too bad


To connect to a local network you often find only a very simple implementation of this kind:

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
}

Obviously, if the ssid or password is wrong, the device will hang in an infinite loop because you never will connect and status will never return WL_CONNECTED(3) when using wrong settings.

But WiFi.status() also has more return codes that may give a hint that is never reported to the Serial output and root causes will be undiscovered.

By looking more into the WiFi library there is a waitForConnectResult() function that is used in the OTA samples (file ESP8266WiFiSTA.cpp).

while(status() == WL_DISCONNECTED) {
delay(100);
}

In the case of no connectable available WiFi the status will return WL_NO_SSID_AVAIL(1) or WL_CONNECT_FAILED(4) so the loop exist. At least no infinitive loop and the samples just restart the chip and the sketch.


In case of a miss-configuration this is just another kind of infinitive loop that needs to be avoided.

Connect during startup


Here is a more robust implementation using a timeout to start a complete new approach after 30 secs and providing more information on the Serial output and terminating with the last return code of the status call.

The possible results of status I observed that end the attempt to connect to the network are WL_CONNECTED(3), WL_NO_SSID_AVAIL(1) and WL_CONNECT_FAILED(4). When one of these status codes exist the loop can end as well.

When you need to connect during startup this sequence can be used.

// wait max. 30 seconds for connecting
unsigned long maxTime = millis() + (30 * 1000);

while (1) {
  wifi_status = WiFi.status();
  Serial.printf("(%d).", wifi_status);

  if ((wifi_status == WL_CONNECTED) || (wifi_status == WL_NO_SSID_AVAIL) ||
      (wifi_status == WL_CONNECT_FAILED) || (millis() >= maxTime))
    break; // exit this loop
  delay(100);
} // while

Serial.printf("(%d)\n", wifi_status);

The delay was reduced to 100 msec. as the implementations inside the SDK also use this timing.

However, when a connection could not be established something needs to be done. A reset of the whole device is a valid option and in the case of a unreliable WiFi that helps connecting after the network is available again.

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

You can find out by calling the WiFi status function from time-to-time and start a re-connect or restart.


More improvements


This is just a replacement for the usual connect sequence you can find in the setup of a device. But there are more situations to be taken in considerations like setting up a fresh network connection, using the WPS feature of your browser etc.



Reading Material