Reconnecting to Ethernet

I've got a program that reads information off the web trying to update information, like the current temperature. I'd like to make it more robust, such that if it loses connection (such as the ethernet cable being unplugged) it can re-establish connection automatically and move on. Right now the program seems to hang if I unplug the ethernet. Any idea how to do this?

I can supply the code if necessary.
Thanks!

I don't know if you are using client or server, but this client code downloads google every 10 seconds. It does ok if you unplug the cable, wait a few fails, then plug it in again.

Don't do that to Google too long. Change it to your server ip.

Thanks for the reply. It does indeed reconnect if you unplug it, but only when it's unplugged between requests.

The problem I have is that the code hangs if you unplug the ethernet when it is in the "while" loop and reading the client. Any thoughts on how to avoid this? I need the code to be robust enough that if it loses internet connection, it can pick up where it left off or start over when it reconnects. Thanks.

Are you talking about my code or yours?

You are a better person than I am. There is no way I can unplug that cable during the connection. Mine is way too fast.

Haha, I don't think my reaction time is that fast. But I have the same problem with both my code and yours.

Using google's server, the page has enough data to load that it takes an appreciable amount of time. Try unplugging the cable while you see the characters scrolling across the serial monitor. Perhaps I'm not describing this well...

I tried it with the Google home page, and I see what you mean. It took a while to see if it was going to time out, but it hasn't yet. I've waited a few minutes and it is still locked up.

It appears that client.connected() is returning true when it shouldn't be. I'll take a look at the w5100 code when I have time.

OK. Try this. It adds a 10 second timeout. If no characters are received for 10 seconds, it closes its end of the connection.

  int noCharCount = 0;
  
  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      noCharCount = 0;
    }

    delay(10);
    noCharCount++;

    // change this value to suit you. this is 10 seconds    
    if(noCharCount > 1000)
    {
      Serial.println();
      Serial.println("Timeout");
      client.stop();
    }
    
  }

That's a good idea, I'll give it a go. Any idea if the false positive is just a nature of the ethernet functionality? My only thought is that client.connected() returns true if the connection closed but there is unread data. This should return a TRUE value for client.available() afterwards to trigger the client.read(), right?

I tested it on IDE v1.0.1-rc1. It closes the connection and then will resume the downloads as soon as the cable is reconnected. Let the while() loops exit normally. The client.stop() call will do that.

That seems to do the trick! Thanks for the help.

Hi guys,

I think my issue may be related to what's previously described in this forum post.

I have connected the ethernet board (not the PoE version) to my Arduino, along with a PIR sensor. So, as you may have surmised, I'm asking it to watch for motion and if it detects motion, request a script that I have out there on a server. This script then shoots me a text message letting me know that my sensor was tripped.

It detects motion reliably, but it only successfully fetches the php script that sends the text message the first time.

Could the failed subsequent connections be because it's holding open that original, successful HTTP connection open too long, preventing the arduino from reaching out again with subsequent GET requests for the script?

Here's my sketch:

//this comes directly matt williamson's work
#include <SPI.h>
#include <Ethernet.h>

// Declare Constants
const int sensorPin = 2;           // PIR Sensor is attached to digital pin 2
const int ledPin = 13;             // Built-in LED
const int ledBlinkTime = 500;      // Blink one for half a second while calibrating

// Wait for the seonsor to calibrate (20 - 60 seconds according to datasheet)
// 60 Seconds in milliseconds
const unsigned int calibrationTime = 60000;

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
char serverName[] = "example.com";

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
  Serial.begin(115200);
   
  pinMode(sensorPin, INPUT);
  pinMode(ledPin, OUTPUT);
    
  // We need to wait one minute for the sensor to calibrate
  // Get out of view of the sensor for this duration!
  
  // Blink the LED while calibrating
  for (unsigned int i=0; i<calibrationTime; i+=ledBlinkTime*2) {
    digitalWrite(ledPin, HIGH);
    Serial.println("Warming up... HIGH");
    Serial.println(i);
    delay(ledBlinkTime);
    Serial.println("Warming up... LOW");
    digitalWrite(ledPin, LOW);
    delay(ledBlinkTime);
  }
}

void loop() {
  // Constantly check the state of pin 2
  // If it is HIGH the sensor is detecting motion
  if (digitalRead(sensorPin) == HIGH) {
    // Turn the LED on
    digitalWrite(ledPin, HIGH);
    
          
         // start the Ethernet connection:
        if (Ethernet.begin(mac) == 0) {
          Serial.println("Failed to configure Ethernet using DHCP");
          // no point in carrying on, so do nothing forevermore:
          while(true);
        }
        
        // give the Ethernet shield a second to initialize:
        delay(1000);
         Serial.println("connecting...");
      
        // if you get a connection, report back via serial:
        
        if (client.connect(serverName, 80)) {
          Serial.println("connected");
          client.println();
       
              Serial.println(" we detected motion, we're going to try to call the file which sends the SMS now");
            // Make a HTTP request:
      //    client.println("GET / HTTP/1.0"); original line
         client.println("GET /sms-script.php HTTP/1.0"); 
         client.println("host:example.com");
          client.println();

              } 
        else {
          // kf you didn't get a connection to the server:
          Serial.println("connection failed");
        }
    
        // Sleep for a second to prevent flooding the serial
    delay(5000);
  } else {
    // Turn the LED off
    digitalWrite(ledPin, LOW);
         
    Serial.println(" we DIDN'T detect motion!");
    delay(2000);
  }
}

I'm quite new to Arduino (and enjoying it!) so if I've made any silly beginner mistakes, be gentle with me!

Every server I've ever heard of sends SOME kind of response when you request a page. The client connection is not closed until you've read the entire response. Make 4 requests, and don't read any responses, and those 4 client connections are going to remain open, and unavailable for reuse.

PaulS:
Every server I've ever heard of sends SOME kind of response when you request a page. The client connection is not closed until you've read the entire response. Make 4 requests, and don't read any responses, and those 4 client connections are going to remain open, and unavailable for reuse.

Thanks for the response. So just to be clear, you're confirming the suspicion that I need to include a snippet of code that explicitly closes the connection after every GET request, right?

So just to be clear, you're confirming the suspicion that I need to include a snippet of code that explicitly closes the connection after every GET request, right?

Not at all. If you plan on only 4 connections total, then you can leave them all open. Otherwise you will need to close them. But they won't close correctly until you empty the socket rx buffer. All that is included in my example code above.

SurferTim:
Not at all. If you plan on only 4 connections total, then you can leave them all open. Otherwise you will need to close them. But they won't close correctly until you empty the socket rx buffer. All that is included in my example code above.

Thank you! I will give it a shot!

The 10 second timeout example above shows how to close a connection from the client end. Note there is no break after the timeout client.stop(). Allow the "while(client.connected()) { while(client.available())" loops to exit normally. That insures the connection is closed.

Hi gang,

I (believe that I) successfully integrated SurferTim's code which adds a 10 second timeout. That is to say, when watching the output in the serial monitor scroll by, it reports back that it closes the initial connection to my server after requesting my php script out there.

However, all subsequent requests for that file after the first one continue to be unsuccessful, just as described before. I guess that suggests that something else was preventing all GET requests for the script after the first one from being successful.

Here's a screenshot of the serial monitor output showing the sequence of events.

If you guys recommend that this deserves a separate thread because the root cause is not the same doubledaffy's , I'm happy to open a new one.

Thanks again for your help.

(thinking out loud...)

I wonder if there is a "verbose mode" where I can get it to belch up the error that prevents it from connecting?

Did you try the code from this link? It gets Google home page every 10 seconds.

Change the network settings to yours, and the server variable to your server ip. Load your home page first. See how that does. Then try the php page.

edit: corrected spelling.

Is your web server using virtual hosting? If so, the "Host:" parameter must be correct. If it is "www.example.com", then "example.com" may not work.