Archivi tag: display

Realizziamo un orologio con l’RTC di Arduino UNO R4 WiFi

Arduino UNO R4 WiFi possiede un RTC interno facilmente programmabile che ci consentirà di mantenere costantemente traccia dell’ora e della data corrente.

Per chi ha iniziato da poco le sperimentazioni elettroniche ricordo che un Real-Time Clock (RTC), o Orologio in Tempo Reale, è un tipo di orologio costituito da un circuito elettronico utilizzato per tracciare il tempo in tempo reale. Questo significa che tiene traccia del giorno della settimana, della data e dell’ora corrente, dei minuti, dei secondi, proprio come un orologio normale, inoltre è possibile impostare un RTC per gestire l’ora legale e l’ora solare.

Nelle versione precedente di Arduino, UNO R3 non era presente un RTC pertanto bisognava utilizzare un apposito circuito elettronico esterno così come dettagliato nel post su questo sito: Utilizzare un orologio RTC con Arduino – Modulo Tiny RTC I2C, modulo RTC dotato di un integrato DS1307 cuore fondamentale della scheda.

L’utilizzo dell’RTC su Arduino UNO R4 WiFi avviene utilizzando la libreria RTC che consente di impostare oppure ottenere l’orario o ancora gestire allarmi per attivare interrupt.

Come accennato ad inizio post l’RTC integrato dispone di un pin VRTC, che viene utilizzato per mantenere in funzione l’RTC, anche quando l’alimentazione della scheda viene interrotta. Per utilizzare questa funzione è sufficiente fornire una tensione compresa tra 1,6 e 3,6 V al pin VRTC. In un post successivo mostrerò come utilizzare il pin VRTC.

Facendo riferimento agli esempi disponibili sul sito Arduino e nell’IDE analizziamo le fasi di configurazione dell’RTC.

Impostazione della data e dell’ora

1RTCTime startTime(01, Month::AUGUST, 2023, 20, 49, 00, DayOfWeek::TUESDAY, SaveLight::SAVING_TIME_ACTIVE)
2 
3RTC.setTime(startTime)

Per impostare l’orario bisogna creare un oggetto RTCTime, in cui deve essere specificato il giorno, il mese, l’anno, l’ora, il minuto, il secondo, il giorno della settimana e l’attivazione dell’ora legale se prevista nella nazione in cui si sta utilizzando la scheda, quindi per impostare l’orario bisogna usare il metodo startTime.

Per chi incomincia con la programmazione il concetto di metodo appartiene alla programmazione ad orientata agli oggetti come ad esempio in C++, quando si programma in C è meglio parlare di funzione, ma spesso i due concetti vengono usati in modo alternativo.

Il primo sketch non fa altro che impostare l’ora corrente:

