Continuo la lezione cominciata la scorsa settimana con i miei studenti di 5A Automazione dell’ITIS G.B. Pininfarina di Moncalieri in merito alla gestione degli input mediante pulsanti e segnalazione stato LED sulla Serial Monitor, questa volta utilizzeremo come sistema di output un Display 16×2 con modulo I2C.
Rispetto all’esercizio svolto nella precedente lezione questa volta utilizzeremo 3 pulsanti la cui pressione provocherà l’accensione rispettivamente di un LED Rosso un LED Verde ed un LED Giallo.
L’esercizio è suddiviso in due parti, la prima parte prevede che l’accensione dei LED avvenga premendo il pulsante ad esso associato, il rilascio provoca lo spegnimento del LED. Lo stato del LED dovrà essere segnalato con il testo ON oppure OFF e nel momento in cui lo stato risulta ON a fianco del testo ON dovrà comparire una sequenza di caratteri che simula la rotazione di un’elica, così come evidenziato dalle immagini che seguono.
Le lettere R, V, G indicano rispettivamente il colore: Rosso, Verde, Giallo dei LED la cui accensione è comandata da un pulsante NO.
La seconda parte dell’esercizio consiste nella realizzazione di uno sketch che permette il mantenimento dello stato ON oppure OFF anche al rilascio del pulsante, il cambiamento di stato avviene nella successiva pressione del pulsante.
Per i dettagli sull’uso del display 16×2 I2C vi rimando al tutorial su questo sito seguendo il link: Utilizzo dell’LCD 16×2 Hitachi HD44780 1602 con modulo I2C PCF8574T
Componenti utilizzati
- Arduino UNO R3
- N. 3 pulsanti NO
- N. 3 resistori da 10 KOhm
- N. 3 resistori da 220 Ohm
- N. 1 LED Rosso
- N. 1 LED Verde
- N. 1 LED Giallo
Di seguito lo schema di collegamento:
Il funzionamento degli sketch è spiegato mediante commenti all’interno del codice.
Parte 1
/* Prof. Michele Maffucci Accensione e spegnimento led con segnalazione su Display LCD I2C 30.09.19 Accensione e spegnimento di LED mediante pulsanti con antirimbalzo e messaggio ripetuto dello stato del LED sul Display Pulsante Rosso: accensione e spegnimento LED Rosso (prima pressione accende, seconda pressione spegne) Pulsante Verde: accensione e spegnimento LED Verde (prima pressione accende, seconda pressione spegne) Pulsante Giallo: accensione e spegnimento LED Giallo (prima pressione accende, seconda pressione spegne) */ #include <Wire.h> #include <LiquidCrystal_I2C.h> // ledRosso variabile di tipo intero a cui viene assegnato // il valore intero 2 che sarà associato al pin digitale 2 int ledRosso = 2; // ledVerde variabile di tipo intero a cui viene assegnato // il valore intero 3 che sarà associato al pin digitale 3 int ledVerde = 3; // ledGiallo variabile di tipo intero a cui viene assegnato // il valore intero 4 che sarà associato al pin digitale 4 int ledGiallo = 4; // pulsanteRosso variabile di tipo intero a cui viene assegnato // il valore intero 10 che sarà associato al pin digitale 10 // a cui sarà collegato il pulsante che comanda il LED Rosso int pulsanteRosso = 10; // pulsanteVerde variabile di tipo intero a cui viene assegnato // il valore intero 11 che sarà associato al pin digitale 11 // a cui sarà collegato il pulsante che comanda il LED Verde int pulsanteVerde = 11; // pulsanteGiallo variabile di tipo intero a cui viene assegnato // il valore intero 12 che sarà associato al pin digitale 12 // a cui sarà collegato il pulsante che comanda il LED Giallo int pulsanteGiallo = 12; // inizializzazione della variabili in cui verrà memorizzato il valore della // digitalRead: 0 non premuto, 1 premuto int valRosso = 0; int valVerde = 0; int valGiallo = 0; // inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee //----------------------------- void setup() { lcd.begin(); // inizializzazione dell'LCD lcd.backlight(); // attivazione della retroilluminazione // imposta i pin digitali a cui sono collegati i LED ad OUTPUT pinMode(ledRosso, OUTPUT); pinMode(ledVerde, OUTPUT); pinMode(ledGiallo, OUTPUT); // imposta i pin digitali a cui sono collegati i pulsanti ad OUTPUT pinMode(pulsanteRosso, INPUT); pinMode(pulsanteVerde, INPUT); pinMode(pulsanteGiallo, INPUT); // messaggio di Avvio visualizzato una sola volta lcd.setCursor(0, 0); // posiziona curasore in colonna 0 e riga 0 lcd.print("Ciao"); // stampa del testo su display lcd.setCursor(0, 1); // posiziona curasore in colonna 0 e riga 1 lcd.print("Comando LED"); // stampa del testo su display delay(2000); // pausa di 2 secondi lcd.clear(); // cancella il contenuto del display } //----------------------------- void loop() { valRosso = digitalRead(pulsanteRosso); // lettura dell'input (pulsante) e memorizzazione in valRosso valVerde = digitalRead(pulsanteVerde); // lettura dell'input (pulsante) e memorizzazione in valVerde valGiallo = digitalRead(pulsanteGiallo); // lettura dell'input (pulsante) e memorizzazione in valGiallo // ---------- Controllo pulsante LED Rosso ---------- /* Se il pulsante viene premuto viene acceso il LED rosso * posizionato il cursore in colonna 0 riga 0 * stampato il testo: R: ON * avviata l'animazione */ if (valRosso == HIGH) { digitalWrite(ledRosso, HIGH); lcd.setCursor(0, 0); lcd.print("R: ON "); animazione(6,0); } /* Se il pulsante NON viene premuto viene spento il LED rosso * posizionato il cursore in colonna 0 riga 0 * stampato il testo: R: OFF * interrotta l'animazione */ else { digitalWrite(ledRosso, LOW); lcd.setCursor(0, 0); lcd.print("R: OFF "); } // ---------- Controllo pulsante LED Verde ---------- /* Se il pulsante viene premuto viene acceso il LED verde * posizionato il cursore in colonna 0 riga 1 * stampato il testo: V: ON * avviata l'animazione */ if (valVerde == HIGH) { digitalWrite(ledVerde, HIGH); lcd.setCursor(9, 0); lcd.print("V: ON "); animazione(15,0); } /* Se il pulsante NON viene premuto viene spento il LED verde * posizionato il cursore in colonna 0 riga 1 * stampato il testo: V: OFF * interrotta l'animazione */ else { digitalWrite(ledVerde, LOW); lcd.setCursor(9, 0); lcd.print("V: OFF "); } // ---------- Controllo pulsante LED Giallo ---------- /* Se il pulsante viene premuto viene acceso il LED giallo * posizionato il cursore in colonna 0 riga 1 * stampato il testo: G: ON * avviata l'animazione */ if (valGiallo == HIGH) { digitalWrite(ledGiallo, HIGH); lcd.setCursor(0, 1); lcd.print("G: ON "); animazione(6,1); } /* Se il pulsante NON viene premuto viene spento il LED giallo * posizionato il cursore in colonna 9 riga 0 * stampato il testo: G: OFF * interrotta l'animazione */ else { digitalWrite(ledGiallo, LOW); lcd.setCursor(0, 1); lcd.print("G: OFF "); } } // Funzione che stampa un cursore che ruota void animazione(int colonna, int riga) { lcd.setCursor(colonna, riga); lcd.print("/"); delay(150); lcd.setCursor(colonna, riga); lcd.print("-"); delay(150); lcd.setCursor(colonna, riga); lcd.print("|"); delay(150); lcd.setCursor(colonna, riga); lcd.print("/"); delay(150); lcd.setCursor(colonna, riga); lcd.print("-"); delay(150); lcd.setCursor(colonna, riga); lcd.print("|"); delay(150); }
Parte 2
/* Prof. Michele Maffucci Data: 30.09.19 Accensione e spegnimento di LED mediante pulsanti con antirimbalzo e messaggio NON ripetuto dello stato del LED sulla su Display LCD I2C Stampa 1 sola volta il messaggio dello stato del LED Sul Display I2C (non va in loop la stampa dello stato del LED) Pulsante Rosso: accensione e spegnimento LED Rosso (prima pressione accende, seconda pressione spegne) Pulsante Verde: accensione e spegnimento LED Verde (prima pressione accende, seconda pressione spegne) Pulsante Giallo: accensione e spegnimento LED Giallo (prima pressione accende, seconda pressione spegne) */ #include <Wire.h> #include <LiquidCrystal_I2C.h> // ledRosso variabile di tipo intero a cui viene assegnato // il valore intero 2 che sarà associato al pin digitale 2 int ledRosso = 2; // ledVerde variabile di tipo intero a cui viene assegnato // il valore intero 3 che sarà associato al pin digitale 3 int ledVerde = 3; // ledGiallo variabile di tipo intero a cui viene assegnato // il valore intero 4 che sarà associato al pin digitale 4 int ledGiallo = 4; // pulsanteRosso variabile di tipo intero a cui viene assegnato // il valore intero 10 che sarà associato al pin digitale 10 // a cui sarà collegato il pulsante che comanda il LED Rosso int pulsanteRosso = 10; // pulsanteVerde variabile di tipo intero a cui viene assegnato // il valore intero 11 che sarà associato al pin digitale 11 // a cui sarà collegato il pulsante che comanda il LED Verde int pulsanteVerde = 11; // pulsanteGiallo variabile di tipo intero a cui viene assegnato // il valore intero 12 che sarà associato al pin digitale 12 // a cui sarà collegato il pulsante che comanda il LED Giallo int pulsanteGiallo = 12; // inizializzazione della variabili in cui verrà memorizzato il valore della // digitalRead: 0 non premuto, 1 premuto int valRosso = 0; int valVerde = 0; int valGiallo = 0; // inizializzazione della variabili in cui verrà memorizzato lo stato del pulsante // All'avvio dello sketch i pulsanti non sono premuti int statoRosso = 0; int statoVerde = 0; int statoGiallo = 0; // inizializzazione della variabili in cui verrà memorizzato lo stato precedente del pulsante // All'avvio dello sketch i pulsanti non sono premuti int valRossoOld = 0; int valVerdeOld = 0; int valGialloOld = 0; // inizializzazione delle variabili che consentono la stampa dello stato del LED int stampoRossoON = 0; int stampoRossoOFF = 0; int stampoVerdeON = 0; int stampoVerdeOFF = 0; int stampoGialloON = 0; int stampoGialloOFF = 0; // inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin LiquidCrystal_I2C lcd(0x27, 16, 2); // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee //----------------------------- void setup() { lcd.begin(); // inizializzazione dell'LCD lcd.backlight(); // attivazione della retroilluminazione // imposta i pin digitali a cui sono collegati i LED ad OUTPUT pinMode(ledRosso, OUTPUT); pinMode(ledVerde, OUTPUT); pinMode(ledGiallo, OUTPUT); // imposta i pin digitali a cui sono collegati i pulsanti ad OUTPUT pinMode(pulsanteRosso, INPUT); pinMode(pulsanteVerde, INPUT); pinMode(pulsanteGiallo, INPUT); // messaggio di Avvio visualizzato una sola volta lcd.setCursor(0, 0); // posiziona curasore in colonna 0 e riga 0 lcd.print("Ciao"); // stampa del testo su display lcd.setCursor(0, 1); // posiziona curasore in colonna 0 e riga 1 lcd.print("Comando LED"); // stampa del testo su display delay(2000); // pausa di 2 secondi lcd.clear(); // cancella il contenuto del display } //----------------------------- void loop() { valRosso = digitalRead(pulsanteRosso); // lettura dell'input (pulsante) e memorizzazione in valRosso valVerde = digitalRead(pulsanteVerde); // lettura dell'input (pulsante) e memorizzazione in valVerde valGiallo = digitalRead(pulsanteGiallo); // lettura dell'input (pulsante) e memorizzazione in valGiallo // ---------- Controllo pulsante LED Rosso ---------- // viene controllato che l'input sia HIGH (pulsante premuto) e cambia lo stato del LED if ((valRosso == HIGH) && (valRossoOld == LOW)) { statoRosso = 1 - statoRosso; // antirimbalzo software - attesa di 15 ms per attendere che l'input si stabilizzi delay(15); // poichè il pulsante è stato premuto la variabile stampoRossoON viene posta a 0 // per consentire la stampa del messaggio "LED Rosso ON" stampoRossoON = 0; } // memorizzazione del valore precedente restituito dalla digitalRead valRossoOld = valRosso; // ---------- Controllo pulsante LED Verde ---------- // viene controllato che l'input sia HIGH (pulsante premuto) e cambia lo stato del LED if ((valVerde == HIGH) && (valVerdeOld == LOW)) { statoVerde = 1 - statoVerde; // antirimbalzo software - attesa di 15 ms per attendere che l'input si stabilizzi delay(15); // poichè il pulsante è stato premuto la variabile stampoVerdeON viene posta a 0 // per consentire la stampa del messaggio "LED Verde ON" stampoVerdeON = 0; } // memorizzazione del valore precedente restituito dalla digitalRead valVerdeOld = valVerde; // ---------- Controllo pulsante LED Giallo ---------- // viene controllato che l'input sia HIGH (pulsante premuto) e cambia lo stato del LED if ((valGiallo == HIGH) && (valGialloOld == LOW)) { statoGiallo = 1 - statoGiallo; // antirimbalzo software - attesa di 15 ms per attendere che l'input si stabilizzi delay(15); // poichè il pulsante è stato premuto la variabile stampoVerdeON viene posta a 0 // per consentire la stampa del messaggio "LED Verde ON" stampoGialloON = 0; } // memorizzazione del valore precedente restituito dalla digitalRead valGialloOld = valGiallo; // ---------- Stampa sul display lo stato del LED Rosso ---------- // Se il pulsante è stato premuto la condizione dell'if risulta vera ed il LED Rosso si accende if (statoRosso == 1) { digitalWrite(ledRosso, HIGH); // Se la variabile stampoRossoON è 0 allora !stampoRossoON vale 1 // ciò consente la stampa del messaggio "LED Rosso ON" if (!stampoRossoON) { lcd.setCursor(0, 0); lcd.print("R: ON "); // Viene posto a 0 stampoRossoOFF per consentire la stampa "LED Rosso OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Rosso. stampoRossoOFF = 0; } } // nel caso in cui il pulsante non sia premuto o nello stato precedente era stato premuto // allora il LED dovrà essere spento ed il messaggio sulla seriale dovrà essere "LED Rosso OFF" else { digitalWrite(ledRosso, LOW); if (!stampoRossoOFF) { lcd.setCursor(0, 0); lcd.print("R: OFF"); // Viene posto a 1 stampoRossoOFF per consentire la stampa "LED Rosso OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Rosso. stampoRossoOFF = 1; } } // ---------- Stampa sul disolay lo stato del LED Verde ---------- // Se il pulsante è stato premuto la condizione dell'if risulta vera ed il LED Verde si accende if (statoVerde == 1) { digitalWrite(ledVerde, HIGH); // Se la variabile stampoVerdeON è 0 allora !stampoVerdeoON vale 1 // ciò consente la stampa del messaggio "LED verde ON" if (!stampoVerdeON) { lcd.setCursor(7, 0); lcd.print("V: ON "); // Viene posto a 0 stampoVerdeOFF per consentire la stampa "LED Verde OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Rosso. stampoVerdeOFF = 0; } } // nel caso in cui il pulsante non sia premuto o nello stato precedente era stato premuto // allora il LED dovrà essere spento ed il messaggio sulla seriale dovrà essere "LED Verde OFF" else { digitalWrite(ledVerde, LOW); if (!stampoVerdeOFF) { lcd.setCursor(7, 0); lcd.print("V: OFF"); // Viene posto a 1 stampoVerdeOFF per consentire la stampa "LED Verde OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Verde. stampoVerdeOFF = 1; } } // ---------- Stampa sul disolay lo stato del LED Giallo ---------- // Se il pulsante è stato premuto la condizione dell'if risulta vera ed il LED Verde si accende if (statoGiallo == 1) { digitalWrite(ledGiallo, HIGH); // Se la variabile stampoGialloON è 0 allora !stampoGialloON vale 1 // ciò consente la stampa del messaggio "LED giallo ON" if (!stampoGialloON) { lcd.setCursor(0, 1); lcd.print("G: ON "); // Viene posto a 0 stampoGialloOFF per consentire la stampa "LED Giallo OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Giallo. stampoGialloOFF = 0; } } // nel caso in cui il pulsante non sia premuto o nello stato precedente era stato premuto // allora il LED dovrà essere spento ed il messaggio sulla seriale dovrà essere "LED Giallo OFF" else { digitalWrite(ledGiallo, LOW); if (!stampoGialloOFF) { lcd.setCursor(0, 1); lcd.print("G: OFF"); // Viene posto a 1 stampoGialloOFF per consentire la stampa "LED Giallo OFF" // nel caso si prema nuovamente il pulsante che controlla il LED Giallo. //stampoGialloON = 0; } } }
Esercizio: utilizzare gli esempi precedenti per realizzare un sistema che consente di avviare ed arrestare 2 ventole, ciascuna comandata da un pulsante. Un terzo pulsante dovrà essere utilizzato come consenso per permettere l’utilizzo del sistema, quindi:
- Pulsante Marcia/Arresto ventola 1
- Pulsante Marcia/Arresto ventola 2
- Pulsante accensione spegnimento sistema
Gli stati dovranno essere indicati mediante LED e con messaggio sul display.
Buon Lavoro 🙂
Bello,
solo un appunto: l’animazione è bloccante quindi bisogna aspettare che sia finita per premere qualsiasi pulsante
Ciao Roberto grazie per il commento. In realtà è voluto e mi serve per fare in classe tra oggi e domani considerazione sul ciclo di loop e chiamate di funzioni.