as many others I wanted to create a NodeMCU based web server from which I can control a relay. The problem I'm facing with is that after a while (couple minutes) the web page running on my nodeMCU stops responding.
I have tried pretty much everything I have found on forums about this topic without any success. What I found though on my own if that I include a meta tag in the HTML code which forces the client browser to reload the page in every 15 seconds
<meta http-equiv="Refresh" content="15; url='/'">
then the webserver keeps working. So for me it seems that the server just stops working if it doesnt get a connection periodically.
Any ideas how can make the server keep working even if there are no connections happen for a while?
thx!
(eg: one topic I have found describing the same behaviour, but I believe it has nothing to do with the real solution: Here)
Sure... this is the code I have started to based my work on and it shows the same behaviour. My code is just an extension with different html content and some relay controlling.
Note: the problem is that by time the page becomes unavailable. If you refresh the page periodically (before it becomes unavailable) then the page stays available. (but of course this is not a solution). I have also tried to stop and to restart the server object every couple minutes, but that doesnt help either.
#include<ESP8266WiFi.h>
#define LED D2 //LED at GPIO4 D2
const char * ssid = "ssidhere";
const char * password = "passwordhere";
unsigned char status_led = 0;
WiFiServer server(80);
void setup() {
Serial.begin(9600);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started at...");
Serial.println(WiFi.localIP());
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while (!client.available()) {
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
// Match the request
// Return the response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("");
// Display the HTML web page
client.println("<!DOCTYPE HTML>");
client.println("<HTML>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<h1>LED CONTROL<h1>");
client.println("<p><a href=\"/ledon\" > < button class = \"button\" > ON < /button></a > ");
client.println("<p><a href=\"/ledoff\" > < button class = \"button2\" >");
client.println("</body></html>"); delay(1); Serial.println("Client disonnected"); Serial.println("");
}
Try adding this line at the top of loop()
Serial.println(WiFi.status() == WL_CONNECTED);
What do you see on serial monitor? What do you see after the page stops responding?
Yeap, I have tried that. Actually I've defined an interrupt running every 5s:
Yeah, thats a mistake in the HTML, but has absolutely nothing to do with the problem. The problem persists even if you dont even have anything in the HTML part. The key is that the server itself stops responding.
Probably not a good idea. Using Serial.print() inside an interrupt is going to make the interrupt quite long to run and esp8266 does not like that because it can interfere with background wi-fi maintenance activities. Better to just use millis() to limit the test to every 5s.
Probably not a good idea. Using Serial.print() inside an interrupt is going to make the interrupt quite long to run and esp8266 does not like that because it can interfere with background wi-fi maintenance activities. Better to just use millis() to limit the test to every 5s.
Thats true Paul, but it has nothing to do with the root cause. I've created this interrupt just to see if I can get more info about the problem I see. I would be very happy if I could delay this
FYI, using the F() macro on esp8266 is pointless. I don't think it actually does anything except on AVR based Arduino. On esp, all code is fetched from SPI flash chip into RAM before it is run, and there is no shortage of RAM.
Ok... new clue!!! I have pasted the Serial.println(WiFi.status() == WL_CONNECTED); to my main loop which kept responding with 1. And then suddenly it stopped doing it. The last message displayed by the main loop is "new client" which - I assume - means that my code is stuck at right here: while(!client.available()){delay(1);}
I believe we are on the right track, although I dont know what should I if the client never becomes available.
UPDATE: the latter described behavior is browser related. I use crome and have just noticed that even if I just start typing the IP of the nodeMCU to the url field, it sends a request to the unit immediately. Its not like this with Firefox.
I'm getting the same problem while testing your code:
15:11:18.060 -> 0⸮~?⸮4⸮!⸮{⸮OzI{⸮⸮8V⸮⸮
15:11:18.193 ->
15:11:18.193 -> Connecting to granary
15:11:18.691 -> .......
15:11:22.405 -> WiFi connected
15:11:22.438 -> Server started at...
15:11:22.438 -> 192.168.1.145
15:11:35.705 -> new client
15:11:35.705 -> GET /ledon HTTP/1.1
15:11:35.739 -> Client disonnected
15:11:35.739 ->
15:11:39.390 -> new client
15:11:39.390 -> GET /ledoff HTTP/1.1
15:11:39.423 -> Client disonnected
15:11:39.456 ->
15:23:14.491 -> new client
15:23:14.525 -> GET /ledon HTTP/1.1
15:23:14.557 -> Client disonnected
15:23:14.557 ->
15:23:16.448 -> new client
The strange thing is, when I clicked the ON button at 15:23:14, I only clicked it once. The esp responded correctly. But then 2 seconds later it reports a new client has connected. But I only clicked once. Now, if I click again, Firefox just hangs.
So it seems that a reboot is not necessary, we can simply break from the loop. I dont have the faintest idea whats going on, but I'm fairly happy with the fact that now my webpage seems working fine.
Let me know if you need the full source code, I'm happy to share it. (Although you might frown when you see my crappy style of programming). And for sure thanks for holding my hands while I was going thru this
To me, that still feels like a workaround, not a proper fix. We don't understand what's going on or why.
Is still like to understand why the server thinks a client is trying to connect.
One thing that I've seen in other sketches like this, and this one, that doesn't sit right with me, is that we are printing "client disconnected" without actually checking if that's true.
I fully agree. I've been programming 30+ years and being fluent (15+ years) in a language in which I would never be this sloppy. Its just that for me I'm a bit lazy to figure out whats going on and I'm happy that I could make it work.