Il 2013 è stato l'anno in cui si è iniziato a parlare fortemente di "Internet of Things" (IoT), anche se il termine è stato proposto nell'ormai lontano 1999 da Kevin Ashton. Questo termine indica la possibilità di interconnettere qualsiasi oggetto a Internet per poter raccogliere e condividere informazioni grazie alle quali poter fornire servizi aggiuntivi agli utilizzatori finali.
Possiamo pensare quindi non solo gli attuali PC, smartphone e tablet, ma agli elettrodomestici, alle automobili e a tutti i dispositivi cosiddetti "wearable" (che possiamo indossare) come smartwatch, bracciali, occhiali e così via.
Si potrebbe parlare a lungo di "Internet delle Cose" ma ciò che ci interessa sottolineare in queste pagine è che un sistema embedded senza alcuna connessione alla rete può essere considerato pressoché "inutile" al giorno d'oggi.
Detto questo risulta necessario capire quali sono le possibilità di interconnessione delle board Arduino ad Internet.
Arduino Ethernet Shield
Come abbiamo anticipato all'inizio di questa guida, esistono diverse board della famiglia Arduino tra cui la "Arduino Ethernet" e la "Arduino Yun" che sono dotate di connessione Ethernet. Nel caso della "Arduino Uno", che stiamo utilizzando per i nostri esempi, non abbiamo questo tipo di connettività ma è necessario utilizzare una delle tantissime shield ossia la "Arduino Ethernet Shield".
Arduino Ethernet Shield
Questa shield va collegata esattamente sopra la board "Arduino Uno", riportando verso l'esterno gli stessi collegamenti della scheda base. È dotata di un controller Ethernet della WIZnet, di un pulsante di reset e fornisce anche il supporto per una microSD che, ad esempio, può tornare utile per la realizzazione di un web server e quindi per ospitare le pagine HTML statiche con tutti i relativi file CSS e JavaScript.
Il controller Ethernet e la micro SD sono collegati al microcontrollore attraverso la porta SPI condividendo di fatto lo stesso bus e quindi utilizzando i pin 10 (chip select per la Ethernet), 11, 12, 13 e 4 (chip select per la microSD) che di fatto risultano inutilizzabili come GPIO. Per poter utilizzare entrambe le funzionalità (es. il caso di un web server) è necessario abilitare/disabilitare di volta in volta il componente a cui voler accedere (Ethernet o microSD) attraverso il corrispondente chip select, a causa del bus SPI condiviso.
Per fortuna abbiamo anche a disposizione la Ethernet library e la SD library che esportano una serie di funzioni attraverso le quali poter accedere ad entrambi i componenti; nel corso del capitolo faremo riferimento solo alla libreria dedicata alla connessione Ethernet.
La prima applicazione
L'applicazione più semplice che possiamo realizzare e che utilizza la connessione ad Internet è un client Web che effettua una richiesta HTTP per ricevere, ad esempio, la pagina HTML principale (home page) del sito HTML.it.
Apriamo l'IDE di Arduino e creiamo un nuovo sketch; la prima operazione da fare è includere la libreria Ethernet attraverso il menu Sketch > Import Library > Ethernet grazie al quale l'IDE aggiunge per noi una serie di direttive di #include
per utilizzare le funzioni della libreria.
Poiché, come abbiamo visto, il controller WIZNet della shield comunica con il microcontrollore (della Arduino Uno) attraverso la porta SPI, è necessario aggiungere anche la libreria per quest'ultima.
L'inizializzazione del controller e della connessione Ethernet viene eseguita attraverso la funzione begin(mac)
se vogliamo utilizzare il DHCP oppure begin(mac, ip)
se vogliamo impostare un indirizzo IP statico. Il parametro comune ad entrambe le funzioni è il MAC (Media Access Control) address ossia un indirizzo assegnato in maniera univoca a ciascun controller o scheda Ethernet e rappresentato da una sequenza di 6 byte (l'azienda che utilizza e rivende il controller acquista tipicamente un certo range di MAC address attraverso la IEEE).
Nel nostro caso qual è il MAC address da utilizzare? Basta prendere la nostra Ethernet shield e leggerlo sullo sticker posto nella parte inferiore della stessa (nel mio caso è 90-A2-DA-00-62-F8
). Nel caso stiate utilizzando la "Arduino Ethernet" o "Arduino Yun", ovviamente il MAC address sarà direttamente su di esse.
MAC address sulla Arduino Ethernet Shield
Per quanto riguarda l'indirizzo IP, proviamo in primo luogo ad ottenerlo attraverso il DHCP e nel caso di fallimento ne impostiamo uno statico; in questo caso dipenderà dalla vostra sottorete (nel mio caso utilizzerò l'indirizzo 192.168.1.50
). Possiamo quindi iniziare a scrivere la prima parte di codice per l'inizializzazione del controller Ethernet e che è eseguita all'interno della funzione setup()
; il MAC address è definito con un semplice array di byte mentre l'indirizzo IP mediante la classe IPAddress.
// MAC address
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x62, 0xF8 };
// eventuale indirizzo IP statico da utilizzare
IPAddress ip(192, 168, 1, 50);
void setup()
{
Serial.begin(9600);
// se la connessione attraverso DHCP fallisce
if (Ethernet.begin(mac) == 0)
{
// eseguo inizializzazione con indirizzo IP statico
Ethernet.begin(mac, ip);
}
}
Nella funzione setup()
, inizializziamo anche la porta seriale per poterla utilizzare, non solo come debug, ma soprattutto per trasmettere al PC i caratteri che rappresentano la pagina HTML che riceveremo dal server.
Una volta inizializzato il controller Ethernet, possiamo utilizzare la classe EthernetClient per poter comunicare con un server attraverso una socket e la prima operazione da effettuare è quella di connessione attraverso il metodo connect(URL,port)
: nel nostro caso l'URL è "www.html.it"
e la porta è la 80
(porta di default di ogni Web Server).
Se la connessione va a buon fine, possiamo inviare la richiesta HTTP al server attraverso il metodo println(data)
; il protocollo HTTP è puramente testuale (ASCII) e prevede l'invio di una request line (in questo caso con una GET della pagine principale del sito web) con una serie di headers (tra cui quello principale è "Host" per indicare l'host destinazione).
// client Ethernet
EthernetClient ethclient;
void setup()
{
// ...
if (ethclient.connect(server, 80))
{
Serial.println("Connessione avvenuta!");
ethclient.println("GET / HTTP/1.1");
ethclient.println("Host: www.html.it");
ethclient.println("Connection: close");
ethclient.println();
}
}
In questo modo, al termine della funzione di setup()
, abbiamo inizializzato il controller Ethernet ed inviato la nostra richiesta HTTP al server. Adesso non ci resta che leggere la risposta e tale operazione sarà ovviamente eseguita all'interno della funzione loop()
.
In primo luogo dobbiamo verificare che ci siano dati disponibili da leggere attraverso il metodo available()
(sempre della classe EthernetClient) ed, in caso di esito positivo, possiamo leggerli mediante il metodo read()
un singolo byte (carattere) alla volta.
void loop()
{
// ci sono byte disponibili
if (ethclient.available())
{
// leggo il prossimo e lo trasmetto sulla seriale
char c = ethclient.read();
Serial.print(c);
}
// se il server ha chiusto la connessione
if (!ethclient.connected())
{
// stop del client
ethclient.stop();
while (true);
}
}
Nel loop principale è anche necessario verificare che il server non abbia chiuso la connessione attraverso il metodo connected()
ed in questo caso arrestarlo con il metodo stop()
.
Eseguiamo la verifica della correttezza del codice sorgente, colleghiamo la nostra board (con sopra la shield), inseriamo un cavo Ethernet nel corrispondente connettore ed eseguiamo il deploy del programma. Aprendo il monitor della porta seriale, vedremo scorrere tutti i caratteri che stiamo ricevendo dalla nostra "Arduino Uno" e che rappresentano l'HTML della home page del sito web di HTML.it (comprensivi della response line e degli headers).
Abbiamo esaminato l'accesso ad Internet con la board "Arduino Uno", realizzando un semplicissimo client Web che esegue una richiesta HTTP e trasmette la relativa risposta sulla porta seriale verso il nostro PC di sviluppo. Nel prossimo capitolo inizieremo lo sviluppo di un semplice progetto che si avvicina maggiormente al concetto di "Internet of Things" con la realizzazione di un logger della temperatura in una stanza che invia i dati rilevati nel Cloud!