TUTORIAL WEB SERVER CON PIC E ESP8266 V.2.0

Ti può interessare: Web Server con PIC16F1825

V.2.0: velocizzata la fase di avviamento del ESP8266. Nova gestione della pagina Web: è possibile inviare pagine con più di 2048 Byte. Le pagine devono essere spacchettate in più pacchetti manualmente.


CONTROLLARE UN LED

Una delle funzioni del web server che colpisce di più riguarda la possibilità di accendere o spegnere un LED. Risulta ovvio che l’operazione da banale accensione di un semplice LED può diventare una funzione importante se sostituiamo il LED con un transistor in grado di pilotare un relè i cui contatti possono controllare un qualsiasi carico. Immaginate di essere seduti sulla vostra poltrona preferita e trovarvi nella necessità di dovere accendere le luci del giardino, ebbene, senza scomodarvi, prendete il vostro smartphone e, dopo esservi collegati in WiFi al router di casa o direttamente al Access Point del ESP8266, accedete al browser e con un semplice tocco allo schermo, come per magia, le luci del giardino verranno accese. Non solo sarete in grado di controllare dei carichi ma, in tempo reale, potrete verificare lo stato dei carichi stessi senza recarvi fisicamente sul posto dove risiedono i dispositivi da controllare.

Vediamo come gestire un’uscita del PIC in tre varianti.

Nella prima variante, controlliamo l’uscita che per comodità d’ora in avanti chiameremo semplicemente LED, senza il feed-back ovvero visivamente non possiamo verificarne lo stato dalla pagina web.

Iniziamo dalla costruzione della pagina web

<tr>\

<th width=60%>LED 1</th>\

<th width=20% bgcolor=green><a href=\"L01n\">ON</a></th>\

<th width=20% bgcolor=red><a href=\"L01f\">OFF</a></th>\

</tr>\

Il pratica ciò che interessa a noi sono i tag

<a href=\"L01n\">ON</a>

per accendere il LED 1 e

<a href=\"L01f\">OFF</a>

per spegnerlo.

I tag, inseriti in tabella per migliorarne l’aspetto come nel nostro esempio o semplicemente inseriti come riga, devono trovare posto nella pagina web tra i tag <html> e </html>. Nelle pagine del firmware trovate gli esempi chiarificatori.

Il risultato ottenuto al browser è il seguente

le scritte “ON” e “OFF” diventano dei pulsanti in grado di compiere delle azioni.

Cliccando su “ON” il browser invia una richiesta al server attraverso il metodo “GET” più semplice da gestire dal firmware del PIC.

La richiesta può essere verificata dalla barra degli indirizzi del browser

In pratica il browser affianca all’indirizzo del server al quale è inviata la richiesta, l’etichetta “L01n” che abbiamo associato al LED 1 per lo stato “ON”. Il messaggio che arriva al PIC dal ESP8266 attraverso la seriale, è il seguente:

E’ importante notare che l’etichetta “L01n” si trova ad una certa posizione nella stringa iniziale. Il software del PIC salva una stringa che, partendo dal carattere “D” di “+IPD”, conserva in memoria i successivi 21 caratteri. Alla posizione [2] troviamo l’identificativo di connessione del browser, alla posizione [13] il carattere “L” scelto per discriminare il tipo di carico, alle posizioni [14] e [15] l’indirizzo del carico, in teoria (molto in teoria) potremmo controllare fino a 100 LED e, associando l’indirizzo ad una diversa lettera dell’alfabeto, si possono immaginare decine di migliaia di carichi diversi (p.e.: da A00 a A99, da a00 a a99, da B00 a B99, ecc.). Nella realtà il PIC non ha ne la capacita ne la memoria per affrontare una sfida del genere. Non per questo il progetto va denigrato, controllare 10 o 15 carichi è già sufficiente per soddisfare la maggior parte delle richieste di domotica.

Alla posizione [16] abbiamo una lettera che indica lo stato che vogliamo fare assumere dal LED, “n” per accenderlo e “f” per spegnerlo.

A questo punto, per sortire l’effetto desiderato, è necessario aggiungere alcune righe di programma al firmware del PIC. È importante notare che non è necessario modificare il firmware proposto ma solo aggiornato aggiungendo le righe che controlleranno il carico in un'unica funzione.

//*************************************************** GESTIONE USCITE

//buff_13 = L (LED)

// **************************************************

void Aggiornamento (char b_13, char b_14, char b_15, char b_16_) {

 unsigned short buff;

//

      if (b_13 == 'L') {           // Aggiornamento LED

        buff = (b_14-0x30) *10;

         buff += (b_15-0x30);

      }

       else return;

//

     switch (buff) {      

//

         default: {

                  break;

         }

  }

}

Il meccanismo che regola la funzione è molto semplice: le posizioni [14] e [15] sono l’indirizzo della funzione “switch”, per ogni LED da controllare, dovremmo aggiungere un “case” che riporti come riferimento l’indirizzo stesso.

Nel nostro caso l’indirizzo del LED è “01” e il “case” da aggiungere riporterà come riferimento “1”. Vediamo la funzione “Aggiornamento(…)” modificata:

NOTA IMPORTANTE: l’indirizzo del LED deve sempre essere di 2 cifre. P.E.: LED 0 ON => L00n, LED 4 OFF => L04f, ecc. Nel caso di errore, il LED non subirà nessun cambiamento di stato.

 
 
// ************************************************ GESTIONE USCITE

//buff_13 = L (LED)

// ************************************************

void Aggiornamento (char b_13, char b_14, char b_15, char b_16_) {

unsigned short buff;

//

      if (b_13 == 'L') {           // Aggiornamento LED

        buff = (b_14-0x30) *10;

         buff += (b_15-0x30);

      }

       else return;

//

     switch (buff) {

         case 1:{ if (b_16_ == 'n') LED_1 = 1;             // ON

                     else if (b_16_ == 'f') LED_1 = 0;      // OFF

                      else { if (LED_1) LED_1 = 0;        // Togle

                               else LED_1 = 1;

                  }

                     break;

         }

//

         default: {

                  break;

         }

     }

 }

 

Osservate che con poche righe siamo in grado di gestire completamente il LED 1.

Lo stato “togle” verrà analizzato più avanti.

Analogamente la gestione del LED 2 sarà uguale a quella per il LED 1 e per tutti i LED che desideriamo controllare.

A questo punto vediamo di complicarci la vita inserendo delle righe in un’altra funzione che ci permetterà di controllare in tempo reale lo stato dei LED. Il meccanismo della nuova funzione è del tutto simile a quello del controllo delle uscite, anche in questo caso nulla viene modificato (tranne le pagine web, ovviamente) ma solo aggiunte alcune righe di programma in un’unica funzione.

Dalla pagina 2, la seconda tabella graficamente si presenta in questo modo:

e la sezione della pagina web risulta un poco più complicata del precedente esempio e l’inserimento dei tag di controllo ON/OFF dei LED in una tabella è essenziale in quanto controlliamo il colore della casella di riferimento del numero del LED in base allo stato del LED stesso.

<tr>\

<th bgcolor=~10 width=60%>LED 1</th>\

<th width=20% bgcolor=green><a href=\"L01n\">ON</a></th>\

<th width=20% bgcolor=red><a href=\"L01f\">OFF</a></th>\

</tr>\

Possiamo notare che la sezione della pagina web che riguarda il controllo del LED 1 è sostanzialmente identica a quella analizzata poco fa. Troviamo unicamente l’aggiunta relativo al colore di fondo della cella che deve rispecchiare lo stato del LED, rosso se acceso, verde nel caso sia spento (il colore è totalmente gestibile e personalizzabile). L’unica particolarità da notare, è un numero preceduto dal simbolo “tilde” al posti del colore di fondo della cella. L’associazione tilde/numero possiamo identificarla come una variabile il cui nome è “10” cioè un numero. In teoria sono possibili 100 variabili (da ~00 a ~99).

NOTA IMPORTANTE: anche in questo caso, l’indirizzo della variabile deve essere unicamente di 2 cifre numeriche. In caso di errore (P.E. ~8 o ~5s), la variabile riporterà la stringa “ERROR”.

Come annunciato, anche in questo caso dobbiamo aggiungere alcune righe di programma nella funzione “unsigned int Calc_Value (unsigned short tilde, unsigned short count)” i cui argomenti sono il numero della variabile da aggiornare (unsigned short tilde) e indicare la fase di invio della pagina web (unsigned short count). Se “count” vale 1, la funzione invia i valori delle variabili che la pagina web contiene via via che vengono analizzate, altrimenti ritorna solo il numero di caratteri contenuti nell’aggiornamento della variabile interrogata.

Poiché tale funzione è richiamata dal firmware del PIC, la descrizione è solo informativa, avremmo solo la necessità di aggiungere del codice, il meccanismo che la regola è del tutto automatico.

unsigned int Calc_Value (unsigned short tilde, unsigned short count) {

  unsigned short cnt_value;

      switch (tilde) {

// --- ERROR

         default : {    // Se non trova la variabile, stringa di errore

            strcpy (txt, "ERROR");

             break;

         }

      }

// ---

     cnt_value =0;      asm {clrwdt}

       while (txt[cnt_value]) {

         if (count== 0) { UART1_Write(txt[cnt_value]); }  //se richiesto invia dato

           cnt_value ++;                                  

       }

//

     return cnt_value;        // altrimenti solo il numero di caratteri

}

