Avvio webserver

Buonasera e buon anno al forum,

Il webserver è parte di un progetto che mi permette di visualizzare con un browser la temperatura misurata con un termistore.

il webserver ha un comportamento anomalo. Quando carico il programma tramite l’IDE tutto funziona regolarmente. Quando spengo Arduino (togliendo l’alimentazione) e lo riaccendo con un alimentatore esterno ( scollegandolo dal pc) , il webserver non riparte. Se, infine, dopo averlo riacceso collegandolo al pc, provo ad analizzare il codice con il serial monitor per il debug, il webserver riparte.
Penso di poter escludere problemi hw o di configurazione di rete.

Vi ringrazio anticipatamente per la disponibilità e resto in attesa di chiarimenti o per ulteriori info.

Hardware: Arduino UNO + Ethernet Shield Rev. 3

Software (solo le impostazioni iniziali + setup() perchè credo sia qui il problema! ) :

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

const int REQ_BUF_SZ = 40;     // Request Buffer Size

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  // inserisco il MAC address 
byte ip[] = { 192, 168, 1, 177};                      // inserisco l'indirizzo IP della rete. 
byte subnet[] = { 255, 255, 255, 0 };              // subnet 
byte gateway [] =  { 192, 168, 1, 254};           // il router
byte dns_server[] = { 8, 8, 8, 8};                    // dns server

EthernetServer server(80);
 
File webFile;                    // gestisce i file sulla SD CARD
char HTTP_req[REQ_BUF_SZ] = {0}; // HTTP request
char req_index = 0;              // l'indice al buffer HTTP_req


const int SERIESRESISTOR = 4700;     // il valore della resistenza 
const int THERMISTORPIN = A0;        // il pin A0 dove è connesso il sensore
const int THERMISTORNOMINAL = 4700;  // la resistenza del termistore a  25 gradi C
const int TEMPERATURENOMINAL = 25;   // temperatura nominale (almost always 25 C)
const int BCOEFFICIENT = 3950;       // il coefficiente beta del termistore (usually 3000-4000)
const int NUMSAMPLES = 5;           // numero di campioni presi per ogni misura 

int samples[NUMSAMPLES];        // array contenente il numero di campioni prelevati

//Scaffold 
 #define DEBUG 1

/*
 ---------------------------------------------------------------------------------------------------------
  CONFIGURAZIONE INIZIALE
 ---------------------------------------------------------------------------------------------------------
 */

void setup()
{
    analogReference(EXTERNAL);   
    
     
    // disabilito Ethernet chip
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);

    #ifdef DEBUG
    Serial.begin(9600);            // Inizializzo la comunicazione seriale per il Debugging.
    #endif
    
    // Inizializzo l'SD Card
    #ifdef DEBUG
    Serial.println(F("Inizializzo l'SD card..."));      // Debug
    #endif
    
    if (!SD.begin(4)) {
        
        #ifdef DEBUG
        Serial.println(F("ERRORE - Inizializzazione dell'SD Card fallita!"));   // Debug
        #endif
        
        return;    // Inizializzazione fallita
    }
    
    #ifdef DEBUG
    Serial.println(F("SUCCESSO - SD card inizializzata."));        // Debug
    Serial.println();                                           // Debug
    #endif
   
    // controllo l'esistenza del file "index.htm" all'interno dell'SD Card
    
    if (!SD.exists("index.htm")) {
        
        #ifdef DEBUG
        Serial.println(F("ERRORE - Non trovo il file <<index.htm>>!"));
        #endif
        
        return;  // non trovo il file "index.htm"
    }
    #ifdef DEBUG
    Serial.println(F("SUCCESSO - File <<index.htm>> trovato."));   // Debug
    Serial.println();                                           // Debug
    #endif
      
    Ethernet.begin(mac, ip, dns_server, gateway, subnet);   // inizializzo la libreria ethernet con le impostazioni di rete
    
server.begin();            // inizializzo il server web. 
    
#ifdef DEBUG
    Serial.println(F("Il server e' AVVIATO all'indirizzo: "));  // Debug
    Serial.print(F("Local IP: "));
    Serial.println(Ethernet.localIP()); // Debug. 
    Serial.print(F("SubnetMask: "));
    Serial.println(Ethernet.subnetMask());
    Serial.print(F("Gateway: "));
    Serial.println(Ethernet.gatewayIP());
    Serial.print(F("DNS Server: "));
    Serial.println(Ethernet.dnsServerIP());
    Serial.println();                              // Debug
    #endif
}

/*
 ---------------------------------------------------------------------------------------------------------
  CICLO
 ---------------------------------------------------------------------------------------------------------
 */

void loop()
{
    ...
}

Che potenza ha l'alimentatore esterno? Forse non è sufficiente per alimentare sia Arduino che lo shield Ethernet.

L'alimentatore è 5V-1A.

Mi sono dimenticato di aggiungere che, dopo averlo alimentato con l'alimentatore, se premo il reset hw sulla scheda, tutto funziona perfettamente.

Ho l'impressione che togliendo l'alimentazione si blocchi in qualche ciclo. In seguito, quando lo alimento di nuovo non riesegue il setup e quindi non mi avvia il server.

1A dovrebbe bastare.

La tua sensazione è sbagliata... Quando stacchi Arduino dal PC si spegne e non esegue più niente, dovre prenderebbe l'alimentazione? :)

Posta lo sketch, magari hai qualcosa che dipende dall'apertura della seriale, che ovviamente avviene solo a PC connesso.

axelfusillo: Buonasera

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni e a leggere il regolamento se non lo hai già fatto: Regolamento Qui una serie di link utili, non inerenti al tuo problema: - qui una serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections - qui le pinout delle varie schede by xxxPighi: Pinout - qui una serie di link [u]generali[/u] utili: Link Utili

SukkoPera:
La tua sensazione è sbagliata… Quando stacchi Arduino dal PC si spegne e non esegue più niente, dovre prenderebbe l’alimentazione? :slight_smile:

Forse non sono riuscito a spiegarmi bene. Il mio dubbio è su cosa succede quando interrompo l’alimentazione e poi la fornisco di nuovo. Il codice viene eseguito da capo?

SukkoPera:
Posta lo sketch, magari hai qualcosa che dipende dall’apertura della seriale, che ovviamente avviene solo a PC connesso.

Ho inserito un #ifdef#endif sulla seriale e funziona tutto. Credo di poterlo escludere.

Inoltre ho fatto un ulteriore prova. Dopo aver rialimentato arduino, il webserver non funziona, ma se premo il pulsante reset sulla scheda, torna a funzionare. Questo mi porta ancora a pensare che il codice non viene eseguito tutto.

In allegato i file.

sketch_jan03a.ino (15.9 KB)

index.txt (1.79 KB)

axelfusillo: Forse non sono riuscito a spiegarmi bene. Il mio dubbio è su cosa succede quando interrompo l'alimentazione e poi la fornisco di nuovo. Il codice viene eseguito da capo?

Certamente, e viene rieseguita la setup()

La ethernet è arduino originale? Ti sei dimenticato anche di dire da dove lo alimenti? il minimo è 7v su jack.

https://www.arduino.cc/en/Main/ArduinoBoardUno Input Voltage (recommended) 7-12V

anche il pin 4 va impostato con pinmode e messo in high ci vorrebbe un delay(1000) all'inizio del setup

pablos: anche il pin 4 va impostato con pinmode e messo in high

Questo non è necessario, ci pensa la libreria.

pablos: La ethernet è arduino originale? Ti sei dimenticato anche di dire da dove lo alimenti? il minimo è 7v su jack.

https://www.arduino.cc/en/Main/ArduinoBoardUno Input Voltage (recommended) 7-12V

anche il pin 4 va impostato con pinmode e messo in high ci vorrebbe un delay(1000) all'inizio del setup

La Ethernet è quella originale Rev.3 L'alimentazione avviene sempre da USB ( da pc o da alimentatore 5V-1A). Non ho provato ad alimentarlo tramite jack DC ma non credo sia un problema HW. Ho provato ad inserire il delay ed ad impostare pin 4 High ma non cambia nulla.

Non capisco perchè, dopo aver riacceso arduino, il webserver non si avvia, per poi avviarsi dopo che premo reset sulla scheda oppure accedendo al monitor seriale (funziona anche se dal codice tolgo Serial.begin()). Ho l'impressione che arduino stia aspettando un qualche input quando viene riavviato

Forse ho individuato il mio problema di Power On Reset della Ethernet Shield con W5100, ma non la soluzione.

Ho trovato i seguenti link che ne parlano:

Ma le soluzioni proposte a me non funzionano. Ho provato a mettere :

  • un condensatore da circa 50nF tra il pin Reset e GND.... niente da fare!
  • una resistenza da 10k tra 3.3V e Reset, un condensatore da 50nF tra Reset e GND, piegato il pin reset della ethernet shield in modo da non inserirlo in arduino... niente da fare!
  • Reset da pin digitale connesso a Reset, ma mi riavviava continuamente anche arduino.

