Sketch si blocca dopo alcuni giorni

Sto cercando, per ora invano, una soluzione ad un problema di blocco di uno sketch che gira su Arduino Ethernet con IDE 022.
Lo sketch invia, ogni 3 minuti circa, i valori di un piccolo impianto fotovoltaico letti sulle 6 porte analogiche e su una porta digitale a Google Spreadsheet tramite una interfaccia autocostruita.
Per alcuni giorni funziona regolarmente e poi si inchioda inspiegabilmente.

Lo sketch è stato copiato da un website e opportunamente modificato.

/* Arduino to Google Docs
 created 2011
 
This example code is in the public domain.
 
http://www.open-electronics.org
 
http://www.futurashop.it
 
https://spreadsheets.google.com/formResponse?formkey=dDBMdUx3TmQ5Y2xvX2Z0V183UVp2U0E6MQ &ifq&entry.0.single=Boris&entry.2.single=Landoni&submit=Submit
Original from http://goodsite.cocolog-nifty.com/uessay/2010/07/arduinogoogle-d.html
Modified by John Missikos 11/6/11
Modified by Andrea Fainozzi 30/6/11
Modified by Boris Landoni 8/7/11
 
*/
#include <OneWire.h>
#include <DallasTemperature.h> 
#include <Ethernet.h>
#include <SPI.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 12

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

char formkey[] = "xxxxxxxxxxxxxxxx"; //Replace with your Key
byte mac[] = { 0x90,0xA2,0xDA,0x0D,0xBC,0x69};  //Replace with your Ethernet shield MAC
byte ip[] = { 192,168,2,165};  //The Arduino device IP address
byte subnet[] = { 255,255,255,0};
byte gateway[] = { 192,168,2,1};
byte server[] = { 173,194,35,152 }; // Google IP
Client client(server, 80);

int analogIn0 = 0;
int analogIn1 = 0;
int analogIn2 = 0;
int analogIn3 = 0;
int analogIn4 = 0;
int analogIn5 = 0;
int TempOut = 0;
int TempIn = 0;
//char Tout [10];
//char Tin [10];
int analog1 = 0;
int analog3 = 0;
int analog5 = 0;
int media1 = 0;
int media3 = 0;
int media5 = 0;


void setup()


{
  Serial.begin(9600);
  Ethernet.begin(mac, ip , gateway , subnet);
  delay(1000);
  Serial.println("connecting...");
}
 
void loop(){
  
  sensors.requestTemperatures(); // Send the command to get temperatures
  TempOut = 100 * sensors.getTempCByIndex(1);
  TempIn = 100 * sensors.getTempCByIndex(0);
  //dtostrf(TempOut ,1 ,2 ,Tout);
  //dtostrf(TempIn ,1 ,2 ,Tin);
  
  
  
                    
                    //campiono il valore di tensione analogica
                    //in ingresso sul pin0 ella borad Arduino UNO
                    analogIn0 = analogRead(0);
                    analogIn1 = analogRead(1);
                    analogIn2 = analogRead(2);
                    analogIn3 = analogRead(3);
                    analogIn4 = analogRead(4);
                    analogIn5 = analogRead(5);
                  
                    
                     
                    
                    float average1 = 0;
                    float average3 = 0;
                    float average5 = 0;
                    for(int i = 0; i < 10000; i++) {
                    analogIn1 = analogRead(1);
                    analogIn3 = analogRead(3);
                    analogIn5 = analogRead(5);
                    //Serial.println(analogIn1);
                    //Serial.println(analogIn3);
                    //Serial.println(analogIn5);
                    average1 = (average1 + analogIn1); // 1000;
                    average3 = (average3 + analogIn3); // 1000;
                    average5 = (average5 + analogIn5); // 1000;
                    delay(10);
                    }
                    
                    media1 = average1 / 10000;
                    media3 = average3 / 10000;
                    media5 = average5 / 10000;
                    //media1 = ((media1-87)*0.05)+5
                    
                    //analog1 = average1;
                    //analog3 = average3;
                    //analog5 = average5;
                   
   
    
   //Serial.println(average1);
   //Serial.println(average3);
   //Serial.println(average5);  
    
  String data;
  data+="";
  data+="entry.0.single=";
  data+=analogIn0;
  data+="&entry.1.single=";
  data+=media1;
  data+="&entry.2.single=";
  data+=analogIn2;
  data+="&entry.3.single=";
  data+=media3;
  data+="&entry.4.single=";
  data+=analogIn4;
  data+="&entry.5.single=";
  data+=media5;
  data+="&entry.6.single=";
  data+=TempIn;
  data+="&entry.7.single=";
  data+=TempOut;
  data+="&submit=Submit";
  
  //Serial.println(data);
 
  if (client.connect()) {
    Serial.println("connected");
 
    client.print("POST /formResponse?formkey=");
    client.print(formkey);
    client.println("&ifq HTTP/1.1");
    client.println("Host: spreadsheets.google.com");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
    client.stop();
 
    Serial.print("POST /formResponse?formkey=");
    Serial.print(formkey);
    Serial.println("&ifq HTTP/1.1");
    Serial.println("Host: spreadsheets.google.com");
    Serial.println("Content-Type: application/x-www-form-urlencoded");
    Serial.println("Connection: close");
    Serial.print("Content-Length: ");
    Serial.println(data.length());
    Serial.println();
    Serial.print(data);
    Serial.println();
    
  }
  delay(1000);
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
 
  delay(60000);
  }

Può essere una soluzione inserire un watchdog ? Mi sto informando e ho visto che serve una libreria che però non riesco a trovare.

Altro piccolo problema, ho scoperto che ogni tanto Google cambia gli indirizzi IP dei server.
In tal caso Arduino chiama un indirizzo che non può rispondere.
Esiste la possibilità di chiamare un server DNS per ovviare al problema ?

Grazie per l'aiuto !

ciao
Perchè uno sketch fatto su ide 0022, prova la 1.0.5 ha subito molte modifiche e correzioni di bug lungo la strada, non ti garantisco che non si inchiodi più, ma prova e torna tra qualche giorno e facci sapere, dato il tuo sketck molto elementare la tua testimonianza può essere molto utile
Il freeze della ethernet è molto discusso ... ti basta googlare un po per leggere parecchio sull'argomento.

La 1.0.5. non è ancora stata rilasciata.
C'è la 1.0.4 per la UNO, MEGA, Leonardo o la 1.5.2 per la DUE.

Si, la nuova libreria prevede anche la possibilità di chiamare tramite DNS.

si volevo dire 152 miii che pignola!!! :smiley: :smiley: :smiley:
la 152 è anche per avr/arm

Caro contivalentino io ho riscritto uno sketch abbastanza modificato il quale invia ogni 3 minuti esatti
n.4 temperature + uno stato Pin di una elettrovalvola al sito Google Spread sheet o meglio Google Drive...

Il sistema stà funzionando dal 1 Novembre 2012 e fino ad oggi ha inviato per n.64298 di volte la stringa con le temperature e la scheda ethernet non si è mai fermata...ma dico mai e proprio mai...

Ti posso confermare e straconfermare che se l'invio si ferma è un problema di scrittura dello sketch...
Io primo di arrivare alla soluzione definitiva per svariati mesi ho avuto i tuoi stessi problemi e ho notato che il Delay non và assolutamente usato e come puoi notare dallo sketch postato ho usato solo il Millis...
spero d'esserti stato d'aiuto...

//RX da seriale 4 temperature+stato valvola a Google ULTIMO
// compilato con Arduino Ide 1.03

#include <SoftwareSerial.h> // libreria creazione porta seriale virtuale
#include <Ethernet.h>
#include <SPI.h>
SoftwareSerial mySerial(7, 8); // RX, TX

char formkey[] = "dFJfLVJfdXM0QVI0NE40NXEzUmdtTFE6MQ"; //Replace with your Key
byte mac[] = { 0x90,0xA2,0xDA,0x0D,0x1C,0xDA};  //Replace with your Ethernet shield MAC

byte subnet[] = { 255,255,255,0};
byte gateway[] = { 192,168,0,1};
byte ip[] = { 192,168,0,140};
String stv = "" ;


byte server[] = { 173,194,35,46 };


EthernetClient client;
//unsigned long time;
//IPAddress ip(192,168,0,140);


int I = 0; 
int J = 0; 
String Z = "";
byte Decimali = 1;  

String SerRx = "";                                   // azzera buffer ricezione
const unsigned long TimeOut = 5000;                  // timeout 1 s
unsigned long Timer = millis();// timer partito
unsigned long Timer1 = millis();// timer partito

int Temp1=0 ;
int Temp2=0 ;
int Temp3=0 ;
int Temp4=0 ;
int Valvola=0 ;

void setup() {
  Serial.begin(9600);  // inizializza porta seriale
  //Ethernet.begin(mac, ip , gateway , subnet);
   //if (Ethernet.begin(mac) == 0) {                                                              // start the Ethernet connection
    Ethernet.begin(mac, ip, gateway, gateway, subnet );                                                              // DHCP failed, so use a fixed IP address
    Serial.println("Failed to configure Ethernet using DHCP");
  
  client.connect(server, 80);
  Serial.println("seriale rx inizio");
  mySerial.begin(19200);
  mySerial.println("seriale virtuale rx inizio");  // inizializza porta seriale ausiliaria
  Serial.println("connecting...");
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  
  Serial.println("inizio loop");

  SerRx = "";                                        // azzera buffer ricezione
  Timer = millis();     // timer partito
  Timer1 = millis();  

  while (millis() - Timer < TimeOut) {               // attesa timeout
    while (mySerial.available() > 0) {              // ricezione da modulo
      SerRx += char(mySerial.read());               // aggiungi carattere al buffer          
      Timer = millis();                              // reset timer 
    }
  }

  if (SerRx.length() > 0) {
    {                          // ci sono dei dati nel buffer (Temp1<CR><LF>Temp2<CR><LF>...Temp5<CR><LF>
    J = 0;
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp1 = Z.toInt();
      J = I + 2;       // nuova posizione di ricerca
      mySerial.println(Temp1, Decimali);
      Serial.print("Temp1 = ");
      Serial.println(Temp1, Decimali);
      
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp2 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp2, Decimali);
      Serial.print("Temp2 = ");
      Serial.println(Temp2, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp3 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp3, Decimali);
      Serial.print("Temp3 = ");
      Serial.println(Temp3, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp4 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp4, Decimali);
      Serial.print("Temp4 = ");
      Serial.println(Temp4, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Valvola = Z.toInt();
      mySerial.println(Valvola);
      Serial.print("Valvola = ");
      Serial.println(Valvola);
      
    }
    }
    
    Serial.println("inizio stringa");
    
     String data;
   
  
    if ( millis() > Timer1 + 5000)
  { 
    Serial.println("inizio dati"); 
    
    data+="";
    data+="entry.0.single=";// prima label temperatura IN acqua
    data+=Temp1;
    
    data+="&entry.3.single=";// seconda label temperatura OUT acqua
    data+=Temp2;
    
    data+="&entry.4.single=";// terza label Stato elettrovalvola 1
    
    data+=Temp3;
    
    data+="&entry.5.single=";// quarta label Stato circolatore caldaia
    data+=Temp4;
    
    
    data+="&entry.6.single=";// quinta label Stato valvola
    if (Valvola == 1){
     stv = ("aperta");       // stampa aperta
    }
    
    if (Valvola == 0) {
     stv = ("chiusa");       // stampa chiusa
    }
    
    
    //data+=Valvola;
    data+=stv;
    data+="&submit=Submit";
    

  Serial.println("connecting Ethernet");
    
  
    client.connect(server,80) ;
    //if (client.connected(server, 80)) {
      if (client.connected()) {
    Serial.println("connected");
 
    client.print("POST /formResponse?formkey=");
    client.print(formkey);
    client.println("&ifq HTTP/1.1");
    client.println("Host: spreadsheets.google.com");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
 
    Serial.print("POST /formResponse?formkey=");
    Serial.print(formkey);
    Serial.println("&ifq HTTP/1.1");
    Serial.println("Host: spreadsheets.google.com");
    Serial.println("Content-Type: application/x-www-form-urlencoded");
    Serial.println("Connection: close");
    Serial.print("Content-Length: ");
    Serial.println(data.length());
    Serial.println();
    Serial.print(data);
    Serial.println();
    Timer1 = millis();
    
    }
   
    

    client.stop();
 
  
  }
    delay(500);
     }
   }

Posso immagginare che il blocco avvenga per esaurimento della memoria RAM.

Se ne discusso alcuni giorni fa e il responsabile potrebbe essere l'oggetto String.

Anziché inizializzare la String data con un stringa vuota, fai così:

...
   // inserire tanti caratteri quanto la più lunga stringa possibile"
  String data = "1234567890123456789012345678901234567890123456789012345678901234567890";
  data = "";  // svuota la stringa
  data += "entry.0.single=";
  data += String(analogIn0, DEC);
  data += "&entry.1.single=";
...

dopo 3-4 giorni il freeze lo causa una stringa dichiarata vuota?
ci mette 4 giorni a riempire il buffer o la ram?
Se è un esaurimento della ram, perchè solo lo shield si inchioda e non arduino?
come mai non risponde alle richieste, ma al ping si?
come mai riavviando l'SPI torna a funzionare correttamente?

Ragazzi sono 2 anni che leggo questo problema, ma una soluzione definitiva non l'ha ancora trovata nessuno, non dico che lo fanno tutti gli sketch, ma il suo è davvero elementare.

Sono quasi convinto che il problema è causato da qualche cosa che va storto all'interno della rete...il problema non si verifica in tutte le reti lan, solo su alcune.

ciao

Se così fosse, non basterebbe che l'Arduino resettasse lo shield ethernet quando si accorge che questo si è piantato?

Ho sentito che il chip W5100 ha alcuni problemi (dicono ci sia un bug hardware ma non ne sono sicuro) che comunque dovrebbero essere stati aggirati negli IDE a partire dalla 1.0.0. Il mio consiglio è di utilizzare sempre l'IDE più aggiornato...

Ciao a tutti e grazie per le risposte.

Seguirò i vostri consigli e vi faccio sapere.
Ora Arduino risponde al ping ma per il resto sembra tutto morto.
Purtroppo è stato installato a 1800 mt. slm ed ha messo troppa neve per andare a recuperarlo.
Ne ho un altro a banco ed inizierò ulteriori prove con quello.

Grazie ancora del prezioso aiuto.

Dovresti mettere tutti i testi stampati nella Flash e non nella RAM. Questo si fa cosí:
Serial.print(F("testo"));
mySerial.println(F("testo")); oppure
client.print(F("testo"));

Questo é stato introdotto con IDE 1.0.0 http://arduino.cc/en/Main/ReleaseNotes

Support has been added for printing strings stored in flash (program
memory) rather than RAM. Wrap double-quoted strings in F() to indicate
that they should be stored in flash, e.g. Serial.print(F("hello world")).

Ciao Uwe