enc28J60 e Arduino (18)

by luca
15 comments

Arduino

Lo sketch per Arduino è disponibile su Github.

Obiettivo dello sketch è inviare al client una immagine spezzandola in più pacchetti. L’immagine è stata convertita in byte array usando l’utility bin2h già vista in un precedente esempio e salvata nel file like.h:

like

Non appena Arduino riceve una richiesta dal browser dell’utente, invia un pacchetto di ACK:

ether.httpServerReplyAck();

All’interno di un ciclo while, l’immagine viene quindi suddivisa in blocchi di 500 bytes (PAYLOAD_SIZE). Ogni blocco viene copiato (usando memcpy_P perché il byte array è salvato nella PROGMEM) nel buffer e inviato.

Se è l’ultimo pacchetto, questo viene inviato con i flag ACK e FIN:

ether.httpServerReply_with_flags(size, flags);

altrimenti il pacchetto viene inviato con il solo flag ACK per non chiudere la connessione:

      else {
        memcpy_P(ether.tcpOffset(), like + like_index, PAYLOAD_SIZE);
        ether.httpServerReply_with_flags(PAYLOAD_SIZE, TCP_FLAGS_ACK_V);
        Serial.print(" -> sent packet ");
        Serial.println(packet_count);        
        like_index += PAYLOAD_SIZE;
        packet_count += 1;
      }

Un test mostra come il browser sia in grado di ricevere tutti i segmenti dell’immagine e di visualizzarla correttamente:

multipkt-1

Grazie ad uno sniffer di rete (Wireshark) è possibile anche controllare che effettivamente i pacchetti arrivino come programmato:

multipkt-2

Conclusioni

La possibilità di frammentare i dati inviati consente di realizzare sketch molto più flessibili e potenti… in questo primo articolo abbiamo visto la teoria alla base e un esempio non molto pratico (l’immagine è hardcoded nello sketch).

Nel prossimo tutorial vedremo invece come realizzare un webserver che legge i dati da una memoria esterna.

Related Posts

15 comments

Ruben 20 settembre 2014 - 14:12

Ciao Luca
Ti ringrazio per i tutorial sull’utilizzo dello shield enc28j60. Li ho seguito tutti e devo dirmi mi hanno molto aiutato a comprendere meglio la library ethercard, cosa non facile se parti dal loro sito. Avevo iniziato ad utilizzare il modulo con la library UIPEthernet, ma ho trovato molti problemi di freeze della scheda. Sto lavorando con una arduino uno e uno shield IE del ITEAD.
Sto sviluppando un primo progetto di controllo della caldaia attraverso una pagina web. Ho iniziato impostando un client che postava e leggeva dati dal mio server, ovvero arduino riceveva istruzioni in base ai parametri che passava al server.
Ho trovato pero’ problematico il fatto che il client dovesse leggere il server ad ogni loop per vedere se vi fossero nuove istruzioni. Cosi’ ho pensato fosse meglio impostare un server all’ascolto di una nuova richiesta da un client, e qui mi sono tornati molto utili i tuoi tutorial. Tuttavia ho notato che: 1. Nonostante il server e’ in attesa di una richesta da un client, i due comandi ether.packetreceived e ether.packetloop, venendo richiamati ad ogni esecuzione dal loop, apparentement fanno riscaldare, e non poco il chip e, 2. Di tanto in tanto il programma (molto semplice, che dire) si blocca ed e’ necessario riavviare la scheda ( forse impostero’ un watchdog x rilevare blocchi nel codice?).
Secondo te, quale soluzione e’ migliore e piu’ robusta? Ovvero un client oppure un server?
E’ chiaro che non ci si puo’ permettere una soluzione che richiede costanti riavvi della scheda per blocchi del programma, anche se questi riavvi avvengano, si fa per dire, una volta alla settimana. Ti ringrazio in anticipo per la tua risposta.
Ruben

Reply
luca 22 settembre 2014 - 19:17

Ciao Ruben,

sicuramente l’approccio di far fare da server ad Arduino è più “lineare”… onestamente non ho mai riscontrato problemi di surriscaldamento del chip (quale? l’atmega o l’enc28j60?) temo che questo possa anche influire sui blocchi (anche qui ho un arduino+enc28j60 che da mesi è acceso senza blocchi)… sicuro che sia tutto collegato correttamente? Usi uno shield o un modulo esterno? Che sia in qualche modo difettoso?

Reply
Ruben 25 settembre 2014 - 13:50

Grazie Luca per la tua risposta
sto utilizzando uno shield posto sopra una scheda Arduino Uno, quindi non ci sono collegamenti volanti. Quando parlo di surriscaldamento mi riferisco al chip enc. nella fattispecie sto provando un semplice sketch che prevede all’inizio un aggiornamento dell’ora attraverso il tuo programmino ntp, quindi ogni volta che viene interrogato da un client restituisce data e ora.
Ma la vera soluzione all’architettura web di una scheda arduino l’ho pensata proprio ieri: ovvero utilizzare il server principale di casa su pc per interrogare a sua volta il server arduino. In questo modo posso programmare qualsivoglia pagina web sul pc combinando html e php senza intaccare la (povera) memoria dell’arduino. Che ne pensi? Puo’ essere una soluzione “furba”?
Grazie,
Ruben

Reply
luca 29 settembre 2014 - 07:44

Ciao Ruben, è strano davvero che scaldi… comunque la tua soluzione è ottima se hai a disposizione un server di appoggio: puoi interrogare Arduino solo per i dati “dinamici” e lasciare al server di casa la gestione del resto del sito

Reply
jmv 27 settembre 2014 - 12:54

very good luca, waiting the next tut, thanks!

Reply
tech 29 settembre 2014 - 14:39

ciao Luca,complimenti per i tuoi tutorial.
Sto progettando un lettore rfid che legge dalla carta il seriale e lo invia ad un database mysql.

sulla parte php residente sul server non ho problemi mentre ho dei problemi sull’invio della stringa da arduino al server.

utilizzo una enc28j60 con la libreria ethercard.

supponendo che ho una stringa da inviare( ad esempio codiceLetto=”abcefg”) mi potresti fare un esempio di come inviarla correttamente?

ho costruito nel mio server una pagina php che riceve in ingresso una variabile

$id=$_POST[‘codiceLetto’]
echo $id;

ho provato con vari metodi come browseUrl, httpPost ma non riesco a farli funzionare bene. Ho ottenuto un indirizzo ip da arduino e quindi la connessione funziona ma al server non arriva niente.

potresti darmi una mano?
ti ringrazio anticipatamente

Reply
luca 29 settembre 2014 - 19:00

Ciao! E’ più facile usando GET che POST, tanto per te lato php è uguale… se guardi il mio esempio 14 faccio proprio quello che serve a te: invio un valore (nel caso è una temperatura ma non cambia nulla) ad una pagina php

Reply
tech 30 settembre 2014 - 12:35

piccolo edit:
ho provato a sniffare la rete ma non passa nessuna richiesta http, solo una connessione tcp da arduino al server

Reply
luca 30 settembre 2014 - 12:44

ciao, ma hai usato lo sketch del mio esempio?

Reply
tech 30 settembre 2014 - 13:00

si, con il tuo sketch non mi crea il file csv e inoltre con wireshark vedo che non passa nessuna richiesta.

tech 30 settembre 2014 - 00:57

ciao ho provato a seguire il tuo tutorial ma con zero risultati, il file csv non viene creato e anche se lo creo io non viene riempito di nessun valore.
potresti farmi un esempio semplice semplice di come spedire una stringa e riceverla su un server php?

Reply
Ruben 1 ottobre 2014 - 09:46

Ciao Luca
grazie delle tue risposte e commenti. Ora tutto sta funzionando correttamente, tuttavia ho notato che in presenza delle righe di comando
word pos=ether.packetLoop(ether.packetReceived)
if (pos)
non è possibile fare eseguire ad Arduino altri comandi al di fuori della comunicazione tcp. Ovvero nella fattispecie io sto rilevando una temperatura da sensore DS18, ma se questa rilevazione avviene nel loop principale del programma, allora il server smette di funzionare, ovvero non risponde più. L’unico modo che ho trovato per far funzionare il tutto è inserire le due/tre righe di lettura della temperatura all’interno del if(pos). Ogni altro tentativo mi blocca il server, ovvero non riesce più a rispondere.
Come si può risolvere questo (apparente) conflitto?
Ti ringrazio in anticipo
Ruben

Reply
Pavel 18 novembre 2014 - 23:51

Hello.
Sorry for my bad English.
I have a question.
Could you make a tutorial based on several html pages. For example index.html, sensors.html, leds.html.

How this can be done?

Thanks in advance

Reply
luca 19 novembre 2014 - 10:20

Hi Pavel, did you read my latest tutorial (SDWebServer)? It can publish an arbitrary number of HTML pages, stored on an SD card.
bye

Reply
Danny 24 novembre 2014 - 09:38

Ciao,
anche a me l’ENC si surriscaldava e ho risolto comprando un modello cinese che sembra più stabile.
Quando si scaldava andava in blocco totale. Ora sto lavorando con la scheda WZ5100, che è molto più stabile, ma i tuoi tutorial mi hanno aperto la mente su molti problemi. Grazie!

Reply

Leave a Comment

undici − sei =