Strano freeze del loop

pablos:
comunque se posso permettermi.

:wink:

pablos:
sarebbe utile settare il pin 10 utilizzato dalla ethernet

aggiungi nelle dichiarazioni variabili
byte SD_CS = 4; // pin 4 is the SPI select pin for the SDcard
byte ETHER_CS = 10; // pin 10 is the SPI select pin for the Ethernet

nel setup()
pinMode(ETHER_CS, OUTPUT);
digitalWrite(ETHER_CS, HIGH);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);

per curiosità, a che serve?

pablos:
prima di chiudere il client svuota il buffer
pc_client.flush();
pc_client.stop();

provo

pablos:
elimina quel serial.write
//Serial.write(Data_RX);

ciao

tanto non viene eseguito perchè è sotto #define.

ciao e grazie

Il pin CS, Chip Select, serve per selezionare quale dispositivo attivare con cui comunicare via SPI.

tanto non viene eseguito perchè è sotto #define.

No. Lo devi proprio togliere, indifferentemente dal define debug, nel bel mezzo di client.read mi mandi byte alla seriale se per funzionare lo devi lasciare il define a 0 che lasci a fare quella riga.... la ethernet è già molto rognosa di suo, interrompere il suo lavoro per fare altre cose e poi riprenderle non la prende bene. Fagli finere il ciclo e poi stampa il debug sempre che sia attivato. I serial.print li metterei al di fuori del while (pc_client.connected())

il tuo sketch ce l'ho in test da ieri sera, è ancora li che gira

ciao

pablos:

tanto non viene eseguito perchè è sotto #define.

No. Lo devi proprio togliere, indifferentemente dal define debug, nel bel mezzo di client.read mi mandi byte alla seriale se per funzionare lo devi lasciare il define a 0 che lasci a fare quella riga.... la ethernet è già molto rognosa di suo, interrompere il suo lavoro per fare altre cose e poi riprenderle non la prende bene. Fagli finere il ciclo e poi stampa il debug sempre che sia attivato. I serial.print li metterei al di fuori del while (pc_client.connected())

il tuo sketch ce l'ho in test da ieri sera, è ancora li che gira

ciao

domani provo, ti ringrazio

finalmente ho due minuti per scrivere ...

// librerie usate nel progetto
#include "Wire.h"             
#include "SRF02.h"
#include "Ethernet.h"
#include "SPI.h"             
#define DEBUG 0
// costanti che contengono il mac e l'IP della scheda di rete
//byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x50, 0x18 }; //ethernet shield mia
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0C, 0x00, 0x6D }; //ethernet shield mia 2
byte ip[] = { 192,168,1,50 };

// inizializzazione componente SRF con l'indirizzo 0x70
SRF02 sensor(0x70, SRF02_CENTIMETERS);
float larghezza_cisterna = 2;
float lunghezza_cisterna = 2;
float altezza_cisterna = 1.3;
float livello_acqua = 0;
float delta_sensore_galleggiante = 13;
const float capienza_metricubi = larghezza_cisterna * lunghezza_cisterna * altezza_cisterna;
const float capienza_litri = capienza_metricubi * 1000;
float disponibilita_metricubi = 0;
float disponibilita_litri = 0;
float livello_attenzione = 2000;
float livello_allerta = 1200;
float livello_allarme = 700;
bool attenzione = false;
bool allerta = false;
bool allarme = false;
String colore = "white";
unsigned long nextPrint = 0;
byte SD_CS = 4;  // pin 4 is the SPI select pin for the SDcard
byte ETHER_CS = 10; // pin 10 is the SPI select pin for the Ethernet

int led = 12;

//creo una variabile char per memorizzare i byte letti dal client
char Data_RX;
String msg = "";
int cmd = 0;
int real_level = 0;
int thelevel = 0;
String thelevel_txt;
float thelevel_flt;
//creo un oggetto server che rimane in ascolto sulla porta
//specificata
EthernetServer ArduinoServer(80);

void ToSerial(String stringa)
{
  #if DEBUG
  Serial.println(stringa);
  #endif
}

void ToSerial(float stringa)
{
  #if DEBUG
  Serial.println(stringa);
  #endif
}

 
void setup()
{
  pinMode(ETHER_CS, OUTPUT);      
  digitalWrite(ETHER_CS, HIGH);
  pinMode(SD_CS, OUTPUT);      
  digitalWrite(SD_CS, HIGH); 
  
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);
  #if DEBUG
  Serial.begin(9600);
  #endif
  Wire.begin();
  sensor.setInterval(500);
  //inizializza lo shield con il mac e l'ip
  ToSerial("Ethernet initialization ...");
  Ethernet.begin(mac, ip);
  msg = "1234567890123456789012345678901234567890123456789012345678901234567890";
  String secs_txt;
  for(int i = 1; i < 6; i++){
    secs_txt = String(30 - i * 5);
	ToSerial("Ethernet ready in " + secs_txt + " sec.");
    digitalWrite(led, HIGH);
    delay(100);
    digitalWrite(led, LOW);
    delay(4900);
  };
  ToSerial("Ethernet ready");
  //inizializza l'oggetto server
  ArduinoServer.begin();
  ToSerial("Webserver ready");
  sensor.update();
  ToSerial("SRF ready");

  // stato di fine setup e inizio loop 
  for(int j = 0; j < 5; j++){
    digitalWrite(led, HIGH);
    delay(250);            
    digitalWrite(led, LOW);
	delay(250);
  }; 
}

//String toWeb(lastringa

void loop()
{
//  SRF02::update();

  //IMPORTANTE pulisco la variabile msg
  msg = "";
  //Ascolto le richieste dei client controllo se ci sono dati da leggere
  //e creo un oggetto relativo a client che sta interrogando l'Ethernet shield
  EthernetClient pc_client = ArduinoServer.available();
  //controllo se pc_client è diverso da false
  if (pc_client != false)
  {
    digitalWrite(led, HIGH);
    //controllo se il client è connesso
    while (pc_client.connected())
    {
      //leggo i byte disponibili
      //provenienti dal client
      Data_RX = pc_client.read();
      //invio i dati letti al Serial Monitor
      ToSerial(Data_RX);
//	  Serial.write(Data_RX);
      //Attendo che tutti i byte siano letti
      //quando Data_RX contiene il carattere
      //di nuova line capisco tutti i byte sono
      //stati letti
      msg += Data_RX;
      if (Data_RX == '\n')
      {
        ToSerial("richiesta http completata");
        //Invio la risposta al client
        //invio lo status code
        pc_client.println(F("HTTP/1.1 200 OK"));
        //imposto il data type
        pc_client.println(F("Content-Type: text/html"));
        pc_client.println(F("\n"));
        //invio codice html
        pc_client.println(F("<html>"));
        pc_client.println(F("<head>"));
        pc_client.println(F("<title>Water level</title>"));
        pc_client.println(F("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"10\">"));
        pc_client.println(F("<META HTTP-EQUIV=\"PRAGMA\" CONTENT=\"NO-CACHE\">"));
        pc_client.println(F("</head>"));
        pc_client.println(F("<body bgcolor=\"black\" text=\"white\" link=\"lime\" vlink=\"lime\">"));
        pc_client.println(F("<div align=\"center\" style=\"font-family:tahoma,verdana,arial;font-size:18px;font-style:italic\">"));
        // chiedo il valore all'SRF
        ToSerial("before sensor.update");
        sensor.update();
        ToSerial("after sensor.update");
        if (millis() > nextPrint)
        {
          ToSerial("before sensor.read");
          real_level = sensor.read();
          thelevel = real_level;
          thelevel = thelevel - delta_sensore_galleggiante; 
          thelevel_txt =  String(thelevel, DEC);
          thelevel_flt = (float) thelevel / 100;
          livello_acqua = altezza_cisterna - thelevel_flt;
          disponibilita_metricubi = livello_acqua  * lunghezza_cisterna * larghezza_cisterna;
          disponibilita_litri = disponibilita_metricubi * 1000;
          ToSerial("disponibilita = ");
          ToSerial(disponibilita_litri);
          colore = "white";
          if (disponibilita_litri <= livello_attenzione) {
            attenzione = true;
            colore = "yellow";
            ToSerial("stato attenzione");
          };     
          if (disponibilita_litri <= livello_allerta) {
            attenzione = false;
            allerta = true;
            colore = "orange";
            ToSerial("stato allerta");
          };     
          if (disponibilita_litri <= livello_allarme) {
            attenzione = false;
            allerta = false;
            allarme = true;
            colore = "red";
            ToSerial("stato allarme");
          };     
          ToSerial("stato attenzione");
          ToSerial("after sensor.read");
          ToSerial("livello = " + thelevel_txt);
          nextPrint = millis () + 1000;
        };
        pc_client.print(F("valore al sensore "));
        pc_client.print(real_level);
        pc_client.println(F("
"));
        pc_client.println(F("valore per i calcoli "));
        pc_client.println(thelevel_flt);
        pc_client.println(F("</div>




"));
        pc_client.println(F("<div align=\"center\" style=\"font-family:tahoma,verdana,arial;font-size:72px\">"));
        pc_client.println(disponibilita_metricubi);
        pc_client.println(F("m<sup>3</sup> di "));
        pc_client.println(capienza_metricubi);
        pc_client.println(F("m<sup>3</sup>"));

        pc_client.println(F("</div>"));
        pc_client.println("<div align=\"center\" style=\"color:" + colore + ";font-family:tahoma,verdana,arial;font-size:72px\">");
        pc_client.println(disponibilita_litri);
        pc_client.println(F(" di "));
        pc_client.println(capienza_litri);
        pc_client.println(F("litri"));
        pc_client.println(F("</div>"));
        pc_client.println(F("</body>"));
        pc_client.println(F("</html>"));
        //aspetto 10 ms affinche la risposta giunga al browser del client
        delay(10);
        //esco dal ciclo while una volta completato l'invio della risposta
        break;
      }
      //chiudo la connessione
    }
	pc_client.flush();
    pc_client.stop();
    pc_client = false;
    msg = "";
	delay(7500);
    digitalWrite(led, LOW);
  } else {
    digitalWrite(led, HIGH);
    delay(80);            
    digitalWrite(led, LOW);
    delay(2000);
  };
}

ecco il codice montato sulla mia leonardo, ma dopo circa 12/15 ore di funzionamento si blocca.
Potrebbe essere guasta? La shield ethernet l'ho già cambiata.

Ho anche una mega 2560, provo con quella?

Ciao e grazie a tutti

Ho anche una mega 2560, provo con quella?

Sí.
Potrebbe essere un problema di RAM. Facendo la prova con la MEGA puoi controllarlo.

Ciao Uwe

uwefed:

Ho anche una mega 2560, provo con quella?

Sí.
Potrebbe essere un problema di RAM. Facendo la prova con la MEGA puoi controllarlo.

Ciao Uwe

montata ... speriamo bene!

Ma l'hai fatto un controllo statico del consumo di memoria con avr-size oppure no?
Tanto per capire dove andiamo a cascare..

Poi hai una miriade di invocazioni ad una funzione ToSerial che altro non fa che stampare stringhe sulla seriale. Peccato che tutte quelle stringhe gliele passi dalla Ram.
Riscrivi il codice togliendo quella funzione e mettendo un semplice Serial.println in modo da poter usare le stringhe gestite in Flash con la funzione F() e racchiudendo tutto tra #define se vuoi stampare solo in caso di debug.
So che così raddoppi la lunghezza del tuo codice ma elimini un sacco di occupazione di memoria.

leo72:
Ma l'hai fatto un controllo statico del consumo di memoria con avr-size oppure no?
Tanto per capire dove andiamo a cascare..

no, come si fa?

leo72:
Poi hai una miriade di invocazioni ad una funzione ToSerial che altro non fa che stampare stringhe sulla seriale. Peccato che tutte quelle stringhe gliele passi dalla Ram.

si, ma solo con il define DEBUG a 1

leo72:
Riscrivi il codice togliendo quella funzione e mettendo un semplice Serial.println in modo da poter usare le stringhe gestite in Flash con la funzione F() e racchiudendo tutto tra #define se vuoi stampare solo in caso di debug.

già ho provato ad usare F() in tutto le Serial.println che non avevano all'interno variabili, ma il sistema andava lo stesso in loop.

leo72:
So che così raddoppi la lunghezza del tuo codice ma elimini un sacco di occupazione di memoria.

questo non è un problema, puoi farmi un esempio? Grazie

essere_digitale:

leo72:
Ma l'hai fatto un controllo statico del consumo di memoria con avr-size oppure no?
Tanto per capire dove andiamo a cascare..

no, come si fa?

Compili lo sketch senza farne l'upload e con la modalità verbose attiva.
Nel terminale dell'IDE leggi dove sono stati creati i file temporanei del progetto e ti sposti in quella cartella.
Lì dai il comando:

avr-size -C nomeFirmware.cpp.elf

leo72:
Poi hai una miriade di invocazioni ad una funzione ToSerial che altro non fa che stampare stringhe sulla seriale. Peccato che tutte quelle stringhe gliele passi dalla Ram.

si, ma solo con il define DEBUG a 1

.
No, sempre! Il check se hai la modalità debug attiva lo fai all'interno della funzione ToSerial, quindi la funzione ToSerial viene chiamata sempre, col risultato che la variabile stringa viene sempre creata nella Ram e passata alla funzione, anche quando poi non stampi sulla seriale.

leo72:
Riscrivi il codice togliendo quella funzione e mettendo un semplice Serial.println in modo da poter usare le stringhe gestite in Flash con la funzione F() e racchiudendo tutto tra #define se vuoi stampare solo in caso di debug.

già ho provato ad usare F() in tutto le Serial.println che non avevano all'interno variabili, ma il sistema andava lo stesso in loop.

leo72:
So che così raddoppi la lunghezza del tuo codice ma elimini un sacco di occupazione di memoria.

questo non è un problema, puoi farmi un esempio? Grazie

Quindi questo:

ToSerial("Ethernet ready");

deve diventare

#if DEBUG
Serial.println(F("Ethernet ready"));
#endif

Solo in questo modo hai la certezza che:

  1. includerai quel serial.println solo quando sei in modalità debug
  2. una volta incluso, la stringa verrà letta dalla Flash

leo72:

essere_digitale:

leo72:
Ma l'hai fatto un controllo statico del consumo di memoria con avr-size oppure no?
Tanto per capire dove andiamo a cascare..

no, come si fa?

Compili lo sketch senza farne l'upload e con la modalità verbose attiva.
Nel terminale dell'IDE leggi dove sono stati creati i file temporanei del progetto e ti sposti in quella cartella.
Lì dai il comando:

avr-size -C nomeFirmware.cpp.elf

ecco il risultato

AVR Memory Usage
----------------
Device: Unknown

Program:   19014 bytes
(.text + .data + .bootloader)

Data:        969 bytes
(.data + .bss + .noinit)

leo72:
Poi hai una miriade di invocazioni ad una funzione ToSerial che altro non fa che stampare stringhe sulla seriale. Peccato che tutte quelle stringhe gliele passi dalla Ram.

si, ma solo con il define DEBUG a 1

.
No, sempre! Il check se hai la modalità debug attiva lo fai all'interno della funzione ToSerial, quindi la funzione ToSerial viene chiamata sempre, col risultato che la variabile stringa viene sempre creata nella Ram e passata alla funzione, anche quando poi non stampi sulla seriale.

leo72:
Riscrivi il codice togliendo quella funzione e mettendo un semplice Serial.println in modo da poter usare le stringhe gestite in Flash con la funzione F() e racchiudendo tutto tra #define se vuoi stampare solo in caso di debug.

già ho provato ad usare F() in tutto le Serial.println che non avevano all'interno variabili, ma il sistema andava lo stesso in loop.

leo72:
So che così raddoppi la lunghezza del tuo codice ma elimini un sacco di occupazione di memoria.

questo non è un problema, puoi farmi un esempio? Grazie

Quindi questo:

ToSerial("Ethernet ready");

deve diventare

#if DEBUG

Serial.println(F("Ethernet ready"));
#endif



Solo in questo modo hai la certezza che:
1) includerai quel serial.println solo quando sei in modalità debug
2) una volta incluso, la stringa verrà letta dalla Flash

ok, adesso lo modifico

leo72:
Quindi questo:

ToSerial("Ethernet ready");

deve diventare

#if DEBUG

Serial.println(F("Ethernet ready"));
#endif



Solo in questo modo hai la certezza che:
1) includerai quel serial.println solo quando sei in modalità debug
2) una volta incluso, la stringa verrà letta dalla Flash

il codice sta già girando ... speriamo bene!

Piccolo appunto: se attivo il debug, il compilatore mi segnala errori perchè alla funzione F() posso passare solo stringhe e non variabili che contengono stringhe.

    #if DEBUG
    Serial.println(F("Ethernet ready in " + secs_txt + " sec.")); ////ERRORE DEL COMPILATORE
    #endif

invece

  #if DEBUG
  Serial.println(F("Ethernet initialization ...")); //// NESSUN ERRORE
  #endif

Per queste uso Serial.println senza F() ?
Grazie

Serial.println(F("Ethernet ready in " + secs_txt + " sec.")); ////ERRORE DEL COMPILATORE

Scomponila in più parti, no? :wink:

Esempio:

#if DEBUG
Serial.print(F("Ethernet ready in "));
Serial.print(secs_txt); //solo questo verrà copiato in Ram
Serial.println(F(" sec."));
#endif

Nota l'uso di println solo con l'ultima stampa.

essere_digitale:

leo72:
Quindi questo:

ToSerial("Ethernet ready");

deve diventare

#if DEBUG

Serial.println(F("Ethernet ready"));
#endif



Solo in questo modo hai la certezza che:
1) includerai quel serial.println solo quando sei in modalità debug
2) una volta incluso, la stringa verrà letta dalla Flash

il codice sta già girando ... speriamo bene!

Niente da fare: dopo 36 ore si blocca.

Perché non provi ad includere la libreria memoryFree ed a spedire ad intervalli regolari il quantitativo libero di RAM? Così capiamo se il blocco avviene per esaurimento della memoria oppure no.

leo72:
Perché non provi ad includere la libreria memoryFree ed a spedire ad intervalli regolari il quantitativo libero di RAM? Così capiamo se il blocco avviene per esaurimento della memoria oppure no.

Scusa l'ignoranza, come si fa?

Installi la libreria, che probabilmente fornirà una funzione tipo freeMemory(), il cui risultato stampi periodicamente (tipo 1 volta ogni 10 secondi) sulla seriale.

essere_digitale:

leo72:
Perché non provi ad includere la libreria memoryFree ed a spedire ad intervalli regolari il quantitativo libero di RAM? Così capiamo se il blocco avviene per esaurimento della memoria oppure no.

Scusa l'ignoranza, come si fa?

Ho scritto un articolino apposta:
http://www.leonardomiliani.com/?p=572

tuxduino:
Installi la libreria, che probabilmente fornirà una funzione tipo freeMemory(), il cui risultato stampi periodicamente (tipo 1 volta ogni 10 secondi) sulla seriale.

10 secondi come intervallo sono troppo pochi. Basta 1 volta all'ora, visto che gli è andato in crash l'Arduino dopo 36 ore.

leo72:

essere_digitale:

leo72:
Perché non provi ad includere la libreria memoryFree ed a spedire ad intervalli regolari il quantitativo libero di RAM? Così capiamo se il blocco avviene per esaurimento della memoria oppure no.

Scusa l'ignoranza, come si fa?

Ho scritto un articolino apposta:
Come sapere l’occupazione di RAM del proprio sketch – Leonardo Miliani

tuxduino:
Installi la libreria, che probabilmente fornirà una funzione tipo freeMemory(), il cui risultato stampi periodicamente (tipo 1 volta ogni 10 secondi) sulla seriale.

10 secondi come intervallo sono troppo pochi. Basta 1 volta all'ora, visto che gli è andato in crash l'Arduino dopo 36 ore.

Non ho parole ...