Tag

, , , , , , , , , , ,

Per proseguire lo studio sull’utilizzo di Arduino come server web, vedremo tra breve come sia possibile creare un servizio più sofisticato di quello mostrato in precedenza.

Nel nostro primo esempio (che trovate in questa pagina), avevamo creato un servizio che ci permetteva di accendere e spegnere 3 LED, cliccando su un semplice link.

Il funzionamento di questo servizio era molto elementare: passavamo un carattere al server, e in base a quello Arduino leggeva il valore del led: lo accendeva se questo era spento, oppure lo spegneva se era acceso.

Limiti

L’esempio però era davvero limitato: che succede, infatti, se voglio accendere un led e nello stesso tempo controllare un motore? O se voglio leggere un secondo valore da un secondo sensore? O se voglio decidere la luminosità di un led, così che sia più o meno brillante?

Per poter realizzare tutte queste cose abbiamo bisogno di un servizio web più sofisticato: un servizio, cioè, in grado di riceve più di un parametro e – cosa ancora più utile – poter ricevere valori più lunghi di un singolo carattere.

Cominciamo allora a creare un servizio web più efficiente!

Obiettivo

Poniamoci come obiettivo, ad esempio, quello di poter decidere la luminosità dei 3 led, in modo da farli brillare più o meno intensamente.

Il circuito

Per farlo, dobbiamo prima di tutto spostare l’ingresso dei nostri 3 led, in modo che siano connessi ad Arduino su 3 ingressi in grado di utilizzare la PWM. Su Arduino, un pin in grado di utilizzare la PWM è indicato con il simbolo tilde (~) accanto al numero del pin. Ci basterà quindi spostare i 3 led sui pin 3, 6 e 9.

Arduino LED Server 2

Arduino LED Server 2

Lo sketch

Una volta fatto questo, passiamo al codice del nostro sketch. Per controllare sia il led che la luminosità, andiamo a sostituire i 3 link utilizzati nel vecchio esempio con un menu a tendina, e aggiungiamo alla pagina un campo di testo nel quale inseriremo la luminosità del led.

In questo modo potremo inviare, con un solo clic sul pulsante Invia, sia il parametro che indica il led da accendere sia la luminosità del led.

Questo è il codice, in formato HTML:

<form method="get">
  <select name="led">
    <option value="v">verde</option>
    <option value="a">arancio</option>
    <option value="r">rosso</option>
  </select>
  <input type="text" name="perc">
  <input type="submit" value="Invia">
</form>

Di conseguenza, andiamo a modificare lo sketch in questo modo:

// Form per controllare i 3 LED e la luminosita'
// Seleziona LED
client.print("<form method='get'>");
client.print("select name='led'");
client.print("<option value='v'>verde</option>");
client.print("<option value='a'>arancio</option>");
client.print("<option value='r'>rosso</option>");
client.print("</select>");
// Luminosita'
client.print("<input type='text' name='perc'>");
// Invio
client.print("<input type='submit' value='Invia'>");

NB: nell’esempio il termine “perc” indica la luminosità, in percentuale.

Il server

Cliccando il pulsante Invia il server riceve adesso due parametri: il primo indica il led che vogliamo accendere, mentre il secondo indica la luminosità. Per fare in modo che Arduino possa interpretare correttamente il comando che gli stiamo inviando, andiamo innanzitutto a recuperare questi due valori:

[...]
if(client.findUntil("led", "?"))
{
  char type = client.read();
  // Fondamentali gli apici singoli (')
  if ( type == 'v' ) { led = pinVerde; }
  if ( type == 'a' ) { led = pinArancio; }
  if ( type == 'r' ) { led = pinRosso; }
}
if(client.findUntil("perc", "\n\r"))
{
  int intensita = client.parseInt();
}
if ( led && intensita ) { accendiLED( led, intensita ); }
[...]

Una volta recuperati i nostri due valori, li passiamo alla funzione per accendere il led. La funzione è stata leggermente modificata in modo che possa accettare anche un secondo parametro per la luminosità – che viene espressa da un numero intero, variabile da un minimo di 0 fino ad un massimo di 100.

void accendiLED(int pin, int intensita)
{
  if ( intensita < 0 || intensita > 100 ) { return; }
  intensita = map(intensita,0,100,0,255);
  analogWrite(pin, intensita);
}

Verifica

Arrivati a questo punto, possiamo scegliere quale led accendere e a quale intensità farlo brillare. Siamo perciò in grado di inviare più di un parametro al server, e il nostro server risponderà correttamente: provate ad aprire il browser sulla pagina del servizio e potrete controllare le luminosità dei 3 led.

Parametri e valori

Per servizi piuttosto semplici, passare come valore un singolo carattere di solito è sufficiente. Ma ben presto ci si accorge dei limiti di questa pratica: in primo luogo, possiamo usare solo un numero limitato di valori (!) – e in secondo luogo si rischia di fare confusione: il colore “b” indica il bianco? oppure il blu? o forse indicava il bordeaux? Confondersi diventa ben presto molto facile.

Cosa indica 'b'? Bianco? Blu? Bordeaux? Beige?... :-(
http://localhost/?colore=b

Per fare in modo che il server accetti valori più lunghi di un singolo carattere bisogna però ricorrere a un piccolo trucco. Dato che una stringa non è altro che una serie – più o meno lunga – di caratteri, dobbiamo “fare posto”, ossia creare uno spazio di memoria nel quale il server sia in grado di salvare la sequenza di caratteri per “creare” una parola.

Vedremo subito che realizzare questo passaggio è molto più semplice di quanto potrebbe sembrare.

Buffer

Con la parola buffer ci si riferisce appunto al “contenitore” che andremo ad utilizzare per il nostro valore. Dobbiamo prima di tutto “creare un buffer”, in questo modo:

const int DIMENSIONE_BUFFER = 10;  // usato per salvare il parametro
char buffer [DIMENSIONE_BUFFER+1]; // termina con il carattere nullo

Il buffer non è altro che un contenitore, un po’ come un array. Viene dimensionato di un carattere più lungo del necessario perché deve obbligatoriamente finire con un carattere vuoto affinché venga riconosciuto dal sistema.

Una volta creato questo spazio in memoria, vediamo come fare in modo che il server lo utilizzi per salvare i caratteri letti e comporre la parola che indica il nostro valore:

// Cerco il LED da accendere
// Es: 192.168.1.10/?led=xxxx&... (xxxx)
if ( client.find("led=") ) 
{ 
  // cancello il buffer salvato in precedenza, se esiste
  memset(buffer,0,sizeof(buffer));
  // salvo nel buffer il valore, passato come elenco di caratteri
  client.readBytesUntil('&',buffer, DIMENSIONE_BUFFER); 
}

In questo modo, l’elenco di caratteri che il server legge tra il simbolo “=” e il simbolo “&” viene salvato nel buffer e interpretato come una parola intera. Per confrontare un buffer, a differenza di quello che accade tra due caratteri, si utilizza la funzione strcmp(), che da come risultato 0 (zero) se la stringa cercata e il buffer sono uguali.

Andiamo quindi a sostituire il vecchio codice:

if ( type == 'v' ) { toggle( pinVerde ); }
if ( type == 'a' ) { toggle( pinArancio ); }
if ( type == 'r' ) { toggle( pinRosso ); }

Con il nuovo codice:

if ( strcmp(buffer,"verde")==0 ) { led = pinVerde; percVerde = luminosita; }
if ( strcmp(buffer,"arancio")==0 ) { led = pinArancio; percArancio = luminosita; }
if ( strcmp(buffer,"rosso")==0 ) { led = pinRosso; percRosso = luminosita; }

Ecco quindi come il server può ricevere un valore più lungo di un carattere! Andiamo infine a modificare anche le poche righe che compongono il form visto in precedenza:

client.print("<option value='verde'>verde</option>");
client.print("<option value='arancio'>arancio</option>");
client.print("<option value='rosso'>rosso</option>");

Il nostro server adesso accetta più di un parametro, e può ricevere anche dei parametri composti da vere e proprie parole. Nel codice da scaricare troverete anche qualcosina in più, sebbene comunque il servizio resti molto semplice. Ma le basi per creare un servizio completo, una volta comprese, si possono perfezionare molto velocemente.

Per ora questo è tutto! A presto.

Download: Arduino_Server_2.zip

Annunci