enc28J60 and Arduino (3)

luca 19/02/2012 58

In this third post, I’m going to show you how to connect and retrieve data from a web site.

After you’ve learned how to connect Arduino to your network (using static ip addresses or with the help of a DHCP server) you’re going to learn how to send/get data from a website.

To make the following example more realistic, I wrote a simple PHP web page that sends a random aphorism everytime you connect (aphorisms from Aphorisms Galore):

You’ll write an Arduino sketch to get those aphorisms and print them to serial connection.

DNS

Usually you contact a website typing its name: your PC, using a DNS server, is able to resolve that name into the corresponding IP address to perform the connection.

It’s so very important to configure in Arduino the IP address of the DNS server in your network:

  • if the configuration comes from a DHCP server, usually Arduino will be able to automatically get also DNS server;
  • if the configuration is entered manually, you need to include the IP address of your DNS server when calling the staticSetup() method:
#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
static byte myip[] = {192,168,1,10};
static byte gatewayip[] = {192,168,1,1};
static byte dnsip[] = {151,99,125,2};
...
ether.staticSetup(myip, gatewayip, dnsip);

You can verify if name resolution works using dnsLookup() method:

char website[] PROGMEM = "www.lucadentella.it";
...
if (!ether.dnsLookup(website))
  Serial.println("DNS failed");
else 
  Serial.println("DNS resolution done");  
ether.printIp("SRV IP:\t", ether.hisip);

Connection

EtherCard library has a very handy method to connect to a website: browseUrl(). This method prepares the connection; which is completed in following steps performed – during the loop – by the two instructions you already learned:

ether.packetLoop(ether.packetReceive());

It’s so very important to keep those instructions if you want that everything works.

browseUrl() method needs some parameters:

  • prog_char *urlbuf, address’ fixed part;
  • const char *urlbuf_varpart, address’ variable part;
  • prog_char *hoststr,website’s name;
  • void (*callback)(byte,word,word)), the name of a callback function, that is the function the library invokes at the end of the connection.

They divided the address in two parts to optimize memory utilization: the static part is stored in program memory (with PSTR() command) to avoid RAM memory , senza quindi sprecare memoria RAM.
In the next page I’m going to show you the complete sketch…

Pages: 1 2