1// inclusione della libreria RTC
2#include "RTC.h"
3 
4void setup() {
5 
6  // impostazione della velocità della serial monitor
7  Serial.begin(9600);
8 
9  // avvio dell'RTC
10  RTC.begin();
11 
12  // creazione dell'oggetto RTCTime (possiamo assegnare un nome a piacimento)
13  // data del giorno, mese, anno, ore, minuti, secondi, giorno della settimana, attivazione passaggio all'ora legale
14  RTCTime startTime(2, Month::AUGUST, 2023, 9, 15, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
15 
16  // impostazione dell'RTC con la data e lora configurate per RTCTime
17  RTC.setTime(startTime);
18}
19 
20// il loop non contiene nulla
21void loop() {
22}

Continua a leggere

Lezione 4 – Arduino GamePad – Disegnare caratteri speciali su LCD1602 Keypad Shield della Keyestudio

In riferimento a quanto esposto a lezione questa mattina durante la lezione a distanza, aggiungo alcune indicazioni per disegnare icone personalizzate sul display: pacman, alieno, fantasmi, ecc… La modalità di realizzazione icone è la medesima di quella spiegata nella lezione svolta alcuni mesi fa: Disegnare caratteri personalizzati con Arduino per un LCD 16×2 in cui veniva utilizzato un display I2C.

Le modifiche per l’utilizzo dell’LCD1602 Keypad Shield della Keyestudio sono minime e di seguito indico alcuni esempi.

E’ importante, per inserire nuove icone sul display, studiare la lezione precedente in cui descrivo come realizzare le icone.

Di seguito tre esempi utili per sviluppare il vostro progetto di PCTO.

Esempio 1

In questo esempio mostro come visualizzare sulla prima riga del display una stringa di presentazione e sulla seconda riga 8 icone

1/*
2 *  Prof. Michele Maffucci
3 *  Crezione di caratteri personali
4 *  Utilizzo di un display LCD1602 Keypad Shield della Keyestudio
5 *  Data: 19.03.2021
6*/
7 
8// inclusione della libreria LiquidCrystal.h
9#include <LiquidCrystal.h>
10 
11// inizializza la libreria con i numeri dei pin dell'interfaccia
12LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
13 
14// caratteri personalizzati
15 
16byte lucchettoChiuso[8] = {
17  0b01110,
18  0b10001,
19  0b10001,
20  0b10001,
21  0b11111,
22  0b11011,
23  0b11011,
24  0b11111
25};
26 
27byte lucchettoAperto[8] = {
28  0b01110,
29  0b10000,
30  0b10000,
31  0b10000,
32  0b11111,
33  0b11011,
34  0b11011,
35  0b11111
36};
37 
38byte Altoparlante[8] = {
39  0b00001,
40  0b00011,
41  0b01111,
42  0b01111,
43  0b01111,
44  0b00011,
45  0b00001,
46  0b00000
47};
48 
49byte batteriaMezza[8] = {
50  0b01110,
51  0b11011,
52  0b10001,
53  0b10001,
54  0b10001,
55  0b11111,
56  0b11111,
57  0b11111
58};
59 
60byte alieno[8] = {
61  0b10001,
62  0b01010,
63  0b11111,
64  0b10101,
65  0b11111,
66  0b11111,
67  0b01010,
68  0b11011
69};
70 
71 
72byte pacmanBoccaChiusa[8] = {
73  0b01110,
74  0b11101,
75  0b11111,
76  0b11111,
77  0b11000,
78  0b11111,
79  0b11111,
80  0b01110
81};
82 
83byte pacmanBoccaAperta[8] = {
84  0b01110,
85  0b11101,
86  0b11111,
87  0b11100,
88  0b11000,
89  0b11000,
90  0b11111,
91  0b01110
92};
93 
94byte fantasmino[8] = {
95  0b01110,
96  0b11111,
97  0b10101,
98  0b11111,
99  0b11111,
100  0b11111,
101  0b11111,
102  0b10101
103};
104 
105void setup()
106{
107 // impostazione del numero di colonne e righe del display
108  lcd.begin(16, 2);
109 
110  // creazione nuovi caratteri
111  lcd.createChar(0, lucchettoChiuso);
112  lcd.createChar(1, lucchettoAperto);
113  lcd.createChar(2, Altoparlante);
114  lcd.createChar(3, batteriaMezza);
115  lcd.createChar(4, alieno);
116  lcd.createChar(5, pacmanBoccaChiusa);
117  lcd.createChar(6, pacmanBoccaAperta);
118  lcd.createChar(7, fantasmino);
119   
120  // Cancella il display
121  lcd.clear();
122 
123  // Stampa la stringa
124  lcd.print("PCTO a.s. 20/21");
125 
126}
127 
128void loop()
129{
130  lcd.setCursor(0, 1);
131  lcd.write(byte(0));
132 
133  lcd.setCursor(2, 1);
134  lcd.write(byte(1));
135 
136  lcd.setCursor(4, 1);
137  lcd.write(byte(2));
138 
139  lcd.setCursor(6, 1);
140  lcd.write(byte(3));
141 
142  lcd.setCursor(8, 1);
143  lcd.write(byte(4));
144 
145  lcd.setCursor(10, 1);
146  lcd.write(byte(5));
147 
148  lcd.setCursor(12, 1);
149  lcd.write(byte(6));
150 
151  lcd.setCursor(14, 1);
152  lcd.write(byte(7));
153}

Esempio 2

In questo secondo esempio mostriamo come visualizzare l’icona del Pacman che va avanti e indietro sulla prima riga del display

1/*
2 *  Prof. Michele Maffucci
3 *  Crezione di caratteri personali
4 *  Utilizzo di un display LCD1602 Keypad Shield della Keyestudio
5 *  Data: 19.03.2021
6 
7 *  Movimento verso destra e sinistra di una icona (alieno)
8*/
9 
10// inclusione della libreria LiquidCrystal.h
11#include <LiquidCrystal.h>
12 
13// inizializza la libreria con i numeri dei pin dell'interfaccia
14LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
15 
16// Velocità con cui viene stampato il l'icona 
17int velocita = 300;
18 
19// caratteri personalizzati
20 
21byte alieno[8] = {
22  0b10001,
23  0b01010,
24  0b11111,
25  0b10101,
26  0b11111,
27  0b11111,
28  0b01010,
29  0b11011
30};
31 
32void setup()
33{
34 // impostazione del numero di colonne e righe del display
35  lcd.begin(16, 2);
36 
37  // creazione nuovi caratteri
38  lcd.createChar(4, alieno);
39 
40  // visualizzazione sul display del nome
41  // dell'attività
42   
43  // Cancella il display
44  lcd.clear();
45 
46  // Stampa la stringa
47  lcd.print("PCTO a.s. 20/21");
48  delay(1000);
49 
50  // Cancella il display
51  lcd.clear();
52}
53 
54void loop()
55{
56   // Movimento verso destra del carattere
57  for (int contatorePosizioneColonna = 0; contatorePosizioneColonna < 16; contatorePosizioneColonna++) {
58    // Cancella il display
59    lcd.clear();
60    // Spostamento di una posizione verso destra del cursore
61    lcd.setCursor(contatorePosizioneColonna, 0);
62    // Stampa del icona: alieno
63    lcd.write(byte(4));
64    // Attesa di un'istante per percepire il movimento del carattere
65    delay(velocita);
66  }
67 
68  // Movimento verso sinistra del carattere
69  for (int contatorePosizioneColonna = 16; contatorePosizioneColonna > 0; contatorePosizioneColonna--) {
70    // Cancella il display
71    lcd.clear();
72    // Spostamento di una posizione verso sinistra del cursore
73    lcd.setCursor(contatorePosizioneColonna, 0);
74    // Stampa del icona: alieno
75    lcd.write(byte(4));
76    // Attesa di un'istante per percepire il movimento del carattere
77    delay(velocita);
78  }
79}

Esempio 3

Realizzare le medesime funzionalità dell’esercizio precedente in cui l’icona del Pacman nell’avanzamento apre e chiude la bocca.
In questo esempio il Pacman quando torna indietro non si gira.

1/*
2    Prof. Michele Maffucci
3    Crezione di caratteri personali
4    Utilizzo di un display LCD1602 Keypad Shield della Keyestudio
5    Data: 19.03.2021
6 
7    Movimento verso destra e sinistra di una icona (Pacman)
8    Durante il movimento il Pacman apre e chiude la bocca
9*/
10 
11// inclusione della libreria LiquidCrystal.h
12#include <LiquidCrystal.h>
13 
14// inizializza la libreria con i numeri dei pin dell'interfaccia
15LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
16 
17// Velocità con cui viene stampato il l'icona
18int velocita = 300;
19 
20// caratteri personalizzati
21 
22byte pacmanBoccaChiusa[8] = {
23  0b01110,
24  0b11101,
25  0b11111,
26  0b11111,
27  0b11000,
28  0b11111,
29  0b11111,
30  0b01110
31};
32 
33byte pacmanBoccaAperta[8] = {
34  0b01110,
35  0b11101,
36  0b11111,
37  0b11100,
38  0b11000,
39  0b11000,
40  0b11111,
41  0b01110
42};
43 
44void setup()
45{
46  // impostazione del numero di colonne e righe del display
47  lcd.begin(16, 2);
48 
49  // creazione nuovi caratteri
50  lcd.createChar(0, pacmanBoccaChiusa);
51  lcd.createChar(1, pacmanBoccaAperta);
52 
53  // Cancella il display
54  lcd.clear();
55 
56  // Stampa la stringa
57  lcd.print("PCTO a.s. 20/21");
58}
59 
60void loop()
61{
62 
63  // Movimento verso destra del carattere
64  for (int contatorePosizioneColonna = 0; contatorePosizioneColonna < 16; contatorePosizioneColonna++) {
65    // Cancella il display
66    lcd.clear();
67    // Spostamento di una posizione verso destra del cursore
68    lcd.setCursor(contatorePosizioneColonna, 0);
69    if (contatorePosizioneColonna % 2 == 0) {
70      // Stampa del icona: Pacman bocca chiusa
71      lcd.write(byte(0));
72    }
73    else
74    {
75      // Stampa del icona: Pacman bocca aperta
76      lcd.write(byte(1));
77    }
78    // Attesa di un'istante per percepire il movimento del carattere
79    delay(velocita);
80  }
81 
82  // Movimento verso sinistra del carattere
83  for (int contatorePosizioneColonna = 16; contatorePosizioneColonna > 0; contatorePosizioneColonna--) {
84    // Cancella il display
85    lcd.clear();
86    // Spostamento di una posizione verso sinistra del cursore
87    lcd.setCursor(contatorePosizioneColonna, 0);
88    if (contatorePosizioneColonna % 2 == 0) {
89      // Stampa del icona: Pacman bocca chiusa
90      lcd.write(byte(0));
91    }
92    else
93    {
94      // Stampa del icona: Pacman bocca aperta
95      lcd.write(byte(1));
96    }
97    // Attesa di un'istante per percepire il movimento del carattere
98    delay(velocita);
99  }
100}

Esercizio 1

Eseguire le stesse funzionalità dell’esempio 3 in cui però il Pacman rivolga il viso nella stessa direzione del movimento.

Esercizio 2

Movimentare il Pacman con i pulsanti RIGHT e LEFT, rivolgendo sempre il viso nella giusta posizione di movimento.

Buon Coding a tutti 🙂

Lezione 3 – Arduino GamePad – LCD1602 Keypad Shield della Keyestudio

Terza lezione in cui aggiungo alcuni esempi che suggeriscono alcune azioni di gioco che gli allievi del gruppo di lavoro dell’attività di PCTO: Arduino GamePad potranno sfruttare per la realizzazione del loro.

Esempio 1

Controllo dello spostamento del carattere:

  • destra/sinistra mediante i pulsanti: RIGHT e LEFT sul display
  • su/giù mediante i pulsanti UP/DOWN

Per realizzare queste azioni riprendiamo quanto realizzato nella lezione precedente aggiungendo all’ultimo sketch il controllo della pressione del pulsante UP o DOWN in cui viene controllato se l’analogRead sul A0 restituisce un valore comprese tra:

Controllo UP
(val >= 50 && val <= 150)

Controllo DOWN
(val >= 150 && val <= 300)

Lo spostamento del carattere dalla prima alla seconda riga deve essere fatta cancellando prima l’intero schermo, poi posizionando il carattere con il metodo setCursor() a cui si passa la variabile globale “contatorePosizioneColonna” che viene modificata di volta in volta alla pressione dei pulsanti RIGHT e LEFT. La selezione della riga avviene passando il valore 0 che identifica la prima riga e il valore 1 per la seconda riga.

1/*
2   Prof. Michele Maffucci
3   Utilizzo dell'LCD Keypad Shield della Keystudio
4   Data: 14.03.2021
5 
6   Controllo dello spostamento del carattere:
7   - destra/sinistra mediante i pulsanti: RIGHT e LEFT sul display
8   - su/giù mediante i pulsanti UP/DOWN
9*/
10 
11// inclusione della libreria LiquidCrystal.h
12#include <LiquidCrystal.h>
13 
14// inizializza la libreria con i numeri dei pin dell'interfaccia
15LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
16 
17// Colonna in cui si trova il carattere
18int contatorePosizioneColonna = 0;
19 
20// Valore restituito dall'analogRead su A0
21int val;
22 
23// Velocità con cui viene stampato il carattere 
24int velocita = 200;
25 
26void setup() {
27  // impostazione del numero di colonne e righe del display
28  lcd.begin(16, 2);
29 
30  // Carattere stampato nella prima colonna e prima riga (0,0)
31  lcd.print("*");
32}
33 
34void loop() {
35 
36  // Memorizza in val il valore presente su A
37  int val = analogRead(A0);
38 
39  // Alla pressione del pulsante UP sul display il carattere si sposta sulla prima riga
40   if (val >= 50 && val <= 150) {
41    // Cancella il display
42    lcd.clear();
43    // Spostamento sulla prima riga nella colonna corrente
44    lcd.setCursor(contatorePosizioneColonna, 0);
45    // Stampa del carattere: *
46    lcd.print("*");
47    // Attesa di un'istante per percepire il movimento del carattere
48    delay(velocita);
49  }
50 
51  // Alla pressione del pulsante DOWN sul display il carattere si sposta sulla seconda riga
52  if (val >= 150 && val <= 300) {
53    // Cancella il display
54    lcd.clear();
55    // Spostamento sulla seconda riga nella colonna corrente
56    lcd.setCursor(contatorePosizioneColonna, 1);
57    // Stampa del carattere: *
58    lcd.print("*");
59    // Attesa di un'istante per percepire il movimento del carattere
60    delay(velocita);
61  }
62 
63  // Premendo il pulsante RIGHT sul display, il carattere si sposta di una posizione
64  // a destra fino a quando non si raggiunge l'ultima colonna a destra.
65  // Premendo ancora il pulsante RIGHT non si ha l'avanzamento del carattere.
66  if ((val >= 0 && val <= 50) && contatorePosizioneColonna < 15) {
67    lcd.scrollDisplayRight();
68    delay(velocita);
69    contatorePosizioneColonna++;
70  }
71 
72  // Premendo il pulsante LEFT sul display, il carattere si sposta di una posizione
73  // a sinistra fino a quando non si raggiunge l'ultima colonna a sinistra.
74  // Premendo ancora il pulsante LEFT non si ha l'avanzamento del carattere.
75  if ((val >= 300 && val <= 500) && contatorePosizioneColonna > 0) {
76    lcd.scrollDisplayLeft();
77    delay(velocita);
78    contatorePosizioneColonna--;
79  }
80}

Esempio 2

In questo secondo esempio viene aggiunta una semplice matrice di cinque “X” che identificano degli ostacoli che devono essere superati. Nell’esempio esposto però gli ostacoli possono essere superati, lascio quindi a voi la realizzazione dello sketch che consente il blocco dell’avanzamento nel caso in cui ci si scontra con l’ostacolo.

1/*
2   Prof. Michele Maffucci
3   Utilizzo dell'LCD Keypad Shield della Keystudio
4   Data: 14.03.2021
5 
6   Controllo dello spostamento del carattere *:
7   - destra/sinistra mediante i pulsanti: RIGHT e LEFT sul display
8   - su/giù mediante i pulsanti UP/DOWN
9 
10   Stampa di una serie di X che rappresentano gli ostacoli
11    
12*/
13 
14// inclusione della libreria LiquidCrystal.h
15#include <LiquidCrystal.h>
16 
17// inizializza la libreria con i numeri dei pin dell'interfaccia
18LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
19 
20// Colonna in cui si trova il carattere
21int contatorePosizioneColonna = 0;
22 
23// Valore restituito dall'analogRead su A0
24int val;
25 
26// Velocità con cui viene stampato il carattere
27int velocita = 200;
28 
29// Riga in cui si trova il carattere *
30int riga = 0;
31 
32void setup() {
33  // impostazione del numero di colonne e righe del display
34  lcd.begin(16, 2);
35 
36  // Carattere stampato nella prima colonna e prima riga (0,0)
37  lcd.print("*");
38}
39 
40void loop() {
41 
42  // Memorizza in val il valore presente su A
43  int val = analogRead(A0);
44 
45  stampaOstacoli();
46 
47  // Alla pressione del pulsante UP sul display il carattere si sposta sulla prima riga
48  if (val >= 50 && val <= 150) {
49    // Cancella il display
50    lcd.clear();
51    stampaOstacoli();
52    // Spostamento sulla prima riga nella colonna corrente
53    lcd.setCursor(contatorePosizioneColonna, 0);
54    riga = 0;
55    // Stampa del carattere: *
56    lcd.print("*");
57    // Attesa di un'istante per percepire il movimento del carattere
58    delay(velocita);
59  }
60 
61  // Alla pressione del pulsante DOWN sul display il carattere si sposta sulla seconda riga
62  if (val >= 150 && val <= 300) {
63    // Cancella il display
64    lcd.clear();
65    stampaOstacoli();
66    // Spostamento sulla seconda riga nella colonna corrente
67    lcd.setCursor(contatorePosizioneColonna, 1);
68    riga = 1;
69    // Stampa del carattere: *
70    lcd.print("*");
71    // Attesa di un'istante per percepire il movimento del carattere
72    delay(velocita);
73  }
74 
75  // Premendo il pulsante RIGHT sul display, il carattere si sposta di una posizione
76  // a destra fino a quando non si raggiunge l'ultima colonna a destra.
77  // Premendo ancora il pulsante RIGHT non si ha l'avanzamento del carattere.
78  if ((val >= 0 && val <= 50) && contatorePosizioneColonna < 15) {
79    // Cancella il display
80    lcd.clear();
81    contatorePosizioneColonna++;
82    // Spostamento di una posizione verso destra del cursore
83    lcd.setCursor(contatorePosizioneColonna, riga);
84    // Stampa del carattere: *
85    lcd.print("*");
86    // Attesa di un'istante per percepire il movimento del carattere
87    delay(velocita);
88  }
89 
90  // Premendo il pulsante LEFT sul display, il carattere si sposta di una posizione
91  // a sinistra fino a quando non si raggiunge l'ultima colonna a sinistra.
92  // Premendo ancora il pulsante LEFT non si ha l'avanzamento del carattere.
93  if ((val >= 300 && val <= 500) && contatorePosizioneColonna > 0) {
94    // Cancella il display
95    lcd.clear();
96    contatorePosizioneColonna--;
97    lcd.setCursor(contatorePosizioneColonna, riga);
98    // Stampa del carattere: *
99    lcd.print("*");
100    // Attesa di un'istante per percepire il movimento del carattere
101    delay(velocita);
102  }
103}
104 
105void stampaOstacoli() {
106  lcd.setCursor(2, 0);
107  lcd.print("X");
108  lcd.setCursor(5, 1);
109  lcd.print("X");
110  lcd.setCursor(7, 1);
111  lcd.print("X");
112  lcd.setCursor(9, 0);
113  lcd.print("X");
114  lcd.setCursor(12, 0);
115  lcd.print("X");
116}

Esercizio 1

Utilizzando l’esempio 2 esposto sopra, aggiungere la funzionalità che blocca l’avanzamento del carattere “*” nel caso in cui ci si scontra con l’ostacolo.

Esercizio 2

Definire tre matrici di ostacoli diversi e fare in modo che ad ogni avvio di Arduino la scelta della matrice venga fatta in modo casuale.

Esercizio 3

Aggiungere la funzionalità che permette di modificare la matrice degli ostacoli se si raggiunge l’ultima colonna a destra.

Esercizio 4

Definire tre scenari diversi costituiti da tre matrici ostacoli diversi. La navigazione può avvenire solamente all’interno di questi tre scenari. La partenza del carattere “*” avviene dalla colonna 0 del secondo scenario, il movimento dovrà essere il seguente:

  • partendo dalla colonna 0 del secondo scenario, la pressione del pulsante LEFT porta allo scenario 1 e il carattere “*” viene posizionato nella colonna 15 del display;
  • se si è nel secondo scenario in colonna 15, la pressione del pulsante RIGHT conduce alla colonna 0 del  3′ scenario;
  • la pressione del pulsante LEFT in colonna 0 del primo scenario non permette nessun cambiamento di scenario
  • la pressione del pulsante RIGHT in colonna 15 del terzo scenario non permette nessun cambiamento di scenario

Buon Coding a tutti 🙂

Gestire con micro:bit un display 1602 I2C

Ho realizzato questo tutorial come risposta ad un quesito che mi è stato posto da un’amica collega sull’utilizzo del display 1602 I2C comandato da micro:bit.
Per quanto riguarda la descrizione tecnica del display vi rimando al post su questo sito:

Utilizzo dell’LCD 16×2 Hitachi HD44780 1602 con modulo I2C PCF8574T

Per un utilizzo con micro:bit è sufficiente conoscere il tipo esatto di integrato I2C che gestisce la comunicazione tra display e micro:bit nella modalità indicata da questo tutorial.

Aprite un nuovo progetto dall’ambiente grafico di programmazione di micro:bit.
Aggiungiamo l’estensione che consente la gestione di un display 16×2 I2C, per far ciò selezionate “+Extensions”:

nel campo di ricerca inserite: I2C

dovreste ottenere il seguente risultato:

Selezionate l’estensione indicata nell’immagine:

All’interno dei blocchi disponibili ritroverete quelli che fanno riferimento al display:

Ogni dispositivo I2C dispone di un indirizzo, un codice a cui bisogna far riferimento in fase di programmazione e per quanto riguarda la scheda di comunicazione I2C disposta sul retro del display troverete due tipi di dispositivi con indirizzo differenti l’uno dall’altro. La differenza consiste nel tipo di circuito integrato che gestisce la comunicazione I2C:

  • PCF8574 > indirizzo 39
  • PCF8574A > indirizzo 63

L’indirizzo dovrà essere inserito all’interno di un apposito blocco come indicato di seguito.

Per sapere quale indirizzo usare potete leggere la sigla dell’integrato, come indicato nell’immagine che segue:

nel mio caso l’indirizzo da inserire sarà il 39.

L’altro metodo consiste nel sostituire, nel codice che segue, gli indirizzi sopra indicati in modo da individuare il numero corretto che permette la visualizzazione del testo sul  display.

Per il collegamento del circuito avete necessità di alimentare il display a 5V, in commercio esistono degli edge connector (connettore per collegare micro:bit alla breadboard) che prelevano dalla USB i 5 volt, nel mio caso questa funzionalità non è fornita, l’unica tensione disponibile è di 3,3V non sufficienti per alimentare il display.

Se anche voi siete nelle medesime condizioni allora alimenterete via USB il micro:bit mentre il display dovrà essere alimentato esternamente mediante una tensione di 5V. Se agite in questo modo ricordate che la terra (GND) dovrà essere la medesima (collegate insieme) per entrambi i dispositivi. Fate riferimento allo schema di seguito indicato:

Sul micro:bit il pin 20 corrisponde all’SDA e il pin 19 all’SCL, pin che avranno una corrispondenza con il display. Per le mie sperimentazioni dispongo di un cavo USB modificato per poter inserire su breadboard la tensione di 5V proveniente dalla USB del computer.

Realizzeremo un semplice programma che consente di visualizzare su due righe il testo:

BBC micro:bit
Italy timer

dove timer è il numero di secondi trascorsi dall’avvio del programma.

L’inserimento della prima istruzione provocherà la visualizzazione del display I2C:

L’istruzione “LCD initialize with Address 39” assegna al display l’indirizzo 39

L’istruzione “show string” mostrerà sul display il testo incluso nel primo campo: “BBC micro:bit” che verrà scritto a partire dalla colonna 0 e riga 0 (in prima riga).

La seconda “show string” mostrerà sul display il testo “Italy” alla colonna 0 e riga 1 (in seconda riga):

Definiamo una nuova variabile che andremo successivamente ad incrementare:

assegnamo alla variabile il nome: contatore

All’interno della funzione “forever” inserire l’istruzione “change” per incrementare di una unità la variabile “contatore”.

Con l’istruzione “show number” visualizziamo sul display un numero, inserendo nel primo campo la variabile “contatore” il numero visualizzato sarà quello memorizzato nella variabile contatore:

La visualizzazione del numero contenuto in “contatore” avverrà in colonna 6 riga 1:

Aggiungendo una pausa di 1 secondo l’incremento del numero che appare sul display sarà di 1 secondo:

Questo il risultato:

Buon Coding a tutti 🙂

Utilizzare un orologio RTC con Arduino – Modulo Tiny RTC I2C – Visualizzazione su display I2C

Continuo la serie di post dedicati all’uso dell’RTC con integrato DS1307, in questa lezione viene suggerito come visualizzare su un display 16×2 Hitachi HD44780 1602 con modulo I2C PCF8574T: giorno della settimana, data e ora.
L’obiettivo che si vorrà raggiungere nei prossimi tutorial sarà quello di realizzare un timer programmabile da utilizzare in diverse esercitazioni di automazione.

Lo Schema di collegamento è il seguente:

Allego lo Sketch generale in cui ho inserito commenti di spiegazione sulle varie parti del codice e sull’utilizzo di specifiche funzioni.

Per quanto riguarda la libreria LiquidCrystal_I2C vi rimando alla lezione:
Utilizzo dell’LCD 16×2 Hitachi HD44780 1602 con modulo I2C PCF8574T

/* Prof. Maffucci Michele
   15.01.2020
   Orologio - v01
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// La data e l'ora funzionano usando un RTC DS1307 collegato tramite I2C e Wire lib
#include "RTClib.h"

RTC_DS1307 rtc;

char stringa1[8]; // per memorizzare la stringa che include la data (dimensione massima data: 8 caratteri)
char stringa2[6]; // per memorizzare la stringa che include l'ora (dimensione massima ora: 6 caratteri)

// Variabile per la verifica della cancellazione del display
int chiaveCancella = 0;

// Array multidimensionale costituito
// da 7 righe (giorni della settimana)
// 4 colonne (le lettere che compongono il giorno più il carattere null con cui deve terminare una stringa)

char giornoDellaSettimana[7][4] = {"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"};

// Inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin dell'LCD,
// impostazione dell'indirizzo dell'LCD 0x27 di 16 colonne e 2 linee

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup () {

  lcd.begin();      // inizializzazione dell'LCD
  lcd.backlight();  // attivazione della retroilluminazione

  if (!rtc.isrunning()) {
    lcd.setCursor(0, 0);
    lcd.print("RTC non funzionante!");
    // la riga che segue permette di impostare data e ora prendendo l'informazione
    // dal computer a cui è collegato Arduino
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // la riga che segue permette di impostare
    // esplicitamente da parte dell'utente data e ora
    // Gennaio 21, 2014 alle 3 del pomeriggio ybisognrà scrivere:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop () {

/* Controllo del funzionamento dell'RTC all'interno del loop

   Il controllo della disconnessione dell'RTC viene effettuato anche all'interno del loop,
   se ciò non venisse effettuato, una disconnessione dell'RTC non permetterebbe la visualizzazione
   del messaggio "RTC non risponde", ma verrebbero visualizzati valori numerici errati.
   La successiva connessione dell'RTC farà riapparire data e ora, ma in una modalità non allineata,
   in cui saranno mostrati i valori numerici derivanti dalla precedente disconessione.
*/

  if (!rtc.isrunning()) {
    lcd.setCursor(0, 0);
    lcd.print("RTC non risponde");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    chiaveCancella = 1;
  }

  else
  {
    if (chiaveCancella == 1) {
      
      /* La cancellazione del display avviene solamente una sola volta, solo se si è verificata
         una precedente disconnessione dell'RTC. L'azione è necessaria perché in fase
         di riconnessione dell'RTC appaiono sul display numeri non coerenti.
         La cancellazione potrebbe essere effettuata  direttamente nel corpo della prima if,
         ma ciò causerebbe un flikering del testo.
      */
      
      lcd.clear();
      chiaveCancella = 0;
    }

    DateTime now = rtc.now();

    lcd.setCursor(0, 0);

    // estrae dall'array giornoDellaSettimana il nome del giorno
    lcd.print(giornoDellaSettimana[now.dayOfTheWeek()]);
    lcd.setCursor(5, 0);

    /*
      int sprintf(char *str, const char *format, ...);
      ha lo stesso funzionamento della printf, con la differenza che
      l'output non sarà visualizzato sullo schermo (standard output), ma
      immagazzinato nel vettore str

      %d è uno dei possibili specificatori di formato che può essere usato nella sprintf
      ha il compito di indicare alla funzione (la sprintf) il tipo della variabile che deve essere
      visualizzata, in questo caso con d indichiamo decimale.
      Con %02d si specifica la stampa di solo due numeri decimali.
    */

    sprintf(stringa1, "%2d/%02d/%d", now.day(), now.month(), now.year());
    lcd.print(stringa1);
    lcd.setCursor(0, 1);
    sprintf(stringa2, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.print(stringa2);
    delay(1000);
  }
}

Di seguito riprendo quanto già inserito nei commenti:

char giornoDellaSettimana[7][4] = {"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"};

Definisce un Array multidimensionale costituito da 7 righe, i giorni della settimana e 4 colonne, le lettere che compongono il giorno (3 lettere) più il carattere null con cui deve terminare una stringa.

...
 if (!rtc.isrunning()) {
    lcd.setCursor(0, 0);
    lcd.print("RTC non risponde");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    chiaveCancella = 1;
  }
...

Il controllo della disconnessione dell’RTC viene effettuato anche all’interno del loop, se ciò non venisse eseguito, una disconnessione dell’RTC non permetterebbe la visualizzazione del messaggio “RTC non risponde”, ma verrebbero mostrati valori numerici errati. La successiva connessione dell’RTC farà riapparire data e ora, ma in una modalità non allineata, in cui saranno mostrati i valori numerici derivanti dalla precedente disconessione.

...
  else
  {
    if (chiaveCancella == 1) {
      
      /* La cancellazione del display avviene solamente una sola volta, solo se si è verificata
         una precedente disconnessione dell'RTC. L'azione è necessaria perché in fase
         di riconnessione dell'RTC appaiono sul display numeri non coerenti.
         La cancellazione potrebbe essere effettuata  direttamente nel corpo della prima if,
         ma ciò causerebbe un flikering del testo.
      */
      
      lcd.clear();
      chiaveCancella = 0;
    }
...

La cancellazione del display avviene una sola volta, solo se si è verificata una precedente disconnessione dell’RTC. L’azione è necessaria perché in fase di riconnessione dell’RTC appaiono sul display numeri non coerenti. La cancellazione potrebbe essere effettuata direttamente nel corpo della prima if, ma ciò causerebbe un flikering del testo così come appare nell’immagine che segue:

sprintf(stringa1, "%2d/%02d/%d", now.day(), now.month(), now.year());

int sprintf(char *str, const char *format, …); ha lo stesso funzionamento della printf, con la differenza che l’output non sarà visualizzato sullo schermo (standard output), ma immagazzinato nel vettore str.

%d è uno dei possibili specificatori di formato che può essere usato nella sprintf ha il compito di indicare alla funzione (la sprintf) il tipo della variabile che deve essere visualizzata, in questo caso con d indichiamo decimale. Con %02d si specifica la stampa di solo due numeri decimali.

Per i miei allievi:

Esercizio 1

Modificare lo sketch proposto in modo che la retroilluminazione dello schermo venga spenta dopo 15 secondi e la pressione di un pulsante la riattivi.

Esercizio 2

Modificare lo sketch realizzato al punto 2 inserendo anche un sensore DHT11 che mostra temperatura ed umidità dell’ambiente.