Tutorial: Arduino led rgb via Web

Continuando la sequenza di tutorial che coinvolgono Arduino e i led RGB hai mai pensato di decidere il colore del tuo lampadario o della tua lampada o le tue palline natalizie via web? Ad esempio con il tuo iPhone o smartphone Android?

Progetto Arduino Ethernet Shield e iPhone

Ed eccoti accontantato, il progetto che puoi realizzare oggi è dedicato a come utilizzare i led RGB, Arduino, l’Ethernet Shield e il tuo smartphone per divertenti giochi di luce da mostrare in casa o con cui realizzare una lampada o un lampadario come il mio.

arduino ethernet shield

Lo sketch non è semplicissimo ma te lo descriverò linea per linea per aiutarti nella sua comprensione e poterci fare le modifiche che riterrai più opportune:

// RGB Led Ethernet
// by Alfieri Mauro
//
// Used libraries and examples:
//
// Arduino Ethershield
// Ethernet Library
// String Library
// SPI Library

#include <SPI.h>
#include <Ethernet.h>
#define maxLength 25

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 237 };
String inString = String(maxLength);
int val;
int r = 0;
int g = 0;
int b = 0;
char colorBuff[4];
Server server(80);

int pinR = 3;
int pinG = 5;
int pinB = 6;

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
  pinMode(pinR, OUTPUT);
  pinMode(pinG, OUTPUT);
  pinMode(pinB, OUTPUT);

  analogWrite(pinR, 0);
  analogWrite(pinG, 0);
  analogWrite(pinB, 0);

  Serial.begin(9600);
}
void loop()
{
  int bufLength;
  Client client = server.available();
  if (client) {
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (inString.length() < maxLength) {
          //inString.append(c);
          inString += c;
        }
        if (c == '\n' && current_line_is_blank) {
          if (inString.indexOf("?") > -1) {
            int Pos_r = inString.indexOf("r");
            int Pos_g = inString.indexOf("g", Pos_r);
            int Pos_b = inString.indexOf("b", Pos_g);
            int End = inString.indexOf("S", Pos_b);
            if(End < 0){
              End =  inString.length() + 1;
            }

            bufLength = ((Pos_g) - (Pos_r+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }
            inString.substring((Pos_r+2), (Pos_g-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            r = atoi(colorBuff);
            bufLength = ((Pos_b) - (Pos_g+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }
            inString.substring((Pos_g+2), (Pos_b-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            g = atoi(colorBuff);
            bufLength = ((End) - (Pos_b+2));
            if(bufLength > 4){  //dont overflow the buffer
              bufLength = 4;
            }
            inString.substring((Pos_b+2), (End-1)).toCharArray(colorBuff, bufLength);  //transfer substring to buffer
            b = atoi(colorBuff);

            analogWrite(pinR,r);
            analogWrite(pinG,g);
            analogWrite(pinB,b);

          }
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<html><head>");
          client.println("<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'><title>:: Arduino Server ::</title>");
          client.println("<style>");
          client.println("body { text-align: center; font-family: Arial, Helvetica, sans-serif; font-size:50px; font-weight: normal; } ");
          client.println("h1, input { font-size: 100%; text-align: center; } ");
          client.println(".dim { border: 1px solid #f0731c; width: 100%; text-align: center; } ");
          client.println(".pulsante { width: 60px; height: 60px; border: 1px solid #000; margin: 5px; } ");
          client.println("</style>");
          client.println("</head><body>");

          client.println("<div class='dim'><h1>RGB Arduino </h1>");
          client.print("<form method=get>");

          client.println("<table border=0 align=center>");
          client.println("<tr>");
          client.println("<td align=center><div class=pulsante style=\"background-color: #FF0000;\"><br>R</div></td>");
          client.println("<td align=center><div class=pulsante style=\"background-color: #00ff00;\"><br>G</div></td>");
          client.println("<td align=center><div class=pulsante style=\"background-color: #0000ff;\"><br>B</div></td>");
          client.println("</tr>");
          client.println("<tr>");
          client.println("<td align=center><input type=text size=3 name=r id=r value=\""); client.print(r); client.println("\"></td>");
          client.println("<td align=center><input type=text size=3 name=g id=g value=\""); client.print(g); client.println("\"></td>");
          client.println("<td align=center><input type=text size=3 name=b id=b value=\""); client.print(b); client.println("\"></td>");
          client.println("</tr>");

          client.println("</table>");

          client.println("<br><input name=\"S\" type=\"submit\" value=\"INVIA\">");
          client.println("</form>");
          client.println("</div>");
          client.println("</body></html>");
          break;
        }
        if (c == '\n') {
          current_line_is_blank = true;
        }
        else if (c != '\r') {
          current_line_is_blank = false;
        }
      }
    }
    delay(1);
    inString = "";
    client.stop();
  }
}

Premetto che dovrai fare largo uso delle librerie presenti nell’IDE Arduino quali: String, Ethernet, SPI.

Iniziamo dalle linee successive ai miei commenti, le linee 11-12: includi le librerie che ti ho indicato, ciascuna di esse ti semplifica la gestione della shield Ethernet o la gestione delle stringhe;

linea 13: definisci una costante maxLength di valore 25 ossia la lunghezza massima della stringa di testo che conterrà i valori passati da interfaccia web;

linee 15-16: definisci due array di tipo byte ciascuno contenente un valore di configurazione della ethernet shield, il mac con cui la scheda si presenterà sulla tua rete, l’ip con cui potrai raggiungere l’applicazione che stai scrivendo;

linee 17-22: definisci alcune variabili necessarie allo sketch durante la sua eseguzione, in particolare la variabile inString della lunghezza di 25 (maxLength) caratteri, è la variabile in cui memorizzerai i valori proveninenti dall’interfaccia web;

linea 23: inizializza il server web sulla porta 80 (default http per i browser) in modo che l’applicazione risponda su tale porta, ti faciliterà l’accesso al server Arduino che stai realizzando con questo sketch;

linee 25-27: definisi i pin per i collegamenti ai led R,G e B, grazie a questa impostazione potrai variare i collegamenti tra Arduino ed i Led in qualsiasi momento, semplicemente modificando la linea rispettiva;

linea 29: definisci la funzione setup() che oramai conosci benissimo e sai essere necessaria al corretto funzionamento ed inizializzazione del tuo sketch;

linea 31: imposta in fase di inizializzazione di tutto lo sketch il mac e l’ip definiti alle linee 15 e 16;

linea 32: inizializza il server vero e proprio, in questo modo dici ad Arduino di utilizzare la libreria Ethernet per creare un server che risponda sull’indirizzo Ip che hai definito e la porta 80;

linee 33-35: definisci i pin a cui saranno collegati i 3 terminali relativi ai colori R,G e B come tipo OUTPUT ossia li utilizzerai per inviare dei segnali da Arduino verso i Led. ATTENZIONE: nella definizione dei 3 pin a cui collegare i terminali dei led R,g e B devi urilizzare sempre uscite digitali di tipo PWM, questa impostazione è necessaria per utilizzare il comendo analogWrite che invia valori da 0 a 255 solo su tali uscite; (Nota: è possibile utilizzare anche le normali uscite digitali con segnali PWM utlizzando la liberia softPWM);

linee 37-39: utilizzando il comando analogWrite impostia a 0 il valore inciato ai led all’accenzione dell’arduino;

linea 41: inizializza la comunicazione seriale a 9600 baud, il monitor seriale puoi non utilizzarlo in una fase successiva quando lo sketch funziona senza problemi, ma in fase di debug è davvero utile;

linea 43: definisci la funzione loop() che ciclicamente eseguirà lo sketch che stai scrivendo.

linea 45: inizializza una variabile di tipo int (intero) bufLength che utilizzerai tra breve;

linea 46: definisci un oggetto di tipo Client in cui memorizzare la presenza di una richiesta da parte di un Client Web, in pratica quando dal tuo browser ti collegherai all’interfaccia web, Arduino riceverà una richiesta di tipo Client che puoi leggere con il metodo available() della classe server inizializzata alla linea 32;

linea 47: leggi se la variabile client contiene una richiesta da parte di un browser allora esegue ciò che è indicato nelle linee successive;

linea 48: setta la variabile current_line_is_blank utilizzata successivamente;

linea 49: inizia un ciclo impostato sulla presenza di una connessione da parte di un browser web, tale verifica ti evita di far elaborazioni durante l’assenza di connessione;

linea 50: verifica che la connessione oltre ad essere presente sia anche utilizzabile;

linea 51: leggi il valore inciato dal client con il metodo read() dell’oggetto client assegnalo ad una variabile di tipo char;

linee 52-55: verifica che la lunghezza del valore contenuto in inString sia inferiore all’impostazione  maxLength definita sopra, ed in funzione di tale lunghezza accoda alla inString i nuovi caratteri letti dalla connessione con il client; il metodo append() commentato era il modo utilizzato dalla versione precedente dell’oggetto String per concatenare un nuovo carattere ad una stringa, dalla versione 0021 dell’IDE la classe String è stata inclusa nell’IDE e il metodo append() non è più disponibile, al suo posto è possibile utilizzare la sintassi +=;

linea 56: verifica che il carattere c letto sia un “\n” (new line) e che contemporaneamente la variabile current_line_is_blank  sia settata a true, nelle ultime righe dello sketch vedrai che un controllo ulteriore definisce ad ogni loop del programma se continuare la lettura ed accodare caratteri o se procedere con l’elaborazione;

linea 57: utilizza il metodo indexOf() della clase String sull’oggetto inString per determinare se nella riga è presente un carattere “?” tale carattere viene automaticamente inserito da un browser nella stringa inviata quando si invia un comando di tipo GET o POST, se vuoi maggiori innformazioni sui metodi GET e POST ti consiglio di ricercare in internet come funzionano le comunicazioni ed il protocollo HTTP; per il tuo sketch è sufficente sapere che il carattere “?” è riservato alla comunicazione HTTP e che identifica un passaggio di dati da un modulo HTML verso un programma in grado di elaborarlo;

linee 58-60: mediante il metodo indexOf() utilizzato anche nella riga precedente, non solo individui la presenza di un carattere “r”, “g” o “b” ma il metodo indicato ti restituisce anche il valore numerico relativo alla posizione che tale carattere occupa nella stringa che stai elaborando;

linea 61: individua anche il punto, all’interno della stringa, in cui è posizionato il carattere “S” che utilizzi come fine della stringa da analizzare;

Digressione: per capire meglio le linee appena viste e per non fare confusione in seguito immagina la stringa che il client spedisce al server (Arduino in questo caso), è di questo tipo:

GET 1.1 /?r=xxx&g=yyy&b=zzz&S=submit
012345678901234567890123456789012345

Ho volutamente aggiunto sotto la numerazione dei caratteri per comprendere meglio la questione delle posizoni, quando utilizzi il metodo indexOf(“?”) sulla stringa otterrai come risultato 9, la posizione del carattere cercato nella stringa, allo stesso modo per “r” otterrai 10, per “g” 16, per “b” 22 ed “S” 28.

linee 62-64: verifica che la ricerca del carattere “S” non restituisca un valore inferiore a 0, in tal caso per evitare errori nell’elaborazione successiva imposta End (che dovrebbe contenere 28, nell’esempio precedente) uguale alla lunghezza della stringa passata +1; in questo modo potresti omettere di passare il valore S=submit, dovresti però riadattare lo sketch verificando che il resto della stringa sia identico;

linee 66-71,72-77,78-83: eseguono la medesima sequenza di comandi solo che ciascun gruppo di linee lo fa per uno dei tre valori r,g e b; analizzerò solo una delle sequenze 66-71;

linea 66: imposta la variabile bufLength come differenza tra la posizione di g (16) e la posizione di r (10) + 2 caratteri, in pratica 16-10+2= 16 -12= 4;

linee 67-69: esegui un controllo di lunghezza della variabile bufLength in modo che non superi il valore 4, in caso contrario la imposti a 4, questo controllo basa la sua veridicità sul fatto che ciascuno dei valori passati sia composto da massimo 3 cifre (255 valore massimo) più il carattere separatore &, ogni carattere in più non è necessario;

linea 70: potresti scrivere questa linea in due per avere un indicazione più chiara di ciò che fa, diverrebbe:

String _tmpStr = inString.substring((Pos_r+2), (Pos_g-1));
_tmpStr.toCharArray(colorBuff, bufLength);

Ossia definendo una variabile di tipo String  _tmpStr a cui assegni la porzione di stringa compresa tra r+2 (12) e g-1 (15) nella pratica il valore di _tmpStr sarebbe xxx, il peso da assegnare al rosso (0-255); la linea successiva assegnerebbe alla variabile colorBuff il valore estratto, bufLength indica al metodo toCharArray() la dimensione del valore da assegnare +1;

linea 71: assegna ad r il valore, convertito in intero, appena trovato;

linee 85-87: assegnano i valori r,g e b ai rispettivi pin di Arduino, provocando la conseguente accensione dei led;

linee 90-123: con il metodo println() assegna all’oggetto client le righe html da inviare al browser per visualizzare la pagina HTML, per approfondimenti ti invito a leggere qualche manuale HTML on-line anche basilare se non possiedi già conoscenze in tal senso.

linea 124: blocca il ciclo while indicando di uscire in quanto l’elaborazione è terminata;

linee 126-131: definiscono i cntrolli di cui ti ho parlato sopra, in pratica se rilevi un valore di tipo “\n” (new line – nuova linea) imposti la variabile current_line_is_blank in modo che al successivo loop sia elaborato il codice ottenuto, in alternativa se non trovi un carattere di tipo “\r” (carriege return – ritorno a capo) e non hai trovato, evidentemente neppure un carattere “\n” imposti a false la current_line_is_blank, in modo che al prossimo loop non sia eseguita alcuna elaborazione ma accodato il carattere letto dal client alla inString;

linea 134: al termine di tutta l’elaborazione e di ogni ciclo attendi circa 1 millesimo di secondo prima di proseguire, è un picolo ritardo che consente al loop di elaborare i comandi da impartire;

linea 135: resetta il valore di inString per prepararla ad una successiva richiesta da parte del client;

linea 136: interrompe la comnunicazione con il lient, questa operazione è fondamentale per indiare al browser che la comunicazione è terminata e non deve attendersi altri dati da elaborare.

Non ti resta che uplodare lo sketch su Arduino, e collegare il tuo iPhone o browser all’IP indicato, nel mio caso 192.168.2.237, il risultato dovrebbe essere simile al seguente:

interfaccia arduino iphome ethernet shield

Buon lavoro

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/tutorial-arduino-led-rgb-via-web.html

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.