loop() stops?

It seems my loop() function stops working after about 18-24 hours. Is there a way to call a cold reboot periodically?

I'm using a number of ESP8266 processors and they all exhibit the same problem. Maybe I should not write to serial if there's no serial device? Maybe I should try to catch web exceptions (is there such a thing) in the web code?

I'm from a Windows programming background so a lot of this is very new to me, but I'm having a great time making things!

Here's my code, it basically waits for a URL /trigger and then simply does a digitalWrite(pin,LOW) to ground signal on my garage door opener to open / close the garage door. I have another on my electric gate, same problem.

It also supports a diagnostics call (/diag) that dumps a few parameters and in the main loop I do a call to a web server to tell it the ESP is still online. This is what stops working after a day or so. The web calls to the ESP9266 still works though - /trigger and /diag still does it's thing, but the loop() loop stops.

I've removed the actual signal pin on the garage door / gate pcb - thinking there might be a spike that comes in and upsets the ESP, but the problem remains.

My code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>

const char* ver="Bean1.4";
const String deviceName="Hek";
const int relay1Pin=12;
const int relay2Pin=13;
const int ledPin=5;
const int checkinPeriod = 1000*600; //10 minutes
const char* wifiSSID="Hein";
//const char* wifiSSID="Mia";
const char* wifiPass="abc0000000";
const IPAddress fixedIP(10, 6, 77, 30);
const IPAddress fixedSubnet(255,255,255,0);
const IPAddress fixedGateway(10,6,77,2);
const IPAddress fixedDNS(8,8,4,4);
const char* espServer = "10.6.77.3";

IPAddress myip,mySubnet,myGateway,myDNS;
long rssi;
String myMac = "";

unsigned long startTime = 0;
unsigned long lastCheckin = 0;
unsigned long lastTrigger = 0;

ESP8266WebServer server(80);
WiFiClient webClient;

void setup() {
  // put your setup code here, to run once:
  startTime = millis();
  Serial.begin(115200);
  delay(10);
  Serial.println("");
  Serial.print("Starting up ");
  Serial.println(ver);

  pinMode(relay1Pin,OUTPUT);
  pinMode(relay2Pin,OUTPUT);
  pinMode(ledPin,OUTPUT);
  digitalWrite(relay1Pin,HIGH);
  digitalWrite(relay2Pin,LOW);
  digitalWrite(ledPin,HIGH); //I'm starting up
  delay(1000);
  digitalWrite(ledPin,LOW); //I'm starting up
  Serial.println("setup complete");

  //Connect to Wifi
  Serial.println("");
  Serial.print("Connecting to WiFi ");
  Serial.print(wifiSSID);
//  WiFi.config(myIP,dns,gateway,subnet);
  WiFi.begin(wifiSSID,wifiPass);

  while(WiFi.status()!=WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    myip=WiFi.localIP();
    myGateway=WiFi.gatewayIP();
    mySubnet=WiFi.subnetMask();
    myMac=WiFi.macAddress();
  }
  Serial.println("");
  Serial.println("Connected OK");
  
  server.on("/diag", handleDiag);
  server.on("/trigger", handleTrigger);
  server.begin();
  Serial.print("www server started: http://");
  Serial.print(myip);
  Serial.println("/");
  Serial.print("Gateway / Subnet / MAC: ");
  Serial.print(myGateway);
  Serial.print(" / ");
  Serial.print(myMac);
  Serial.print(" / ");
  Serial.println(mySubnet);

  Serial.println("Connected to wifi");
  checkIn();
}

void handleDiag() {
  rssi=WiFi.RSSI();
  String s = "OK.
Uptime: "+String((millis()-startTime) / 1000 / 60 / 60)+" hours
Last Trigger: "+String((millis()-lastTrigger)/1000)+" s ago"+
    "
RSSI: "+String(rssi)+
    "
Gateway: "+String(myGateway)+
    "
Subnet: "+String(mySubnet);
  server.send(200, "text/html", s);
}

void handleRoot() {
  server.send(200, "text/html", "<h1>You are connected</h1>");
}

void handleTrigger() {
  server.send(200, "text/html", "Trigger OK");
  digitalWrite(relay1Pin,LOW);
  digitalWrite(ledPin,LOW);
  delay(500);
  digitalWrite(ledPin,HIGH);
  digitalWrite(relay1Pin,HIGH);
  lastTrigger=millis();
}

void loop() {
  unsigned long t;
  server.handleClient();

  //Flash LED if WiFi is down

  if (WiFi.status()!=WL_CONNECTED) {
    digitalWrite(ledPin,LOW);
    delay(500);
    digitalWrite(ledPin,HIGH);
    delay(500);
    }
  else //otherwise check in every 10 seconds
    { 
    digitalWrite(ledPin,HIGH);
    if (checkinPeriod < (millis()-lastCheckin)) {
      Serial.print("****Eval Reg: ");
      Serial.print(checkinPeriod);
      Serial.print(" > ");
      Serial.println(millis()-lastCheckin);
      checkIn();
    }
  }
  ESP.reset();

}

//Call in to ESPresso server to update IP etc and confirm alive
void checkIn() {
  lastCheckin = millis();
  Serial.println("\nStarting registration...");
  // if you get a connection, report back via serial:
  if (webClient.connect(espServer, 80)) {
    rssi=WiFi.RSSI();
    Serial.println("connected to server");
    // Make a HTTP request:
    webClient.println("GET /ESPresso.dll/RegisterDevice?DeviceName="+deviceName+"&DeviceMac="+myMac+"&RSSI="+String(rssi)+"&app="+ver+" HTTP/1.1");
    webClient.println("Host: "+String(espServer));
    webClient.println("Connection: close");
    webClient.println();
    Serial.println("Sent stuff");
  }  
  while(webClient.available()){
    String line = webClient.readStringUntil('\r');
    Serial.println(line);
  }  
}

Thanks for your patience with my green code! Any help would be hugely appreciated.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

Problems that take time to emerge are often the result of the String class corrupting memory.

...R

    if (checkinPeriod < (millis()-lastCheckin)) {
      Serial.print("****Eval Reg: ");
      Serial.print(checkinPeriod);
      Serial.print(" > ");
      Serial.println(millis()-lastCheckin);
      checkIn();
    }

If it is not yet time to checkin, print that it is not yet time and checkin.

Strange...

Robin2:
It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

Problems that take time to emerge are often the result of the String class corrupting memory.

...R

Ok, thank you - will try that.

Whandall:
If it is not yet time to checkin, print that it is not yet time and checkin.

Strange...

If you're referring to the Serial.print(" > "); I was playing around with the conditions and didn't update the debug trace. Should be < of course, but doesn't affect logic.

I was confused by the uncommon order of the timing comparison and the contradicting output.

Not my best work :slight_smile: Result of too much fiddling with the code, I'm cleaning it up. If I can just figure out why loop() stops or how to restart it on a schedule...