Inconsistent ESP8266WebServer Behavior

Hello,

I am having a very strange problem that I cannot figure out and I am out of options of what even to search.

I am using a ESP8266 to connect to my wifi router, and act as a web server that executes one of two functions based on the request. The issue is it sometimes works perfectly, and sometimes it doesn’t execute the functions. When it doesn’t work, I make the request and see output in the Arduino Serial Monitor, which indicates that the internet connection works and the ESP8266 is receiving something from the internet, but it doesn’t execute the functions. It can go from working to not working within the same hour, with no change to anything except unplugging the board and plugging it in again.

What can I do to make it work consistently?

Arduino IDE Serial Monitor output:

  • Failing case: When I make one network request and it doesn’t execute the function
WS:ac
:ref 1
WS:av
:ref 2
:ur 2
New client
:ref 2
:ur 2
  • Successful case: When I make the same network request and it does execute the function
WS:ac
:rn 247
:ref 1
WS:av
:ref 2
:ur 2
New client
:ref 2
:ur 2
request: GET /ledOff HTTP/1.1
method: GET url: /ledOff search: 
headerName: Content-type
headerValue: application/json
headerName: host
headerValue: nataliaandandy.hopto.org:8880
headerName: x-newrelic-id
headerValue: VwAOU1RRGwAFUFZUAwQE
headerName: x-newrelic-transaction
headerValue: PxQCVANSXlVSVwJVBVJUVkYdUFIOFQZOElcNBwleUlAABg5TUgIDQEgUUQMDW1kEVQZDPw==
headerName: Connection
headerValue: close
:c0 1, 247
args: 
args count: 0
args: 
args count: 0
Request: /ledOff
Arguments: 
final list of key/value pairs:
LED off page
:wr 83 0
:wrc 83 83 0
:wr 10 0
:wrc 10 10 0
:ack 83
:rcl
:abort
:ur 1
WS:dis
:del
  • When I restart the board, I get this output on startup for both success and failing cases:
.....scandone
state: 0 -> 2 (b0)
.state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 3
cnt 

connected with MyWifiSSID, channel 1
ip:192.168.1.176,mask:255.255.255.0,gw:192.168.1.1
ip:192.168.1.176,mask:255.255.255.0,gw:192.168.1.1
wifi evt: 0
wifi evt: 3
.
WiFi connected
HTTP server started
192.168.1.176
pm open,type:2 0

My setup:

Hardware:

Software:

Code

// Import required libraries
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <Servo.h>

//Static IP address configuration
IPAddress staticIP(192, 168, 1, 176); //ESP static ip
IPAddress gateway(192, 168, 1, 1);   //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0);  //Subnet mask
IPAddress dns(8, 8, 8, 8);  //DNS

const char* deviceName = "deviceName.com";

//On board LED Connected to GPIO2
#define LED 2  

// WiFi parameters
const char* ssid = "MyWifiSSID";
const char* password = "MyWifiPassword";

////Declare a global object variable from the ESP8266WebServer class.
ESP8266WebServer server(80); //Server on port 80
Servo servo;

void handleLEDon() { 
 Serial.println("LED on page");
 digitalWrite(LED,LOW); //LED is connected in reverse
 delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
 servo.write(0);
 server.send(200, "text/html", "LED is ON"); //Send ADC value only to client ajax request
}

void handleLEDoff() { 
 Serial.println("LED off page");
 digitalWrite(LED,HIGH); //LED off
 delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
 servo.write(120);
 server.send(200, "text/html", "LED is OFF"); //Send ADC value only to client ajax request
}

void setup(void)
{
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output

  // Start Serial
  Serial.begin(115200);
  WiFi.disconnect();  //Prevent connecting to wifi based on previous configuration
  
  WiFi.hostname(deviceName);      // DHCP Hostname (useful for finding device for static lease)
  WiFi.config(staticIP, subnet, gateway);
  WiFi.begin(ssid, password);

  WiFi.mode(WIFI_STA); //WiFi mode station (connect to wifi router only
  

  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.on("/ledOn", handleLEDon); //as Per  <a href="ledOn">, Subroutine to be called
  server.on("/ledOff", handleLEDoff);

  server.begin();                  //Start server
  Serial.println("HTTP server started");

  // Print the IP address
  Serial.println(WiFi.localIP());

  servo.attach(14); //GPIO15 = D5
}

void loop() {
  server.handleClient();          //Handle client requests
  delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
}

Arduino IDE Settings:

  • Preferences > Additional Boards Manager URLs > http://arduino.esp8266.com/stable/package_esp8266com_index.json
  • Tools > Board > Board Manager > esp8266 by ESP8266 Community version 2.6.3 installed
  • Tools > Board > NodeMCU 1.0 (ESP-12E Module)
  • Tools > Upload Speed > 115200
  • Tools > CPU Frequency > 80 MHz
  • Tools > Flash Size > 4MB (FS:2MB OTA:~1019KB)
  • Tools > Debug port > Serial
  • Tools > Debug Level > SSL+TSL_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP…UPDATE+UPDATER+OTA+OOM+MDNS
  • Tools > IwIP Variant > v2 Lower Memory
  • Tools > VTables > Flash
  • Tools > Exceptions > Legacy (new can return nullptr)
  • Tools > Erase Flash > Only Sketch
  • Tools > SSL Support > All SSL ciphers (most compatible)
  • Tools > Port > /dev/cu.SLLAB_USBtoUART

Power:
I am using the usb input to power the board. I read that if there is not enough power supplied to the board, it could behave strangely. I have powered the board from my computer’s USB, and a usb power brick that outputs 5V/2A. With both these power sources, the board worked and didn’t work at different times, which makes me think power isn’t the issue. Isn’t 5V/2A enough?

Internet connection:
I don’t think this is the issue, since the board is logging something in the Serial Monitor when I make the request, indicating it is connected to the internet properly. However, I will add the setup here just in case.

I am setting a static IP for the ESP8266 in code. I setup port forwarding on my router and can see the port is open using https://www.portchecktool.com/. I then setup a DDNS using NoIp.com. I then use IFFF to trigger a request to the domain name on a “Button Widget” tap.

So what is the power source for the servo?

does it happen without the servo connected?

Thanks for replies zoomkat and Juraj.

The servo is powered from the 3.3v pin on the board. The behavior is exactly the same with and without the servo plugged in. I even removed all servo related code and still there was no difference in behavior.

is the IP unique?

I've run the code you posted (on a WeMOS D1 development board, no servo attached) and it controls the LED on/off without any seeming issues. Below is what I see in the serial monitor, which is significantly different from what you have posted. I'm using windows 10 and IDE 1.8.10. I notice that using the static IP that is assigned to the board does not show up in the client list on my router, so that needs to be looked into.

WiFi connected
HTTP server started
192.168.0.9
LED off page
LED on page
LED off page
LED off page
LED on page

I think the reason you aren’t seeing all the logs in the Serial Monitor is because your debug level isn’t the same as mine:
Tools > Debug Level > SSL+TSL_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP…UPDATE+UPDATER+OTA+OOM+MDNS

For me, the static ip set in code is the same as the ip of the device connected to my router. The board consistently appears on my router with this ip every time I turn the board on.

"For me, the static ip set in code is the same as the ip of the device connected to my router. The board consistently appears on my router with this ip every time I turn the board on."

I see my board in my router's wireless client list, but with the IP address 192.168.0.5 that is normally assigned by the router, and not the 192.168.0.9 static ip that I assigned to the board. The 192.168.0.9 is working, so it might be a router listing issue. I have seen something that may indicate that making the assignment may differ as to when the static ip is assigned. Things may depend on when WiFi.begin and WiFi.config are called.

Thank you very much for your replies zoomkat. It makes me feel less hopeless to have someone trying to help!

My router is currently showing the board's IP address as 192168.1.176, which is what the value is in the code. I will keep an eye on it based on your advice, in case that changes.

However, I don't think the issue is with the static IP address, because even when the problem is happening, the board does receive something from the server request, since it logs something to the Serial Monitor. If the static IP was not the same as what I set in code, then my Port Forwarding wouldn't work and the board would never have received the request.

My hunch is I am doing something wrong with the ESP8266WebServer, since the server's subroutines are not called. However, I don't know what it could be, since it sometimes works fine.

After much searching, I made some adjustments to both the code and the Arduino IDE settings that have fixed this inconsistent behavior.

New Code:

// Import required libraries
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include <Servo.h>
#include <ESP8266mDNS.h>

