Ago 182013
 

Abbiamo già parlato ampiamente dei display LCD  HD44780 compatibili, ma ci siamo soffermati a descrivere nel dettaglio solamente le funzioni indispensabili per padroneggiare il display, tralasciando le funzionalità più avanzate. Fra queste c’è sicuramente quella che ci permette di definire alcuni nuovi caratteri da utilizzare nei nostri progetti.

Creare caratteri personalizzati

Se ricordate dicevamo che la codifica dei caratteri di questi display rispecchia a grandi linee l’ASCII per cui i caratteri dal 32 al 127 sono pressapoco standardizzati. Ora aggiungiamo che quelli da 0 a 7 sono personalizzabili da noi, se ne deduce perciò che sono solamente 8. Per comprendere il meccanismo di generazione di nuovi caratteri dovete fare affidamento alla tabella che vi riporto quivicino. Dovete innanzitutto preparare una griglia di 5 colonne e 8 righe, ossia le dimensioni del font che sono 5×8 (non mi soffermerò sui 5×10). A questo punto riempite i quadrati di vostro interesse, ossia i pixel che volete accendere per formare il carattere personalizzato.

tabella_punti_lcd

Se cercate in rete trovate tutta una serie di generatori di caratteri online in cui è sufficiente premere sulle caselle con il mouse. Fra questi generatori vi segnalo questo che oltre a fare i calcoli che vedremo a breve, vi prepara anche la sketch da usare con la LiquidCrystal. Ora analizziamo le singole righe della tabella. La prima è vuota per cui, anche senza conoscere la codifica binaria, il valore di quella riga non potrà che essere zero. Passiamo alla seconda. Notiamo che sono state riempite le caselle contrassegnate con 1 e 3. Con la codifica binaria dovremmo perciò fare: 2 elevato alla 1 + 2 elevato alla 3 ossia 2+8=10, che in esadecimale è 0x0A. Perciò quando andiamo a sommare i valori, la riga 0 varrà 1, la 1 vale 2, la 2=4, 3=8, 4=16. Ripetendo il processo per tutte le linee otteniamo i valori che vi ho preparato nella figura a lato. Si noti che la riga numero 7 è vuota. Nessuno ci impedisce di riempire questa linea, ma ricordatevi che se viene visualizzato il cursore, questo andrà a coprire proprio questa linea quando passa sopra al nostro carattere.

Con la LiquidCrystal

Ora dobbiamo solo vedere come usare i valori ottenuti per formare il carattere che ci interessa. Con la LiquidCrystal potremmo scrivere:

#include <LiquidCrystal.h>

LiquidCrystal ldc(12, 11, 5, 4, 3, 2);

byte MyChar[8] = {0,10,21,10,0,17,14,0};

void setup()
{

lcd.createChar(0, MyChar);
lcd.begin(16, 2);
lcd.write(0);

}

void loop() {}

Come vedete ho definito un array dal nome MyChar che contiene i valori calcolati qui sopra, poi vedete voi se metterli in decimale, esadecimale o binario, secondo le vostre preferenze. Nella fase di setup viene utilizzata la funzione createChar. Il primo parametro passato è il numero di carattere che vogliamo ridefinire, ricordandoci che può andare da 0 a 7. Il secondo è l’array contenente i dati binari sopra calcolati. Con l’istruzione lcd.write(0) viene stampato sullo schermo il nostro carattere per cui il risultato sarà qualcosa simile all’immagine che vedete in fondo all’articolo. Il loop è vuoto perchè non abbiamo necessità di fare null’altro.

Con la gestione diretta

Se siete invece interessati alla gestione più diretta del display, darò per scontato che abbiate già letto il precedente articolo e che abbiate sotto mano la sketch con le funzioni SetCommandPin e PulseEnable che avevamo scritto la scorsa volta. Nel caso attuale il comando da utilizzare ha la seguente sintassi:

DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 1 A A A 0 0 0

Il bit 6 indica il comando di scrittura nella memoria CGRAM (quella definibile dall’utente), i tre bit seguenti (A)  indicano l’indirizzo del carattere da ridefinire. Essendo solamente 3bit possiamo indirizzare 8 caratteri, dallo 0 al 7. Una volta inviato il comando di scrittura non dobbiamo far altro che inviare gli 8 bytes con i valori calcolati in precedenza. L’invio del comando non ha nulla di diverso rispetto a quanto visto nel primo articolo:

digitalWrite(pin_RS, LOW); // porto RS ad LOW per indicare l'invio di un COMANDO
SetCommandPin(0,1,0,0); // primi 4
PulseEnable();
SetCommandPin(0,0,0,0); // ultimi 4
PulseEnable();

Come vedete viene prima portato il pin RS a LOW per indicare l’invio di un comando, dopodichè viene inviato il comando stesso. Nell’esempio qui sopra ho indicato l’intenzione di riprogrammare il carattere 0 per cui a parte il bit 6 posto a 1, il resto è tutto a 0. Successivamente al comando dobbiamo inviare gli 8 byte che compongono la “mappatura” del carattere. Per farlo possiamo usare una procedura quasi identica a quanto appena visto, l’unica grossa differenza sta nel fatto che essendo DATI e non COMANDI, il pin RS deve essere portato ad un livello alto:

 digitalWrite(pin_RS, HIGH); // porto RS ad HIGH per indicare l'invio di DATI
 SetCommandPin(0,0,0,0); // primi 4 del PRIMO byte
 PulseEnable();
 SetCommandPin(0,0,0,0); // ultimi 4 del PRIMO byte
 PulseEnable();
 SetCommandPin(0,0,0,0); // primi 4 del SECONDO byte
 PulseEnable();
 SetCommandPin(1,0,1,0); // ultimi 4 del SECONDO byte
 PulseEnable();
 .......

Ho scritto la procedura solamente per i primi due bytes, ma bisogna inviare anche gli altri 6 mancanti. Ovviamente in un progetto più completo è auspicabile la scrittura di una funzione dedicata a questo scopo. Vi faccio notare che siccome i caratteri hanno una larghezza di 5 bit, i 3 più significativi resteranno sempre a zero.lcd-customchar

Ora una domanda: “Cosa succede se ridefiniamo un carattere già stampato sullo schermo?”. Potremmo aspettarci due scenari, ossia la ridefinizione di entrambi, anche quello già scritto sul display, oppure la coesistenza di due simboli diversi. Purtroppo la risposta è la prima, ossia viene ridefinito anche il primo carattere. Sembra infatti che ad ogni scrittura vengano ristampati tutti i caratteri del display, un vero peccato perchè ne avremmo potuto approfittare per superare il limite degli otto caratteri personalizzabili. D’altro canto possiamo sfruttare questo meccanismo per risparmiare caratteri: facciamo l’esempio di un simbolo che indica la carica di una batteria, da completamente piena a completamente vuota con vari steps intermedi. In questo caso non serve usare un simbolo per ogni step di carica ma possiamo usare sempre lo stesso che andiamo poi a ridefinire quando dobbiamo modificare la visualizzazione.