Modulo LCD03
Perché sprecare tanti pin di I/O per gestire un display ed una tastiera?
Sacrificandone solo due si può gestire bene (ed in modo molto semplice) il display LCD03 ed una tastiera a 12 tasti... Più, eventualmente, altri dispositivi I2C.
In modo relativamente poco intuitivo (anche se ben documentato nelle istruzioni per la libreria Wire), sulla maggior parte delle schede Arduino SDA è sul pin dell'ingresso analogico 4, mentre SCL su quello dell'ingresso analogico 5 (notevole eccezione il Mega, dove sono sulle linee digitali 20 e 21). Se volete evitare i mal di testa che ho avuto io, ricordatevi di aggiungere le resistenze di pull-up (io ho usato 4,7KΩ): pare funzionare anche senza (probabilmente grazie alle resistenze interne da 20KΩ), ma ogni tanto ci sono strani errori.
La prima particolarità da notare è che gli indirizzi dei device vanno divisi per due. Ecco quindi la prima macro utile da aggiungere:
#define I2C_ADDR(x) ((x)>>1)
Forse sarebbe più sensato far gestire la cosa alle classi che si interfacciano con l'HW... Ma per retrocompatibilità non ho voluto modificare la cosa.
Altra particolarità: l'inizializzazione del display, nelle demo, viene fatta come se fosse un 40x4 invece di un 20x4. Vabbé, si sistema molto facilmente.
La libreria "precotta" per gestire il display in questione è LCDi2cR. Si tratta di un normale LCD 4x20 con saldata una controller (basata su un PIC 16F819) che si occupa della gestione dei bus seriali (RS232 o I2C) e della tastiera (avanzava qualche pin ). La controller viene venduta da Robot Electronics ma si trova anche in Italia (io l'ho presa da Futura Elettronica, insieme ad altro materiale).
Fin quando ho usato la libreria in modo molto semplice, tutto OK. Ma quando ho modificato un po' il codice che la richiamava facendogli leggere la tastiera piuttosto (troppo? mah!) velocemente, un tasto risultava sempre premuto a meno che non ne fosse premuto un altro. Con la demo non succedeva, col mio programma sì.
Ci ho perso parecchio tempo ma, poi, scorrendo il sorgente e confrontandolo con la documentazione del display, ho notato che il metodo keypad()
legge 3 byte di stato, mentre dovrebbe leggerne 4 (FIFO, Key1, Key2, Version).
Ho quindi modificato la libreria di conseguenza:
Wire.requestFrom(g_i2caddress, 3); // Read 3 bytes
è diventato:
Wire.requestFrom(g_i2caddress, 4); // Read 4 bytes
E tutto 'magicamente' si risolve, anche se non leggo effettivamente il quarto byte dal bus (forse sarebbe meglio farlo...)!