Pages: 1 [2]   Go Down
Author Topic: Ethernet sheild stops connecting after an extended period  (Read 1871 times)
0 Members and 1 Guest are viewing this topic.
Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Loe and behold, I've fucked up again.

Code:
void Ethercheck(){
 //Ethernet Client
   if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();
     // Serial.print (inChar);

     // add incoming byte to end of line:
      currentLine[index++] = inChar;
      currentLine[index] = '\0';

      // if you get a newline, clear the line:
      if (inChar == '\n') {
        previousTweet == tweet;
      }
      // if the current line ends with <text>, it will
      // be followed by the tweet:
      if (strncmp(currentLine,"<text>")==0) {
        // tweet is beginning. Clear the tweet string:
        readingTweet = true;
      }
      // if you're currently reading the bytes of a tweet,
      // add them to the tweet String:
      if (readingTweet) {
        if (inChar != '<') {
          tweet[index++] = inChar;
        //  currentLine[index] = '\0';
         
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the tweet:
          readingTweet = false;
           if (tweet != previousTweet){
          Serial.println(tweet);   
          // close the connection to the server:
          Serial.println(F("disconnecting"));
          client.stop();
               
                if (firstTweetRead != false){
                if (strncmp(tweet,"<text>")==0) {
                 
                  //if( waterLevel is higher than said amount){
                  Serial.println (F("Making coffee"));
                  tweetString.begin();
                  tweetString = " Making coffee now, random number: ";
                  randNumber = random(1000);
                  tweetString.print (randNumber);
                 
                  make();
                }

                }
                else{
                 firstTweetRead = true;
                }
                }
         else {
           Serial.println(F("no new tweets"));
           Serial.println(F("disconnecting"));
           client.stop();
         
         }
        }
      }
    }
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and fifteen seconds have passed since
    // your last connection, then attempt to connect again:
    client.flush();
    totalCount++;
    Serial.print (F("Total count:"));
    Serial.println(totalCount);
    connectToServer();
   
  }
 
}




Quote
setup
connecting to server...connected
making HTTP request...
Total count:1
connecting to server...

I'm not sure how to use the strncmp(). I thought this would be correct.
PaulS, Thanks for helping me with every stage of this project. I'd say I was teaching myself but that would be a lie.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46300
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
      if (strncmp(currentLine,"<text>")==0) {
It's hard to believe that that even compiles, since strncmp() takes three arguments. The third is the number of characters to compare.

Code:
      if (readingTweet) {
        if (inChar != '<') {
          tweet[index++] = inChar;
        //  currentLine[index] = '\0';
         
        }
You need a separate index for each array, or, at a minimum you need to reset index to 0 before you use it to index another array.

Uncomment the print that shows what was read. You can't debug serial/client reading code without seeing what you read.
Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm lost, This is printing jibberish.
Code:
void Ethercheck(){
 //Ethernet Client
   if (client.connected()) {
    if (client.available()) {
      // read incoming bytes:
      char inChar = client.read();
      //Serial.print (inChar);

     // add incoming byte to end of line:
      currentLine[currentIndex++] = inChar;
      currentLine[currentIndex] = '\0';
      Serial.print (currentLine);
       
      // if you get a newline, clear the line:
      if (inChar == '\n') {
        previousTweet == tweet;

      }
      // if the current line contains <text>, it will
      // be followed by the tweet:
      if (strncmp(currentLine,"<text>",6)==0) {
        // tweet is beginning. Clear the tweet string:
        readingTweet = true;
      }
      // if you're currently reading the bytes of a tweet,
      // add them to the tweet String:
      if (readingTweet) {
        if (inChar != '<') {
          tweet[tweetIndex++] = inChar;
          tweet[tweetIndex] = '\0';
         
        }
        else {
          // if you got a "<" character,
          // you've reached the end of the tweet:
          readingTweet = false;
         
           if (tweet != previousTweet){
            Serial.println(F("TWEET"));
            Serial.println(tweet);   
            // close the connection to the server:
            Serial.println(F("disconnecting"));
            client.stop();
               
                if (firstTweetRead != false){
                if (strncmp(tweet,makeCoffee, 16)==0) {
                 
                  //if( waterLevel is higher than said amount){
                  Serial.println (F("Making coffee"));
                  tweetString.begin();
                  tweetString = " Making coffee now, random number: ";
                  randNumber = random(1000);
                  tweetString.print (randNumber);
                 
                  make();
                }

                }
                else{
                 firstTweetRead = true;
                }
                }
         else {
           Serial.println(F("no new tweets"));
           Serial.println(F("disconnecting"));
           client.stop();
         
         }
        }
      }
    }
  }
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and fifteen seconds have passed since
    // your last connection, then attempt to connect again:
    client.flush();
    totalCount++;
    Serial.print (F("Total count:"));
    Serial.println(totalCount);
    connectToServer();
   
  }
 
}



Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i have same problem,
if you connectinc using DHCP , connection drops after 60 minuts
its easily fix problem
You need to use Ethernet.maintain() every 15-30 minuts


Code:
unsigned long previousMillis = 0;
int interval = 900000;

void loop()
{
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    Ethernet.maintain();
    delay(100);
  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46300
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
      if (inChar == '\n') {
        previousTweet == tweet;
No. An equality operator is NOT what you want to use. You can't assign (=) a char array this way, either. You need strcpy().

At some point, you need to set index and tweetIndex back to 0, and put the NULL in position 0 in each array.

You also need to stop posting snippets. How are we supposed to know how previousTweet, tweet, currentLine, currentIndex, and tweetIndex are defined?
Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been working on this and I think I have cracked two thirds of the problem.
on another forum post I found a method of clearing the c strings when they got too big.

http://arduino.cc/forum/index.php/topic,106699.msg802859.html#msg802859
Code:
void clearStr (char* str) {
   int len = strlen(str);
   for (int c = 0; c < len; c++) {
      str[c] = 0;
   }
}


I use this in every cycle after they are no longer needed.

Code:
void Ethercheck(){
 //Ethernet Client
   if (client.connected()) {
    if (client.available()) {
        
         finder.getString("<text>","<",tweet,141);
         Serial.print(F("Incoming Tweet:"));
         Serial.println(tweet);  
      
         if (strcmp(tweet,previousLine)!=0){
         clearStr(previousLine);
          Serial.print(F("New Tweet:"));
          Serial.println(tweet);  
          Serial.print(F("Previous Tweet:"));
          Serial.println(previousLine);
          strcpy(previousLine, tweet);
          
            if (firstTweetRead != false){
               Serial.println ("first tweet Read");
              
            if (strncasecmp(tweet,makeCoffee,14)==0){
               Serial.println ("Making coffee");
               tweetString.begin();
               tweetString = " Making coffee now, random number: ";
               randNumber = random(1000);
               tweetString.print (randNumber);
               make();
            }
          }
          else{
            firstTweetRead = true;
          }
          
        
         }
         else {
           Serial.println(F("no new tweets"));  
         }
          
              
        

        client.stop();
        clearStr(tweet);
        
 }
 }
 
  
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and fifteen seconds have passed since
    // your last connection, then attempt to connect again:
    client.flush();
    totalCount++;
    Serial.print (F("Total count:"));
    Serial.println(totalCount);
    Ethernet.maintain();
    delay(100);
    connectToServer();
    
  }
  
}




Before I had three Strings and now I only have one
Code:
        finder.get[glow=yellow,2,300]String[/glow]("<text>","<",tweet,141);

As the code takes roughly three times as long to crash now I suspect this getString function from textFinder is responsible. Although if the information is stored in char tweet[141];  and tweet gets cleared by void clearStr();  is getString the problem at all?

I understand PaulS suggested a way in which I use an index like this..
Code:
currentLine[currentIndex++] = inChar;
      currentLine[currentIndex] = '\0';

I do not really know how to approach this method. An example would be welcome.

Code:
//setup for all libs
#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>
#include <EthernetUdp.h>
#include <PString.h>
#include <TextFinder.h>

int ledPin = 3;
byte mac[] = { 0x--, 0x--, 0x--, 0x--, 0x--, 0x-- };
byte ip[] = {--,---,---,--- };
Twitter twitter("-------------------------------------");

int len;

//Ethernet Client
int totalCount = 0;
EthernetClient client;
const unsigned long requestInterval = 30000;  // delay between requests
char serverName[] = "api.twitter.com";  // twitter URL
boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds
char previousLine [141];           //String to hold the previous text from server for comparison
char tweet[141];                  // string to hold the tweet
char makeCoffee[15] = "make me coffee";
boolean readingTweet = false;       // if you're currently reading the tweet
TextFinder finder( client );

//TweetString
char buffer[140] = {0};
PString tweetString(buffer, sizeof(buffer));
long randNumber;
boolean firstTweetRead = false;



void setup(){
 
  pinMode (ledPin, OUTPUT);
  randomSeed(analogRead(5));
  
  //Serial Reader
  Serial.begin(9600); // Initialize serial port
  
  //General
  delay(1000);
  Ethernet.begin(mac);
  Serial.begin(9600);
    
 //Ethernet Client
   // attempt a DHCP connection:
  Serial.println("setup");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed, trying manually");
    Ethernet.begin(mac, ip);
  }

// connect to Twitter:
  connectToServer();
}

void loop(){
  
  Ethercheck();
}

void Ethercheck(){
 //Ethernet Client
   if (client.connected()) {
    if (client.available()) {
        
         finder.getString("<text>","<",tweet,141);
         Serial.print(F("Incoming Tweet:"));
         Serial.println(tweet);  
      
         if (strcmp(tweet,previousLine)!=0){
          clearStr(previousLine);
          Serial.print(F("New Tweet:"));
          Serial.println(tweet);  
          Serial.print(F("Previous Tweet:"));
          Serial.println(previousLine);
          strcpy(previousLine, tweet);
          
            if (firstTweetRead != false){
               Serial.println ("first tweet Read");
              
            if (strncasecmp(tweet,makeCoffee,14)==0){
               Serial.println ("Making coffee");
               tweetString.begin();
               tweetString = " Making coffee now, random number: ";
               randNumber = random(1000);
               tweetString.print (randNumber);
               make();
            }
          }
          else{
            firstTweetRead = true;
          }
          
        
         }
         else {
           Serial.println(F("no new tweets"));  
         }
          
              
        

        client.stop();
        clearStr(tweet);
        
 }
 }
 
  
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and fifteen seconds have passed since
    // your last connection, then attempt to connect again:
    client.flush();
    totalCount++;
    Serial.print (F("Total count:"));
    Serial.println(totalCount);
    Ethernet.maintain();
    delay(100);
    connectToServer();
    
  }
  
}

