MODULI: Esempio DISPLAY LCD CON INTERFACCIA I2C
CIAO - Per implementare questo progetto occorre un display LCD con interfaccia I2C "YwRobot Arduino LCM1602 IIC V1").
Il potenziometro blu serve ad aggiustare il contrasto del display. La linea dei dati è riconoscibile con la sigla SDA mentre quella del clock con SCL. Grazie a tale interfaccia I2C è possibile collegare il display, che solitamente prevederebbe un minimo di 6 pin (RS, E, D4, D5, D6, D7) più un pin per la gestione della retroilluminazione (vedi esempio sul display LCD 16x2) ,
con soli 2 pin ( SCL ed SDA ) oltre all’alimentazione +5v e Gnd.
I²C è l'abbreviazione di Inter Integrated Circuit (pronuncia i-quadro-ci o i-due-ci), è un sistema di comunicazione seriale bifilare utilizzato nei circuiti integrati.
Il protocollo hardware dell'I2C richiede due
linee seriali
di comunicazione:
SDA (Serial DAta) per i dati
SCL (Serial CLock) per il clock.
Per la presenza del clock
I2C è un bus sincrono.
Va aggiunta una connessione di riferimento,
(detta talvolta impropriamente GND) e una linea di alimentazione
Vdd a cui sono connessi dei resistori di pull-up
(le resistenze di pull-up e pull-down sono usate per garantire che gli
ingressi di un sistema logico siano a livelli logici previsti) e che può anche
non essere condivisa da tutti i dispositivi connessi.
L'I²C
ha 7 bit di indirizzo e quindi può gestire 128 possibili indirizzi (detti nodi).
Il classico bus I²C è composto da almeno un master ed uno slave. Il nodo master è il dispositivo che emette il segnale di clock mentre il nodo slave è quello che si sincronizza sul segnale di clock senza poterlo controllare.
Per poter utilizzare tale interfaccia è necessario scaricare un'altra libreria LiquidCrystal_I2C alternativa a quella di sistema LiquidCrystal fornita con l'ambiente IDE di Arduino.
Per utilizzarla è necessario rimuovere la cartella originale associata alla libreria di sistema.Successivamente occorre scompattare il file e copiare la cartella prodotta (LiquidCrystal) all'interno della cartella contenente le librerie di Arduino (solitamente C:\Program Files\Arduino\libraries). Terminare aggiungendo la cartella appena copiata, mediante il menu "Add Library", all'interno dell'IDE di Arduino.
Al termine dell'importazione i files vengono ricopiati nella cartella C:\Users\<User>\Documents\Arduino\libraries. Se ci sono problemi nell'installazione occorre svuotare la cartella di libreria appena ricopiata.
La libreria "LiquidCrystal_I2C" possiede tutte le funzioni presenti nella libreria di sistema "LiquidCrystal". Inoltre supporta gran parte delle funzioni listate nella specifica ufficiale per i display LCD presente all'indirizzo http://playground.arduino.cc/Code/LCDAPI. I metodi disponibili della classe LiquidCrystal_I2C sono: begin(), clear(), home(), setCursor(), write(), print(), cursor(), noCursor(), blink(), noBlink(), display(), noDisplay(), scrollDisplayLeft(), scrollDisplayRight(), autoscroll(), noAutoscroll(), leftToRight(), rightToLeft(), createChar()
Esercitazione pratica 1:
Obiettivo progetto: Scrivere sul display LCD la scritta "AVE\nPROF" (su 2 righe) seguita dalla frase (sempre su 2 righe) che indica i secondi trascorsi dall'avvio del programma su Arduino (non è ammesso l'utilizzo di millis()). Ad esempio: "Sono trascorsi\n2 secondi".
Consegna:
Fornire 2 soluzioni equivalenti che implementano gli obiettivi del nostro progetto.
Nella prima soluzione utilizzare il seguente template come prototipo iniziale per il programma (utilizzo la funzione predefinita loop() per aggiornare lo scorrere dei secondi).
/* --------------------------------------------------------------------------
1^ TEMPLATE
Scrivo su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C
"YwRobot Arduino LCM1602 IIC V1", la frase "AVE\nPROF\Sono trascorsi\n%d secondi"
SDA è connesso alla pin analogico A4
SCL è connesso alla pin analogico A5
-------------------------------------------------------------------------- */
#include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp
#include <LiquidCrystal_I2C.h> // Libreria LCD I2C
// Imposta i pin usati sul chip I2C per le connessioni
// con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol
// ed inoltre pone l'indirizzo del display a 0x27
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
// Devo inizializzare il display LCD 20 caratteri per 4 linee
// Devo pulire lo schermo
// posizionarsi nei punti del display richiesti e scrivere
// le frasi richieste
}
void loop()
{
// INSERIRE QUI LE ISTRUZIONI CHE REPUTI NECESSARIE
// PER L'AGGIORNAMENTO DELLO SCHERMO
}
Successivamente fornire un ulteriore soluzione seguendo il template seguente (sfrutto un loop infinito all'interno della funzione setup per aggiornare lo scorrere dei secondi).
/* --------------------------------------------------------------------------
2^ TEMPLATE
Scrivo su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C
"YwRobot Arduino LCM1602 IIC V1", la frase "AVE\nPROF\Sono trascorsi\n%d secondi"
SDA è connesso alla pin analogico A4
SCL è connesso alla pin analogico A5
-------------------------------------------------------------------------- */
#include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp
#include <LiquidCrystal_I2C.h> // Libreria LCD I2C
// Imposta i pin usati sul chip I2C per le connessioni
// con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol
// ed inoltre pone l'indirizzo del display a 0x27
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
// Devo inizializzare il display LCD 20 caratteri per 4 linee
// Devo pulire lo schermo
// posizionarsi nei punti del display richiesti e scrivere
// le frasi richieste
// INSERIRE QUI LE ISTRUZIONI CHE REPUTI NECESSARIE
// PER L'AGGIORNAMENTO DELLO SCHERMO
}
void loop()
{
// IN QUESTA SOLUZIONE NON E' AMMESSO SCRIVERE ALCUNA
// ISTRUZIONE NELLA FUNZIONE DI SISTEMA LOOP()
}
Soluzioni:
Ecco la soluzione relativa al 1° template:
/* -------------------------------------------------------------------------- 2^ TEMPLATE Scrivo su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C "YwRobot Arduino LCM1602 IIC V1", la frase "AVE\nPROF\Sono trascorsi\n%d secondi" SDA è connesso alla pin analogico A4 SCL è connesso alla pin analogico A5 -------------------------------------------------------------------------- */ #include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp #include <LiquidCrystal_I2C.h> // Libreria LCD I2C // Imposta i pin usati sul chip I2C per le connessioni // con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol // ed inoltre pone l'indirizzo del display a 0x27 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); void setup() { // Devo inizializzare il display LCD 20 caratteri per 4 linee lcd.begin(20, 4); // Pulisce l'LCD e pone il cursore all'inizio lcd.clear(); // posizionarsi nei punti del display richiesti e scrivere // le frasi richieste lcd.print("AVE"); // Stampo a video il AVE ... lcd.setCursor(0, 1); // 1° colonna - 2° riga lcd.print("PROF"); // e prosegue sulla stessa riga lcd.setCursor(0, 2); // 1° colonna - 3° riga lcd.print("Sono trascorsi "); // e prosegue sulla stessa riga lcd.setCursor(0, 3); // 1° colonna - 3° riga lcd.print("0 secondi "); // e prosegue sulla stessa riga } void loop() { // INSERIRE QUI LE ISTRUZIONI CHE REPUTI NECESSARIE // PER L'AGGIORNAMENTO DELLO SCHERMO lcd.setCursor(0, 3); // 1° colonna - 3° riga lcd.print(millis()/1000); lcd.print(" SECONDI"); // e prosegue sulla stessa riga }
e quella relativa al 2° template:
/* -------------------------------------------------------------------------- 2^ TEMPLATE Scrivo su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C "YwRobot Arduino LCM1602 IIC V1", la frase "AVE\nPROF\Sono trascorsi\n%d secondi" SDA è connesso alla pin analogico A4 SCL è connesso alla pin analogico A5 -------------------------------------------------------------------------- */ #include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp #include <LiquidCrystal_I2C.h> // Libreria LCD I2C // Imposta i pin usati sul chip I2C per le connessioni // con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol // ed inoltre pone l'indirizzo del display a 0x27 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); void setup() { // Devo inizializzare il display LCD 20 caratteri per 4 linee lcd.begin(20, 4); // Pulisce l'LCD e pone il cursore all'inizio lcd.clear(); // posizionarsi nei punti del display richiesti e scrivere // le frasi richieste lcd.print("AVE"); // Stampo a video il AVE ... lcd.setCursor(0, 1); // 1° colonna - 2° riga lcd.print("PROF"); // e prosegue sulla stessa riga lcd.setCursor(0, 2); // 1° colonna - 3° riga lcd.print("Sono trascorsi "); // e prosegue sulla stessa riga lcd.setCursor(0, 3); // 1° colonna - 3° riga lcd.print("0 secondi "); // e prosegue sulla stessa riga for (;;) // Loop infinito { lcd.setCursor(0, 3); // 1° colonna - 3° riga lcd.print(millis()/1000); lcd.print(" SECONDI"); // e prosegue sulla stessa riga } } void loop() { // IN QUESTA SOLUZIONE NON E' AMMESSO SCRIVERE ALCUNA // ISTRUZIONE NELLA FUNZIONE DI SISTEMA LOOP() }
Si osservi come la parte iterata del ciclo infinito for (;;) coincida con il corpo della funzione predefinita loop().
Obiettivo progetto: Pilotare un display lcd con interfaccia I2C in modo che appaia il testo digitato sul Serial Monitor. Si noti che la linea di invio del Serial Monitor accetta al massimo 69 caratteri.
soluzione:
Costruiamo il seguente circuito
utilizzando il seguente codice:
/* -------------------------------------------------------------------------- Esempio creato partendo dal codice all'indirizzo: http://arduino-info.wikispaces.com/LCD-Blue-I2C Scrive su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C "YwRobot Arduino LCM1602 IIC V1", quello che digito sul Serial monitor SDA è connesso alla pin analogico A4 SCL è connesso alla pin analogico A5 -------------------------------------------------------------------------- */ #include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp #include <LiquidCrystal_I2C.h> // Libreria LCD I2C // Imposta i pin usati sul chip I2C per le connessioni // con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol // ed inoltre pone l'indirizzo del display a 0x27 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); void setup() { Serial.begin(9600); lcd.begin(20,4); // Inizializzo LCD 20 caratteri per 4 linee // e accende la retroilluminazione. // lcd.backlight(); // Accende la retroilluminazione // lcd.noBacklight(); // Accende la retroilluminazione // Invita l'utente a scrivere qualcosa sul serial monitor // che verrà poi replicato sul display LCD (impostare "Nesun fine riga" o // "No Line Ending" sul serial Monitor). lcd.clear(); // pulisce lo schermo lcd.setCursor(0,0); // Si posiziona sulla prima riga, prima colonna lcd.print("Digita sul"); lcd.setCursor(0,1); lcd.print("Serial Monitor"); lcd.setCursor(0,2); lcd.print("del testo ..."); Serial.println("Digita del testo ..."); } void loop() { char ch; int r=0, c=0; if (Serial.available()) // Se ci sono caratteri sul Serial Monitor { // aspetta un attimo affinchè arrivi l'intero messaggio delay(100); lcd.clear(); // pulisce lo schermo while (Serial.available() > 0) { lcd.setCursor(c,r); lcd.write(Serial.read()); c++; if (c==20) {c=0; r++;} } } }
Avviato il programma sul display appare questo messaggio:
Digitando il testo "Ciao, sono Marco Sechi ed ho implementato questo progetto"
otteniamo sul display il seguente output:
Si osservi, nonostante la tipologia del circuito utilizzata sia completamente diversa, l'estrema somiglianza di questo programma con quello proposto nell'esempio (analogo come funzionalità richieste) al codice sorgente C proposto per LCD senza bus I2C.
Esercitazione pratica 2:
Obiettivo progetto: Implementare un circuito che utilizzando un keypad ed un display LCD 20x4 simula la lettura di una password di accesso e mostra la scritta "ACCESSO NEGATO" oppure "BENVENUTO" a seconda se è stata digitata la password corretta (supponiamo sia 123456) o meno. Il tasto * assume il significato di invio del codice segreto e pertanto quando Arduino rileva tale carattere deve procedere con le routine di controllo dell'accesso. Il tasto # ha la funzione di reset e pertanto quando Arduino rileva tale carattere deve scartare tutti i numeri precedentemente digitati e procedere con la lettura di una nuova password. Il sistema di accesso, una volta raggiunti gli 11 caratteri, azzera la sequenza memorizzata e si comporta come se fosse stato premuto il tasto *.
soluzione:
Connettiamo i pin del Keypad seguendo lo schema riportato:
Per il display utilizziamo il medesimo circuito visto nell'esempio specifico del dislay LCD 20x4 I2C
Prima di iniziare a scrivere il codice Immaginiamo il contenuto del display a secondo delle diverse situazioni:
MESSAGGI DI ACCESSO | |
![]() |
![]() |
L'accesso è stato autorizzato | La password non è corretta |
MESSAGGI DI ERRORE | |
![]() |
![]() |
Avviso quando digito più di 10 caratteri | Avviso quando invio una password vuota |
Il codice del programma è il seguente:
/* -------------------------------------------------------------------------- Simulo l'accesso ad un sistema dove la password e' digitata su un keypad e l'esito appare su un display LCD 20 caratteri x 4 linee, con interfaccia seriale I2C "YwRobot Arduino LCM1602 IIC V1" SDA è connesso alla pin analogico A4 - SCL è connesso alla pin analogico A5 -------------------------------------------------------------------------- */ // ************************************************************* // IMPOSTAZIONE PER IL KEYPAD // ************************************************************* #include <Keypad.h> const byte ROWS = 4; //4 righe const byte COLS = 3; //3 colonne char keys[ROWS][COLS] = { {'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'} }; byte rowPins[ROWS] = {8, 7, 6, 5}; // Pin di arduino connessi ai pin 1,2,3 e 4 delle righe del keypad byte colPins[COLS] = {4, 3, 2}; // Pin di arduino connessi ai pin 5,6,7 delle righe del keypad Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // ************************************************************* // IMPOSTAZIONI PER IL DISPLAY LCD // ************************************************************* #include <Wire.h> // Libreria di sistema - E' richiesta da I2CIO.cpp #include <LiquidCrystal_I2C.h> // Libreria LCD I2C // Imposta i pin usati sul chip I2C per le connessioni // con il display LCD: addr, en, rw ,rs ,d4 ,d5 ,d6 ,d7 ,bl ,blpol // ed inoltre pone l'indirizzo del display a 0x27 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // ------------------------------------------------------------- // PROGRAMMA VERO E PROPRIO // ------------------------------------------------------------- String passwd=""; int pos=3; // Posizione del carattere * relativo alla password void PulisciRigaPassword() { lcd.setCursor(0, 1); // 1° colonna - 2° riga lcd.print(" "); // Pulisce la riga lcd.setCursor(0, 1); // 1° colonna - 2° riga lcd.print("-> "); // e prosegue sulla stessa riga passwd=""; pos=3; } void ScriviRiga3e4(String Frase3, String Frase4) { lcd.setCursor(0, 2); // 1° colonna - 3° riga lcd.print(Frase3); lcd.setCursor(0, 3); // 1° colonna - 4° riga lcd.print(Frase4); lcd.setCursor(pos, 1); // Ritorno alla posizione originale // sulla 2° riga } void Pulisci3e4Riga() { String Vuota=" "; ScriviRiga3e4(Vuota,Vuota); } void MessaggioErrore(String Frase) { String Frase3="...::: AVVISO :::..."; String Frase4=">> "+Frase; ScriviRiga3e4(Frase3,Frase4); } void setup() { // Devo inizializzare il display LCD 20 caratteri per 4 linee lcd.begin(20, 4); // Pulisce l'LCD e pone il cursore all'inizio lcd.clear(); lcd.print("DIGITA LA PASSWORD:"); PulisciRigaPassword(); } void loop() { char key = keypad.getKey(); if (key != NO_KEY) { Pulisci3e4Riga(); if (key=='#') // Tasto di reset PulisciRigaPassword(); else if (key=='*') // Tasto di invio { if (passwd.length()!=0) { lcd.setCursor(0, 2); // 1° colonna - 3° riga if (passwd=="123456") lcd.print("|| BENVENUTO ||"); else lcd.print("** ACCESSO NEGATO **"); PulisciRigaPassword(); } else MessaggioErrore("Nessun carattere!"); } else { if (passwd.length()<10) { lcd.setCursor(pos++, 1); lcd.print("*"); // Maschero il numero digitato passwd=passwd+String(key); } else { MessaggioErrore("Troppi caratteri!"); PulisciRigaPassword(); } } } }