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}

Leggere data e ora

Per recuperare l’ora e la data corrente bisogna usare la funzione:

1RTC.getTime(currentTime)

è necessario creare un oggetto RTCTime, così come abbiamo fatto nello sketch precedente, usiamo il metodo getTime() per ottenere ora e data corrente:

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

Stampa della data e dell’ora

Gli esempi indicati sopra mostrano come impostare e ottenere l’orario e memorizzarlo in un oggetto. Questi dati possono essere recuperati attraverso diversi metodi:

1getDayOfMonth()   // giorno del mese
2getMonth()        // mese
3getYear()         // anno
4getHour()         // ora
5getMinutes()      // minuti
6getSeconds()      // secondi

L’esempio che segue stampa data ed ora utilizzando l’oggetto currentTime:

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, 12, 43, 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 
20void loop() {
21 
22    // Assegnamo alla variabile currentTime il tipo (oggetto) RTCTime
23  RTCTime currentTime;
24 
25  // Ottieni l'orario corrente dall'RTC
26  RTC.getTime(currentTime);
27 
28  // Stampa la data (DD/MM//YYYY)
29  Serial.print(currentTime.getDayOfMonth());
30  Serial.print("/");
31  Serial.print(Month2int(currentTime.getMonth()));
32  Serial.print("/");
33  Serial.print(currentTime.getYear());
34  Serial.print(" - ");
35 
36  // Stampa l'ora (HH/MM/SS)
37  Serial.print(currentTime.getHour());
38  Serial.print(":");
39  Serial.print(currentTime.getMinutes());
40  Serial.print(":");
41  Serial.println(currentTime.getSeconds());
42 
43  // attesa di 1 secondo
44  delay(1000);
45}

Tempo Unix

Nei sistemi operativi Unix e Unix-like, il tempo è indicato come un offset in secondi rispetto alla mezzanotte (UTC – Tempo coordinato universale o Tempo Cicile) del 1º gennaio 1970, un punto nel tempo noto come “epoca Unix”, questo numero viene chiamato anche timestamp.

Ad esempio, alle 03:46:40 CET del 9 settembre 2001, questo differenziale era esattamente un miliardo. Questo significa che in quel preciso momento erano passati un miliardo di secondi dall’inizio dell’epoca Unix. Per esprimere questo differenziale temporale, si utilizza il tipo di dato time_t.

Il timestamp nel momento in cui scrivo questa lezione, l’ora Unix, è:

Oggi è il 02/08/2023 e sono le 09:34:14
Timestamp: 1690961654

Se vuoi approfondire l’argomento segui il link.

Ma perché utilizzare un tempo Unix?

Come segnalato nel link sopra:

Questo tipo di rappresentazione, oltre che a essere compatta, è indipendente dai fusi orari, ed è quindi direttamente confrontabile anche tra calcolatori situati a grandi distanze geografiche tra loro, ed evita di dover effettuare aggiustamenti nel caso per esempio di dati trasmessi da un fuso orario all’altro. Lo svantaggio è che per averne una rappresentazione sotto forma di data e ora locali è necessario effettuare una conversione; il sistema operativo offre allo scopo delle funzioni che consentono di effettuarle in entrambe le direzioni.

Il codice per la stampa del timestamp Unix è:

1// inclusione della libreria RTC
2#include "RTC.h"
3 
4void setup() {
5    // impostazione della velocità della serial monitor
6  Serial.begin(9600);
7 
8  // avvio dell'RTC
9  RTC.begin();
10   
11  // creazione dell'oggetto RTCTime (possiamo assegnare un nome a piacimento)
12  // data del giorno, mese, anno, ore, minuti, secondi, giorno della settimana, attivazione passaggio all'ora legale
13  RTCTime startTime(2, Month::AUGUST, 2023, 12, 49, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
14   
15    // impostazione dell'RTC con la data e lora configurate per RTCTime
16  RTC.setTime(startTime);
17}
18 
19void loop() {
20    // Assegnamo alla variabile currentTime il tipo (oggetto) RTCTime
21  RTCTime currentTime;
22 
23  // Ottieni l'orario corrente dall'RTC
24  RTC.getTime(currentTime);
25   
26  //Ottiene il timestamp Unix
27  Serial.print("Timestamp Unix: ");
28  Serial.println(currentTime.getUnixTime());
29 
30  // attesa di 1 secondo
31  delay(1000);
32}

Ovviamente è possibile stampare con facilità entrambe le notazioni di tempo:

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, 12, 51, 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 
20void loop() {
21 
22  // Assegnamo alla variabile currentTime il tipo (oggetto) RTCTime
23  RTCTime currentTime;
24 
25  // Ottieni l'orario corrente dall'RTC
26  RTC.getTime(currentTime);
27 
28  // Stampa la data (DD/MM//YYYY)
29  Serial.print(currentTime.getDayOfMonth());
30  Serial.print("/");
31  Serial.print(Month2int(currentTime.getMonth()));
32  Serial.print("/");
33  Serial.print(currentTime.getYear());
34  Serial.print(" - ");
35 
36  // Stampa l'ora (HH/MM/SS)
37  Serial.print(currentTime.getHour());
38  Serial.print(":");
39  Serial.print(currentTime.getMinutes());
40  Serial.print(":");
41  Serial.println(currentTime.getSeconds());
42 
43  // Ottiene il timestamp Unix
44  Serial.print("Timestamp Unix: ");
45  Serial.println(currentTime.getUnixTime());
46 
47  // attesa di 1 secondo
48  delay(1000);
49}

Visualizziamo data ed ora su un display

L’applicazione più semplice che possiamo realizzare è quella che permette di realizzare un semplice orologio mostrando data ed ora su un display 1602 di tipo I2C. Per l’utilizzo di un display I2C fare riferimento alle guide che trovate su questo sito.

Ricordate di impostare l’indirizzo corretto per l’LCD che potrebbe differire da quello inserito nei miei esempi.
La modifica al codice precedente consiste nell’aggiungere la libreria di gestione del display, la sua configurazione e successivamente sostituire il metodo serial.print con il metodo lcd.print. Nello sketch nei commenti trovate tutti i dettagli.

1// Prof. Maffucci Michele
2// 02.08.23
3// Realizzazione di un orologio con Arduino UNO R4 WiFi
4 
5// inclusione della libreria RTC
6#include "RTC.h"
7#include <Wire.h>
8#include <LiquidCrystal_I2C.h>
9 
10// inizializzazione della libreria in cui è descritta la modalità di utilizzo dei pin
11LiquidCrystal_I2C lcd(0x27, 16, 2);  // impostazione dell'indirizzo dell'LCD 0x27 di 16 caratteri e 2 linee
12 
13// prevDay variabile per memorizzare la data del giorno precedente
14// utilizzata per verificare il passaggio al giorno successivo
15// e cancellare il display per non avere stampe di doppie cifre
16// non cancellate
17int prevDay = 0;
18 
19// prevHour variabile per memorizzare l'ora precedente
20// utilizzata per verificare il passaggio all'ora successivo
21// e cancellare il display per non avere stampe di doppie cifre
22// non cancellate
23int prevHour = 0;
24 
25void setup() {
26 
27  // impostazione della velocità della serial monitor
28  Serial.begin(9600);
29 
30  // inizializzazione dell'LCD
31  lcd.begin();
32 
33  // attivazione della retroilluminazione
34  lcd.backlight();
35 
36  // avvio dell'RTC
37  RTC.begin();
38 
39  // creazione dell'oggetto RTCTime (possiamo assegnare un nome a piacimento)
40  // data del giorno, mese, anno, ore, minuti, secondi, giorno della settimana, attivazione passaggio all'ora legale
41  RTCTime startTime(3, Month::AUGUST, 2023, 18, 59, 00, DayOfWeek::THURSDAY, SaveLight::SAVING_TIME_ACTIVE);
42 
43  // impostazione dell'RTC con la data e lora configurate per RTCTime
44  RTC.setTime(startTime);
45 
46  // Testo di Avvio
47  lcd.setCursor(0, 0);
48  lcd.print("Maffucci Michele");
49  lcd.setCursor(0, 1);
50  lcd.print("www.maffucci.it");
51  delay(2000);
52  lcd.clear();
53  lcd.setCursor(0, 0);
54  lcd.print("Orologio");
55  delay(2000);
56}
57 
58void loop() {
59 
60  // Assegnamo alla variabile currentTime il tipo (oggetto) RTCTime
61  RTCTime currentTime;
62 
63  // Ottieni l'orario corrente dall'RTC
64  RTC.getTime(currentTime);
65 
66  // Stampa la data (DD/MM//YYYY)
67 
68  // verifica se si è pasati al giorno successivo
69  // se ciò avviene si cancella il display per evitare
70  // la visualizzazione di doppie cifre non cancellate
71  if (currentTime.getDayOfMonth() != prevDay) {
72    lcd.clear();
73    prevDay = currentTime.getDayOfMonth();
74  } else {
75    lcd.setCursor(0, 0);
76    lcd.print("Data: ");
77    lcd.print(currentTime.getDayOfMonth());
78    lcd.print("/");
79    lcd.print(Month2int(currentTime.getMonth()));
80    lcd.print("/");
81    lcd.print(currentTime.getYear());
82 
83    // Stampa l'ora (HH/MM/SS)
84 
85    // verifica se si è pasati all'ora successiva
86    // se ciò avviene si cancella il display per evitare
87    // la visualizzazione di doppie cifre non cancellate
88    if (currentTime.getHour() != prevHour) {
89      lcd.clear();
90      prevHour = currentTime.getHour();
91    } else {
92      lcd.setCursor(0, 1);
93      lcd.print("Ora: ");
94      lcd.setCursor(6, 1);
95      lcd.print(currentTime.getHour());
96      lcd.print(":");
97      lcd.print(currentTime.getMinutes());
98      lcd.print(":");
99 
100      // Controllo per evitare la non cancellazione della cifra meno significativa
101      // al passaggio del minuto successivo
102      if (currentTime.getSeconds() == 0) {
103        lcd.print("0 ");
104        lcd.setCursor(12, 1);
105      } else {
106        lcd.print(currentTime.getSeconds());
107      }
108    }
109  }
110}

Per quanto riguarda l’interrupt periodico a cui si fa riferimento nella pagina di esempio del sito di Arduino, attualmente ci sono alcuni problemi di utilizzo e lo sketch presenta alcuni refusi, di cui si fa menzione anche nel forum di Arduino, confido che nel breve il problema venga risolto.

Nelle prossime lezioni proporrò ulteriori esempi di utilizzo dell’RTC di Arduino UNO R4, per ora no mi resta che augurarvi:

Buon Making 🙂

5 pensieri su “Realizziamo un orologio con l’RTC di Arduino UNO R4 WiFi

  1. Mirco Lasagni

    Buongiorno. Articoli sempre interessanti e ben spiegati (si vede che è un professore e sa come spiegare le cose in modo semplice e comprensibile, e comunque non tutti i professori ci riescono).
    Seguirò con interesse il seguito di questo articolo.
    Grazie e buona giornata

    Rispondi
  2. Domenico Bramanti

    Buongiorno Sig. Maffucci
    Da qualche giorno sto provando la precisione dell’ RTC di Arduino R4, ma ahime mi risulta poco preciso.
    Non faccio altro che visualizzare l’ora sul seriale (ho seguito il suo esempio), confrontandolo con un orologio si vede che gia’ dopo qualche minuto, ci sono delle imprecisioni, l’RTC di Arduino risulta di qualche secondo in avanti, e se si aspetta qualche ora si nota che e’ qualche minuto avanti!
    Non e’ una bella cosa!
    L’ha notato?
    Grazie e buona giornata

    Rispondi
    1. admin Autore articolo

      Gentilissimo,
      grazie per avermi scritto, perdoni la risposta tardiva ma ero in vacanza.

      Si ho notato ed ho verificato ed effettivamente su un test di un giorno si ha una perdita di precisione importante. Guardando gli schemi di Arduino UNO R4 Minima e WiFi noto che entrambi NON usano il quarzo esterno da 32.768khz sui pin XCIN/XCOUT del microcontrollore RA4M1 e ciò non è positivo in quanto porta inevitabilmente ad una perdita di precisione che può raggiungere, dai test che sto effettuando, a circa ± 20 minuti al giorno. Utilizzando un cristallo esterno la perdita non supererebbe i ± 2 secondi (circa) al giorno. Cercherò appena possibile di approfondire meglio questo aspetto con ulteriori test.
      Le lascio un link ad una discussione sul forum di Arduino che rimanda ad una discussione dove si parla proprio di questo problema.
      https://forum.arduino.cc/t/uno-r4-wifi-rtc-runs-fast-by-about-1-second-per-minute/1145956

      Saluti.

      Rispondi

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.