La rapida evoluzione ed espansione delle schede Arduino è legata allo sviluppo e vendita di accurate shield funzionali che permettono di interfacciare un semplice microcontrollore, quale l’ATmega328PU, con il mondo esterno a seconda delle nostre esigenze. Tra le tante board disponibili troviamo la Shield Ethernet che permette di gestire il microcontrollore tramite una rete ethernet. Tale shield ha un costo ridotto (circa 10€ per le repliche, 25€ per gli originali) e permette di interagire da remoto con la nostra scheda.
Di seguito riportiamo tre esempi pratici che possono rappresentare il punto di partenza per sviluppare i vostri progetti, tra cui data logger, gestione di relay per carichi in AC in campo domotico, web server e molto altro.
Volendo fare un minimo di chiarezza sul codice utilizzato per gli sketch possiamo individuare generalmente l’utilizzo delle seguenti librerie:
- SPI: Serial Peripheral Interface, è un protocollo seriale utilizzato dai microcontrollori per comunicare con uno o più dispositivi in modo rapido. Con una connessione SPI vi è sempre un dispositivo master (di solito un microcontrollore) il quale controlla i dispositivi periferici.
Refrence: http://arduino.cc/en/Reference/SPI
- Ethernet: Necessaria per la comunicazione Ethernet
Refrence: http://arduino.cc/en/Reference/Ethernet
- WebServer: trattasi della libreria Webduino la quale permette di implementare al nostro sketch: elaborazione dei parametri racchiusi in un URL, elaborazione dei metodi HTTP come GET, POST, PUT, HEAD, DELETE e PATCH, gestione dei FORM, gestione di Immagini, interfaccia JSON/REST, autenticazione BASE64.
Refrence: http://code.google.com/p/webduino/
- SD: libreria che permette la lettura e scrittura su dispositivi SD utilizzabili mediante una scheda ethernet.
Reference: http://arduino.cc/en/Reference/SD
Quelle sopra elencate sono le librerie più gettonate per progetti che sfruttano la comunicazione ethernet. Ogni sketch presenterà due dati di estrema importanza che possono essere modificati in base alle proprie necessità. Tali parametri sono l’indirizzo mac e l’indirizzo IP della scheda. In tutti gli esempi trattati in questo articolo l’indirizzo IP è 192.168.1.177. Ovviamente si lavora all’interno di una rete locale, ma nulla toglie che realizzando un forward con il router sia possibile rendere il nostro dispositivo accessibile anche da una rete esterna. Un altro dato importante è la porta utilizzata, solitamente viene impostata la 80 (ovvero la porta utilizzata per i servizi web).
Esempio 1: Hello World (no scheda SD)
Con questo esempio si vuole mostrare il funzionamento dello shield ethernet senza l’utilizzo della memoria SD ausiliaria. Tale sistema è consigliato solo se la pagina web da generare è minimale. Infatti, le informazioni per la creazione della pagina sono all’interno del codice Arduino e pertanto andranno a saturare la memoria disponibile dedicata per lo sketch.
Il seguente codice stamperà all’url indicato (nel nostro esempio 192.168.1.177) quanto segue:
Vieni a visitare MST TUTORIAL
//Includiamo le librerie necessarie al progetto #include <SPI.h> #include <Ethernet.h> //indirizzo mac fisico dello shield byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //indirizzo ip rete locale (inserire indirizzo valido per la propria rete) byte ip[] = {192, 168, 1, 177}; //definiamo la porta di lavoro EthernetServer ArduinoServer(80); //variabile char per memorizzare i pacchetti char Data_RX; void setup() { //inizializziamo la scheda con indirizzo mac e IP definiti in precedenza. //Attiviamo il server web Ethernet.begin(mac, ip); ArduinoServer.begin(); } void loop() { //Ascolto delle richieste EthernetClient pc_client = ArduinoServer.available(); //Verifico se ci sono richieste tramite "pc_client" true if (pc_client) { //con un ciclo while verifico che il client sia connesso while (pc_client.connected()) { //Controllo se ci sono byte disponibili per la lettura if (pc_client.available()) { //leggo i byte provenienti dal client Data_RX = pc_client.read(); //mediante la presenza di "\n" presente in Data_RX possiamo dedurre che abbiamo ricevuto i dati if (Data_RX == '\n') { //invio pagina HTML pc_client.println("HTTP/1.1 200 OK"); pc_client.println("Content-Type: text/html"); pc_client.println(); pc_client.print("<html><body><h1>"); pc_client.print("<h1>Hello world Arduino Web Server</h1><br /><br />Vieni a visitare <a href=\"http://www.mst-tutorial.it\">MST TUTORIAL</a></body></html>"); //aspetto 1 ms affinche la risposta giunga al browser del client delay(1); //esco dal ciclo break; } } } //chiudo la connessione pc_client.stop(); } }
Esempio 2: Hello World (file htm su scheda SD)
In questo esempio andremo a sfruttare lo shield ethernet con annessa memoria SD. Prima di continuare verificare che la memoria SD sia formattata con filesystem fat32 e al suo interno dev’essere presente il file htm con i contenuti da noi desiderati.
L’obiettivo è far visualizzare il contenuto della pagina web htm dal nostro server Arduino. Nel nostro caso, il server Arduino sarà raggiungibile all’indirizzo ip 192.168.1.177.
//Aggiungo le librerie necessarie #include <SPI.h> #include <Ethernet.h> #include <SD.h> //definiamo due arrey: il primo per definire l'indirizzo mac, il secondo per definire l'indirizzo IP. //Per quanto riguarda l'indirizzo IP selezionate un indirizzo valido per la vostra rete locale. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = {192, 168, 1, 177}; //definiamo la porta di ascolto EthernetServer server(80); File htmlFile; void setup (){ Ethernet.begin(mac, ip); server.begin(); if (!SD.begin(4)) { return; } Serial.begin(9600); } void loop (){ EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); if (c == '\n' && currentLineIsBlank) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); htmlFile = SD.open("index.htm"); if (htmlFile) { while (htmlFile.available()) { client.write(htmlFile.read()); } // close the file: htmlFile.close(); } break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } delay(1); client.stop(); } }
Esempio 3: Gestione output da remoto
In questo esempio l’intera pagina web risiede all’interno del microcontrollore (pertanto non si necessita di memoria microSD esterna). Questo fattore ovviamente incide sullo spazio disponibile per lo sketch. Pertanto, è possibile spostare tutta la gestione della pagina web su un file htm memorizzato in una microSD.
Il seguente codice permette di pilotare tramite shield ethernet un carico posto sul pin 8 della nostra scheda. L’indirizzo IP utilizzato nel seguente sketch è 192.168.1.177.
//Includo librerie necessarie #include <SPI.h> #include <Ethernet.h> //Indirizzo mac shield ethernet byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //Configurazione indirizzo IP di rete IPAddress ip(192, 168, 1, 177); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); //Inizializzazione porta server web EthernetServer server(80); String readString; // posizione fisica output (collegare led o output) int uscita = 8; void setup() { //definisco il terminale "uscita" come output pinMode(uscita, OUTPUT); //attivo porta seriale per eventuale debug Serial.begin(9600); //attivo connessione eth Ethernet.begin(mac, ip, gateway, subnet); server.begin(); Serial.print("Indirizzo ip server: "); Serial.println(Ethernet.localIP()); Serial.println("Gestione OUTPUT www.mst-tutorial.it"); } void loop() { EthernetClient client = server.available(); if (client) { Serial.println("new client"); while (client.connected()) { if (client.available()) { char c = client.read(); if (readString.length() < 100) { readString += c; Serial.write(c); if (c == '\n') { Serial.println(readString); //print to serial monitor for debuging //-------------------------------------------------------------------------------------------------------- //creaione pagina web client.println("HTTP/1.1 200 OK"); //send new page client.println("Content-Type: text/html"); client.println(); client.println("<HTML>"); client.println("<HEAD>"); client.println("<TITLE>MST TUTORIAL controllo remoto eth shield</TITLE>"); client.println("<center>"); client.println("</HEAD>"); client.println("<BODY>"); client.println("<p><img src=\"http://www.mst-tutorial.it/wp-content/uploads/2017/11/logo2.png\" width=\"500px\"</p>"); client.println("<H1>controllo remoto eth shield</H1>"); client.println("<hr />"); client.println("<center>"); client.println("<br />"); client.println("<p>Posizionare il led / buzzer tra il pin 8 e GND</p>"); client.println("<br /><br />"); client.println("<a href=\"/?outputon\"\">OUTPUT ON</a>"); client.println("<br />"); client.println("<br />"); client.println("<a href=\"/?outputoff\"\">OUTPUT OFF</a><br />"); client.println("<br />"); client.println("<br />"); client.println("<br />"); client.println("<br />"); client.println("visita <a href=\"http://www.mst-tutorial.it\">www.mst-tutorial.it</a><br />"); client.println("</BODY>"); client.println("</HTML>"); delay(1); client.stop(); //USCITA ON if (readString.indexOf("?outputon") > 0) { digitalWrite(uscita, HIGH); Serial.println("LED/BUZZER On"); } else { //USCITA OFF if (readString.indexOf("?outputoff") > 0) { digitalWrite(uscita, LOW); Serial.println("LED/BUZZER Off"); } } readString = ""; delay(1); client.stop(); Serial.println("client disonnected"); } } } } } }