enc28J60 e Arduino (5)

luca 27/02/2012 20

Nella quinta parte di questo tutorial, inizieremo ad utilizzare il nostro ethernet shield per trasformare Arduino in un server web.

World Wide Web

Tra i servizi di rete, quello sicuramente più utilizzato è il servizio web: ogni volta che “navigate” su un sito, il programma che utilizzate (chiamato browser) contatta il server web che ospita tale sito utilizzando il protocollo HTTP e ottiene i contenuti (pagine, immagini, animazioni…) da visualizzare.

Le pagine web sono scritte utilizzando un linguaggio di marcatura chiamato HTML; tale linguaggio utilizza dei tag per descrivere il contenuto della pagina.

I principali vantaggi di utilizzare HTTP anche per comunicare via rete con Arduino sono:

  • non è necessario sviluppare un client dedicato, è possibile utilizzare un comune browser (Internet Explorer, Firefox…);
  • il protocollo HTTP è testuale, facilmente interpretabile da Arduino con le funzioni di string compare
  • anche il linguaggio HTML è testuale, rendendo comodo generare pagine -anche dinamiche- da Arduino.

 Programma

Scriveremo un semplice programma che stamperà su seriale le richieste del nostro browser e risponderà con una semplice pagina HTML. Il programma sarà utile sia per vedere come gestire la comunicazione HTTP, sia per capire quali informazioni il browser ci manda (informazioni che saranno utilizzate in un prossimo tutorial).

Lo sketch completo è disponibile sul repository di GitHub, di seguito commentiamo le righe di codice più significative:

  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);

All’interno del loop salviamo in una variabile il valore di ritorno del metodo packetLoop(): questo valore indica la posizione, all’interno dei buffer di ricezione, in cui inizia la richiesta del browser.

  if(pos) {
 
    Serial.println("---------- NEW PACKET ----------");
    Serial.println((char *)Ethernet::buffer + pos);
    Serial.println("--------------------------------");
    Serial.println();

Se pos è maggiore di zero, significa che abbiamo effettivamente ricevuto una richiesta e possiamo stamparla su seriale (buffer + pos indica proprio la posizione da cui partire ad estrarre i dati dal buffer di ricezione).

    BufferFiller bfill = ether.tcpOffset();

Per memorizzare la risposta da inviare al browser, utilizziamo un oggetto BufferFiller. Questo oggetto deriva dalla classe Print e viene costruito passando l’indirizzo (tcpOffset) del buffer ethernet da cui partire per memorizzare la risposta.

    bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
         "Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"
         "<html><body><h1>BasicServer Demo</h1></body></html>"));

Il metodo emit_p() ci consente di inserire dati nel buffer: in questo caso creiamo una semplice pagina HTML che visualizza la scritta BasicServer Demo. Per risparmiare spazio in memoria RAM, utilizziamo la macro PSTR() che memorizza le stringhe in PROGRAM.

    ether.httpServerReply(bfill.position());

Infine utilizzando il metodo httpServerReply() possiamo inviare al browser la risposta. Il metodo richiede, come parametro, il numero di caratteri da inviare; numero di caratteri che possiamo ottenere dal BufferFiller con il suo metodo position().

Caricato lo sketch, possiamo provarne il funzionamento inserendo nel browser l’indirizzo IP di Arduino… il risultato dovrebbe essere:

E sul monitor seriale:

Vi starete domandando come mai il browser ha fatto due richieste, una per la pagina “/” (ovvero la homepage del sito) e una per l’immagine favicon.ico. Questa è l’immagine che alcuni siti visualizzano accanto al loro indirizzo; ecco ad es. l’icona di DangerousPrototypes:

 

20 Comments »

  1. Angelo 05/03/2012 at 00:47 - Reply

    sono assolutamente digiuno di informatica ed elettronica, ma ho molto apprezzato i tutorial per arduino che mi hanno aiutato a capire come connetterlo ad una rete. Vorrei ancora avere indicazioni per trasmettere dati a google spreadsheet (magari usando i moduli) e anche come impostare una porta diversa dalla 80 sulla quale ho già un altro webservver. grazie per il lavoro già fatto che ha condiviso.

  2. mario 14/04/2012 at 19:45 - Reply

    Hai provato questa nuova libreria per ENC28j60 ??
    https://github.com/turicas/Ethernet_ENC28J60

    • luca 23/04/2012 at 11:27 - Reply

      Ciao Mario,

      no, non l’ho ancora provata… ad un primo sguardo sembra condividere molto codice di base con la EtherCard, anche se qualche parte sembra scritta in maniera più “pulita”…

  3. Ciprian 20/04/2012 at 09:55 - Reply

    Hello,

    I found your tutorials very interesting. I have a question if you can help me.
    I am trying to create a temperature sensor on a web page. I use ENC28j60 and the ethercard library.
    How can i write down on the webpage the temperature that my sensor is sensing and another variable from my arduino program?

    Another question is how to make buttons on the webpage act on a variable in my program.

    Regards.

    • luca 23/04/2012 at 11:28 - Reply

      Hi Ciprian,

      I’m working on a new tutorial with a more complex webserver… stay tuned ;)

  4. ettore 19/05/2012 at 20:24 - Reply

    ciao luca,

    complimenti per il tutorial.
    Sono riuscito a eseguirlo e ad integrarlo in una mia applicazione che legge degli impulsi da un contalitri e al momento li spedisce sulla seriale.
    Tramite un timer, eseguo il codice relativo alla parte ethernet e riesco correttamente a collegarmi al server e visualizzare sul browser la pagina demo che hai proposto. In questa pagina, vorrei inserire il valore dei miei impulsi che è salvato in una variabile di tipo int. Ho provato a creare una stringa contenente la risposta HTTP ma quando faccio bfill.emit_p(PSTR(miastringa)); il compilatore mi da questo errore:

    initializer fails to determine size of ‘__c’

    Sono abbastanza nuovo di Arduino per cui non conosco ancora bene la sintassi e le best practices….hai un consiglio da darmi ?

    Grazie!

    • luca 23/05/2012 at 18:57 - Reply

      Ciao Ettore!

      “miastringa” è una stringa statica oppure una tua variabile?

  5. Peter 24/05/2012 at 07:53 - Reply

    Luca, thanks for your great tutorial, I have a question: I’d like to connect 3-4 EthernetArduinos via Ethernet and allow them to share files stored on their respective SD cards.
    I’ve found examples for making the Arduino a web-server, but it needs a DHCP server being provided by e.g. a PC.
    And it doesnt really allow one arduino to access the files on the other arduino’s SD card.
    I was wondering if you think this would be possible and maybe give me a few pointers how to best go about it. Thank you in advance!
    Peter

    • luca 24/05/2012 at 08:29 - Reply

      Hi Peter

      you don’t need a DHCP server, you can configure ethernet shield with a static IP address using staticSetup().
      I wasn’t able to find an example using SD card with enc28j60 shield… I’m working on it! ;)

  6. Axel 27/12/2012 at 20:29 - Reply

    Ciao Luca,
    During the last days I learned a lot from you about the EtherCard library and collaboration with Arduino – Thanks!

    However, I still got one for you: With “smaller” Arduinos I run into buffer size limitations. Do you know whether there is a way to split the response to the server in smaller chunks allowing to keep the message within the buffer size limits?
    Thanks a lot in advance!
    Axel

    • luca 31/12/2012 at 12:26 - Reply

      Hi Axel!

      Unfortunately at the moment the EtherCard library doesn’t support TCP fragmentation and you’re required to buffer the entire packet in Arduino’s memory… The developers are working on a rewritten version of the library so keep an eye on its Github repository!

  7. Pedro 09/04/2013 at 23:08 - Reply

    Hi!
    how I can send a string to indicate the state of a digital input?
    Thanks

    • luca 12/04/2013 at 21:26 - Reply

      Hi Pedro,

      are you trying to display the state of a digital pin on a webpage? Or send it to a script/program?

  8. Jean 28/05/2013 at 15:09 - Reply

    Do the tutorials for the enc28j60 also work with ethernet shield & W5100?

    • luca 28/05/2013 at 16:31 - Reply

      no, the two ICs are very different… for W5100 you can refer to the official Arduino documentation.

  9. Renato Aloi 01/12/2013 at 00:36 - Reply

    Hi Luca!

    Do you have any news about TCP fragmentation? I am working on this behavior and it getting me crazy!

    Do you have contact with EtherCard developers? Do you think they would interest in my work?

    Take a look at: https://github.com/renatoaloi

    Please, if you can send me some feedback it will be very nice for my work. Thanks!

    Renato

    • luca 02/12/2013 at 09:39 - Reply

      Hi Renato,

      no, at the moment my workaround is the use of Yun, where the ethernet connection is managed by a Linux distribution. I contacted the authors of EtherCard via Github, I think they may be interested as I know they are rewriting the library to support such functionalities!

  10. Maryori Sabalza 20/01/2015 at 04:53 - Reply

    Hi, congratulations for tutorial!

    Please help me..
    In my serial monitor:

    BasicServer Demo
    Ethernet controller initialized
    Failed to get configuration from DHCP
    IP Address: 0.0.0.0
    Netmask: 0.0.0.0
    Gateway: 0.0.0.0

    What wrong¿?

    • luca 21/01/2015 at 20:01 - Reply

      Hi Maryori,

      it’s hard to find out what’s wrong… it seems that Arduino doesn’t receive a valid address: is a DHCP server active in your network? Try changing the Mac address in the sketch, it may help.

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi