enc28J60 and Arduino (3)

by luca
60 comments

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…

Related Posts

60 comments

Domenico Friday March 9th, 2012 - 09:04 PM

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.

Reply
luca Sunday March 11th, 2012 - 08:28 PM

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 😉

Reply
Domenico Monday March 12th, 2012 - 07:31 PM

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

Reply
luca Monday March 12th, 2012 - 07:46 PM

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 😉

Reply
Domenico Tuesday March 20th, 2012 - 03:46 PM

Ciao, Luca

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

Saluti

Reply
luca Tuesday March 20th, 2012 - 04:59 PM

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 😉

Reply
Domenico Monday April 2nd, 2012 - 06:26 PM

Ciao Luca,

Spero che non ti sia dimenticato di me !

Reply
Domenico Thursday April 26th, 2012 - 06:32 PM

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

Reply
luca Saturday April 28th, 2012 - 04:03 PM

Ciao Domenico,

ce l’ho fatta finalmente a completare il post 😉
http://www.lucadentella.it/2012/04/28/enc28j60-e-arduino-6/

Reply
Massimiliano Thursday January 17th, 2013 - 09:42 AM

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??????? :-((((

Reply
luca Thursday January 17th, 2013 - 11:04 AM

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.

Reply
Massimiliano Thursday January 17th, 2013 - 11:17 AM

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!!!!!! :-))))))))

Reply
Massimiliano Thursday January 17th, 2013 - 11:34 AM

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 :-)))))

Reply
luca Thursday January 17th, 2013 - 02:07 PM

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/

Reply
Massimiliano Friday January 18th, 2013 - 01:40 AM

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 Friday January 18th, 2013 - 11:21 PM

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.

Massimiliano Tuesday January 22nd, 2013 - 10:51 AM

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??? :-))))

Reply
luca Tuesday January 22nd, 2013 - 01:31 PM

Ciao Massimiliano

sì, mandamelo che ci do un’occhiata!

Reply
Massimiliano Tuesday January 22nd, 2013 - 04:36 PM

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

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

Reply
luca Wednesday January 23rd, 2013 - 08:48 AM

ciao

ti ho scritto una mail… 😉

Reply
Massimiliano Saturday January 26th, 2013 - 01:51 AM

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

Reply
John Tuesday February 19th, 2013 - 10:54 PM

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

Reply
Axel Saturday February 23rd, 2013 - 07:54 AM

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

Reply
luca Saturday February 23rd, 2013 - 11:17 AM

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!

Reply
Axel Sunday February 24th, 2013 - 08:41 AM

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

Best regards,
Axel

Reply
Leroy Wednesday May 8th, 2013 - 05:56 AM

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

Reply
sam Sunday March 17th, 2013 - 06:23 AM

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

Reply
Riccardo Friday April 26th, 2013 - 08:04 AM

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.

Reply
luca Friday April 26th, 2013 - 02:09 PM

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…

Reply
Leroy Tuesday May 7th, 2013 - 02:37 PM

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..

Reply
luca Tuesday May 7th, 2013 - 06:49 PM

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.

Reply
Leroy Wednesday May 8th, 2013 - 06:06 AM

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…

Reply
luca Monday May 13th, 2013 - 09:46 AM

Hi Leroy

I assume you’re webserver has a page to the following address: http://192.168.1.104/demo/abc.html right? Can you display it using a browser?

Reply
Martin Thursday July 25th, 2013 - 12:07 PM

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.

Reply
luca Wednesday August 14th, 2013 - 02:01 PM

Hi Martin,

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

Reply
Martin Wednesday August 14th, 2013 - 06:55 PM

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

Reply
Emanoeli Tuesday October 15th, 2013 - 07:06 PM

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)

Reply
luca Wednesday October 23rd, 2013 - 09:39 PM

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

Reply
polly Saturday February 15th, 2014 - 03:39 AM

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

Reply
polly Saturday February 15th, 2014 - 03:44 AM

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

Reply
luca Monday February 17th, 2014 - 11:03 PM

Hi Polly,

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

Reply
polly Tuesday February 18th, 2014 - 01:36 AM

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

Reply
polly Tuesday February 18th, 2014 - 02:06 AM

why can’t println ‘response_callback’ Content?

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

Reply
enrico Tuesday April 29th, 2014 - 10:57 PM

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… 🙁

Reply
enrico Tuesday April 29th, 2014 - 10:57 PM

…e mi dice ank “dns failed”

Reply
Zafer Thursday May 29th, 2014 - 03:45 PM

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. 🙂

Reply
luca Thursday June 5th, 2014 - 08:49 PM

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.

Reply
Mate Monday August 18th, 2014 - 08:22 AM

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.

Reply
luca Tuesday August 19th, 2014 - 09:27 AM

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?

Reply
Mate Saturday August 23rd, 2014 - 03:05 PM

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

Reply
Mate Saturday August 23rd, 2014 - 04:58 PM

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.

Reply
luca Monday August 25th, 2014 - 07:52 AM

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)

Reply
Mate Monday August 25th, 2014 - 10:50 AM

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.

Reply
krzysiek Wednesday August 27th, 2014 - 12:06 PM

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!

Reply
adeeb Sunday February 7th, 2016 - 02:39 PM

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.

Reply
luca Sunday February 7th, 2016 - 02:43 PM

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.

Reply
lucadentella.it – ESP32 (8) – connessione tcp Monday January 30th, 2017 - 09:14 AM

[…] sul mio sito che in maniera randomica restituisce un aforisma (ho già usato questa pagina in un tutorial relativo al chip […]

Reply
Andrea Wednesday March 22nd, 2017 - 05:33 PM

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

Reply
Italo Wednesday January 16th, 2019 - 02:40 AM

Buonasera Luca

Sorry for my bad English

There is the possibility of programming the
  char website [] PROGMEM = “www.lucadentella.it”;
in another way to be able to change it dynamically without having to record the micro again, I receive the data by serial port.

Tante grazie

Reply
luca Saturday January 19th, 2019 - 09:55 AM

Hi Italo, not at the moment… there’s an open issue in Github for this problem but it hasn’t been solved yet. You can have a dynamic website but not use it with the browseUrl() method.

Reply

Leave a Comment

seven + 18 =