//Static IP address configuration
IPAddress staticIP(192, 168, 1, 176); //ESP static ip
IPAddress gateway(192, 168, 1, 1);   //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0);  //Subnet mask
IPAddress dns(8, 8, 8, 8);  //DNS

//On board LED Connected to GPIO2
#define LED 2  

// WiFi parameters
const char* ssid = "MyWifiName";
const char* password = "MyWifiPassword";

////Declare a global object variable from the ESP8266WebServer class.
ESP8266WebServer server(80); //Server on port 80
Servo servo;

void handleLEDon() { 
 Serial.println("LED on page");
 digitalWrite(LED,LOW); //LED is connected in reverse
 delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
 ESP.wdtFeed(); 
 servo.write(1);
 server.send(200, "text/html", "LED is ON"); //Send ADC value only to client ajax request
}

void handleLEDoff() { 
 Serial.println("LED off page");
 digitalWrite(LED,HIGH); //LED off
 delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
 ESP.wdtFeed(); 
 servo.write(120);
 server.send(200, "text/html", "LED is OFF"); //Send ADC value only to client ajax request
}

void setup(void)
{
  pinMode(LED, OUTPUT);     // Initialize the LED_BUILTIN pin as an output

  // Start Serial
  Serial.begin(115200);
  WiFi.disconnect();  //Prevent connecting to wifi based on previous configuration
  ESP.eraseConfig();

  WiFi.config(staticIP, subnet, gateway);
  WiFi.mode(WIFI_STA); //WiFi mode station (connect to wifi router only
  WiFi.setSleepMode(WIFI_NONE_SLEEP);
  WiFi.begin(ssid, password);
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { // blink to indicate the device is trying to connect to WIFI
    digitalWrite(LED,LOW);
    delay(100);
    digitalWrite(LED,HIGH);
    delay(400);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  // Start the server
  server.on("/ledOn", handleLEDon); //as Per  <a href="ledOn">, Subroutine to be called
  server.on("/ledOff", handleLEDoff);

  server.begin();                  //Start server
  Serial.println("HTTP server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
  digitalWrite(LED,LOW);
  
  servo.attach(14); //GPIO15 = D5
  servo.write(1);
}

void loop() {
  server.handleClient();          //Handle client requests
  MDNS.update();

}

These two posts lead me to change the code:
https://www.esp8266.com/viewtopic.php?f=32&t=17126&p=74125&hilit=inconsistent#p74125

Arduino IDE Settings change:

  • Tools > Board > Board Manager > esp8266 by ESP8266 Community version 2.5.2 installed
  • Tools > Board > NodeMCU 1.0 (ESP-12E Module)
  • Tools > Upload Speed > 115200
  • Tools > CPU Frequency > 80 MHz
  • Tools > Flash Size > 4MB (2M SPIFFS)
  • Tools > Debug port > Serial
  • Tools > Debug Level > None
  • Tools > IwIP Variant > v2 Lower Memory
  • Tools > VTables > Flash
  • Tools > Exceptions > Disabled
  • Tools > Erase Flash > All Flash Contents
  • Tools > SSL Support > All SSL ciphers (most compatible)
  • Tools > Port > /dev/cu.SLLAB_USBtoUART

I hope this helps someone in the future.

you have WiFi.begin twice.
why MDNS?
instead of disconnect() I would use WiFi.persistent(false) and WiFi.setAutoConnect(false). now the ssid and password are written to the flash with every begin() and erased with every disconnect()

Yeah the 2.6.x version of the ESP core causes issues for me as well, mind you so does the 2.5.2 version (i'm using 2.4.2 for now)
These 2 lines can be omitted

 delay(20); // If the issue is caused by the watchdog timer, adding small delays fix the issue
 ESP.wdtFeed();

or just replace byyield();there is no need to slow the process down, just to reset the wdt & executed scheduled tasks should be sufficient, mind you the code does not show an actual need for that, it will happen soon enough (at the end of loop() )

If you are anyway using mDns lookup, you may as well just use a dynamic IP-address and add a button or 2 to your html code,and as i am writing this and look at your server.send(200, "text/html", "LED is ON");i realize that this was and may still be another issue, "LED is ON" is not an html page ! either you should send server.send(200, "text/plain", "LED is ON");or you should send a properly formatted html page, or your browser will get upset and it will result in exactly the sort of behavior that you have described.