The use of the ESP8266 in the world of IoT

User avatar
By storckm
#87704 So I put together a garage door opener, but am having problems: it stops running after a day or two--sometimes after only a few hours.

The code code running on the esp8266 is below. To be specific, it's the sparkfun thing dev version. Pin 14 connects to a photorelay (via a resistor), pin 16 connects to a NO reed switch, and pin 4 connects to a three lead piezo buzzer (via a little circuit with a transistor, inductor, and a couple of resistors). The system works fine, but after a couple of days, it becomes unresponsive, and I can't figure out why.

I soldered a capacitor across the 5V power input and the 3.3V power. Currently, I have it running from the USB of a raspberry pi (v.2). At first, I'd see a few low voltage messages when I ran dmesg on the pi, but after switching power supplies, I don't see that any longer. But the board still hangs after a day or two. It still responds to pings, and an nmap scan of the LAN shows port 80 is "filtered." When the board is connecting properly, it says "open."

Having it running from the pi (on wifi) lets me reboot the pi from my cell phone. So I can still open the door if I'm standing outside with my bicycle. But it's not an ideal solution. I might as well run the door from the pi and skip the esp8266. That's overkill, and I made an enclosure for the esp8266, so I'd rather not.

Is there something wrong with the code? Or does more need to be done on the hardware side to ensure stability? Please help with some ideas of what to try next.

Code: Select all
#include <ESP8266WiFi.h>


const int sensor = 16;
const int door = 14;
const int buzz = 4;
const int led = 5;


WiFiServer server(80); //This is the port to listen. Need to be in your router to open the door remotely. If you need only local. Put 80 instead and forget the router part
WiFiClient client;

const char* SSID = "xxx";
const char* PASS = "xxx";

//Static IP Address
IPAddress ip(x.x.x.x);
IPAddress gateway(x.x.x.x);
IPAddress subnet(255, 255, 255, 0);


void setup() {
  Serial.begin(115200);
  pinMode(sensor, INPUT);
  pinMode(door, OUTPUT);
  pinMode(buzz, OUTPUT);
  pinMode(led, OUTPUT);
  tone(buzz, 1193);
  digitalWrite(door, LOW);
  digitalWrite(led, HIGH); 
  delay(150);
  digitalWrite(led, LOW);
  digitalWrite(buzz, LOW);
 

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(SSID);
  WiFi.hostname("GDM");

  WiFi.config(ip, gateway, subnet);

  WiFi.begin(SSID, PASS);

  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(led, HIGH);
    delay(400);
    Serial.print(".");
    digitalWrite(led, LOW);
    delay(100);
  }
  Serial.println();
  Serial.println("WiFi connected");
 
  //Start the server
  server.begin();
  Serial.println("Server started");

  //Print the IP Address
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  digitalWrite(led, HIGH);
  delay(100);
  digitalWrite(led, LOW);
  delay(400);
}

void loop()
{
  client = server.available();
  if (client)  // if you get a client
  {
    char getLine[128];
    int i = 0;
    bool getLineFound = false;
    bool currentLineIsBlank = true;

    Serial.println("");
    Serial.println("new 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 1 byte from client
        Serial.print(c);

        if (!getLineFound && i < sizeof(getLine))
        {
          //save the char to getLine
          getLine[i] = c;
          i++;
        }
       
         // Request end: Now responds to it
        if (c == '\n' && currentLineIsBlank) // respond to client only after last line is received, last line is blank and ends with \n
        {
          ProcessRequest(getLine);
          break;
        }

        if (c == '\n') // end of the line, next char read will be a new line
        {
          if (!getLineFound) //the GET line is the first line from the client, save it for later
          {
            getLineFound = true;

            //strip off the HTTP/1.1 from the end of the getLine
            const char *ptr = strstr(getLine, "HTTP/1.1");
            if (ptr)
              getLine[ptr - getLine - 1] = '\0';
          }

          currentLineIsBlank = true;
        }
        else if (c != '\r') //text char received
        {
          currentLineIsBlank = false;
        }
      } //end if (client.available())
    } //end while (client.connected())


    // close the connection
    digitalWrite(led, HIGH);
    delay(120); //allow client to receive the data
    digitalWrite(led, LOW);
    client.stop();
    Serial.println("Client disconnected");
  }
}


void mainPage(WiFiClient& client)
{
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: keep-alive\r\n");
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("<title>GDM</title>");
  client.println("<script>");
  client.println("function GetSwitchState() {");
  client.println("nocache = \"&nocache=\"+ Math.random() * 1000000;");
  client.println("var request = new XMLHttpRequest();");
  client.println("request.onreadystatechange = function() {");
  client.println("if (this.readyState == 4) {");
  client.println("if (this.status == 200) {");
  client.println("if (this.responseText != null) {");
  client.println("document.getElementById(\"switch_txt\").innerHTML = this.responseText;");
  client.println("}}}}");
  client.println("request.open(\"GET\", \"ajaxswitch\" + nocache, true);");
  client.println("request.send(null);");
  client.println("setTimeout('GetSwitchState()', 1000);");
  client.println("}");
  client.println("</script>");
  client.println("</head>");
  client.println("<body onload=\"GetSwitchState()\">");
  client.println("<center>");
  client.println("<h1>GDM</h1>");
  client.println("<hr>\r\n<br>");
  client.println("<button style=\"width:100%;font-size: 50px;\"><a href=\"/ready/activate\">ACTIVATE</a></button>");
  client.println("<p id=\"switch_txt\">Garage Door is now:</p>");
 
  //uptime
   int SecUp = millis()/1000;
   int sec = SecUp%60;
   int min = (SecUp/60)%60;
   int hr = (SecUp/(60*60))%60;
   int day = (SecUp/(24*60*60))%24;

   client.println("Uptime: ");
   client.println(day);
   client.println(" days, ");
   client.println(hr);
   client.println(" hours, ");
   client.println(min);
   client.println(" minutes, ");
   client.println(sec);
   client.println(" seconds");
   client.println("</p>");
  client.println("</center>\r\n</body>\r\n</html>");

}


void redirect(WiFiClient& client)
{
  client.println("HTTP/1.1 303 See other");
  client.println("Location: /ready");
}

void ActivateDoor()
{
  tone(buzz, 1193);
  delay(800);
  yield();
  digitalWrite(door, HIGH);
  delay(800);
  digitalWrite(door, LOW);
  digitalWrite(buzz, LOW);
}

void doorState(WiFiClient& client){
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: keep-alive\r\n");
 
  if (digitalRead(sensor) == 0) {
    client.println("Current State: <font color=\"red\">Open</font>");
  }
  else {
    client.println("Current State: <font color=\"green\">Closed</font>");
  }
}


void ProcessRequest(char* getLine)
{
 
  if (strstr(getLine, "GET /ready") != NULL)
  {
    if (strstr(getLine, "GET /ready/activate") != NULL)
    {
      Serial.println("ACTIVATING");
      ActivateDoor();
      redirect(client);
    }
    else
    {
      mainPage(client);
    }
  }
  else if(strstr(getLine, "GET /ajaxswitch") != NULL)
    {
      doorState(client);
   }
}
User avatar
By schufti
#87731 if you are on a recent esp core (2.7.x,2.6.x,2.5.x) try downgrading to next lower major. WiFi and webserver stability is an issue ...
it might be helpfull to keep the esp connected via serial to see what is happening. Go for 74880 baud (instead of 115200) to also see boot messages in case of wdt / reboot issues.