1

I have a Keyes Espressif ESP8266 NodeMCU, I have two LEDs that I want to control which are connected to the ESP. When I open the webpage http://10.0.0.5/5 after uploading the sketch it works fine. If I don't open and close the website before ~ 02:30[mm:ss] the server becomes unreachable even if I close the existing connection and open a new connection in a new tab the same error yields: ERR_CONNECTION_TIMED_OUT

If I don't open a web page before ~ 02:30[mm:ss] I also receive error ERR_CONNECTION_TIMED_OUT

The web server is only made available when I hard reset the board then the same rules apply as above.

ESP.getFullVersion() outputs: 
SDK:2.2.1(cfd48f3)/Core:2.5.1=20501000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1-7-g82abda3/BearSSL:a143020

Question:

How can I make the web server accessible constantly?

With the help of @Juraj I tried changing to SDK V3 which made no difference I also tried:

  • All lwip variants

My Code:

// Load Wi-Fi library
#include <ESP8266WiFi.h>

// Replace with your network credentials
const char* ssid     = "DO_231455";
const char* password = "0828842107";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output5State = "off";
String output4State = "off";

// Assign output variables to GPIO pins
const int output5 = 16;
const int output4 = 4;

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

  // Initialize the output variables as outputs
  pinMode(output5, OUTPUT);
  pinMode(output4, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output5, LOW);
  digitalWrite(output4, LOW);

  Serial.print(ESP.getFullVersion());
  //WiFi.disconnect() ;
  //WiFi.persistent(false);
  //WiFi.setSleepMode(WIFI_NONE_SLEEP);
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients
  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /5/on") >= 0) {
              Serial.println("GPIO 5 on");
              output5State = "on";
              digitalWrite(output5, HIGH);
            } else if (header.indexOf("GET /5/off") >= 0) {
              Serial.println("GPIO 5 off");
              output5State = "off";
              digitalWrite(output5, LOW);
            } else if (header.indexOf("GET /4/on") >= 0) {
              Serial.println("GPIO 4 on");
              output4State = "on";
              digitalWrite(output4, HIGH);
            } else if (header.indexOf("GET /4/off") >= 0) {
              Serial.println("GPIO 4 off");
              output4State = "off";
              digitalWrite(output4, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 5  
            client.println("<p>GPIO 5 - State " + output5State + "</p>");
            // If the output5State is off, it displays the ON button       
            if (output5State=="off") {
              client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 

            // Display current state, and ON/OFF buttons for GPIO 4  
            client.println("<p>GPIO 4 - State " + output4State + "</p>");
            // If the output4State is off, it displays the ON button       
            if (output4State=="off") {
              client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Worth noting (while debugging):
The new client disconnects.

enter image description here

  • if a client is returned from server, then the problem is in sketch – Juraj Jun 19 at 11:55
  • What resources would you suggest I look at to learn how to fix this problem? – Brandon Pillay Jun 19 at 12:16
  • does it help if you restart the WiFi router/AP? – Juraj Jun 19 at 17:22
  • No effect, the site still drops if not requested from my W8.1 Chrome browser within 2 minutes of resetting or uploading. – Brandon Pillay Jun 19 at 17:32
  • does it stop working after two minutes - even if you do not make any requests to it until 2 minutes has passed? Or, does it stop after a certain number of requests that happen to take about 2 minutes to execute?? The point is, does it fail after a certain number of requests, or does it fail after a period of operation - irrespective of the workload??? – GMc Jun 20 at 3:32
1

It worked when the IP was in the range because there are no valid IP addresses outside the range.

WW.XX.YY.0 and WW.XX.YY.255 are reserved. The router is using the .1 and .2 addresses. That leaves 3-254 available, which as we see are the addresses within the DHCP range.

You can assign a static IP address within the DHCP range, but you run the risk of disabling 1 or 2 devices. DHCP doesn’t know you’ve used one of it's addresses, so can assign it to another device. Boom! Two devices with the same address and both will not function.

The correct way to resolve this is to log into the router and change the DHCP range. For example, increase the lower limit of 3 to (random pick) 20. Now, DHCP won’t be disturbed and will happily give out addresses to your devices. But if you need a static IP address, you’ve defined a pool, from WW.XX.YY.3 to WW.XX.YY.19

1

The short answer: Config a static IP!

After looking at Git Issue #2371 I found out that I need to create a static IP address to fix this issue. I can do this by inserting WiFi.config(ip, gateway, subnet) just before WiFi.mode(WIFI_STA) in the code above.

  • First I found the information gateway & subnet I needed by opening the command prompt on a computer that's connected to the access point(router) as the one connected to the ESP8266 which functions in station mode. I did this on Windows by searching Command Prompt then typing ipconfig to obtain the following information:

enter image description here

Replace the points with commas! See this references for more information regarding other parameters and DNS.


  • To create an IP address you need to see your IP address in the red square in the picture above taken from the command prompt. The first three octects (numbers) of your router IP (probably 10.0.0.x, 192.168.0.x, or 192.168.1.x) must match your chosen static IP. For my example the numbers to match would be 10.0.0.

  • Next, I needed to obtain the DCHP range for my router. My router is a Netgear Wireless ADSL2+ Modem Router DG834Gv5. To obtain the range I needed to access my router settings. To access this I looked for an HTTP link under the router. For my router it was http://10.0.0.2 along with the username and password which was admin, admin respectively. This is what it looks like:

enter image description here

This will vary according to your router - Then I went into Advanced settings and saw the DHCP range. This is an error on my part noted by @djsfantasi. Please see his answer regarding DHCP range selection.The new static IP needs to be within the DHCP range According to one of the comments brendanmatkin made in Git Issue #2371 the last number of my static IP (which is ZZ in WW.XX.YY.ZZ) needs to be outside of this range. For me it didn't work, it worked when I used a value inside this range but brendanmatkin knows much more than me, I'm just a novice. There might be implications that I am not aware of so I think it's worth looking into. A DHCP range looks like this below:

enter image description here

My inserted code looks like this below:

void setup(void) {
  .
  .
  .
  Serial.begin(115200);
  //WiFi.disconnect();  //Prevent connecting to wifi based on previous configuration
  IPAddress ip(10,0,0,15); // this 3 lines for a fix IP-address
  IPAddress gateway(10,0,0,2); 
  IPAddress subnet(255,255,255,0);
  //WiFi.hostname("ESP8266");      // DHCP Hostname (useful for finding device for static lease)
  WiFi.config(ip, gateway, subnet);
  //Station mode:
  WiFi.mode(WIFI_STA); 
  .
  .
  .
}

Please comment for more info :)

Additional information and changes I've made to IDE:

OS : Windows 8.1

IDE : Arduino IDE V1.9.8

Board : Keyes ESP8266

Arduino IDE > Tools >Board (in boards manager) : Generic ESP8266 Board

Arduino IDE > Tools >lwip : V2 Low Memory

Arduino IDE > Tools >Esp FW:"nonos.." : nonos-sdk pr-3(known issues)*

Power Supply : USB COM from 300Watt desktop power supply. ~ 1.5A current output.

Much appreciation to @Juraj. Juraj

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.