[RISOLTO]leonardo si blocca dopo un paio di giorni

Buongiorno a tutti

Ho realizzato un apricancello collegando un leonardo eth ad un telecomando a 433Mhz (ho fattto questo perche’ il telecomando in questione e’ un rolling code , e non ho trovato soluzione piu rapida).

Il tuttto funziona tramite una pagine web.

Il tutto funziona perfettamente senza intoppi per 3-4 giorni. Dopo circa quattro giorni quando mi connetto alla pagina web , questa non viene caricata (premetto che viene caricada da una sd), e restituisce una pagina vuota.

Semplicemente spegno e riaccendo l’arduino e tutto riprende a funzionare regolarmente.

Qualche idea sul perche faccia cosi?

questo il codice arduino

#include <SPI.h>
#include <Ethernet2.h>
#include <SD.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xB8, 0x27, 0xEB, 0x0B, 0xE6, 0x06 };
IPAddress ip(192, 168, 0, 168); // IP address, may need to change depending on network
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(80);  // create a server at port 80
File webFile;
String HTTP_req;            // stores the HTTP request

void setup()
{
   Serial.begin(9600);       // for diagnostics
  
  // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
    pinMode(7, OUTPUT);// switch is attached to Arduino pin 3
    digitalWrite(7, LOW);
    pinMode(3, INPUT);
  Ethernet.begin(mac, ip, gateway, subnet);  // initialize Ethernet device
  server.begin();           // start to listen for clients
  Serial.print("Server is at");
  Serial.print(Ethernet.localIP());
  pinMode(7, OUTPUT);        // switch is attached to Arduino pin 3

}

void loop()
{
  EthernetClient client = server.available();  // try to get client

  if (client) {  // got client?
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {   // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        HTTP_req += c;  // save the HTTP request 1 char at a time
        // last line of client request is blank and ends with \n
        // respond to client only after last line received
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: keep-alive");
          client.println();
          // AJAX request for switch state
          if (HTTP_req.indexOf("opengate") > -1) {

            digitalWrite(7, HIGH);
            delay(475);
          int readopened = digitalRead(3);
            delay(375);
            digitalWrite(7, LOW);
           if(readopened = HIGH){
              client.println("opened");
              }
            if(readopened = LOW){
              client.println("notopened");
                 }
          }
          else {  
            // web page request
                        // send web page
                        webFile = SD.open("index.htm");        // open web page file
                        if (webFile) {
                            while(webFile.available()) {
                                client.write(webFile.read()); // send web page to client
                            }
                            webFile.close();
                        }
          }
          // display received HTTP request on serial port
          Serial.print(HTTP_req);
          HTTP_req = "";            // finished with request, empty string
          break;
        }
        // every line of text received from the client ends with \r\n
        if (c == '\n') {
          // last character on line of received text
          // starting new line with next character read
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // a text character was received from client
          currentLineIsBlank = false;
        }
      } // end if (client.available())
    } // end while (client.connected())
    delay(1);      // give the web browser time to receive the data
    client.stop(); // close the connection
  } // end if (client)
}

questa la pina web

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <link rel="icon" href="/favicon.ico" type="image/ico">
  <style>
  
    body {
   text-align:center;
   vertical-align:middle;
   height: 100%;
   }
    div {
     
    width:100%;
    height:100%;
    position:absolute;
    top:40%;
    margin: 0 0 0 0;
    text-align:center;
    vertical-align:middle;
    }
 
   button {
    width: 4em; 
    height: 1.5em;
      font-size:4em;
      
     }
     
     #opened{
     font-size:2em;
     color: #32CD32;
     }
     #notopened{
     font-size:3em;
     color: #FF0000;
     }
     #error{
     font-size:5em;
     color: #FF0000;
     font-weight: bold;
     
     }
   
  
    </style>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="generator" content="PSPad editor, www.pspad.com">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script>
    function Openthegate() {
             nocache = "&nocache="+ Math.random() * 1000000;
             var request = new XMLHttpRequest();
             request.onreadystatechange = function() {
          if (this.readyState == 4) {
            if (this.status == 200) {
              if (this.responseText = "opened") {
                 document.getElementById("opened").innerHTML = "Opened"; 
                 }
              else if (this.responseText = "notopened") {
                 document.getElementById("notopened").innerHTML = "Something wrong, check the gate!!"; 
                  }
              else{
                 document.getElementById("error").innerHTML = "ERROR, CALL CRISTIAN"; 11
              
              }}}}
            request.open("POST", "opengate" + nocache, true);
            request.send(null);
            }
         </script>
    <title></title>
    </head>
    <body>
          <div >
            <button type="button"  onclick="Openthegate()">Apri</button>
            <p id="opened"></p>
            <p id="notopened"></p>
            <p id="error"></p>
          </div>
    </body>
  </html>

Grazie a tutti per l’aiuto

ciao…non me ne intendo di dialogo tra arduino e pagine web…però nel tuo sketch ci sono un po’ di “errori” negli if()…confondi “=” per “==”…poi nel setup() metti due volte il pin 7 in OUTPUT…questo non penso sia un problema ma giusto per fartelo notare.
io farei così…dato che hai un bel po’ di pin liberi metterei qualche LED con l’attivazione e disattivazione in diversi punti del programma…giusto per vedere dove si blocca…potresti fare che si accendano uno dopo l’altro ed alla fine dello sketch li spegni tutti…e così via…

grazie non mi ero accorto del doppio ouput del pin 7, e nemmeno del ==.

Sono alle prime armi con questo mondo ;D

Questo codice e' ancora "sporco" a livello di sintassi e commenti non l'ho ancora sistemato del tutto

Forse mi e' venuta un idea.

L'arduino leonardo ha un reset automatico se si apre e si richiude la serial port a 12000

ora se io facessi una cosa del genere , funzionerebbe anche se l'arduino non e' collegato a nessun pc ??

 if (webFile) {
                            while(webFile.available()) {
                                client.write(webFile.read()); // send web page to client
                            }
                            webFile.close();

                            }
         else{

           Serial.begin(12000);
           delay(1);
           Serial.end();
          }

Se vuoi un reset automatico quando si blocca puoi usare il [u]WDT[/u].

-zef-:
Se vuoi un reset automatico quando si blocca puoi usare il [u]WDT[/u].

grazie mille, non avevo idea che esistesse una cosa del genere sui microprocessori.

Anche se non so se questa soluzione possa risolvere del tutto il problema. Se ho ben capito wdt resetta il microchip , non l'intera scheda. Dato che il leonardo ha anche il microchip della parte ethernet ,se fosse quello che va in blocco il reset del 32u4 potrebbe non essere sufficente a risolvere il problema . O forse mi sbaglio? Voi ne sapete piu di me, spero in qualche vostra delucidazione

usa la makro F() per risparmiare RAM nei .print("testo") e .println("testo").
esempio:
Serial.println(F("ERROR - SD card initialization failed!"));
Ciao Uwe

Potrebbe essere l’uso di String.
La classe String può portare alla microframmentazione della memoria. Hai solo 2Kb di SRAM, per fare prove va bene, ma si consiglia l’uso delle stringhe classiche del C (array/vettore di char) di cui conosci sempre la dimensione massima, allocazione statica e non dinamica come fa la String. A forza di allocare/liberare pezzetti di memoria, la esaurisce e si blocca tutto.

uwefed:
usa la makro F() per risparmiare RAM nei .print("testo") e .println("testo").
esempio:
Serial.println(F("ERROR - SD card initialization failed!"));
Ciao Uwe

grazie mille . correggero subito

cri_pava:
grazie mille . correggero subito

Si, ma considera che, SE è un problema di esaurimento della memoria causa frammentazione da classe "String", sicuramnete con l'uso della macro (F) migliori temporaneamente la situazione, ma comunque ... il problema prima o poi si ripresenterà.

In tale caso, o si passa alle stringhe classiche del 'C' (che altro non sono che array di caratteri prefissati) o, sapendo QUANTO la tua String sarà lunga come massimo, preallocarla con l'apposita funzione (che è stata introdotta apposta per tamponare il problema) reserve().

Guglielmo

nid69ita:
Potrebbe essere l'uso di String.
La classe String può portare alla microframmentazione della memoria. Hai solo 2Kb di SRAM, per fare prove va bene, ma si consiglia l'uso delle stringhe classiche del C (array/vettore di char) di cui conosci sempre la dimensione massima, allocazione statica e non dinamica come fa la String. A forza di allocare/liberare pezzetti di memoria, la esaurisce e si blocca tutto.

Grazie . in effetti anche io ho pensato ad un problema con la ram. Dato che comunque il tutto funziona per un paio di giorni . Grazie cerchero' di sostituire come dici tu. Spero di esserne in grado e di non incappare in qualche altro problema.

gpb01:
Si, ma considera che, SE è un problema di esaurimento della memoria causa frammentazione da classe "String", sicuramnete con l'uso della macro (F) migliori temporaneamente la situazione, ma comunque ... il problema prima o poi si ripresenterà.

In tale caso, o si passa alle stringhe classiche del 'C' (che altro non sono che array di caratteri prefissati) o, sapendo QUANTO la tua String sarà lunga come massimo, preallocarla con l'apposita funzione (che è stata introdotta apposta per tamponare il problema) reserve().

Guglielmo

ho capito cosa intendi. si forse in effetti F() non e' la soluzione.

Intanto grazie a tutti . Ho bisogno di qualche ora per elaborare tutte le informazioni che mi avete dato :slight_smile: . ci si vede tra qualche ora, o al massimo stasera . Buona giornata a tutti

buon pomeriggio

gpb01:
In tale caso, o si passa alle stringhe classiche del 'C' (che altro non sono che array di caratteri prefissati) o, sapendo QUANTO la tua String sarà lunga come massimo, preallocarla con l'apposita funzione (che è stata introdotta apposta per tamponare il problema) reserve().

Guglielmo

dunque sono arrivato ad un altro punto cieco. La mia stringa è una richiesta http. una cosa del genere:

POST /opengate&nocache=575554.9432709698 HTTP/1.1
Host: 00.00.00.00
Origin: 00.00.00.00
Content-Length: 0
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_1 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0 Mobile/15C153 Safari/604.1
Accept-Language: ru
Referer: 00.00.00.00
Accept-Encoding: gzip, deflate

la sua lunghezza varia molto a seconda del tipo di browser, del tipo di sistema operativo ecc..

non vedo una maniera semplice di calcolarne la lunghezza. Inoltre credo che se dovessi allocare con Reserve() una lunghezza troppo corta la richiesta fallirebbe.

io non conosco bene il c, ma da quello che ho letto in queste ore mi sembra molto difficile gestire queste richieste con gli array e i char. O mi sbaglio?

Maestri , aspetto i vostri consigli

ps.Ho sostituito ip con 00.00.00.00 per nn metterlo visibile sul forum

a parer mio da dopo "HTTP/1.1" tutto il resto serve veramente a poco. La parte interessante (con POST) è prima.

nid69ita:
a parer mio da dopo "HTTP/1.1" tutto il resto serve veramente a poco. La parte interessante (con POST) è prima.

non saprei , ma credo che anche

Connection: keep-alive

abbia qualche utilità. Soprattutto visto il fatto che poi viene inviata una risposta a questa richiesta

Comunque mi sembra di aver capito che il watchdog su arduino leonardo eth sia problematico

uff.. perche si trovano sempre tanti problemi :sob:

Forse non mi sono spiegato bene o non ci capiamo.
TU rispondi con questo tuo pezzo:

// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();

C'e' un keep-alive, ma... cosa c'entra con la String che ricevi ? Non è la tua risposta da Arduino ma quello che il browser manda al tuo Arduino che tu memorizzi in HTTP_req e che analizzi. Li dentro c'e' quello che tu hai postato al msg #11.
Stiamo parlando di sapere quanto spazio fare per quella richiesta che arriva dal browser. Richiesta interessante dal /post fino al "HTTP/1.1", tutto il resto sono solo dati "inutili"

nid69ita:
Forse non mi sono spiegato bene o non ci capiamo.
TU rispondi con questo tuo pezzo:

// send a standard http response header

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();




C'e' un keep-alive, ma... cosa c'entra con la String che ricevi ? Non è la tua risposta da Arduino ma quello che il browser manda al tuo Arduino che tu memorizzi in HTTP_req e che analizzi. Li dentro c'e' quello che tu hai postato al msg #11.
Stiamo parlando di sapere quanto spazio fare per quella richiesta che arriva dal browser. Richiesta interessante dal /post fino al "HTTP/1.1", tutto il resto sono solo dati "inutili"

scusa sono io che no mi spiego bene e che comunque non ho tutte le vostre conoscenze percio puo capitare che mi sbaglio.

ho capito adesso cosa intendi.

Comunque per il momento ho aggiunto reserve() come suggerito da guglielmo . Poi vedro se cambiare altre cose.

Grazie a tutti per il supporto . Siete fantastici 8)