58 Comments »

  1. Domenico 09/03/2012 at 21:04 - Reply

    Ciao,

    Ho provato tutti i tuoi esempi, e sono veramente interessanti.Ora, ho la necessità di accedere alla mia WebPage Arduino, dall’esterno. Mi sono iscritto al server NO-IP, che funziona abbastanza bene, ma devo necessariamente avere il PC acceso, che provvede ad effettuare la richiesa di autorizzazione, ogni volta che cambia l’indirizzo IP. E’ possibile far effettuare la richiesta direttamente da ARDUINO, senza dover necessariamente tenere il PC acceso ?
    Oppure conosci un altro sistema per risolvere il problema dell’IP dinamico ?

    Grazie in anticipo dell’aiuto.

    • luca 11/03/2012 at 20:28 - Reply

      Ciao Domenico,

      molti router ADSL hanno incorporata la funzione di aggiornamento per i più famosi servizi di Dynamic IP, prova a vedere se anche il tuo ti offre questa possibilità.

      Non ho mai pensato ad un modo per farlo fare ad Arduino, mi sembra un ottimo spunto per un futuro articolo ;)

  2. Domenico 12/03/2012 at 19:31 - Reply

    Ciao Luca,

    in realtà, il mio modem ha la possibilità di inserire il DDNS, ma solo con il server dyndns.org, che purtroppo è diventato a pagamento.
    Io, sono riuscito ad ottenere l’IP tramite Arduino, utilizzando il tuo esempio con browseUrl() al sito http://www.indirizzo-ip.com/ip.php?.txt.
    Questo sito, restituisce il solo indirizzo IP senza testi aggiuntivi e senza tag html.
    Ora, se riuscissimo a farci inviare tale IP tramite un sms gratis, ad esempio, Google calendar, avremmo risolto il problema senza iscriverci a nessun server.
    Non a caso ho nominato Google calendar, perchè ho letto che è possibile farsi inviare tali sms a ogni richiesta, la partre oscura, per me, sono dei file .php che onestamente non so come possono interagire e soprattutto dove metterli.
    Ricordo che ho la necessità di accedere a PC spento.
    Scusa se sono stato un po lungo, ma per me risolvere la questione è molto importate.

    Saluti

    • luca 12/03/2012 at 19:46 - Reply

      Ciao Domenico,

      ho guardato le API che no-ip mette a disposizione… sembra abbastanza semplice far fare l’aggiornamento ad Arduino: una cosa tipo:

      – ogni tot minuti controllo il mio IP
      – se l’IP è diverso da quello precedente, aggiorno no-ip e me lo memorizzo

      Per aggiornare no-ip serve fare una GET:
      http://www.no-ip.com/integrate/request

      faccio qualche prova e posto uno sketch di esempio nei prossimi giorni ;)

  3. Domenico 20/03/2012 at 15:46 - Reply

    Ciao, Luca

    Sei, riuscito a fare qualche prova per il no-ip ?

    Saluti

    • luca 20/03/2012 at 16:59 - Reply

      Ciao Domenico,

      sì, ho quasi pronto uno sketch… mi manca l’interpretazione dei possibili codici di errore ma l’aggiornamento avviene.
      Dovrei pubblicarlo entro fine settimana, stay tuned ;)

  4. Domenico 02/04/2012 at 18:26 - Reply

    Ciao Luca,

    Spero che non ti sia dimenticato di me !

  5. Domenico 26/04/2012 at 18:32 - Reply

    Ciao Luca,

    se ai già la solizione del get con no-ip, potresti postare il progetto; per gli errori penso di cavarmela da solo.
    Scusami per l’insistenza.

    Saluti

  6. Massimiliano 17/01/2013 at 09:42 - Reply

    Ciao Luca, grazie mille dei tuoi tutorial, chiarissimi e funzionanti!!! :-)
    Ho provato però a fare una variante a questo tuo sketch, ossia ho provato a leggere un’altro file su un sito diverso e tutto funziona bene, però non riesco a far alternare all’interno dello stesso sketch la chiamata a due siti differenti! Cioè ho creato una piccola sequenza in cui in un primo passo ripeto completamente tutto quello che è la parte di chiama e risposta alla tua pagina e poi faccio lo stesso con una mia pagina, però non funziona nulla!!!! :-(((( Se le chiamo individualmente in due sketch distinti, tutto lavora, così sono sicuro che anche l’altra pagina è accessibile, poi se li metto insieme, non leggo ne l’una ne l’altra!!! Dove sbaglio??????? :-((((

    • luca 17/01/2013 at 11:04 - Reply

      Ciao Massimiliano,

      riesci a mandarmi il tuo sketch che ci guardo? Ogni volta che cambi sito ricordati di chiamare la funzione
      ether.dnsLookup(nuovoSito)

      in modo che la libreria risolva l’IP del sito e lo memorizzi.

      • Massimiliano 17/01/2013 at 11:17 - Reply

        Ciao Luca,

        In realtà pensando che fosse proprio un problema di inizializzazione avevo richiamato tutto, pure la richiesta DHCP, ma ora controllando la parte ether.dnslookup ho visto che avevo col copia e incolla, lasciato il primo sito!!!!!!!
        Sono un pirla!
        Nel leggere quello che mi hai scritto sono andato subito a vedere e l’ho trovato!!!!

        Ora funziona!!!!

        Grazie mille per il tempo e per l’illuminazione!!!!!! :-))))))))

      • Massimiliano 17/01/2013 at 11:34 - Reply

        Luca, approfitto ancora un attimo del tuo tempo e della tua pazienza :-)

        Il puntatore che è presente nella:

        static void response_callback (byte status, word off, word len) {

        Serial.print((const char*) Ethernet::buffer + off + 207);
        }

        Lo posso portare fuori in modo da poterlo manipolare anche nel Loop() ?
        E se si, come posso trasformare un puntatore di char in una String?

        Grazie :-)))))

        • luca 17/01/2013 at 14:07 - Reply

          Ciao Massimiliano,

          vorresti “leggere” nel loop il contenuto del buffer di risposta?
          se usi la tcpReply() puoi ottenere già un puntatore a char della risposta, guarda il mio esempio su DynDNS:
          http://www.lucadentella.it/2012/04/28/enc28j60-e-arduino-6/

          • Massimiliano 18/01/2013 at 01:40 -

            Proverò a fare come suggerisci!

            Un’altra domanda, ho provato a cambiare il valore all’interno della “byte Ethernet::buffer[700];”, provando con valori come 750 o 800 non funziona più nulla!!! Immaginavo che fosse la profondità del buffer, ma forse non ho capito qualcosa!!!!

            Ho bisogno di fare questo perchè io ho più dati da ricevere ed ho notato che inoltre su una chiamata, quando arrivo a leggere 550 byte, mi fermo nonostante ce ne siano altri da leggere (ho fatto un conteggio della lunghezza dei byte all’interno della response_callback che vengono passati alla Serial.println per la stampa su seriale, comprensiva di header).

          • luca 18/01/2013 at 23:21 -

            Ciao Massimiliano,

            quello è il buffer dove lo shield va a memorizzare l’intero pacchetto… se si blocca Arduino significa che aumentando la sua dimensione stai saturando tutta la (poca) memoria RAM che Arduino ha a disposizione.
            Il buffer contiene tutto il pacchetto, compresi gli header dello stack protocollare TCP/IP… per questo dei 700 bytes totali, quelli utili per il payload sono sicuramente meno! Se la lettura si ferma significa che hai raggiunto in memoria il terminatore di stringa (‘\0′) e quindi la fine del paypload.

  7. Massimiliano 22/01/2013 at 10:51 - Reply

    Luca ciao, son sempre io e son sempre più disperato!!!!

    Allora seguendo i tuoi consigli, son riuscito a connettermi a diverse pagine su diversi server, ho prelevato i “pochi” dati concessi e ho fatto quello che dovevo fare con loro.
    Ora se ripeto tutta la mia sequenza una sola volta, fila tutto liscio, le varie parti di programma fanno quello che desidero e tutto gira liscio.

    Ora, nel momento in cui voglio ripetere in continuo questa sequenza, il primo passo viene rieseguito ma poi si riavvia il micro!!!!! Non capisco cosa cavolo sia!!!!!
    Ti posso passare lo sketch per un’occhiata??? :-))))

    • luca 22/01/2013 at 13:31 - Reply

      Ciao Massimiliano

      sì, mandamelo che ci do un’occhiata!

      • Massimiliano 22/01/2013 at 16:36 - Reply

        Grazie mio salvatore!!!!!! :-)))

        Dove trovo nel sito una tua mail alla quale spedirlo????

        • luca 23/01/2013 at 08:48 - Reply

          ciao

          ti ho scritto una mail… ;)

  8. Massimiliano 26/01/2013 at 01:51 - Reply

    Ciao, ti ho spedito lo Sketch sulla mail, peró non so se ti è arrivata oppure no. Non vorrei fosse finita nella Spam :-))))

  9. John 19/02/2013 at 22:54 - Reply

    Hello Luca,
    Could I connect with 2 websites?
    Should I run the dnslookup for both sites?
    I tried this but I could establish connection with only the second website I ran the dnslookup.
    Could that be possible?
    Thank you,
    John

  10. Axel 23/02/2013 at 07:54 - Reply

    Ciao Luca,
    Thanks for this great tutorial, I learned a lot and was already able to realize some servers.
    My question for you regarding the client is whether you have a solution if only the IP address of the server is known? In my case I’d like to connect to a server in my local network i.e. server address 192.168.1.1.

    Would be great if you could give me a hint.

    Thanks in advance,

    Axel

    • luca 23/02/2013 at 11:17 - Reply

      Hi Axel,

      it’s easy: you have only to manually asign the IP address to the variable ether.hisip, without calling ether.dnsLookup:

      static byte hisip[] = { 192,168,1,1 }; // remote webserver
      […]
      ether.copyIp(ether.hisip, hisip);

      let me know if it works!

      • Axel 24/02/2013 at 08:41 - Reply

        Thank you Luca,
        Yes, it’s a simple as this.

        Best regards,
        Axel

        • Leroy 08/05/2013 at 05:56 - Reply

          Could you please show me you code? I’m a beginner…Thank you so much…

  11. sam 17/03/2013 at 06:23 - Reply

    Ciao luca,
    i tried your code of this tutorial.am getting DNS failed message.What will be the reason? Am pasting the data i got on arduino serial window.
    Client Demo

    Setting up DHCP
    My IP: 192.168.1.102
    Netmask: 255.255.255.0
    GW IP: 192.168.1.1
    DNS IP: 208.67.222.222
    DNS failed
    SRV IP: 0.0.0.0

  12. Riccardo 26/04/2013 at 08:04 - Reply

    Ciao Luca,
    sto facendo alcune prove per interfacciare un Arduino via Ethernet ad un WebService. Ho seguito le indicazioni che ho trovato nell’esempio WebClient di EtherCard e le ho confrontate con il tuo articolo. Tutto funziona, ma nella risposta che ricevo dal WebService sembra perdersi circa un terzo della risposta. Ho provato ad aumentare la dimensione del buffer fino a 1300 byte, ma il risultato non cambia.
    Ho anche provato a stampare il buffer carattere per carattere per vedere bene il contenuto, ma la parte terminale è tutta a zero.
    E’ come se si perdesse un pacchetto di risposta (e anche in questo caso la colpa potrebbe essere proprio del buffer troppo piccolo…).
    Hai qualche suggerimento?

    Grazie per il tuo tempo.

    • luca 26/04/2013 at 14:09 - Reply

      Ciao Riccardo,

      purtroppo anche in fase di ricezione il buffer ha un limite vicino ai 700 bytes: se la risposta è superiore il pacchetto viene troncato. Prova a chiamare il webservice da un browser o usando un client (tipo SoapUI) e vedi quanto è grande la risposta…

  13. Leroy 07/05/2013 at 14:37 - Reply

    My English is not good. .I want to access a server on the LAN (IP 192.168.1.104).But does not know how to use BrowseUrl this function to access.And I also want to POST some data to this IP address.Can you please give me some advice it?Very, very grateful.Thank you..

    • luca 07/05/2013 at 18:49 - Reply

      Hi Leroy,

      first, set the ether.hisip to the IP of your server (192.168.1.104), so methods like tcpSend() and browseUrl() connects to that IP.
      Then, for POSTing data you need to create a Stash (using :prepare) that contains your POST data (including HTTP headers) and send it to the server using tcpSend(). Take a look to this example, where I’m POSTing data to Skebby’s webservice.

      • Leroy 08/05/2013 at 06:06 - Reply

        Thank you so much…I’m sorry for my english..If I have offended, please forgive me….I tried the following code..

        static byte hisip[] = { 192,168,1,104 };

        And in setup function:
        ether.copyIp(ether.hisip, hisip);

        In loop function:
        ether.browseUrl(PSTR(“/demo/”), “abc.html”, “192.168.1.104”, response_callback);

        But does not seem to work…

  14. Martin 25/07/2013 at 12:07 - Reply

    Hi Luca,
    I am a bit new in arduino but I really like all the tutorials you made here. Great to learn many things.
    I would like to ask you if you can help me with sketch which should get/post data from web but using password. I was thinking to have a file which would be in folder protected by .htaccess . Then I would need to get the data by basic authorization http request. Is that possible to be done with ethercard.h library? If so can you help me with it please?
    Thanks.

    • luca 14/08/2013 at 14:01 - Reply

      Hi Martin,

      yes, you can implement basic authentication… I’ll write a post about it!

      • Martin 14/08/2013 at 18:55 - Reply

        Hi Luca,
        great, thanks for it. I will wait the post.

  15. Emanoeli 15/10/2013 at 19:06 - Reply

    Hi Luca,
    This tutorial worked perfectly. Now I’m trying to make it work with another server, but I only have the IP address. I saw the comments above, so I tried this:
    static byte hisip[] = ip adress

    and instead to use dnsLookUp:
    ether.copyIp(ether.hisip, hisip);

    Now I don’t know how to set the parameters of browseUrl function, since I don’t have the parameter “website” and I have the variable “hisip”. I tried to do this in different ways, without sucess. Do you have any sugestion?
    Thanks! (and sorry about my english)

    • luca 23/10/2013 at 21:39 - Reply

      Hi Emanoeli, define the variable “website” with the IP address of your webserver, for example:
      char website[] PROGMEM = "10.0..1";

  16. polly 15/02/2014 at 03:39 - Reply

    MY C Demo
    Ethernet controller initialized
    DHCP configuration done
    IP Address: 192.168.5.102
    Netmask: 255.255.255.0
    Gateway: 192.168.5.1
    dnsip: 192.168.5.1

    DNS failed
    SRV IP: 0.0.0.0

  17. polly 15/02/2014 at 03:44 - Reply

    ether.browseUrl(PSTR(“/examples/servlets/servlet/”), “HelloWorldExample”, “192.168.5.108:8080″, response_callback);

    • luca 17/02/2014 at 23:03 - Reply

      Hi Polly,

      which is your problem? No response? The callback is never executed?

      • polly 18/02/2014 at 01:36 - Reply

        My English is poor, do not know how to describe the problem,

      • polly 18/02/2014 at 02:06 - Reply

        why can’t println ‘response_callback’ Content?

        see this —
        http://www.520665.com/problem.html

  18. enrico 29/04/2014 at 22:57 - Reply

    cia luca…
    nn capisco xk quando vado a compilare mi da errore sulla stringa ether.printIp(“Netmask:\t”, ether.mymask): ‘classethercard’ has no member named ‘mymask’
    ps mi e successo ank sul 2° progetto… xo mi pinga lo stesso… aiutami… :(

  19. enrico 29/04/2014 at 22:57 - Reply

    …e mi dice ank “dns failed”

  20. Zafer 29/05/2014 at 15:45 - Reply

    I print the text which come from the website to a LCD, but it is too long. And the text is autoscrolling on the LCD. There is a problem. Text is scrolling in the first line but some last characters are printing to the second line. I need to all of them in the first line.

    My English is bad. Hopefully, you have understood my problem. :)

    • luca 05/06/2014 at 20:49 - Reply

      Hi, the problem seems in the way you’re printing the text… are you using LiquidCrystal library? Probably the text you’re printing includes a “new line” and therefore the library goes to the second line automatically.

  21. Mate 18/08/2014 at 08:22 - Reply

    Hi, you have nice tutorials, just to say at the begining. But I have problem retrieving info from site other than one in your example? What do you use to produce that random phrase? PHP or?
    When i try to retrive Hello world even from simple txt file on server, I can’t connect to it.

    • luca 19/08/2014 at 09:27 - Reply

      Hi Mate,

      yes, I wrote a simple php page to generate aphorisms… but the code should work with every site/page that returns a text message: which URL are you trying to fetch? Can you get it using a web browser?

  22. Mate 23/08/2014 at 15:05 - Reply

    HI Luca, sorry for delay, I was on business trip. Well, I made a simple hello world text/html web page and tried to access it but in vain, so I wasn’t sure if you were using something other than just simple echo command in PHP for phrase generation (since PHP code is invisible from client side so i can’t check it).

    But even better for me would be solution to access .txt file on server (which I can from the browser). Is tha also possible?

    Btw this is what i get in serial:

    >>> REQ
    <<< reply 383 ms
    HTTP/1.1 301 Moved Permanently
    Content-Type: text/html; charset=UTF-8
    Location: http://btcgoodies.com/hello.html
    Server: Microsoft-IIS/8.0
    X-Powered-By: ASP.NET
    X-Powered-By-Plesk: PleskWin
    Date: Sat, 23 Aug 2014 14:04:35 GMT
    Connection: close
    Content-Length: 155

    Document Moved
    Object MovedThis document may be found here

  23. Mate 23/08/2014 at 16:58 - Reply

    Hm, it seems your server is powered by Apache and mine by Windows IIS (crap), so that might be it. Or maybe Godaddy hosting is causing problem (again) as they are using redirects in their system as typical procedure. But thing is I can open it with any browser normally, only Arudino has trouble reaching it.

    • luca 25/08/2014 at 07:52 - Reply

      Hi Mate,

      well you are right: it seems your ISP (godaddy) is always using redirects when accessing to the hosted pages… web browsers can seamlessly follow the redirects but Arduino can’t. I don’t know the reason of that behaviour, but it’s clear from the log you sent me (HTTP 301)

      • Mate 25/08/2014 at 10:50 - Reply

        It seems that was the issue. This thing don’t work either on windows based servers or just Godaddy windows based servers.

        I bought another linux based (apache) server also on Godaddy and it works great now! Be notified that Godaddy doesn’t offer switching from Windows to Linux after you already bought initial package.

  24. krzysiek 27/08/2014 at 12:06 - Reply

    Hi luca!
    I noticed that some people have the same problem as me. It’s about a problem with the DNS. I noticed that the majority report this problem this year. Maybe it has to do with the library EtherCard? Can you put your version of the library? Alternatively, if you could check the operation of your design on a new version of the library?
    Anyway – great job with your tutorial!

  25. adeeb 07/02/2016 at 14:39 - Reply

    Hello. Thanks a lot for this tutorial, I’ve got it working.

    My question is about the timer in the loop().
    if (millis() > timer) {
    timer = millis() + 5000;

    }
    Can you elaborate on the use of these lines please.

    Also I’ve been figuring out how to store the response into a string or sd card instead of serial.print it but with no success. Can you help me out please.

    Thanks.

    • luca 07/02/2016 at 14:43 - Reply

      Hi! It’s just a way to “wait” 5 seconds without blocking the execution… give a look to the blinkNoDelay tutorial. For your question about storing data in a file located on an SD card, there are many tutorials on the playground.

  26. Andrea 22/03/2017 at 17:33 - Reply

    Buonasera Luca, innanzitutto voglio ringraziarti per il lavoro che hai fatto per il ENC28j60, è illuminante visto che sono alle prime esperienze.Sulla ricezione delle stringhe e decodifica nel buffer, non ho problemi, mentre ne ho sull’invio delle richieste HTTP. Vorrei che Arduino inviasse il seguente comando”http://192.168.1.188:81/cam/Cam11/trigger”. Potresti cortesemente inviarmi uno sketch che realizza tale funzione? Ti ringrazio .Andrea

Leave A Response »

This website uses cookies to ensure you get the best experience on our website 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