ESP8266 wifi connection - a puzzle

I've been developing a unit based on a nODEMCU 8266 to respond to incoming pings.
(code below)
The circuit is simple: a pull-down on D8, required to allow it to boot.
An LED and resistor to ground on D1, and
a switch to gound on D2.

I've been bamboozled by a strange behaviour. I use a flashing LED to show the wifi connection being established. It always seemed to do this twice. Heres the relevant bit of code

 WiFi.begin(ssid, password);
  Serial.println("\nConnecting");

  while (WiFi.status() != WL_CONNECTED) {  //this will continue trying until a connection is made:
    flashLed(200);                         //slow flashes to show wifi trying to connect while running setup
    Serial.print('w');                     //so no option to handle a failure to connect.
    //delay(200);
  }

after spending a bit of time checking for program loops, putting in serial prints, or debouncing the switch, I've realised that the wifi connection pauses in mid-stream!

Can anyone explain what is happening please?

And is there a simple way to handle a situation where the wifi is unable to connect?

/*
ping responder on NodeMCU ESp8266: switch on d2, BLUE LED to ground on d1 via 1k: needs pull-down on pin d8 or wont boot.
wifi doesnt turn back on very quickly compared to esp32 "restart"
very quick response to ping to URL, sometimes slower via mdns
added simple static web page
NB some data pins will prevent upload if connected.
*/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>       //support for multicast to assign name to ip address
#include <ESP8266WebServer.h>  //to create a web page response so a browser can see the unit
#include "creds.h"             // my wifi credentials
#include "webpage.h"           //simple web page to display

ESP8266WebServer server(80);  //create instance of server: need web page to give name on port scanner

constexpr int offOn = D2;  //also on board led?
constexpr int bLED = D1;   //blue LED to show wifi state
int bounceDelay = 200;     //milliseconds
int oldX;                  //for debouncing switch

String newHostname = "Ping_responder";

void flashLed(int rate) {  //indicate wifi connecting
  digitalWrite(bLED, 1);
  delay(rate);
  digitalWrite(bLED, 0);
  delay(rate);
}

//Handles http request
void handleRoot() {
  String s = MAIN_page;
  server.send(200, "text/html", s);
}

void setup() {
  Serial.begin(115200);
  delay(5000);  //allow me time to clear serial monitor
  pinMode(offOn, INPUT_PULLUP);
  pinMode(bLED, OUTPUT);
  // WiFi.mode(WIFI_STA);  //Optional
  WiFi.hostname(newHostname.c_str());  //dont think this works.  Network picks up the title from the web page]
  WiFi.begin(ssid, password);
  Serial.println("\nConnecting");

  while (WiFi.status() != WL_CONNECTED) {  //this will continue trying until a connection is made:
    flashLed(200);                         //slow flashes to show wifi trying to connect while running setup
    Serial.print('w');                     //so no option to handle a failure to connect.
    //delay(200);
  }

  Serial.println("\nConnected to the WiFi network");
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  digitalWrite(bLED, 1);

  // Initialize mDNS
  if (!MDNS.begin("responder")) {  // Set the hostname to "responder.local"
    Serial.println("Error setting up MDNS responder!");
  }
  Serial.println("mDNS responder started");

  server.on("/", handleRoot);  //Associate handler function to path
  server.begin();              //Start server
  Serial.println("HTTP server started");
  oldX = digitalRead(offOn);
}
void testloop() {}

void loop() {

  server.handleClient();

  MDNS.update();

  int newX = digitalRead(offOn);  //debounce?
  if (newX != oldX) {
    Serial.printf("Switch has changed now state %i \n", newX);
    oldX = newX;
    if (!newX) {  //switch is now OFF
      if (WiFi.status() == WL_CONNECTED) {
        WiFi.disconnect();
        Serial.println("wifi disconnected");
        digitalWrite(bLED, 0);
      }

    } else if (WiFi.status() != WL_CONNECTED) {  //switch is ON but  wifi not yet connected
      //WiFi.reconnect();  //reconnect doesnt work on esp8266 so start afresh
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        flashLed(50);  //fast flash to show we are in the loop and trying to connect
      }
      Serial.println("WiFi reconnected");
      digitalWrite(bLED, 1);
      // Initialize mDNS
      if (!MDNS.begin("responder")) {
        Serial.println("Error setting up MDNS responder!");
      }
      Serial.println("mDNS responder started");
    }
  }

  delay(500);  //no need to debounce the switch
}

How many times do you see 'w' printed ?

Do you mean you receive "ww" from the serial? It could be due to the fact the WiFi connection needs some time to be completed depending on the signal strength and access point timings, I don't see any strange or blocking behaviour.
Just to test it, add a "delay(500);" after WiFi.begin() and see if you still get two "w"s.

Idk what it means.

I generally use a "connectWiFi()" function in both setup() and loop() to make sure che connection is always checked and restored, if possible.
Something like this one (this is an example snippet, from one of my ESP8266 projects):

void ConnectWiFi(int FlashTime) {
  while (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    digitalWrite(WIFI_LED, LED_ON);
    delay(FlashTime/2);
    digitalWrite(WIFI_LED, LED_OFF);
    delay(FlashTime/2);
  }
  digitalWrite(WIFI_LED, LED_ON);
}

This part may be cause of causing Wifi Disconnect in mid stream you are checking with int so any little change would trigger it .I ll recommend using it with bool and also add debounce . For this i would recommend using interrupt function it would be more efficient .Check the value of newX using serial print so you can understand why it stops in the middle. int variable any value other than its initial state will make the if condition true. so try with bool

Maybe changing this line like this would solve your issue

bool newX = digitalRead(offOn);

also

int oldX;

to

bool oldX = false;

Connecting

wwwwwwwwwwwwww

Connected to the WiFi network

Local IP: 192.168.1.111

mDNS responder started

HTTP server started

and after a reset:

Connecting

wwwwwwwwwwwwww

Connected to the WiFi network

Local IP: 192.168.1.111

mDNS responder started

HTTP server started

The issue also happens in the simple wifi connection in setup.

The blue light flashes a few times; pauses;then flashes again.

surely that (2 * 200msec delays) is just as good as a simple delay?

no I dont get two "w"s, I get a few - then a pause - then more. And a few flashes, a pause, and more.
Following which I have a wifi connection.

Can you tell me what kind output you expecting from it

Nope, I meant to add a delay before first testing of "WiFi.status()".
Btw, that output tells me the connection requires 14 cycles of 200ms, equivalent to 7 seconds before a successful connection: it seems to be a lot for a local connection. Are you sure the WiFi signal level where the Arduino is running is good enough, i.e. high signal level, and no interefences or overlapping networks? Test it using one of the many WiFi scanner apps available showing a graph of all the networks with channels and strength.

I see that on post #5 (btw, when posting output please enclose it between "code" tags also).

About the output of post #5, the only section where the connection will be programatically disconnected is when "digitalRead(offOn)" returns 0 or LOW, but in this case you should read a "wifi disconnected" message before the next attempt, so it seems to not be the culprit.
Analyzing the loop() section, from the first output section (I assume it came out from regular sketch running, i.e. the "loop()", right?) I see if the network disconnects and no offOn button is pressed, you have no serial output (aka no "w"...), except for the ending message "WiFi reconnected" but I still can't find it anywhere in your output here!

So unless you haven't reported the whole output here, as the "w"s are being printed out from "setup()" function only, it looks like either the board unexpetedly restarted or the real sketch code isn't the one you posted here, making things weirder than expected...

A few side notes (not critical):

  1. why "constexpr"? Ardunio standard should be just "const"...
  2. when reading from digitalRead() the best and clearer way to test the value is always comparing to LOW or HIGH
  3. get rid of "testloop()"

Thanks to all who have contributed. I've had a few suggestions it may be a timing issue so I've added lines to check that. Here is the result (code below): the flashLed(100) runs at 200msec. You will see there is a significant delay at t = 2912 to t=3933;

time 106 : Connecting 
107 .. connecting
307 .. connecting
507 .. connecting
708 .. connecting
908 .. connecting
1109 .. connecting
1309 .. connecting
1510 .. connecting
1710 .. connecting
1910 .. connecting
2111 .. connecting
2311 .. connecting
2511 .. connecting
2711 .. connecting
2912 .. connecting
3933 .. connecting
4133 .. connecting
4334 .. connecting
4534 .. connecting
4734 .. connecting
4935 .. connecting
5135 .. connecting
5335 .. connecting
5536 .. connecting
5736 .. connecting
5936 .. connecting
at 6137 Connected to the WiFi network 
Local IP: 192.168.1.111
at 6138 mDNS responder started
HTTP server started
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>       //support for multicast to assign name to ip address
#include <ESP8266WebServer.h>  //to create a web page response so a browser can see the unit
#include "creds.h"             // my wifi credentials
#include "webpage.h"           //simple web page to display

ESP8266WebServer server(80);  //create instance of server: need web page to give name on port scanner

constexpr int offOn = D2;  //also on board led?
constexpr int bLED = D1;   //blue LED to show wifi state
int oldX;                  //for debouncing switch

String newHostname = "Ping_responder";

void flashLed(int rate) {  //indicate wifi connecting
  digitalWrite(bLED, 1);
  delay(rate);
  digitalWrite(bLED, 0);
  delay(rate);
}

//Handles http request
void handleRoot() {
  String s = MAIN_page;
  server.send(200, "text/html", s);
}

void setup() {
  Serial.begin(115200);
  delay(5000);  //allow me time to clear serial monitor
  pinMode(offOn, INPUT_PULLUP);
  pinMode(bLED, OUTPUT);
  long tStart = millis();
  long tNow;

  // WiFi.mode(WIFI_STA);  //Optional
  WiFi.hostname(newHostname.c_str());  //dont think this works.  Network picks up the title from the web page]
  WiFi.begin(ssid, password);
  tNow = millis() - tStart;
  Serial.printf("time %i : Connecting \n", tNow);

  while (WiFi.status() != WL_CONNECTED) {  //this will continue trying until a connection is made:
    tNow = millis() - tStart;
    flashLed(100);          //100msec flashes to show wifi trying to connect while running setup
    Serial.printf("%i .. connecting\n",tNow);  //so no option to handle a failure to connect.
  }

  tNow = millis() - tStart;

  Serial.printf("at %i Connected to the WiFi network \n", tNow);
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  digitalWrite(bLED, 1);

  // Initialize mDNS
  if (!MDNS.begin("responder")) {  // Set the hostname to "responder.local"
    Serial.println("Error setting up MDNS responder!");
  }
  tNow = millis() - tStart;
  Serial.printf("at %i mDNS responder started\n", tNow);

  server.on("/", handleRoot);  //Associate handler function to path
  server.begin();              //Start server
  Serial.println("HTTP server started");
  oldX = digitalRead(offOn);
}

A 1s delay does nowt; but after a 3 sec delay the pause is no longer present

time 106 : Connecting 
3830 .. connecting
4031 .. connecting
4232 .. connecting
4432 .. connecting
4632 .. connecting
4833 .. connecting
5033 .. connecting
5233 .. connecting
5434 .. connecting
5634 .. connecting
5834 .. connecting
6035 .. connecting
at 6235 Connected to the WiFi network 
Local IP: 192.168.1.111
at 6236 mDNS responder started
HTTP server started

its not relevant to this issue, although the delay in connection process also shows there. However there is no print out or change in activity unless the switch is changed.

a nodeMCU will already have that

No the oboard led is on GPIO 2, which is D4

You do not initialize this variable, and the first 'read' will probably be 'HIGH' if the button is not pressed, so that explains part of what is happening.

[quote="Deva_Rishi, post:11, topic:1379694"]
a nodeMCU will already have that
[/quote] //SHOULD - this one (made by Amica) needs the pull-down.

at the end of setup

oldX = digitalRead(offOn); 
}

its a switch, not a button.

no, it appears the pause is part of the way the node processes the connection to the wifi network. As has been noted, it doesnt happen if I put a long (3 second) delay after WiFi.begin
I'll just need to remember it happens.

The Node doesnt support WiFi.reconnect; the ESP32 does and is MUCH faster.

I used some ESP8266 boards (Wemos D1, ranging from R1 to R2 and mini) but I have never had such kind of problem, they aren't fast, but as far as I can remember the connection is always made after less than one or two seconds, you here are at 6+ seconds...
At the moment I can only think it's nothing bad on your code side but something related to your infrastructure like weak signal strength, a DHCP slowly releasing IP address (idk why it should), or some other kinda config problem.
Maybe even a duplicated MAC address could lead to similar problems.

I don't have any other possible indications at the moment, sorry.

Seriously ?? well in that case they made a faulty board imo. There are quite a few variants around but this is the first time i have heard of such a thing.

Ah yeah sorry i missed that.

because ? Either way it might be better to add some de-bounce, although i guess it sort of does during the connection attempt.
I actually do the connection attempt aSync usually (except in example sketches) I call begin(), set a (millis() ) timer and and check for 5 seconds to see if there is success, before i start completing the process, which includes WiFi.reconnect() to re-connect any device which was connected to it as an AP, which is needed if i use my phone to tell it to connect to a specific network or something like that.

The esp8266 does support it but it is used to re-connect any device that has connected to it's access point and has been temporarily disconnected to perform say a 'wifi-network-scan' or connection to a network,but it should have no influence on the station mode.
The ESP32 isn't that much faster. It has a higher clock- rate, but on my home network, connection times are very similar.

Neither have i. that is to say i don't think so. All my devices connect without issue, though the length of the list of available networks can be so long at times that my favorite doesn't always show up, but this is the same with ESP32. An ERESP8266 i would say is not slow, but it is always what you compare it too. Actually it takes my laptop much longer to connect to any network than any of the ESPs.

I would consider blaming the board. If they can design a board that just won't work without a pulldown on GPIO 15, there is a good chance they made some other design faults, possibly related to power regulation.
Have you tried supplying the board with 3.3v through the 3.3v pin directly with a supply that can deliver 300mA reliably ? The peak current demand of an esp8266 is when connecting to a network in station mode, and with lack of current this connection may be problematic. If the nodeMCU does not have enough heatsink for it's onboard 3.3v regulator this can be a cause. You could also add an extra capacitor to the 3.3v rail (something like 10uF) to see if that helps.
Other possible causes could be shielding of the antenna. The PCB needs to be free of any copper trace where the antenna sits, but that may not be fully the case here.

I changed the board for a LOLIN node, and added a cap across 3v3 & GND
: no difference except its been assigned a different URL.

Local IP: 192.168.1.23 Signal strength RSSI: -42 HTTP server started

the node is just half sitting on a small breadboard.
tried a different usb supply, no change.

That's because the standard behaviour for DHCP is to have a certain "lease time" based on the MAC address (aka "assigns the same local IP to a specific device for a specific amout of time", it could even be forever, making ot kinda "static").
If the board has a different MAC a different dynamic IP address will be assigned.

I'm not sure what you mean: it won't connect even changing the board (which LOLIN board? D1 R2? Mini? Other?...)? In this case, it looks like the culprit is in your network...

Thanks @docdoc Alex;

It does connect, just with that strange pause. Looks as if its not the board, and my other devices seem to connect fairly quickly so I guess its a "design feature"

If both come from the same reseller/vendor, more than "design" it looks probably kinda faulty device batch (especially if they've been bought from a chinese shop...). I bought many boards before but I've never had problems with eBay or Amazon (I choose european based sellers if possible).
If you want, and just out of curiosity, could you show us the links to the two boards you have?

PS: btw, a standard for Windows things "it isn't a bug, it's a feature"... :smiling_face_with_halo:

1 Like