Arduino Uno R3 being used as a web server periodically failing

Hello Arduino community!

I am having an issue that i've not yet been able to figure out. I have an Arduino Uno R3 with a digital I2C light sensor on it and an ethernet shield. I'm using this setup to take some readings from the sensor, do some math and other fun stuff, and then publish to a web-server. I have been having issues with the Arduino periodically failing, where the serial printing (used for troubleshooting purposes) will stop and the IP address will give me a Proxy Error "Connection Refused" message. The arduino essentially just hangs. I initially thought that this might be a memory leak issue so I went through my code trying to optimize it and stored my strings in flash using PROGMEM. I also attempted to use the Ethernet2 library as I read that it has fixed memory leak issues, but I could not get it to work. I have attached my code. I am honestly baffled by this one. Any ideas would be much appreciated.

TSL2561Counter.ino (11.2 KB)

TSL2561Counter.ino (11.2 KB)

There is no reason to cast things to a double. Float and double are the same thing.

Also multiple places you store millis() into a long. Millis() and associated math should be done on unsigned longs, unless you want rollovers to occur sooner than later.

This is ironic:

  Serial.println("DES TSL2561 Light Sensor Test");
        Serial.print("freeMemory()=");

You are concerned enough about memory to test hoe much is available, but not enough to use the F() macro to minimize it or enough to tell us what the output shows.

The while(client.connected()) loop should contain a while(client.available()) statement, rather than a if(client.available()) statement.

You want to make sure that you have read everything the client sends. Otherwise, stopping the client will fail, since there is unread data, leaving a socket unavailable. 4 times, and you are out of sockets.

The I2C is blocking in some parts.
If you for example use a breadboard for the I2C device, you might get trouble because of bad contacts.

Since the sensor is 3.3V, it might work and it might not.
To be sure it will work, you could use a I2C level shifter or an Arduino Leonardo board.

The webserver part is the only part that uses a lot of memory, so I'm guessing it will fit in a Arduino Uno. If you plan to use the microSD card as well, you might need an Arduino Mega 2560.

I had this yesterday, my I2C was blocking, causing my webserver to stop. I do have a level shifter, but I forgot a capacitor for 3.3V decoupling on the I2C module. Today it runs fine.

Do you use Arduino 1.0.5 ?
There has been a number of improvements in previous versions, so I suggest to use the newest Arduino software.

Sorry, I meant to also say that after tests printing out the available memory I found that the number was constant and not decreasing as I had originally expected. I'm also realatively new at this and am not familiar with the F() macro.

PaulS:
The while(client.connected()) loop should contain a while(client.available()) statement, rather than a if(client.available()) statement.

Would this while loop need a break; of it's own?

Would this while loop need a break; of it's own?

Neither of the while loops (for connected or for available) needs a break; statement. You want to read everything that the client has to say, every time a client connects.

PaulS:
Neither of the while loops (for connected or for available) needs a break; statement. You want to read everything that the client has to say, every time a client connects.

When i remove the break; statements the IP never loads and the Arduino hangs. it works when it looks like this:

void ServerLoop(){
  // listen for incoming clients
  
        
  EthernetClient client = server.available();
  if (client) {
    //Serial.println("new client");
    // an http request ends with a blank line
    TextFinder finder(client); 
    while (client.connected()) {
      while (client.available()) {
        if( finder.find("GET /") ) { //get request
          if(finder.findUntil("q=","\n")){  // then we are programming
              long id = finder.getValue();
              if (id == 1){
                machineResponse(client);
              }
              if (id == 2){
                resetCounters(client);
              }
          }
          else{
              sendServerResponse(client);
          }
          break;
        }
       break; 
      }
      break;
    }
    // give the web browser time to receive the data
    delay(10);
    client.stop();
    delay(10);    
  }
}

it works when it looks like this:

I'd ditch the finder instance. It takes over control of reading, or not, from the client. Personally, I refuse to give up such control. But, then, I know how to store characters in an array, NULL terminate the array, do string parsing, etc.

How would I get rid of the finder instance while maintaining the current fuctionality?

If the failure is random, maybe it's something electrical that has nothing to do with your code. Put a piece of code in to toggle a pin high/low during execution. Maybe two or more pins, at different points so you can monitor where your code is without using an ICE or serial debug tool. Put a scope on the pins and watch them. Also use the scope to watch the supply pins, I2C interface, reset pin of the uC, etc... If it isn't your code that's causing the problem, maybe it's something from an electrical standpoint.

How often is the failure occurring (hours, days, etc.)? You might want to drop back to basic code that connects to the server with dummy info to see if the freeze still occurs. The below might be of interest if the freezing continues.

http://playground.arduino.cc/Code/WebClient

zoomkat:
How often is the failure occurring (hours, days, etc.)?

The freezing was occuring very frequently (every 20 minutes or so). Since then however I have simplified my ServerLoop code more and just finished a test where it lasted almost 2 hours without freezing.

Does that mean it ran almost 2 hours and it still hasn't failed? Or it ran almost 2 hours and then failed.

I use this. It works well.
http://playground.arduino.cc/Code/WebServerST

SurferTim:
Does that mean it ran almost 2 hours and it still hasn't failed? Or it ran almost 2 hours and then failed.

it failed just under 2 hours, but I think I may have found out why. I sent it a request that caused it to hang in a section of the serverLoop. After making sure that there is no opportunity for that to happen (by adding else {client.close();} statements) I believe I have fixed the problem and am running another test to confirm now. I'll check out those links as well to see if theres anything else i can do if it becomes necessary.

Thanks to all so much for your help and advice

PaulS:
The while(client.connected()) loop should contain a while(client.available()) statement, rather than a if(client.available()) statement.

You want to make sure that you have read everything the client sends. Otherwise, stopping the client will fail, since there is unread data, leaving a socket unavailable. 4 times, and you are out of sockets.

Is that right? It's not what the Ethernet library's example web server does, and doesn't seem logically necessary since the 'if' statement would be evaluated repeatedly while the client remains connected.

PeterH:
Is that right? It's not what the Ethernet library's example web server does, and doesn't seem logically necessary since the 'if' statement would be evaluated repeatedly while the client remains connected.

It seems to function both ways, and I'm not sure if there is a difference between the two.