Web server hangs few hours into operating (2560 Mega + ENC28J60)


I have a web server that checks and displays sensor data and relay states. A few hours into operation though it hangs (few hours as it is never the same period of time - can vary from 2 to 12). I can ping the device from CMD, but it is inaccessible through the browser or through my software that sends requests via HTTP. I researched and tried different things, and as reboot of the device is not really preferable in my case, as it resets the relays to their initial state, I set to a refresh of the server by calling out server.begin() every 5 minutes. It crashed several times since last night when I implemented this. Sometimes it hangs for a while and comes back, sometimes I need to reset the Arduino.
I considered memory shortage, but since I create some arrays of data (non-dynamic) and constantly use them, without using strings or some other type of information that stacks up, I ruled this out as an option, though I can be wrong. Here is my sketch, could someone tell me please, what do I do wrong?

P.S. As I exceeded the 9000 character, the sketch is in the attachment.

table_firmware2.ino (24.9 KB)

Is it allowed to call Ethernet.begin() and EthernetServer server.begin() mutiple times in the UIPEthernet library ? Did you see that somewhere in an example ? If you check the sensors every 29 seconds and reset the server every 300 seconds, it is only a matter of time before they happen at the same time.

You use many text strings, which are located in ram. What is the ram usage ?

without using strings or some other type of information that stacks up, I ruled this out as an option, though I can be wrong.

Yep, wrong:

String HTTP_req;
        HTTP_req += c;

There ya' go. Don't use String. Now you know why.

Some might suggest a library called TextFinder... It watches for keywords to go by, and it doesn't have to buffer a whole line. It's ok if you can block to wait for a response, but you seem to have timed tasks that need to run (i.e., CheckSensors and CheckInputs). If it's ok to let the timed tasks be deferred a little while, until after the Ethernet client disconnects, you could use it.

A Finite-State Machine (FSM) would be more flexible, allowing the check routines to be called during a client connection. An FSM handles each character from client.read() as it is received. However, the program structure is different from the while-loops you are currently using.

Also, you can save a bunch of RAM by using the F macro on these:

client.println( F("request.send(null);") );

All this RAM usage, plus unbounded String growth, is guaranteed to cause the flaky behaviour you're seeing.

Another suggestion; all these routines:

void Relay15State(EthernetClient cl)
{ if (digitalRead(relay[15]) == HIGH) {
    digitalWrite(relay[15], LOW);
    stateRelay[15] = 1;
  else {
    stateRelay[15] = 0;
    digitalWrite(relay[15], HIGH);

could be replaced by one short routine:

void RelayState( uint8_t num )
  byte oldState = digitalRead( relay[num] );

  digitalWrite( relay[num], !oldState );
  stateRelay[ num ] = oldState;

And change the calls from this:

          if (HTTP_req.indexOf("relay01") > -1) {

...to this:

          if (HTTP_req.indexOf("relay01") > -1) {
            RelayState( 1 );

Cheers, /dev

Thank you all for the replies! I'll work on your suggestions as soon as I come back from work. The detailed explanation you gave me was exactly what a newbie like me needed. :) Have a great day/night!