Ecco finalmente un progetto con l’ethernet shield.

Lo avevo completato già qualche giorno fa, ma per mancanza di tempo non sono riuscito a fare il post.

Di cosa si tratta il progetto?
In poche, anzi pochissime parole, accedendo ad una pagina internet si possono inviare messaggi all’arduino che li mostrerà su un display lcd 20×4 collegato ad esso, in più tramite un radiobutton si può decidere se alla ricezione del messaggio debba suonare o no un cicalino che appunto ci avverte del nuovo messaggio.

Ecco uno screen della pagina internet:

Ed ecco uno screen del display lcd:

Passiamo al codice:

 

#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal.h>

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,0, 123);

EthernetServer server(81);
LiquidCrystal lcd(9,8,7,6,5,4);

String lettura = "";
String suona = "";

String riga1 = "";
String riga2 = "";
String riga3 = "";
String riga4 = "";

void setup(){
  Ethernet.begin(mac, ip);
  server.begin();

  lcd.begin(20, 4);

  Serial.begin(9600);
  Serial.println("Avvio del programma");

  lcd.setCursor(0,0),
  lcd.print("Attesa...");

  pinMode(3, OUTPUT);
}

void loop(){
  EthernetClient client = server.available();

  if(client){
    while (client.connected()){
      if (client.available()){
        char c = client.read();
        lettura.concat(c);

        Serial.print(c);

        if (c == '\n'){
          if(lettura.indexOf("?") < 0){
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Messaggi su display LCD</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Invia un messaggio:</H1>");

            client.println("<form method=\"get\">");

            client.println("<input type=\"text\" name=\"riga1\" maxlength=\"20\" autocomplete=off> <br>");
            client.println("<input type=\"text\" name=\"riga2\" maxlength=\"20\" autocomplete=off> <br>");
            client.println("<input type=\"text\" name=\"riga3\" maxlength=\"20\" autocomplete=off> <br>");
            client.println("<input type=\"text\" name=\"riga4\" maxlength=\"20\" autocomplete=off> <br>");

            client.println("Suona? Si<input type=radio name=\"suona\" value=\"1\"> No<input type=radio name=\"suona\" value=\"0\" checked> <br>");

            client.println("<input type=\"submit\" value=\"Invia messaggio\">");
            client.println("</form>");

            client.println("</BODY>");
            client.println("</HTML>");
          }
          else{
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Messaggi su display LCD</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            //client.println("<META HTTP-EQUIV=\"REFRESH\" CONTENT=0; URL=/>");

            client.println("<H1>Messaggio inviato con successo</H1>");
            client.println("<a href=\"/\">Torna indietro</a>");
            client.println("</BODY>");
            client.println("</HTML>");

          }

          client.stop();

          if(lettura.indexOf("?") > 0){
            dividirighe();
            mostradisplay();

            if(suona == "1"){
              new_message_alert();
            }
          }

          lettura = "";
        }
      }
    }
  }
}

void dividirighe(){

  //Sostituisci caratteri HTML
  lettura.replace("+", " ");
  lettura.replace("%21", "!");
  lettura.replace("%3F", "?");
  lettura.replace("%27", "'");
  lettura.replace("%2C", ",");
  lettura.replace("%3A", ":");
  lettura.replace("%3B", ";");
  lettura.replace("%28", "(");
  lettura.replace("%29", ")");
  lettura.replace("%2F", "/");
  lettura.replace("%5C", "\\");
  lettura.replace("%2B", "+");
  lettura.replace("%3D", "=");

  riga1 = lettura.substring(lettura.indexOf("riga1=")+6, lettura.indexOf("&riga2"));
  delay(5);

  riga2 = lettura.substring(lettura.indexOf("riga2=")+6, lettura.indexOf("&riga3"));
  delay(5);

  riga3 = lettura.substring(lettura.indexOf("riga3=")+6, lettura.indexOf("&riga4"));
  delay(5);

  riga4 = lettura.substring(lettura.indexOf("riga4=")+6, lettura.indexOf("&suona"));
  delay(5);

  suona = lettura.substring(lettura.indexOf("suona=")+6, lettura.indexOf("HTTP")-1);
  delay(5);

  Serial.println("---------------------------------------");
  Serial.print("Riga1: ");
  Serial.println(riga1);

  Serial.print("Riga2: ");
  Serial.println(riga2);

  Serial.print("Riga3: ");
  Serial.println(riga3);

  Serial.print("Riga4: ");
  Serial.println(riga4);

  Serial.print("Suona: ");
  Serial.println(suona);
  Serial.println("---------------------------------------");

}

