ENC28J60: Arduino web server

Sicuramente molti di voi almeno una volta si saranno chiesti se fosse possibile comandare Arduino da remoto tramite internet oppure in locale tramite wifi o ethernet.
Oggi vediamo come tutto questo è possibile aggiungendo un piccolo modulo di rete con a bordo il controller ENC28J60.

Lo scopo di questo articolo è quindi di dimostrare come sia possibile comandare l’accensione o lo spegnimento di un semplice diodo led.

Inziamo a vedere quali sono i collegamenti tra Arduino e Enc28j60:

collegamenti_arduino_enc28j60

dopo aver collegato il nostro modulo ethernet colleghiamo un led ad Arduino sul pin digitale numero 7.

Arrivati a questo punto per poter scrivere il nostro sketch abbiamo bisogno di una libreria, cercando in rete se ne trovano diverse, la mia scelta è stata questa EtherCard.

Dopo aver scaricato la libreria scompattiamola e rinominiamo la cartella estratta in ethercard e spostiamola come di consueto all’interno della cartella libraries di Arduino.

Adesso cerchiamo di capire velocemente come funzionano le cose, senza dilungarci in dettagli tecnici e senza annoiare nessuno; perché non è l’articolo adatto dove parlare di protocolli di rete e tutto quello che concerne tale ambito; anche se il mio consiglio è quello di andare a cercare in rete ed approfondire un pò su quello che state facendo, almeno così sarete in grado di gestire con una maggiore comprensione eventuali problemi futuri che potreste avere scambiando dati in rete!!!

Come alcuni di voi già sapranno lo scambio di dati in rete avviene tramite pacchetti in questi pacchetti si trova dentro un header e quindi l’intestazione del pacchetto con tutte le informazioni ed un payload il contenuto vero e proprio del pacchetto!

Quindi nella pratica quando noi andremo a contattare Arduino ad esempio dal nostro web browser, invieremo proprio dei pacchetti composti da un header ed un payload.
Ma non preoccupatevi :) tutto il lavoro sporco che ci sta dietro sarà la libreria a farlo per noi… noi dobbiamo semplicemente prendere questi pacchetti di volta in volta ed analizzarne il contenuto verificando che si tratti o meno del contenuto che noi ci aspettiamo di ricevere.

Per inserire le nostre informazioni all’interno dei pacchetti ci viene in aiuto il caro e buon vecchio metodo GET del protocollo HTTP.
Per chi non avesse chiaro al momento il metodo GET possiamo dire che si tratta di un metodo concepito appunto per inviare richieste ad un web server tramite URL.
Facciamo finta di voler dire ad Arduino di accendere un led come nell’esempio che andremo a vedere in questo articolo, allora basterà inviare una richiesta del genere:

http://IP_ARDUINO/ledON

a questo punto basterà andare a cercare all’interno del buffer che conterrà il pacchetto una stringa del genere:

GET /ledON

Ok adesso passiamo al codice:

#include <EtherCard.h>


static byte mac[] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x01 };
static byte ip[] = { 192, 168, 1, 7 };
byte Ethernet::buffer[700];
#define ENC28J60_CS 10
#define LED 7


const char accendiLED[] PROGMEM = "HTTP/1.0 200 OK\r\n"
                                  "Content-Type: text/html\r\n"
                                  "Pragma: no-cache\r\n\r\n"
                                  "<html><head><title>ARDUINO - ENC28J60</title></head>"
                                  "<body><center>"
                                  "<h1> - Arduino in rete - </h1>"
                                  "<h2> - Test led - </h2>"
                                  "<a href='/on'><input type='button' value=' - ACCENDI LED - '/></a>"
                                  "</body>"
                                  "</center></html>";


const char spegniLED[] PROGMEM = "HTTP/1.0 200 OK\r\n"
                                 "Content-Type: text/html\r\n"
                                 "Pragma: no-cache\r\n\r\n"
                                 "<html><head><title>ARDUINO - ENC28J60</title></head>"
                                 "<body><center>"
                                 "<h1> - Arduino in rete - </h1>"
                                 "<h2> - Test led - </h2>"
                                 "<a href='/off'><input type='button' value=' - SPEGNI LED - '/></a>"
                                 "</center></body>"
                                 "</html>";


void setup ()
{
  pinMode(LED, OUTPUT);

  Serial.begin(115200);
  Serial.println("ARDUINO IN RETE");
  Serial.println(" - TEST LED - ");
  Serial.println(" ");

  if ( !ether.begin(sizeof Ethernet::buffer, mac, ENC28J60_CS) ) Serial.println("ERROR: ether.begin!");

  if ( !ether.dhcpSetup() )
    if ( !ether.staticSetup(ip) )
      Serial.println("ERROR: Set IP failed!");

  ether.printIp("Ip locale: ", ether.myip);
  ether.printIp("Netmask: ", ether.netmask);
  ether.printIp("Gateway: ", ether.gwip);
  ether.printIp("Dns: ", ether.dnsip);

}


void loop()
{
  word pos = ether.packetLoop( ether.packetReceive() );
  BufferFiller bfill = ether.tcpOffset();

  if ( pos ) {
    Serial.println(" ");
    Serial.println("<hr class='bbcode_rule'>");
    Serial.println( (char *) Ethernet::buffer + pos );
    Serial.println("<hr class='bbcode_rule'>");
    Serial.println("");
    Serial.println(" ");

    if ( strstr( (char *) Ethernet::buffer + pos, "GET /on") ) {
      digitalWrite(LED, HIGH);
      Serial.println("Led acceso!");
      bfill.emit_p(PSTR("$F"), spegniLED);
      ether.httpServerReply( bfill.position() );
    }
    else if ( strstr( (char *) Ethernet::buffer + pos, "GET /off") ) {
      digitalWrite(LED, LOW);
      Serial.println("Led spento!");
      bfill.emit_p(PSTR("$F"), accendiLED);
      ether.httpServerReply( bfill.position() );
    }
    else if ( strstr( (char *) Ethernet::buffer + pos, "GET /led") ) {
      if ( (int) digitalRead(LED) ) {
        bfill.emit_p(PSTR("$F"), spegniLED);
        ether.httpServerReply( bfill.position() );
        Serial.println("Spegni LED!");
      }
      else {
        bfill.emit_p(PSTR("$F"), accendiLED);
        ether.httpServerReply( bfill.position() );
        Serial.println("Accendi LED!");
      }
    }
  }
}

adesso non ci rimanere che caricare lo sketch su Arduino, aprire il monitor seriale e copiare il suo indirizzo IP che troverete alla voce: Ip locale.
Adesso aprite il vostro web browser e digitate: http://IP_ARDUINO/led

In fine ecco un video dimostrativo e come al solito buon lavoro :)