Sbaglio qualcosa o ci sono anche altre soluzioni (anche comprando altre shield) che risolvono il problema? Nel forum non sono riuscito a trovarle...

nella funzione setup() prova a mettere un delay(100) prima di fare qualsiasi altra cosa. Una buona soluzione è anche quella di collegare il pin reset dell'ethernet shield ad arduino in modo da poterla resettare via software.

Infine se vuoi creare del debug senza impazzire con le macro #if puoi fare cosi:

#ifdef DEBUG
    #define dbgInit(S) Serial.Begin(S)
    #define dbg(S) Serial.print(S)
    #define dbgln(S) Serial.println(S)
#else
    #define dbgInit(S)
    #define dbg(S)
    #define dbgln(S)
#endif

ora nel codice:

void setup()
{
    delay(100);//x ethernet shield
    
    dbgInit(9600);

    dbgln("Loading...");
    ...
    ...

SukkoPera: Questo non è necessario, ci pensa la libreria.

Sicuro? io vedo che la lib SD non riporta nemmeno alla lib SPI, dove solo SPIClass::begin() fa un reale pinmode e mette in high, non SD.begin(4), nessuna istruzione della SD.h o SD.cpp fa riferimento a pinmode o attraverso i registri, il begin(4) dice che va usato il pin 4 come attivatore della periferica, può darsi che ho seguito male i percorsi, se mi mostri dove lo fa ci togliamo il dubbio per sempre :)

questo mi ricorda un vecchio problema saltuario di cui parlai molto tempo fa, che versione della UNO hai ?

lo chiedo perche' le prime versioni erano senza diodo sul reset e con il vecchio bootloader, ed a volte faceva sto scherzo. Caricando l'attuale bootloader ed inserendo il diodo (1n4148 dovrebbe andare) sul reset vedi un po' se risolvi

pablos:
Sicuro?

Se non fosse così, ci sarebbe un problema concettuale: se uso una libreria per interfacciarmi con una periferica, allora mi aspetto che sia sua premura fare tutto ciò che è necessario a basso livello, a meno di indicazioni esplicite in merito, che però devono essere in qualche modo giustificate. Se la libreria ha bisogno che quel pin sia un output, sarà lei a doverlo settare così, non devo preoccuparmene io, che sono assolutamente libero di ignorare tutti i dettagli di basso livello, visto che uso una libreria proprio per questo!

A volte non è così perché ci sono in giro un mucchio di porcate, questo è innegabile, ma le librerie “di serie” di Arduino sono in genere fatte molto bene, per cui non esulano da questo principio.

Nella fattispecie, SD.begin() fa:

return card.init(SPI_HALF_SPEED, csPin) /* e altro... */;

E card.init() fa:

chipSelectPin_ = chipSelectPin;
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
digitalWrite(chipSelectPin_, HIGH);

Per cui, come vedi, la cosa è perfettamente gestita dalla libreria. Altrettanto avviene per la Ethernet, in cui si arriva a chiamare:

SPI.begin(ETHERNET_SHIELD_SPI_CS);

Se non fosse così, ci sarebbe un problema concettuale: se uso una libreria per interfacciarmi con una periferica, allora mi aspetto che sia sua premura fare tutto ciò che è necessario a basso livello

proprio così hai azzeccato il problema... tu sei arrivato qualche anno dopo e non sei diventato pazzo per mesi a capire perchè.

Per cui, come vedi, la cosa è perfettamente gestita dalla libreria. Altrettanto avviene per la Ethernet, in cui si arriva a chiamare:

non penso proprio. fai un web server con SD senza pin mode e lascialo acceso 1 giorno/ 2 ... fallo con pinmode e lascialo acceso 6 mesi

Rileggiti i miei post di 5 anni fa +/- i primi 1000... rileggi il forum di 5 anni fa sul crash delle sd e ethernet, ci sono voluti 2 anni per fare una correzioni inutile sulle lib ufficiali (convinti che fosse un timeout) ma che ancora non avevano risolto il problema. Ci siamo stati anni a capire perchè c'era questo difetto ... tale che nessuno comprava più le shield ... però ieri ho testato la shield con la 1.6.1 senza pinmode ed è crashata ancora al 3° refresh .. le cose non sono ancora state ufficialmente sistemate o chiarite.

Ti posso dimostrare immediatamente o quando vuoi con sketch le 2 differenze ... una crasha l'altra no

A questo punto facciamo un debug a quelle linee che sostieni facciano il compito (anche se non le ho trovate) con un bel serial.print ... sia sul 4 che sul 10 Ma anche se le trovo ti dico che il programma non ci arriva a quelle funzioni altrimenti non ci sarebbero i crash. Hai la ethernet tu?

Se non sbaglio non c'e' di mezzo anche un bug hw al componente stesso ? Tanto che per gli standalone si consiglia di isare il 5200 ?

@pablos: Beh, se dici che fino a un po' di anni fa la libreria aveva dei problemi, mi fido. Come dici tu, io sono arrivato "dopo", per cui non posso esprimermi in merito.

Quel che posso fare è dire come dovrebbero essere le cose da un punto di vista teorico, e su questo mi sembra che siamo d'accordo. I problemi di anni fa potevano essere dovuti alla giovinezza di Arduino e/o dell'Ethernet Shield, ma mi sembra che ormai i due siano decisamente consolidati, per cui credo che [u]adesso[/u] sia lecito aspettarsi che la pratica corrisponda alla teoria.

Ho un paio di Ethernet Shield (cloni ma fatti bene), con cui ho smanettato un po' in passato, ma per una serie di motivi sugli aggeggi che ho costruito e che stanno accesi a lungo ho usato ENC28J60 (che ha i suoi problemi :(), con il Wiz non ho mai fatto test di "resistenza", per cui non posso esprimermi direttamente nemmeno su questo. Però posso dire che non è mai crashato al 3° refresh :).

Guardando il codice (versione attuale però, non ha senso discutere della 1.6.1! https://github.com/arduino/Arduino/tree/master/libraries/Ethernet) mi sembra che sia tutto corretto. Se hai tempo e voglia possiamo fare dei test e vedere se riusciamo ad individuare il problema preciso.

La libreria SD non l'ho mai utilizzata, invece. Tuttavia, guardando il codice mi sembra che sia come mi aspetto.

Non sono esperto di librerie ma ho fatto ulteriori test che spero possano aiutare a capire di più il problema e a trovare una soluzione.

  • Ho caricato lo sketch " WebServer" dagli Esempi. Poi ho fatto la prova al “power-up” e tutto funziona regolarmente. Penso di poter di nuovo escludere un problema hw
  • Ho modificato il mio sketch per far in modo che la pagina web non sia caricata da SD, ma si trovi all’interno del codice. Poi ho fatto la prova al “power-up” e tutto funziona regolarmente. Questo mi fa pensare di nuovo ad un problema software (forse nelle librerie come sostenete voi)

Poi ho modificato il setup,avviando il webserver prima di fare il controllo sull’SD card:

 // disable Ethernet chip
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);

    Serial.begin(9600);       // Inizializzo la comunicazione seriale per il Debugging
    
            
    Ethernet.begin(mac, ip, dns_server, gateway, subnet);   // inizializzo la libreria ethernet 
    server.begin();            // inizializzo il server web. 

    Serial.print("il server e' all'indirizzo: ");   // Debug
    Serial.println(Ethernet.localIP()); 

 // Inizializzo l'SD Card
    Serial.println("Inizializzo l'SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERRORE - Inizializzazione dell'SD Card fallita!");
        return;    // Inizializzazione fallita
    }
    Serial.println("SUCCESSO - SD card inizializzata.");
    
    // controllo l'esistenza del file "index.htm" all'interno dell'SD Card
    if (!SD.exists("index.htm")) {
        Serial.println("ERRORE - Non trovo il file <<index.htm>>!");
        return;  // non trovo il file "index.htm"
    }
    Serial.println("SUCCESSO - File <<index.htm>> trovato.");

Adesso, al “power-up” il webserver si avvia (lo riesco a pingare) ma la SD Card no!!! Ho ottenuto il problema contrario… Ma non me lo so spiegare. Ovviamente se premo il pulsante di reset o avvio il monitor seriale, tutto funziona regolarmente.
Ho l’impressione che ci sia un problema di gestione tra il W5100 e la SD Card solo all’accensione.

Testato:
questo mi ricorda un vecchio problema saltuario di cui parlai molto tempo fa, che versione della UNO hai ?

lo chiedo perche’ le prime versioni erano senza diodo sul reset e con il vecchio bootloader, ed a volte faceva sto scherzo.
Caricando l’attuale bootloader ed inserendo il diodo (1n4148 dovrebbe andare) sul reset vedi un po’ se risolvi

Non ho l’ultima versione della UNO ma ho provato a usare il diodo e la scheda si riavvia continuamente.

axelfusillo: Non ho l'ultima versione della UNO ma ho provato a usare il diodo e la scheda si riavvia continuamente.

Lo hai messo al contrario ;) Se e' la vecchia versione allora ti conviene, indipendentemente dal risolvere o meno, di aggiornare il bootloader