void mostradisplay(){
  lcd.clear();

  lcd.setCursor(0,0);
  lcd.print(riga1);

  lcd.setCursor(0,1);
  lcd.print(riga2);

  lcd.setCursor(0,2);
  lcd.print(riga3);

  lcd.setCursor(0,3);
  lcd.print(riga4);
}

void new_message_alert(){
  //Al pin 3 va inserito uno speaker
  tone(3, 131,150);
  delay(150);
  tone(3, 147,150);
  delay(150);

  tone(3, 131,150);
  delay(150);
  tone(3, 147,150);
  delay(150);

  tone(3, 131,150);
  delay(150);
  tone(3, 147,250);
  delay(250);
}

Le funzioni principali sono, ovviamente setup() e loop() che sono native per l’inizializzazione e il loop principale di arduino, dividirighe(), mostradisplay() e new_message_alert().

 

Dopo aver effettuato l’inclusione delle librerie e le inizializzazioni di quest’ultime siam passati alla dichiarazioni delle variabili per il programma e poi l’inizializzazione dell’ethernet shield, del display e dei pin (in questo caso viene dichiarato come pin di uscita il pin n° 3 che viene collegato ad un cicalino).

 

La prima parte di codice nel loop principale serve per ricevere le richieste dal browser, i caratteri vengono ricevuti ad uno ad uno quindi una variabile char si occupera di riceverli ed una stringa di concatenarli.

  if(client){
    while (client.connected()){
      if (client.available()){

        char c = client.read();
        lettura.concat(c);

        Serial.print(c);

}
}
}

Nel programma ho inserito il comando “Serial.print(c)” che mostra sul serial monitor i dati ricevuti per verificare il corretto funzionamento.

Ecco la stringa ricevuta per visualizzare il messaggio dell’immagine sopra:

GET /?riga1=Ecco&riga2=una&riga3=prova%21&riga4=&suona=1 HTTP/1.1

“GET” identifica il tipo di richiesta.

Successivamente si possono leggere i dati ognuno dopo il nome della variabile nella quale verranno successivamente immagazinate.

E per finere “HTTP/1.1” indica il tipo di protocollo utilizzato.

 

Successivamente un banalissimo controllo cerca il carattere di fine riga per poter rispondere:

        if (c == '\n'){
...
}

Un ulteriore controllo verifica la pagina di provenienza, ovvero, se il messaggio è già stato spedito restituisce una pagina con un messaggio di conferma altrimenti restituisce il modulo per l’invio del messaggio.

 

Passiamo alle altre funzioni; la prima è dividirighe().

dividirighe() si occupa di “elaborare” il messaggio ricevuto. I caratteri come lo spazio, il punto esclamativo/interrogativo, parentesi, punti, virgole vengono inviate tramite codice html non così come le visualizziamo, per questo la prima parte di questa funzione si occupa di sostituire il codice html nel corrispondente simbolo grafico:

  //Sostituisci caratteri HTML
  lettura.replace("+", " ");
  lettura.replace("%21", "!");
  lettura.replace("%3F", "?");
  lettura.replace("%27", "'");
  lettura.replace("%2C", ",");
  lettura.replace("%3A", ":");
  lettura.replace("%3B", ";");
  lettura.replace("%28", "(");
  lettura.replace("%29", ")");
  lettura.replace("%2F", "/");
  lettura.replace("%5C", "\\");
  lettura.replace("%2B", "+");
  lettura.replace("%3D", "=");

Successivamente ogni riga deve essere “presa” e inserita nella variabile che poi andrà scritta sul display, ecco come:

  riga1 = lettura.substring(lettura.indexOf("riga1=")+6, lettura.indexOf("&riga2"));
  delay(5);

  riga2 = lettura.substring(lettura.indexOf("riga2=")+6, lettura.indexOf("&riga3"));
  delay(5);

  riga3 = lettura.substring(lettura.indexOf("riga3=")+6, lettura.indexOf("&riga4"));
  delay(5);

  riga4 = lettura.substring(lettura.indexOf("riga4=")+6, lettura.indexOf("&suona"));
  delay(5);

  suona = lettura.substring(lettura.indexOf("suona=")+6, lettura.indexOf("HTTP")-1);
  delay(5);

E’ facile capire che l’ultima variabile contiene il valore di controllo per il cicalino, se il suo valore è “1” il cicalino deve suonare altrimenti se il suo valore è “0” non deve suonare.

Vengono inserite anche nella funzione dividirighe() alcune righe che mostrano sul serial monitor il risultato delle operazioni precedentemente svolte:

  Serial.println("---------------------------------------");
  Serial.print("Riga1: ");
  Serial.println(riga1);

  Serial.print("Riga2: ");
  Serial.println(riga2);

  Serial.print("Riga3: ");
  Serial.println(riga3);

  Serial.print("Riga4: ");
  Serial.println(riga4);

  Serial.print("Suona: ");
  Serial.println(suona);
  Serial.println("---------------------------------------");

Ed ecco cosa viene fuori sul serial monitor prendendo come esempio sempre la stessa immagine inserita a inizio post:

 

—————————————
Riga1: Ecco
Riga2: una
Riga3: prova!
Riga4:
Suona: 1
—————————————

 

Passiamo alla prossima funzione; mostradisplay().

void mostradisplay(){
  lcd.clear();

  lcd.setCursor(0,0);
  lcd.print(riga1);

  lcd.setCursor(0,1);
  lcd.print(riga2);

  lcd.setCursor(0,2);
  lcd.print(riga3);

  lcd.setCursor(0,3);
  lcd.print(riga4);
}

Com’è facile capire questa funzione si occupa del display lcd, ovvero lo “pulisce” e mostra il contenuto delle stringhe che contengono il messaggio ricevuto.

 

E per finire l’ultima funzione; new_message_alert();

void new_message_alert(){
  //Al pin 3 va inserito uno speaker
  tone(3, 131,150);
  delay(150);
  tone(3, 147,150);
  delay(150);

  tone(3, 131,150);
  delay(150);
  tone(3, 147,150);
  delay(150);

  tone(3, 131,150);
  delay(150);
  tone(3, 147,250);
  delay(250);
}

Questa si occupa semplicemente di generare delle frequenze sul piedino 3 (alla quale ricordo che va collegato un cicalino).

 

Concludo questo articolo dicendo che uno dei probabili prossimi progetti con l’ethernet shield potrebbe essere il controllo di posizione (asse x e y) di una ip-cam. Non posso però promettere niente. :D

 

P.S.

Ho dimenticato di aggiungere una cosa importante:

La pagina web è una pagina interna alla rete ove viene collegata l’ethernet shield.

Per potervi accedere anche esternamente è necessario inserire nel browser l’indirizzo ip esterno della rete, la porta scelta alla quale viene collegata l’ethernet shield e fare il port forwarding nelle configurazioni del router.

Per evitare di mostrare il proprio indirizzo ip si possono utilizzare servizi come NO-IP che permettono di assegnare un indirizzo statico ad un ip dinamico.

Arduino Ethernet Shield e messaggi su display LCD
Tags: