How to achieve continious connection? (Ehternet)

Hello!

As I wrote in an earlier post (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235341200), I’m trying to set the color of a BlinkM remotely via my server.

Have achieved partial success!!!

My Arduino can now connect tom my server, check the current color and set the BlinkM to that color. The problem is that I haven’t got the whole thing to repeat in the loop() function. Here is my code, partially masked to fit this post:

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 2 }; // The IP
byte server[] = { 100, 100, 100, 100 }; // The server
char Str[10]; // String to transcribe and send to BlinKM
byte BlinkM_addr = 0x09;

Client client(server, 80);

void setup()
{

  Wire.begin();
  
  Wire.beginTransmission(BlinkM_addr);
  Wire.send('o');
  Wire.endTransmission(); // Set the BlinkM to not start its own life..
  
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  
  delay(1000);
  
  Serial.println("connecting...");
  
  if (client.connect()) {
    Serial.println("connected");
    client.println("GET /color.php HTTP/1.1");
    client.println("Host: www.example.se");
    client.println();
    client.println();
  } else {
    Serial.println("connection failed");
  }
} // End of setup()

void loop()
{
  if (client.available()) {
   // function to read and parse and change the colour, 
   // the whole page is parsed
   }
  
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
}

Obviously this only make the loop to run the parsing once and the end with ‘client.stop();’, but still it works .

I’ve got inspired by this piece of code that seems to do the same as I want (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1231812230):

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting WebWx");
  Serial.println("connecting...");
  Ethernet.begin(mac, ip);
  delay(1000);

  if (client.connect()) {
    Serial.println("connected");
    client.println("GET /xml/current_obs/KRDU.xml HTTP/1.0");    
    client.println();
    delay(2000);
  } else {
    Serial.println("connection failed");
  }  
}

void loop() {

  // Read serial data in from web:
  while (client.available()) {
    serialEvent();
  }

  if (!client.connected()) {
    //Serial.println();
    //Serial.println("Disconnected");
    client.stop();

    // Time until next update
    //Serial.println("Waiting");
    for (int t = 1; t <= 15; t++) {
      delay(60000); // 1 minute
    }

    if (client.connect()) {
      //Serial.println("Reconnected");
      client.println("GET /xml/current_obs/KRDU.xml HTTP/1.0");    
      client.println();
      delay(2000);
    } else {
      Serial.println("Reconnect failed");
    }      
  }
}

Problem is that when I insert the if(client.connected()) stuff again in the main loop (as in the above example), everything craches. I can’t get it to connect, and it doesn’t reconnect either, and even the parsing gets fucked up…

Is this the way to go to achieve a continious connection (and check up on the current colour) or am I missing something?

Thankful for any help on the subject!

-Per

What version of the library are you using? Have you seen this thread?
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1234006420/0

-Nic

It's on Arduino 12... My problem is that I haven't got the whole understanding of the synax, what exactly client.stop does, client.connect etc.

--Per

I think 12 might have a different but equally broken bug in terms of multiple connects, so first things first I would recommend grabbing 13 and applying the patch in that thread to change the source port.

I’ve been banging my head against the same issues for the past few weeks, it is REALLY frustrating that there were bugs in the Ethernet libraries still.

I am no expert, but here are some learnings from playing around:

  1. some of the ‘official’ ethernet boards suffer from being unable to connect after a cold boot, they require a reset first. Some people have found they can work around it with a capacitor worked into the reset switch, I just decided to use LadyAda’s board instead, which had the additional advantage of having the expensive bit (the wiznet chip) be on a daughterboard and easy to reset independently of the arduino. This doesn’t sound like your particular problem though.

  2. as for the correct ‘sequence’ of calls, trial and error has me doing this which seems to be reliable… note that in my case I’m just calling a URL which in turn causes an action, I don’t care about or read the response:

in setup():

Ethernet.begin(mac, ip);
  Client client(server, 80);

in my loop():
To connect:

Ethernet.begin(mac, ip);
delay(500);
if (client.connect()){
   // do your stuff here
}

After each connect:

client.flush();
client.stop();

Here’s my full script, which is basically an RFID controller for my squeezebox, but you can see what I do for connecting and resetting with the ladyada board.

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,250 };
byte server[] = {192,168,0,105};

Client client(server, 80);

enum STATE {  
  RFID, RFID_VERIFY, CONNECTING, READING
};

static STATE state;

#define DEBUG 0
#define FAKE 0

// reset pin for ethernet module, only works on LadyAda shield
#define RESET_PIN 7

// RFID enable pin
#define RFID_ENABLE 2

int  val = 0; 
char reading[11];
char verify[11];
char current[11];
char target[11];
int bytesread = 0; 

void setup(){
  // rfid is slow as all get out 
  Serial.begin(2400); 
  
  pinMode(RESET_PIN, OUTPUT);
  pinMode(RFID_ENABLE, OUTPUT);

  // sleep for 30 seconds, this gives the squeezebox time to boot up
  delay(30000);

  // reset the ethernet board
  digitalWrite(RESET_PIN, LOW);
  delay(2);
  digitalWrite(RESET_PIN, HIGH);

  delay(1000);

  Ethernet.begin(mac, ip);
  Client client(server, 80);
  
  if (DEBUG) Serial.println("Finishing setup..");
  
  current[0] = '\0';
  reading[0] = '\0';
  verify[0] = '\0';
  target[0] = '\0';
 
  current[10] = '\0';
  reading[10] = '\0';
  verify[10] = '\0';
  target[10] = '\0';
}

void loop(){
  if (state == RFID){
    // spin a bit to see if the we are ahead of the reader
    Serial.flush();
    digitalWrite(RFID_ENABLE, LOW);
    int loops = 0;
    while(loops < 10){
      if (Serial.available()) break;
      loops++;
      delay(100);  
    }
    
    val = Serial.read();
        
    if((val == 10)){   // check for header 
      bytesread = 0; 
      while(bytesread<10){  // read 10 digit code 
        val = Serial.read(); 
        if((val == 10)||(val == 13)){  // if header or stop bytes before the 10 digit reading 
          break;                       // stop reading 
        } 
        // or if it looks invalid
        if ((val < 'A' || val > 'Z') && (val < '0' && val > '9')){
          break; 
        } 
        
        reading[bytesread] = val;         // add the digit           
        bytesread++;                   // ready to read next digit  
      } 
      
      // didn't read a whole tag, clear it
      if(bytesread != 10){
        reading[0] = '\0';  
      }
    } else {
      reading[0] = '\0';  
    }
    
    if (DEBUG) Serial.print("reading: ");
    if (DEBUG) Serial.println(reading);
      
    // this is something is different, verify it
    if (strcmp(reading, current) != 0){
      state = RFID_VERIFY;  
    }      
    bytesread = 0; 
    
    if (FAKE){
      reading[0] = '1';
      reading[1] = '\0';
      state = RFID_VERIFY;
    }
    
    digitalWrite(RFID_ENABLE, HIGH);
    delay(250);
  } 
  
  else if (state == RFID_VERIFY){
    // spin a bit to see if the we are ahead of the reader
    Serial.flush();
    digitalWrite(RFID_ENABLE, LOW);
    int loops = 0;
    while(loops < 10){
      if (Serial.available()) break;
      loops++;
      delay(100);  
    }
    
    val = Serial.read();
        
    if((val == 10)){   // check for header 
      bytesread = 0; 
      while(bytesread<10){  // read 10 digit code 
        val = Serial.read(); 
        if((val == 10)||(val == 13)){  // if header or stop bytes before the 10 digit reading 
          break;                       // stop reading 
        } 
        // or if it looks invalid
        if ((val < 'A' || val > 'Z') && (val < '0' && val > '9')){
          break; 
        } 
        
        verify[bytesread] = val;         // add the digit           
        bytesread++;                   // ready to read next digit  
      } 
      
      // didn't read a whole tag, clear it
      if(bytesread != 10){
        verify[0] = '\0';  
      }      
    } else {
      verify[0] = '\0';  
    }
    
    if (DEBUG) Serial.print("verify: ");
    if (DEBUG) Serial.println(verify);
      
    // first and second pass the same
    if (strcmp(reading, verify) == 0){
      if (strcmp(reading, current) != 0){
        strncpy(target, reading, 10);
        state = CONNECTING;
      }    
    } else {
      state = RFID;
    }
    bytesread = 0; 

    if (FAKE){
      target[0] = '1';
      target[1] = '\0';
      state = CONNECTING;
    }
    
    digitalWrite(RFID_ENABLE, HIGH);
    
    delay(250);
  }  
  else if (state == CONNECTING){     
    if (DEBUG) Serial.println("connecting...");
    Ethernet.begin(mac, ip);
    delay(500);
    
    if (client.connect()) {
      if (DEBUG) Serial.println("connected");
    
      if (strlen(target) == 10){
        client.print("GET /tuner/index.php?key=");
        client.print(target);
      } else {
        client.print("GET /tuner/index.php?stop=1");  
      }
      client.println(" HTTP/1.0");
      client.println("Host: 192.168.0.105");
      client.println("User-Agent: AVR ethernet");
      client.println("Accept: text/html");

      client.println();  

      strcpy(current, target);

      state=RFID;
      
      client.flush();
      client.stop();
  } else {
      if (DEBUG) Serial.println("connection failed");
      client.flush();
      client.stop();
      
      // reset the board      
      if (DEBUG) Serial.println("resetting!");
      // reset the ethernet board
      digitalWrite(RESET_PIN, LOW);
      delay(2);
      digitalWrite(RESET_PIN, HIGH);
   }
   delay(500);
   state = RFID;
  }
  
  // never get into this state, just for debugging
  else if (state==READING){
    if (client.available()) {
      char c = client.read();
      if (DEBUG) Serial.print(c);
      state=READING;
    } else if (!client.connected()){
      if (DEBUG) Serial.println();
      if (DEBUG) Serial.println("disconnecting.");
      client.stop();
      delay(2000);
      state=RFID;
    }
  }
  }

PS. BTW for your particular application it seems like the better route would be to have your Arduino act as a server as opposed to constantly polling. I guess that wouldn't work if you are behind a firewall, but it would be a far better solution if not. Just have your web script make an HTTP GET to your arduino with the new color (and maybe also save it in case the arduino isn't on). The arduino could then check the server upon first boot and set the blinkM and then from then on just be kept up to date directly via your web script calling it.

Thank you for the help, and the code. I’ll look in to the whole reconnecting issue and try to get a hang of it before implementing it in my sketch.

Interesting idea to have the Arduino as the server. Prehaps I’ll try that efter I’ve got this to work.

Again, thank you so much for the help provided. I’ll post my code when it’s ready.