Pages: [1] 2 3 4   Go Down
Author Topic: Strano freeze del loop  (Read 3822 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve,
ho collegato un sensore SRF02 alla mia Leonardo per misurare l'altezza d'acqua in una vasca e pubblico il risultato usando una risposta http, di seguito il codice:

Code:
// librerie usate nel progetto
#include "SPI.h"             
#include "Wire.h"             
#include "SRF02.h"
#include <Ethernet.h>
// costanti che contengono il mac e l'IP della scheda di rete
byte mac[] = { 0x90, 0xA2, 0x__, 0x__, 0x__, 0x__ };
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;

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 setup()
{
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);
  Serial.begin(9600);
  Wire.begin();
  sensor.setInterval(500);
  //inizializza lo shield con il mac e l'ip
  Serial.println("Ethernet initialization ...");
  Ethernet.begin(mac, ip);
  String secs_txt;
  for(int i = 1; i < 6; i++){
    secs_txt = String(30 - i * 5);
    Serial.println("Ethernet ready in " + secs_txt + " sec.");
    digitalWrite(led, HIGH);
    delay(100);
    digitalWrite(led, LOW);
    delay(4900);
  };
  Serial.println("Ethernet ready");
  //inizializza l'oggetto server
  ArduinoServer.begin();
  Serial.println("Webserver ready");
  sensor.update();
  Serial.println("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);
  };
}

void loop()
{
  //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
      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')
      {
        Serial.println("richiesta http completata");
        //Invio la risposta al client
        //invio lo status code
        pc_client.println("HTTP/1.1 200 OK");
        //imposto il data type
        pc_client.println("Content-Type: text/html");
        pc_client.println();
        //invio codice html
        pc_client.println("<html>");
        pc_client.println("<head>");
        pc_client.println("<title>Water level</title>");
        pc_client.println("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"10\">");
        pc_client.println("<META HTTP-EQUIV=\"PRAGMA\" CONTENT=\"NO-CACHE\">");
        pc_client.println("</head>");
        pc_client.println("<body bgcolor=\"black\" text=\"white\" link=\"lime\" vlink=\"lime\">");
        pc_client.println("<div align=\"center\" style=\"font-family:tahoma,verdana,arial;font-size:18px;font-style:italic\">");
        // chiedo il valore all'SRF
        Serial.println("before sensor.update");
        sensor.update();
        Serial.println("after sensor.update");
        if (millis() > nextPrint)
        {
          Serial.println("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;
          Serial.print("disponibilita = ");
          Serial.println(disponibilita_litri);
          colore = "white";
          if (disponibilita_litri <= livello_attenzione) {
            attenzione = true;
            colore = "yellow";
            Serial.println("stato attenzione");
          };     
          if (disponibilita_litri <= livello_allerta) {
            attenzione = false;
            allerta = true;
            colore = "orange";
            Serial.println("stato allerta");
          };     
          if (disponibilita_litri <= livello_allarme) {
            attenzione = false;
            allerta = false;
            allarme = true;
            colore = "red";
            Serial.println("stato allarme");
          };     
          Serial.println("stato attenzione");
          Serial.println("after sensor.read");
          Serial.println("livello = " + thelevel_txt);
          nextPrint = millis () + 1000;
        };
        pc_client.print("valore al sensore ");
        pc_client.print(real_level);
        pc_client.println("<br>");
        pc_client.println("valore per i calcoli ");
        pc_client.println(thelevel_flt);
        pc_client.println("</div><br><br><br><br><br>");
        pc_client.println("<div align=\"center\" style=\"font-family:tahoma,verdana,arial;font-size:72px\">");
        pc_client.println(disponibilita_metricubi);
        pc_client.println("m<sup>3</sup> di ");
        pc_client.println(capienza_metricubi);
        pc_client.println("m<sup>3</sup>");

        pc_client.println("</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(" di ");
        pc_client.println(capienza_litri);
        pc_client.println("litri");
        pc_client.println("</div>");
        pc_client.println("</body>");
        pc_client.println("</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.stop();
    pc_client = false;
    msg = "";
delay(7500);
    digitalWrite(led, LOW);
  } else {
    digitalWrite(led, HIGH);
    delay(80);           
    digitalWrite(led, LOW);
    delay(80);           
    digitalWrite(led, HIGH);
    delay(80);           
    digitalWrite(led, LOW);
    delay(80);           
    digitalWrite(led, HIGH);
    delay(80);           
    digitalWrite(led, LOW);
    delay(250);
  };
}



metto un pò di lampeggi del led per vedere cosa succede anche quando non ho l'IDE collegato.

Il problema sorge a random almeno 30 minuti dopo l'avvio: il led non lampeggia più, se effettuo una richiesta al webserver non ho alcuna risposta, ma se lancio un ping, la scheda mi risponde.
Infine, con la scheda in questo stato, se provo ad uploadare uno sketch, l'IDE resta su upload binary (o qualcosa del genere, adesso non ricordo).

Quale potrebbe essere il problema?
Grazie
Logged

--
Alfredo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

La risposta al ping credo sia data dall'altra scheda, non dalla Leonardo, giusto? (non conosco le schede Ethernet).
Quando la scheda si blocca, hai altri LED accesi, oltre a quello ON?
Hai provato ad usare la funzione F() per leggere le stringhe direttamente dalla Flash? Potrebbe essere un problema di RAM saturata.
Logged


Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 45
Posts: 1505
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quasi certamente ha ragione Leo, il tuo problema è la variabile stringa msg (e forse anche le altre variabili stringa).

Correttamente ad ogni ciclo la resetti, ma il problema è la sua lunghezza variabile: se supera una certa dimensione, alloca altro spazio nella HEAP e dopo alcuni cicli saturi la memoria.

Di solito risolvo il problema inizializzando in setup la stringa non con una stringa vuota, ma con una "piena" (tipo msg = "123456789012345") in modo da allocare sufficiente spazio in memoria.

Ettore Massimo Albani

 
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

provo e vi faccio sapere, grazie
Logged

--
Alfredo

Italy
Offline Offline
Full Member
***
Karma: 6
Posts: 102
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Secondo me se eviti di stampare tutti sti messaggi di debug, il loop non si freeza. Tutto quello che passi a serial. Printl e client.println va in RAM che, grazie anche a msg, tende a saturarsi. Se ti rimane spazio in flash e non vuoi eliminare i messaggi di debug, prova come dice Leo a mandare tutte le stringhe in flash con PROGMEM o,  se ide>1.0, utilizzando la funzione F().  qua dice:
Quote
Version 1.0 of the Arduino IDE introduced the F() syntax for storing strings in flash memory rather than RAM. e.g.
Serial.println(F("This string will be stored in flash memory"));
N.
Logged

"The question is not whether intelligent machines can have emotions, but whether machines can be intelligent without any emotions"

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, qualche esempio sull'uso di F(), dove lo trovo?
Logged

--
Alfredo

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 114
Posts: 7194
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, qualche esempio sull'uso di F(), dove lo trovo?
E' semplice.
Ad esempio una parte del tuo codice
Code:
pc_client.println("<html>");
pc_client.println("<head>");
pc_client.println("<title>Water level</title>");
pc_client.println("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"10\">");
con la funzione F() diventa
Code:
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\">"));

Applicalo a tutti i print, pc_client e serial, e sei a posto.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quasi certamente ha ragione Leo, il tuo problema è la variabile stringa msg (e forse anche le altre variabili stringa).

Correttamente ad ogni ciclo la resetti, ma il problema è la sua lunghezza variabile: se supera una certa dimensione, alloca altro spazio nella HEAP e dopo alcuni cicli saturi la memoria.

Di solito risolvo il problema inizializzando in setup la stringa non con una stringa vuota, ma con una "piena" (tipo msg = "123456789012345") in modo da allocare sufficiente spazio in memoria.

Ettore Massimo Albani

 

con questa soluzione gira da più di 24 ore senza freeze ...
grazie

adesso provo con F(), che mi pare la soluzione migliore, in vista di arricchire le risposte web ...
Logged

--
Alfredo

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, qualche esempio sull'uso di F(), dove lo trovo?
E' semplice.
Ad esempio una parte del tuo codice
Code:
pc_client.println("<html>");
pc_client.println("<head>");
pc_client.println("<title>Water level</title>");
pc_client.println("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"10\">");
con la funzione F() diventa
Code:
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\">"));

Applicalo a tutti i print, pc_client e serial, e sei a posto.

mi torna questo errore "initializer fails to determine size of '__c'"
Logged

--
Alfredo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Forse la libreria che usi tu non supporta la funzione F().
La funzione F() è stata aggiunta a partire dall'ultima versione dell'IDE ed è inclusa in Print.h, che a sua volta viene invocata dalla libreria Stream.h, usata come base per gli oggetti Serial e LiquidCrystal.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Forse la libreria che usi tu non supporta la funzione F().
La funzione F() è stata aggiunta a partire dall'ultima versione dell'IDE ed è inclusa in Print.h, che a sua volta viene invocata dalla libreria Stream.h, usata come base per gli oggetti Serial e LiquidCrystal.

la versione dell'IDE è la 1.0.1 e ho provato ad includere anche Print.h o Stream.h, ma niente.
Altri suggerimenti?
Logged

--
Alfredo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non basta includerla tu, deve essere il codice scritto per poterla usare.
L'altro suggerimento è modificare il codice della lib oppure riscrivere il tuo inserendo il supporto alle stringhe in Flash con ProgMem.
Logged


Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 45
Posts: 1505
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

E' evidente che la libreria che usi per inviare comandi HTML non supporta la funzione F().

Puoi risparmiare spazio, invece, usandola con tutte le istruzioni Serial.print.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

E' evidente che la libreria che usi per inviare comandi HTML non supporta la funzione F().

Puoi risparmiare spazio, invece, usandola con tutte le istruzioni Serial.print.

L'errore "initializer fails to determine size of '__c'" mi viene tornato quando nel Serial.println o pc_client.println c'è una variabile, ad esempio:
Serial.println(F("Ciao")); // non da errore
Serial.println(F(nome_variabile_di_tipo_testo)); // da errore

qual'è il corretto utilizzo di F()?
Logged

--
Alfredo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22966
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma "nome_variabile_di_tipo_testo" di che tipo è?
F() dovrebbe lavorare con i tipi String.
Logged


Pages: [1] 2 3 4   Go Up
Jump to: