Arduino Garage Contoll with W5100 Ethernet Shield often freezes. Arduino works.

Hi all,

So I am controlling a sliding gate with a Arduino UNO R3 and a W5100 Shield on top. The Arduino serves 4 basic functions. The first 3 work flawlessley and always. The 4th function stops working after some time, however the first 3 still work, so the Arduino is not frozen or anything like that. Here is a short youtube video overview of the problem.

Working Functions:

  1. Monitoring weather the rollup garage gate is open or not. This works totally fine. It checks if the rollup garage door is open via a switch and if so, it sends a signal to also open the sliding gate as well. So both are either closed or open at the same time.

  2. Monitoring light barriers on the sliding gate. This also works totally fine. It only closes the sliding gate if there is nothing in the path of the laser beams. This also keeps monitoring them while it closes. The motor has a force shut off anyway. So its safe even without the light barriers.

  3. Sending signals to the sliding gate motor to open, stop or close the gate. This also works totally fine. It does so by activating a bank of relays that each short two leads that go to the motor controller.

Only temporarily working functions:

  1. Web server that lets you open or close the sliding gate from my home network. Also lets you open or close the roll up garage gate via the relay bank. This works, but only for a few hours or sometimes 1 or 2 days, but then the W5100 shield freezes and I cannot access it anymore from my browser. This is the main problem.

I don´t know much about networking, so I followed this tutorial. It works but not for long unfortunately. (The 511 resistor bug that can happen with this shield is rulled out. I have the correct 510 resistor.)

Main Tab:

/*
  Created by Rui Santos
  Visit: https://randomnerdtutorials.com for more arduino projects

  Arduino with Ethernet Shield
*/

#include <SPI.h>
#include <Ethernet.h>
int led = 4;
int pos = 0;
byte mac[] = { 0xDE, 0xAB, 0xBE, 0xEF, 0xFE, 0xED };   //physical mac address
byte ip[] = { 192, 168, 178, 95 };                      // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = { 192, 168, 1, 1 };                   // internet access via router
byte subnet[] = { 255, 255, 255, 0 };                  //subnet mask
EthernetServer server(80);                             //server port
String readString;

//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
int Schranke1Pin = 6;
int Schranke1 = 0;
int Schranke2Pin = 7;
int Schranke2 = 0;

int TorAufPin = 36;
int TorStopPin = 34;
int TorZuPin = 32;

int PlatformAufPin = 28;
int PlatformRunterPin = 30;

int LichtPin = 22;

int EndschalterGaragePin = 37; //Guckt ob das Garagentor auf oder zu ist.
int EndschalterGarage;
unsigned long StartMillis = 0;
unsigned long ElapsedMillis = 0;
unsigned long CurrentMillis = 0;
bool TimerActive = false;

unsigned long StartSchrankeMillis = 0;
unsigned long ElapsedSchrankeMillis = 0;
unsigned long CurrentSchrankeMillis = 0;
bool TimerSchrankeActive = false;


bool RolltorAufgegangen = false;  //Guckt ob das Garagentor gerade aufgegangen ist und ob es wieder zu muß.
bool CloseGatePerformed = false;  //Notitzzettel der sich merkt, ob der Befehl des schließens bereits gegeben wurde.
bool OpenGatePerformed = false; //Notitzzettel der sich merkt, ob der Befehl des öffnens bereits gegeben wurde.

//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);

  pinMode(Schranke1Pin, INPUT);
  pinMode(Schranke2Pin, INPUT);

  pinMode(TorAufPin, OUTPUT);
  pinMode(TorStopPin, OUTPUT);
  pinMode(TorZuPin, OUTPUT);

  pinMode(LichtPin, OUTPUT);

  pinMode(PlatformAufPin, OUTPUT);
  pinMode(PlatformRunterPin, OUTPUT);
  pinMode(EndschalterGaragePin, INPUT);
  EndschalterGarage = digitalRead(EndschalterGaragePin);
  digitalWrite(TorAufPin, HIGH);
  digitalWrite(TorStopPin, HIGH);
  digitalWrite(TorZuPin, HIGH);
  digitalWrite(LichtPin, HIGH);

  digitalWrite(PlatformAufPin, HIGH);
  digitalWrite(PlatformRunterPin, HIGH);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  pinMode(led, OUTPUT);
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

//LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP
void loop() {
  EndschalterGarage = digitalRead(EndschalterGaragePin);
  Schranke1 = digitalRead(Schranke1Pin); //Guckt ob die Lichtschranke frei ist oder nicht.
  Schranke2 = digitalRead(Schranke2Pin);

  if (RolltorAufgegangen == true && EndschalterGarage == LOW) // Diese Aktion wird ausgeführt, nachdem das Rolltor aufgegangen war (true) und nun automatisch (oder manuell durch den Platform Drücker) wieder schließt.
  {
    CloseGatePerformed = false;
    CloseGate();
    RolltorAufgegangen = false; //Dieser Teil wird benötigt, damit das Schiebetor nur dann automatisch wieder schließt, nachdem es automatisch geöffnet wurde. Sonst schließt er rund um die uhr das Schiebetor obwohl man es vielleicht manuell öffnen möchte nur weil das Garagentor zu ist.
  }

  if (EndschalterGarage == HIGH) //Wenn der Endschalter über dem Rolltor öffnet, weil das Garagentor sich öffnet, dann geht das Schiebetor auf.
  {
    if (RolltorAufgegangen == false)
    {
      OpenGatePerformed = false;
    }
    OpenGate();
    RolltorAufgegangen = true;

  }


  if (TimerActive == true)
  {
    CurrentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
    if (CurrentMillis - StartMillis >= 300000)
    {
      TimerActive = false;
      CloseGate ();
    }
  }

  if (TimerSchrankeActive == true)
  {

    Schranke1 = digitalRead(Schranke1Pin);
    Schranke2 = digitalRead(Schranke2Pin);

    if (Schranke1 == LOW || Schranke2 == LOW)
    {
      OpenGatePerformed = false;
      OpenGate();
      TimerSchrankeActive = false;
    }

    CurrentSchrankeMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
    if (CurrentSchrankeMillis - StartSchrankeMillis >= 40000)
    {
      TimerSchrankeActive = false;
    }
  }

  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {
          Serial.println(readString); //print to serial monitor for debuging

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
          client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
          client.println("<link rel='stylesheet' type='text/css' href='https://randomnerdtutorials.com/ethernetcss.css' />");
          client.println("<TITLE>Random Nerd Tutorials Project</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");
          client.println("<H1>Random Nerd Tutorials Project</H1>");
          client.println("<hr />");
          client.println("
");
          client.println("<H2>Arduino with Ethernet Shield</H2>");
          client.println("
");
          client.println("<a href=\"/?button1on\"\">Schiebetor AUF</a>");
          client.println("<a href=\"/?button1off\"\">Schiebetor ZU</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button2on\"\">Platform HOCH</a>");
          client.println("<a href=\"/?button2off\"\">Platform RUNTER</a>
");
          client.println("<p>Created by Rui Santos. Visit https://randomnerdtutorials.com for more projects!</p>");
          client.println("
");
          client.println("</BODY>");
          client.println("</HTML>");

          client.println("<p>Lichtschranke A</p>");
          client.println(Schranke1);

          client.println("<p>Lichtschranke B</p>");
          client.println(Schranke2);

          client.println("<p>EndschalterGarage</p>");
          client.println(EndschalterGarage);

          client.println("<p>Timer Active</p>");
          client.println(TimerActive);

          client.println("<p>Current Millis</p>");
          client.println(CurrentMillis);


          delay(1);
          //stopping client
          client.stop();
          //controls the Arduino if you press the buttons
          if (readString.indexOf("?button1on") > 0)
          {
            StartMillis = millis();
            OpenGatePerformed = false;
            OpenGate();
            TimerActive = true;

          }
          if (readString.indexOf("?button1off") > 0)
          {
            CloseGatePerformed = false;
            CloseGate();
          }

          if (readString.indexOf("?button2on") > 0)
          {
            digitalWrite(PlatformRunterPin, LOW);
            delay (200);
            digitalWrite (PlatformRunterPin, HIGH);
          }

          if (readString.indexOf("?button2off") > 0)
          {
            digitalWrite(PlatformAufPin, LOW);
            delay (200);
            digitalWrite (PlatformAufPin, HIGH);
          }
          //clearing string for next read
          readString = "";

        }
      }
    }
  }
}

Second Tab:

void OpenGate()

{
  if (OpenGatePerformed == false)
  {

    digitalWrite(TorStopPin, LOW);  //Gibt einen Impuls das Tor anzuhalten. Egal ob es sich bewegt, oder bereits still steht.
    delay (1100);
    digitalWrite(TorStopPin, HIGH);

    delay (1100); //Gibt eine kleine Wartepause bevor das Tor geöffnet wird.

    digitalWrite(TorAufPin, LOW); //Gibt einen Impuls das Tor zu öffnen.
    delay (1100);
    digitalWrite(TorAufPin, HIGH);
    
    OpenGatePerformed = true;
    digitalWrite(LichtPin, LOW);
  }
}

void CloseGate()

{
  EndschalterGarage = digitalRead(EndschalterGaragePin);
  if (EndschalterGarage == LOW) //Checkt ob das Garagentor geschlossen ist und schließt nur dann das Schiebetor
  {
    Schranke1 = digitalRead(Schranke1Pin);
    Schranke2 = digitalRead(Schranke2Pin);

    if (Schranke1 == HIGH && Schranke2 == HIGH && CloseGatePerformed == false)          //Schranke must be HIGH, I changed this to low for testing.
    {
      digitalWrite(TorStopPin, LOW);  //Gibt einen Impuls das Tor anzuhalten. Egal ob es sich bewegt, oder bereits still steht.
      delay (1100);
      digitalWrite(TorStopPin, HIGH);

      delay (1100);  //Gibt eine kleine Wartepause bevor das Tor geschlossen  wird.

      digitalWrite(TorZuPin, LOW); //Gibt einen Impuls das Tor zu schließen.
      delay (1100);
      digitalWrite(TorZuPin, HIGH);
      CloseGatePerformed = true;
      digitalWrite(LichtPin, HIGH);

      TimerSchrankeActive = true;
      StartSchrankeMillis = millis();
    }

    if (Schranke1 == LOW || Schranke2 == LOW)
    {

      TimerActive = true;
      StartMillis = millis();

    }

  }
}

You’re using a String object, which is often the culprit in “it works for a while” cases, especially when you don’t have much memory to spare. Try using a C string instead.

Before that though, get yourself some more free memory using the F macro, e.g.

          client.println(F("<HTML>"));

Lots of opportunity there to save.

wildbill:
You’re using a String object, which is often the culprit in “it works for a while” cases, especially when you don’t have much memory to spare. Try using a C string instead.

Before that though, get yourself some more free memory using the F macro, e.g.

          client.println(F("<HTML>"));

Lots of opportunity there to save.

Thank you. I looked into the whole string vs char topic but I find it difficult to understand.
Are you refeering to this area of code?

   client.println("HTTP/1.1 200 OK"); //send new page[color=#222222][/color]
          client.println("Content-Type: text/html");[color=#222222][/color]
          client.println();[color=#222222][/color]
          client.println("<HTML>");[color=#222222][/color]
          client.println("<HEAD>");[color=#222222][/color]
          client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");[color=#222222][/color]
          client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");[color=#222222][/color]
          client.println("<link rel='stylesheet' type='text/css' href='https://randomnerdtutorials.com/ethernetcss.css' />");[color=#222222][/color]
          client.println("<TITLE>Random Nerd Tutorials Project</TITLE>");[color=#222222][/color]
          client.println("</HEAD>");[color=#222222][/color]
          client.println("<BODY>");[color=#222222][/color]
          client.println("<H1>Random Nerd Tutorials Project</H1>");[color=#222222][/color]
          client.println("<hr />");[color=#222222][/color]
          client.println("
");[color=#222222][/color]
          client.println("<H2>Arduino with Ethernet Shield</H2>");[color=#222222][/color]
          client.println("
");[color=#222222][/color]
          client.println("<a href=\"/?button1on\"\">Schiebetor AUF</a>");[color=#222222][/color]
          client.println("<a href=\"/?button1off\"\">Schiebetor ZU</a>
");[color=#222222][/color]
          client.println("
");[color=#222222][/color]
          client.println("
");[color=#222222][/color]
          client.println("<a href=\"/?button2on\"\">Platform HOCH</a>");[color=#222222][/color]
          client.println("<a href=\"/?button2off\"\">Platform RUNTER</a>
");[color=#222222][/color]
          client.println("<p>Created by Rui Santos. Visit https://randomnerdtutorials.com for more projects!</p>");[color=#222222][/color]
          client.println("
");[color=#222222][/color]
          client.println("</BODY>");[color=#222222][/color]
          client.println("</HTML>");[color=#222222][/color]
[color=#222222][/color]
          client.println("<p>Lichtschranke A</p>");[color=#222222][/color]
          client.println(Schranke1);[color=#222222][/color]
[color=#222222][/color]
          client.println("<p>Lichtschranke B</p>");[color=#222222][/color]
          client.println(Schranke2);[color=#222222][/color]
[color=#222222][/color]
          client.println("<p>EndschalterGarage</p>");[color=#222222][/color]
          client.println(EndschalterGarage);[color=#222222][/color]
[color=#222222][/color]
          client.println("<p>Timer Active</p>");[color=#222222][/color]
          client.println(TimerActive);[color=#222222][/color]
[color=#222222][/color]
          client.println("<p>Current Millis</p>");[color=#222222][/color]
          client.println(CurrentMillis);[color=#222222][/color]

If so, should I replace this:

  client.println("<HTML>”);
client.println("<HEAD>”);

With this?

client.println(F("<HTML>”));
client.println("<HEAD>”);

So just add the (F……) part to every client.println?
Alternatively, could I from time to time reset the memory if it becomes full? If this is like a water bucket fully filling up, just reducing the water input will only slow it down, but not stop the problem entirely. Sorry, I am not that good with memory and programming. CAD is more my thing.

MaxMaker:
So just add the (F……) part to every client.println?

Pretty much, yes, if it's just a piece of static text like those examples.

Alternatively, could I from time to time reset the memory if it becomes full? If this is like a water bucket fully filling up, just reducing the water input will only slow it down, but not stop the problem entirely.

That's the curse of String objects. increasing the amount of free memory with the F macro might actually solve the problem. Or it might make it fail on a weekly basis rather than daily. Or monthly. It's hard to know.

There are various ways you can reboot the Arduino to reset the system, but better to actually fix your code I think.

@ MaxMaker be careful with the usage of the F-Makro.
The F-Makro works fine for Serial.print, but I advice against to use it together with Ethernet.h client.print because it will enlarge your TCP traffic and slow down your communication.

instead use a buffer or the StreamLib library from Juraj. Here you can read more about how to optimize the webserver:
https://werner.rothschopf.net/microcontroller/202011_arduino_webserver_optimize_en.htm

german: https://werner.rothschopf.net/microcontroller/202011_arduino_webserver_optimieren.htm

additionally you could check ALL your variables if you really need a 2 byte integer. Lot of your int will fit in a byte. If they never change it's value, mark them as const:

const byte Schranke1Pin = 6;
const byte Schranke2Pin = 7;

by the way, this forum has an active German section also...

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.