La funzione di base si presenta molto simile alla precedente, ovvero ogni variabile agisce in un “case”. Vediamo in particolare la funzione e implementiamo la variabile “~10”.

L’aggiunta della variabile “~10” è composta da poche righe che riportano il colore di fondo della cella in base al valore booleano del LED 1.

 
unsigned int Calc_Value (unsigned short tilde, unsigned short count) {

  unsigned short cnt_value;

      switch (tilde) {

case 10: {         // Stato LED 1 (colore fondo rosso/verde)

                if (LED_1) StrCopy_red ();  // Red

                  else StrCopy_green ();    // Green

                   break;

         }

// --- ERROR

         default : {    // Se non trova la variabile, stringa di errore

            strcpy (txt, "ERROR");

             break;

         }

      }

// ---

Da notare la presenza di due funzioni che assegnano il colore alla cella tramite la variabile “~10”. Si è scelta tale modalità al fine di risparmiare RAM del PIC. In presenza di più uscite e/o ingressi da gestire come colore di fondo o scritte come “ON, OFF, ACCESO, SPENTO, APERTO, CHIUSO” ecc., viene impegnata la RAM per il feed-back di un’utenza per tutte le altre dello stesso tipo. P.E. il LED 1 e il LED 2 generalmente richiedono gli stessi colori per riportarne lo stato.

A LED 1 acceso, la tabella riporterà la seguente grafica:

La gestione del secondo LED è del tutto analoga, l’importante è assegnare al colore di fondo della cella del LED 2 un nome diverso p.e. ~11.

L’ultimo modo di gestire un LED che vi descriviamo, sebbene ve ne siano infiniti altri, è quello di toglare, ovvero un unico pulsante accende il LED se spento e viceversa.

La parte del firmware da aggiungere è stato analizzato precedentemente, e non vi è null’altro da aggiungere, mentre il codice della pagina web è del tutto simile al caso precedente:

 
<tr>\

<th width=60%>LED 1</th>\

<th width=20% bgcolor=~10><a href=\"L01t\">ON/OFF</a></th>\

</tr>\

Vi è poco da aggiungere, rispetto alla tabella precedente il colore di fondo viene gestito alla stessa maniera, mentre ritorna la stringa “L01t” dove “t” distingue il modo di gestire l’uscita.

     switch (buff) {

         case 1: { if (b_16_ == 'n') LED_1 = 1;             // ON

                     else if (b_16_ == 'f') LED_1 = 0;      // OFF

                      else { if (LED_1) LED_1 = 0;        // Togle

                               else LED_1 = 1;

                  }

                     break;

         } 

Graficamente non presenta novità. Vediamo la tabella con il LED 1 spento e acceso.

VISIONARE LO STATO DI UN PULSANTE E AGGIORNARE UN VALORE NUMERICO

In questa sezione analizziamo il metodo adottato dal progetto per informare con delle scritte lo stato di un ingresso o di un’uscita, con delle informazioni diverse da un semplice colore o un mix delle due. Analogamente è possibile inviare informazioni di tipo numerico poiché anche questo tipo di dato altro non è che una stringa codificata in codice ASCII. Possiamo leggere e riportare il dato aggiornato sulla pagina web di un valore analogico di un ingresso del PIC o acquisito per mezzo della seriale e nel formato che più ci aggrada. Solo la fantasia pone limiti all’utilizzo di un web server. A tale fine sono disponibili delle funzioni che trasformano un valore intero (unsigned int) in stringa con o senza zeri iniziali, con o senza virgola.

Da notare che non essendoci uscite da controllare, l’unica funzione che ci consente di agire sulle informazioni contenute nella pagina web è quella della gestione delle variabili. Iniziamo subito con un esempio di lettura dello stato dei pulsanti 1 e 2.

La pagina di riferimento è quella principale

Il pulsante 1 riporta lo stato letto con l’informazione “ON/OFF”, mentre il 2, a titolo di esempio, restituisce lo stato con le scritte “ACCESO/SPENTO” e allo stesso tempo cambia il colore di fondo per una visuale immediata dello stato. Analizziamo la sezione della pagina web che riguarda i pulsanti.

<table border=1 width=50% align=center>\

<tr>\

<th colspan=2>INPUT DIGITALI</th></tr>\

<tr><td width=25%>Pulsante 1</td><td width=25%>~02</td>\

</tr>\

<tr>\

<td>Pulsante 2</td><td bgcolor=~03>~04</td>\

</tr>\

</table>\

Il tutto risulta più semplice rispetto alle tabelle viste precedentemente riguardanti il controllo dei LED. Non ci sono pulsanti da premere e l’aggiornamento delle variabili viene effettuata durante l’invio della pagina al browser.

È chiaro che per visualizzare lo stato dei pulsanti è necessario ricaricare la pagina cliccando sulla scritta “reload”

o sul pulsante “home” della barra di navigazione.

Nell’esempio, al pulsante 1 viene abbinata la variabile “~02” indicante lo stato con la scritta “ON/OFF”, mentre al 2 il colore di fondo è controllato dalla variabile “~03” e la “~04” è responsabile dell’informazione alfanumerica “ACCESO/SPENTO”. Per ottenere questo risultato è sufficiente aggiungere le tre variabili alla funzione “unsigned int Calc_Value (unsigned short tilde, unsigned short count)”. Un modo molto semplice può essere questo:

 
      switch (tilde) {

// --- Variabili main page

         case 2: {    //               // Stato pulsante 1 (ON/OFF)

                if (pul_1) StrCopy_off ();     // OFF

                  else StrCopy_on ();          // ON

                  break;

         }

         case 3: {    //              // Stato pulsante 2 (colore fondo rosso/verde)

                if (pul_2) StrCopy_red ();     // Red

                  else StrCopy_green (); // Green

                  break;

         }

         case 4: {    //              // Stato pulsante 2 (acceso/spento)

                if (pul_2) StrCopy_spento ();  // SPENTO

                  else StrCopy_acceso ();      // ACCESO

                   break;

         }

Premendo i pulsanti e aggiornato la pagina web, il risultato visivo è notevole

Leggermente più complicata è la visualizzazione di valori analogici, solo perché quest’ultimi richiedono un’elaborazione con dei calcoli che variano da caso in caso. Vediamo come possiamo affrontare due problemi diversi. Nel primo elaboriamo il valore rilevato dal ADC per convertirlo in volt con un decimale considerando nei calcoli il rapporto di ingresso del partitore resistivo. Nel secondo visualizziamo semplicemente i bit letti dal secondo ingresso analogico senza nessuna elaborazione.

La tabella visualizza il valore in Volt (13,4V) del primo ingresso analogico (CH4), confermato dalla lettura del tester, il valore del secondo ingresso sono i bit della conversione analogico/digitale (507 bit) copiati dal relativo registro del ADC CH5.

La parte di codice HTML necessaria per costruite la tabella sopra riportata è molto semplice e non presenta nessuna difficolta rispetto a quanto visto finora

 
<table width=\"60%\" align=center bgcolor=yellow border=3>\

<tr>\

<th colspan=2>INPUT ANALOGICI</th>\

</tr>\

<tr>\

<td>AN 0</td><td>~00</td>\

</tr>\

<tr>\

<td>AN 1</td><td>~01</td>\

</tr>\

</table>\

Una possibile implementazione viene proposta dal codice seguente

    case 0: {                                 // ADC 0

       cnt = ADC_Read(4);            // Canale 4

        cnt *= K_Volt;

         cnt/=100;                   // tmp/=100; ==> 1 decimale

          Volt = cnt/10;      // Salva il valore (vedi "case 23")

           Word_to_str_wout_zeros_virgola();

             break;

         }

         case 1: {                                  // ADC 1

                cnt = ADC_Read(5);                 // Canale 5

                 Word_to_str_wout_zeros();

                  break;

         }

La riga in rosso ci servirà nella descrizione delle funzioni della pagina 4, è stata inserita per non essere costretti a doppiare inutilmente lo stesso codice.

La variabile ~00 è il risultato della elaborazione tra i bit del ADC CH4, collegato al nostro ingresso analogico 0 e una costante calcolata considerando il rapporto resistivo in ingresso e il valore mV/bit del ADC. La formula della costante “K_Volt” è molto semplice:

per 3,3V di alimentazione del PIC:  0,0032 * 5,68 = 0,018 * 1000 = 18

per 5V di alimentazione del PIC: 0,0049 * 5,68 = 0,0278 * 1000 = 28

dove

0,0032 il rapporto V/bit a 3,3V (3,3[V] / 1023[bit])

0,0049 il rapporto V/bit a 5V (5[V] / 1023[bit])

5,68 rapporto resistivo in ingresso [(22K + 4K7) / 4K7] = 5,68

1000 per ottenere il valore intero in mVolt

Anche in questo caso, un’operazione che a prima vista può sembrare complicata, con un po’ di attenzione è risolta in maniera molto semplice.

Il problema maggiore che si incontra quando è necessario visualizzare dei valori o dati sul browser è l’aggiornamento dei dati stessi. Esistono diversi modi per aggiornare i dati di una pagina web, il più semplice è l’aggiunta nel codice HTML di un semplice tag:

<meta http-equiv=\"refresh\" content=\"60\">

Il tempo di attesa tra un aggiornamento e l’altro è espresso in secondi. Nell’esempio la pagina viene aggiornata ogni 60 secondi.

Attenzione: l’aggiornamento riguarda l’intera pagina web e non solo i dati desiderati. Una soluzione che permetta l’aggiornamento di soli dati è quello di sfruttare il codice AJAX. Vedremo più avanti un’esempio pratico.

Occupiamoci ora dell’utilizzo dei form.

FORM

Visualizzare un dato o un valore in una pagina web, abbiamo visto come farlo in maniera molto semplice, ma se dobbiamo trasferire un dato dal browser al PIC possiamo farlo con i form. Nell’esempio che prenderemo in esame, aggiorneremo le ore e i minuti dell’orologio del progetto, ma sono tantissime le occasioni di utilizzo dei form.

Bisogna precisare che per i form è stata sviluppata nel firmware del PIC una funzione che risponde alle esigenze del progetto e a quelle che similarmente possono essere richieste dall’utilizzatore finale. Vediamo innanzi tutto come sviluppare una pagina web con i form. Il nostro riferimento è la pagina 3 e analizziamo subito il codice HTML richiesto

<tr>\

<td width=\"20%\"><b>ORE:</b></td><td width=\"20%\">\

<form method=get>\

<input type=\"text\" name=\"Por\" maxlength=\"2\"></td>\

<td width=\"10%\">\

<div><input type=\"submit\" value=\" ~20 \"</div>\

</form></td>\

</tr>\

Il codice HTML è quello classico per la costruzione di un form. Anche in questo caso è stato inserito in una tabella per migliorare l’aspetto complessivo della pagina, non è un obbligo. Prendiamo in esame la parte utilizzata per modificare le ore, lo stesso discorso vale per i minuti.

Il tag che si occupa dello spazio di scrittura e invio è <input> e l’attributo necessario per inserire un elemento è “type=text”, in questo caso una casella di testo. Altro attributo inserito per controllare la richiesta dal browser è “maxlength="2"” che limita a 2 i caratteri inseribili nella casella di testo.

Il form non distingue tra caratteri numerici o alfabetici, sono codificati in ASCII perciò invia ciò che viene digitato. Niente paura ci pensa il PIC a prendere in esame solo i caratteri che corrispondono ai numeri da 0 a 9, nel caso di errori, il PIC non elabora il contenuto del form, semplicemente lo ignora.

Altro tag <input> con l’attributo “type="submit"” crea un pulsante che permette l’invio di quanto digitato nel form. L’attributo “value” riporta sul pulsante un’etichetta sulla funzione del pulsante. Al fine di risparmiare Byte preziosi, riportiamo sul pulsante il valore della variabile “ore” al posto di un’indicazione, magari più logica sulla funzione del pulsante (p.e. “invia” o “send”) ma onerosa in termini di Byte da sottrarre al PIC.

Vediamo come funziona l’invio di un’informazione digitata su un form con l’aiuto della grafica.

Dal valore impresso sul pulsante del form delle ore, il valore della variabile “ore” attuale è 11. Ipotizziamo di dovere aggiornare l’orologio alle ore 18, digitiamo il valore nella casella di testo e premiamo il pulsante relativo alle ore. Il browser invia la richiesta verificabile dalla casella degli indirizzi del browser stesso come riportato in figura

Possiamo identificare il nome della pagina web(p3), il nome del form identificato dall’attributo “name” (Por) che ci permette di capire inanzitutto che si tratta di un form (P) nello specifico quello delle ore (or) e, ovviamente, il valore da trasferire nella variabile “ore” (=18).

Il modulo WiFi riceve la richiesta dal browser e la gira (dopo averla pulita dagli indirizzi IP, MAC, ecc.) al PIC per mezzo della seriale.

Come descritto all’inizio dell’articolo, la posizione nella richiesta del browser di quanto riportato nel form, è fissa. In particolare, nella famosa stringa che copia i 21 Byte della richiesta del browser, la posizione [16] contiene il carattere [P] (provate a contare in che posizione si trova il carattere ‘P’ iniziando dal carattere ‘D’ di ‘+IPD’) che, se presente, conferma l’invio di dati dai form, la [17] e [18] discriminano il tipo di form, nel nostro caso si tratta o di quello delle ore o dei minuti, la posizione [19] deve avere il codice corrispondente al simbolo ‘=’ e gli ultimi due un valore che va da 48 a 57 ciascuno (0x30 = ‘0’, 0x39 =’9’).

 
void Set_Value (char b_17, char b_18, char b_19, char b_20, char b_21) {

 unsigned short temp;

 unsigned int tmp;

//

      if (b_17 == 'o'&& b_18 == 'r') {          // Aggiornamento ORE

        temp = Set_Prog (b_19, b_20, b_21);

         if (temp) {

           ore = (b_20 - 0x30) *10;

            ore += (b_21 - 0x30);

         }

           else return;

      }

        else if (b_17 == 'm' && b_18 == 'i') {    // Aggiornamento MINUTI

          temp = Set_Prog (b_19, b_20, b_21);

           if (temp) {

             minuti= (b_20 - 0x30) *10;

              minuti+= (b_21 - 0x30);

           }

             else return;

        }

            else return;

 }   

Anche in questo caso tutto molto semplice. La funzione “temp = Set_Prog (b_19, b_20, b_21);” controlla che: b_19 sia ‘=’, b_20 e b_21 abbiano ciascuno un valore compreso tra 48 e 57.

Terminato il ciclo di correzione della variabile, il PIC invia al ESL8266 la pagina aggiornata. Da notare che l’aggiornamento viene riportato dal pulsante.

AJAX

A volte ci si trova nella necessità di dovere controllare un determinato dispositivo ad intervalli più o meno regolari. Ci sono comandi HTML che soddisfano tale necessità in maniera molto semplice: è sufficiente inserire un singolo tag con l’argomento adeguato per risolvere il problema in particolare in presenza di una pagina sobria, con pochi Byte. Un esempio è stato analizzati poche righe fa. Il discorso cambia se la pagina è complessa e piena di figure, foto o altro, l’aggiornamento diventa problematico e la qualità della pagina ne risente. Allo scopo di proporre alcune soluzioni a 360 gradi, nella pagina web 4 possiamo testare un assaggio di ciò che il codice AJAX è in grado di offrire. Nulla di impressionante, solo un banale orologio aggiornato ogni 10 secondi. La porzione di codice javascript deve trovarsi all’interno della sezione <head> della pagina web, quindi tra il tag di apertura <head> e quello di chiusura <head>.

<script>\

function GetD(){\

nocache=\"&nocache=\"+Math.random()*1000000;\r\n\

var request=new XMLHttpRequest();\r\n\

request.onreadystatechange=function(){\

if(this.readyState==4){\

if(this.status==200){\

if(this.responseText!=null){\

document.getElementById(\"PIC\").innerHTML=this.responseText;\

}}}}\r\n\

request.open(\"GET\",\"ajax\"+nocache,true);\r\n\

request.send(null);\r\n\

setTimeout('GetD()',10000);\r\n\

}\

</script>\r\n\

Da notare la presenza di “\r\n” (inizio linea, a capo o nuova linea) in alcuni punti del codice, sono necessari per il corretto funzionamento del codice. Il realtà sarebbe sufficiente ‘\n’ (a capo) ma nelle verifiche con Hyper Terminal, il tutto risulta più leggibile con l’uso dei due caratteri.

È importante notare che nel tag di apertura <body> è presente un comando che fa riferimento allo script e lo richiama all’apertura della pagina

<body bgcolor=#7495a5 onload=\"GetD()\">\

mentre la parte dello script in blue, richiama la funzione di aggiornamento ogni 10 secondi. Se desideriamo cambiare il tempo di aggiornamento, dobbiamo agire in questo punto del programma. Il tempo è espresso in millisecondi (10 s = 10000 ms).

NOTA: il tempo di risposta del PIC dipende dal numero di Byte della pagina web, comunque non meno di 0,5 secondi. Non è consigliabile scendere al di sotto di 2-3 secondi di richiesta di aggiornamento dello script.

Trascorso il time-out impostato, il browser invia la richiesta al server in questo modo

Il PIC risponde inviando la pagina dedicata all’aggiornamento AJAX

const char *AJAX =                             

"\

<?xml version=\"1.0\"?>\

<p>ORE: ~20:~21.~22</p>\

  \r\n\

";

La pagina AJAX contiene il tag che definisce il tipo di codice (xml) e ciò che è inserito tra i tag <p> e </p> verrà visualizzato dal browser. Nell’esempio proposto, il pacchetto contiene tre variabili che corrispondono allo scorrere del tempo diviso in ore, minuti e secondi. A rendere dinamico il codice è la solita funzione che ha il compito di aggiornare, su richiesta, le variabili contenute nelle pagine web.

  case 20: {    //

                cnt = ore;                          // ORE

                 Word_to_str_wout_zeros();

                  break;

         }

         case 21: {    //

                cnt = minuti;                       // MINUTI

                 Word_to_str_wout_zeros();

                  if (txt[1]==0) {                  // Formato a due cifre

                    txt[1]=txt[0];

                     txt[0]='0';

                  }

                    txt[2]=0;

                     break;

         }

         case 22: {    //

                cnt = sec;                          // SECONDI

                 Word_to_str_wout_zeros();

                  if (txt[1]==0) {                  // Formato a due cifre

                    txt[1]=txt[0];

                     txt[0]='0';

                  }

                    txt[2]=0;

                     break;

         }

La parte riguardante i minuti e i secondi sembra più complicata rispetto a quella delle ore, il tutto è finalizzato alla formattazione dei minuti e dei secondi sempre con due cifre, come richiesto da ogni orologio che si rispetti.

A titolo di esempio, aggiungiamo un’ulteriore informazione alla risposta AJAX, a dimostrazione della facilità e semplicità nel modificare il file.

 
const char *AJAX =                            

"\

<?xml version=\"1.0\"?>\

<p>ORE: ~20:~21.~22</p>\

<p>Volt: ~00</p>\

 \r\n\

";

Abbiamo aggiunto la tensione misurata all’ingresso analogico 0. La variabile è la stessa degli esempi visti precedentemente.

Con lo stesso meccanismo possono essere inserite diverse informazioni, messaggi compresi. L’unico limite sono i 2048 Byte massimi inviati dal ESP8266 al browser.

Dal lato browser il punto della pagina web in cui lo script stampa i dati ricevuti dal ESP8266 tramite il file “AJAX”, è determinato dalla posizione dall’istruzione

<div id=\"PIC\">\</div>\

la quale può essere inserita anche all’interno di una cella di una tabella.

I FOGLI DI STILE (CSS)

Per rendere più vivace e dinamica la pagina web (e non solo…) è stato inventato un nuovo tipo di linguaggio che si occupasse di formattare i layout delle pagine web lasciando al HTML il compito di strutturarle. Non che il linguaggio non si possa occupare della formattazione delle strutture della pagina web, ma il CSS, o foglio di stile, lo fa meglio con opzioni più sofisticate. Inoltre il linguaggio CSS è supportato da tutti i browser.

Iniziamo confrontando un attributo di un tag HTML con un attributo CSS all’interno del tag HTML <style>

<BODY bgcolor=#7495a5>

l’attributo bgcolor=#7495a5 del tag <body> colora l’intera pagina del colore di windows classico, mentre l’attributo “style” all’interno del tag <h1> crea una striscia gialla della larghezza dei caratteri che formano la scritta e colora la stessa di rosso

<h1 align=center style=\"color:red;background:yellow;\">JUMBO elettronica WEB SERVER</h1>

"color:red;background:yellow;" sono attributi CSS.

Nell’esempio visionato, il codice CSS era contenuto all’interno di un tag, quindi inglobato nella pagina web che ne fa uso. Il più delle volte il codice viene separato dalla/e pagine web, segregandolo in un file a se stante, in particolar modo se il CSS è condiviso da più pagine o da più strutture. Un altro motivo riguarda la leggibilità del codice e la successiva manutenzione che risulta più semplice. Nel nostro caso il motivo è banale: limitare l’uso e l’abuso di Byte per non eccedere il limite massimo di 2048 per pagina, inserendo nella pagina web il link al foglio di stile CSS, demandando al browser il compito di richiedere successivamente al ricevimento della pagina, il file CSS e aggiornare, seppure con un attimo di ritardo, la pagina web.

Moltissimi sono gli esempi da riportare per dimostrare le meraviglie che si possono implementare con i fogli di stile, considerando che la maggior parte di coloro che leggeranno il presente tutorial sono appassionati di elettronica, abbiamo sviluppato (con l’aiuto di Microchip) una barra la cui lunghezza varia in rapporto al valore associato e il colore può cambiare in base a delle specifiche che andremmo ad imporre nel firmware del PIC.

Sempre alla pagina 4, troviamo un’informazione seguita da una barra

La variabile che influiscono sul valore e sulla lunghezza della barra sono associate al ADC dell’ingresso 0, aumentando il valore di tensione otteniamo una barra più lunga e di un colore diverso.

Siamo certi che starete già macchinando diverse applicazioni per la barra, come misurare e visualizzare graficamente la tensione e la corrente dei pannelli solari, la corrente assorbita/ceduta da una batteria (ciclo di carica/scarica), potenza assorbita dall’abitazione, la velocità del vento, la pressione atmosferica, e un’infinità di altre applicazioni. Vediamo come funziona e come applicarla.

Cominciamo dal link inserito nella pagina web

<link href=\"/sty\"rel=\"stylesheet\"type=\"text/css\"/>

come è facile intuire, il browser, dopo avere ricevuto la pagina web, invia la richiesta imposta dal tag <link> e dall’attributo “href=”. Nel solito modo, il modulino ESL8266 gira la richiesta al PIC attraverso la seriale

Il quale risponde inviando il file contenente i fogli di stile della barra.

const char *style =            // Bargraph      

"\

<style type=\"text/css\">\

#barg{\

width:10em;\

margin:0px auto;\

}\

\

.bar{\

color:#fff;\

margin-top:0px;\

font-weight:bold;\

font-size:0.9em;\

padding:1px;\

border:1px solid #000;\

}\

.bar .up{background:#0c0;}\

.bar .dn{background:#c00;}\

</style>\

\r\n\

";

La parte in verde determina la struttura della larghezza della barra.

Quella in turchese definisce la struttura della lunghezza della barra e le caratteristiche del carattere che visualizzerà il dato all’interno della barra (nel nostro caso la tensione).

La parte in viola si occupa del colore di fondo della barra.

A questo punto è necessario determinare il punto della pagina in cui visualizzare la barra. Come sempre a ciò provvede un tag.

 
<div id=\"location\"></div>\

<div id=\"barg\">\

\

<div class=bar style=width:~23em>\

<div class=~24>~00 V</div>\

</div>\

Abbiamo diviso in due colori per distinguere le funzioni. In rosso la parte che richiama i fogli di stile e trova posto nella pagina web una sola volta, mentre la parte turchese può essere richiamata più volte generando più barre.

Le variabili evidenziate in fucsia, corrispondono alla tensione in ingresso analogico 0 (~00), la tensione (~00) divisa per 10 per contenere le dimensioni della barra (~23) e il colore di fondo della barra (~24). Le tre varabili sono gestite dalla solita funzione del firmware. Vediamo una possibile gestione delle ultime due variabili

 
         case 23: {                          // Volt ingresso AN 0 (intero per barra)

                 cnt = Volt;

                  Word_to_str_wout_zeros();

                   break;

         }

         case 24: {                         // Colore barra

                if (Volt >= 12) StrCopy_dn ();

                  else StrCopy_up ();

                   break;

         }

In particolare il colore di fondo della barra è discriminato dal valore della tensione misurata all’ingresso analogico 0, se inferiore ai 12 V, la variabile ritorna con il valore “up” di conseguenza il codice CSS colora la barra di verde (vedi codice CSS colorato di fucsia “.bar .up{background:#0c0;}“), altrimenti ritorna “dn” e la barra diventa rossa (“.bar .dn{background:#c00;}”).

Alcuni esempi per controllare un LED (uscita)

HTML:

LED 1: <a href=\"L01t\">~00</a>\

C:

case 00: {

               if (LED_1) StrCopy_on();

                 else StrCopy_off ();

                  break;

         }

Semplice gestione di un LED con la scritta che descrive lo stato dell’uscita.

HTML:

<a style=\"color:red;background:~04\" href=\"L01t\">LED 1: ~00</a>\

C:

case 04: {

               if (LED_1) StrCopy_yellow ();

                 else StrCopy_green ();

                  break;

         }

Nel codice C la variabile “~00” è la stessa dell’esempio precedente ed è stata omessa dall’esempio per evitare doppioni di codice.

Oltre a cambiare la scritta, cambia il colore di fondo. Alla stessa maniera è possibile cambiare il colore della scritta.

HTML:

<form method=\"get\"action=\"L03t\"><button type=\"submit\">~02</button></form>\

C:

case 02: {

               if (LED_3) StrCopy_on();

                 else StrCopy_off ();

                  break;

         }

Gestione del LED con il tag “botton”. Premendolo cambia l’uscita, visualizzandone lo stato sul pulsante stesso.

HTML:

<form method=\"get\"action=\"L02t\"><button style=\"background-color:~03\" type=\"submit\">LED 2: ~01</button></form>\

C:

case 01: {

               if (LED_2) StrCopy_on();

                 else StrCopy_off ();

                  break;

         }

case 03: {

               if (LED_2) StrCopy_red ();

                 else StrCopy_green ();

                  break;

         }

Altro pulsante che visualizza lo stato del LED e adegua il colore di fondo.

HTML:

<style type=\"text/css\">\

#Button {width:300px;height:90px;background:~03;border-style:none;cursor:pointer;margin:150px auto;}\

</style>\

<form method=\"get\"action=\"L02t\">\

<button id=\"Button\"type=\"submit\">LED 2 ~01</button>\

</form>\

C:

case 01: {

               if (LED_2) StrCopy_on();

                 else StrCopy_off ();

                  break;

         }

case 03: {

               if (LED_2) StrCopy_red ();

                 else StrCopy_green ();

                  break;

         }

Serve un pò di codice HTML in più  per la costruzione del pulsante di dimensioni notevoli (width:300px;height:90px sono le dimensioni assolute in pixel), utile nella visualizzazione delle pagine web da cellulare.

HTML:

<form method=\"get\"action=\"L01t\">\

<button type=\"submit\" onclick=\"alert('Il LED 1 sta per essere ~05')\" >LED 1</button>\

</form>\

C:

case 05: {

               if (LED_1) strcpy(txt, "SPENTO");

                 else strcpy(txt, "ACCESO");

                  break;

         }

Cliccando sul pulsante compare a video il messaggio di allerta. Cliccando sul “OK” del messaggio, viene cambiato lo stato del LED come da indicazione del messaggio.

Ti può interessare: Web Server con PIC16F1825


 

RITORNA ALLA MAIN PAGE