void clearStr (char* str) {
   int len = strlen(str);
   for (int c = 0; c < len; c++) {
      str[c] = 0;
   }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.print(F("connecting to server..."));
  if (client.connect(serverName, 80)) {
    Serial.println(F("connected"));
    Serial.println(F("making HTTP request..."));

    // make HTTP GET request to twitter:
    client.println(F("GET /1/statuses/user_timeline.xml?screen_name=/*Twitter account name*/&count=1 HTTP/1.1"));
    client.println(F("HOST: api.twitter.com"));
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
  
}  

void make(){
  Serial.println(F("Tweeting ..."));
  if (twitter.post(tweetString)) {
    // Specify &Serial to output received response to Serial.
    // If no output is required, you can just omit the argument, e.g.
    // int status = twitter.wait();
    int status = twitter.wait(&Serial);
    if (status == 200) {
      digitalWrite(ledPin, HIGH); //turn coffee maker on
      Serial.println(F(", Reply was tweeted. Making coffee now."));
      //Start the coffee making
        //when water level is low
          //Stop the coffee making and run the finished function
        
        
    }
    else {
      Serial.print(F("failed : code "));
      Serial.println(status);
      Serial.println(tweetString);
      Serial.print(F("new Tweet is this: "));
              tweetString.begin();
              tweetString = " Making coffee now, random number: ";
               randNumber = random(1000);
              tweetString.print (randNumber);
              Serial.println(tweetString);
              delay(10000);
              return make();
    }
  }
  else {
    Serial.println(F("connection failed. Cannot Tweet"));
  }
}



Just a pointer to an example of someone using the char [byte array] method will hopefully be enough.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46300
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have been working on this and I think I have cracked two thirds of the problem.
on another forum post I found a method of clearing the c strings when they got too big.
A C string is a NULL terminated array of chars.

NULL,a,a,a,a,a,a,a,a,a,a,,a,a,a,a,a,a is a 0 length string. As is
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL

More than one NULL is like more than one stop sign on a post.

Quote
Before I had three Strings and now I only have one
You'll be a lot better of with ZERO.

Quote
As the code takes roughly three times as long to crash now I suspect this getString function from textFinder is responsible.
The getString() function, despite the capital S, does not use Strings. Is 141 characters a reasonable number of characters? If the tweet to make coffee is considerably shorter than that, make tweet a lot smaller.

Quote
I do not really know how to approach this method. An example would be welcome.
You quoted one, and you have access to the source for the TextFinder library that uses char arrays to look at. I'm not sure what else to suggest.

Code:
char makeCoffee[15] = "make me coffee";
Psst. The compiler can count.
Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
Quote
Before I had three Strings and now I only have one
You'll be a lot better of with ZERO.
If getString isn't a String, what is in my sketch? I thought I had fixed it.

Quote
Quote
As the code takes roughly three times as long to crash now I suspect this getString function from textFinder is responsible.
The getString() function, despite the capital S, does not use Strings. Is 141 characters a reasonable number of characters? If the tweet to make coffee is considerably shorter than that, make tweet a lot smaller.
I eventually want to display the tweets in full on an LCD display. 141 will not cut the ends off of any message.

Quote
Code:
char makeCoffee[15] = "make me coffee";
Psst. The compiler can count.
Thanks, I was getting over cautious
« Last Edit: October 02, 2012, 09:10:48 am by StuHooper » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46300
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If getString isn't a String, what is in my sketch? I thought I had fixed it.
The getString() method returns a string (case IS important).

Whether you have any Strings is unclear, without seeing all of your current code.

Quote
I eventually want to display the tweets in full on an LCD display. 141 will not cut the ends off of any message.
On the other hand, it is unlikely that you will be able to display 141 characters on one line, anyway. Chopping the tweet up into smaller pieces is not a bad thing to do. You can always concatenate them together if you find the need.

Quote
Thanks, I was getting over cautious
Actually, overly cautious would be to let the compiler do the counting, since it rarely makes mistakes.
Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

All the code:

Code:
//setup for all libs
#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>
#include <EthernetUdp.h>
#include <PString.h>
#include <TextFinder.h>

int ledPin = 3;
byte mac[] = { 0x--, 0x--, 0x--, 0x--, 0x--, 0x-- };
byte ip[] = {--,---,---,--- };
Twitter twitter("-------------------------------------");

int len;

//Ethernet Client
int totalCount = 0;
EthernetClient client;
const unsigned long requestInterval = 30000;  // delay between requests
char serverName[] = "api.twitter.com";  // twitter URL
boolean requested;                   // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;            // last time you connected to the server, in milliseconds
char previousLine [141];           //String to hold the previous text from server for comparison
char tweet[141];                  // string to hold the tweet
char makeCoffee[15] = "make me coffee";
boolean readingTweet = false;       // if you're currently reading the tweet
TextFinder finder( client );

//TweetString
char buffer[140] = {0};
PString tweetString(buffer, sizeof(buffer));
long randNumber;
boolean firstTweetRead = false;



void setup(){
 
  pinMode (ledPin, OUTPUT);
  randomSeed(analogRead(5));
 
  //Serial Reader
  Serial.begin(9600); // Initialize serial port
 
  //General
  delay(1000);
  Ethernet.begin(mac);
  Serial.begin(9600);
   
 //Ethernet Client
   // attempt a DHCP connection:
  Serial.println("setup");
  if (!Ethernet.begin(mac)) {
    // if DHCP fails, start with a hard-coded address:
    Serial.println("failed, trying manually");
    Ethernet.begin(mac, ip);
  }

// connect to Twitter:
  connectToServer();
}

void loop(){
 
  Ethercheck();
}

void Ethercheck(){
 //Ethernet Client
   if (client.connected()) {
    if (client.available()) {
       
         finder.getString("<text>","<",tweet,141);
         Serial.print(F("Incoming Tweet:"));
         Serial.println(tweet); 
       
         if (strcmp(tweet,previousLine)!=0){
          clearStr(previousLine);
          Serial.print(F("New Tweet:"));
          Serial.println(tweet); 
          Serial.print(F("Previous Tweet:"));
          Serial.println(previousLine);
          strcpy(previousLine, tweet);
         
            if (firstTweetRead != false){
               Serial.println ("first tweet Read");
               
            if (strncasecmp(tweet,makeCoffee,14)==0){
               Serial.println ("Making coffee");
               tweetString.begin();
               tweetString = " Making coffee now, random number: ";
               randNumber = random(1000);
               tweetString.print (randNumber);
               make();
            }
          }
          else{
            firstTweetRead = true;
          }
         
         
         }
         else {
           Serial.println(F("no new tweets")); 
         }
           
               
         

        client.stop();
        clearStr(tweet);
       
 }
 }
 
 
  else if (millis() - lastAttemptTime > requestInterval) {
    // if you're not connected, and fifteen seconds have passed since
    // your last connection, then attempt to connect again:
    client.flush();
    totalCount++;
    Serial.print (F("Total count:"));
    Serial.println(totalCount);
    Ethernet.maintain();
    delay(100);
    connectToServer();
   
  }
 
}

void clearStr (char* str) {
   int len = strlen(str);
   for (int c = 0; c < len; c++) {
      str[c] = 0;
   }
}

void connectToServer() {
  // attempt to connect, and wait a millisecond:
  Serial.print(F("connecting to server..."));
  if (client.connect(serverName, 80)) {
    Serial.println(F("connected"));
    Serial.println(F("making HTTP request..."));

    // make HTTP GET request to twitter:
    client.println(F("GET /1/statuses/user_timeline.xml?screen_name=/*Twitter account name*/&count=1 HTTP/1.1"));
    client.println(F("HOST: api.twitter.com"));
    client.println();
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
 
}   

void make(){
  Serial.println(F("Tweeting ..."));
  if (twitter.post(tweetString)) {
    // Specify &Serial to output received response to Serial.
    // If no output is required, you can just omit the argument, e.g.
    // int status = twitter.wait();
    int status = twitter.wait(&Serial);
    if (status == 200) {
      digitalWrite(ledPin, HIGH); //turn coffee maker on
      Serial.println(F(", Reply was tweeted. Making coffee now."));
      //Start the coffee making
        //when water level is low
          //Stop the coffee making and run the finished function
       
       
    }
    else {
      Serial.print(F("failed : code "));
      Serial.println(status);
      Serial.println(tweetString);
      Serial.print(F("new Tweet is this: "));
              tweetString.begin();
              tweetString = " Making coffee now, random number: ";
               randNumber = random(1000);
              tweetString.print (randNumber);
              Serial.println(tweetString);
              delay(10000);
              return make();
    }
  }
  else {
    Serial.println(F("connection failed. Cannot Tweet"));
  }
}

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 241
Posts: 24480
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@hisadshadow
Quote
i have same problem,
if you connectinc using DHCP , connection drops after 60 minuts
its easily fix problem
You need to use Ethernet.maintain() every 15-30 minuts
Code:
int interval = 900000;
That isn't going to work as you think it should on an Arduino.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The getString() method returns a string (case IS important).

Whether you have any Strings is unclear, without seeing all of your current code.

am I right in thinking that ...

Strings cause problems
strings don't?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 553
Posts: 46300
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
am I right in thinking that ...

Strings cause problems
strings don't?
Not exactly. Strings cause memory allocation/deallocation issues, and are not the most suitable class for a small microcontroller.

C strings are not immune from problems, given how easy it is to write beyond the end of an array, but, as least with strings, only you can shoot yourself in the foot. C hands you the gun, and gives you aiming instructions.

The String class (actually, the free() function) aims the gun and squeezes on the trigger.
Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
C strings are not immune from problems, given how easy it is to write beyond the end of an array, but, as least with strings, only you can shoot yourself in the foot. C hands you the gun, and gives you aiming instructions.

The String class (actually, the free() function) aims the gun and squeezes on the trigger.

Fantastic analogy.
Logged

Pages: 1 [2]   Go Up
Jump to: