Come gestire il tempo con Arduino

I microcontrollori funzionano grazie ad una sorgente di clock che permette di temporizzare e sincronizzare tutti i moduli che lo compongono. Il clock è un segnale con una frequenza fissa e stabile tipicamente prodotta da un oscillatore al quarzo. Questo segnale è la base per tutte quelle applicazioni che devono gestire date e orari. In effetti esistono molte applicazioni in cui la gestione del tempo è il fattore principale, pensiamo a tutti quegli automatismi che vengono attivati in funzione dell’ora e della data corrente o che devono compiere delle azioni cicliche.
La gestione del tempo viene affidata a librerie esterne all’Arduino IDE, on line troviamo decine di progetti, quella che io utilizzo è la libreria Arduino Time scritta da Michael Margolis. Questa libreria comprende le classi Time, TimeAlarms e DS1307RTC, con cui è possibile avere un controllo pressoché completo sulle data e sull’orario.

La sorgente di clock alla base della generazione del dato di tempo può essere quella interna al microcontrollore oppure quella gestita da un circuito esterno, tipicamente chiamato Real Time Clock(RTC) come l’itegrato DS1307.
La differenza sostanziale è che usando un RTC avremmo sempre a disposizione il tempo e la data correnti poiché questo circuito tiene in memoria il conteggio impiegando una batteria tampone. Quando la base dei tempi è il clock interno del mirocontrollore, avremo il vantaggio di risparmiare sul costo dell’hardware esterno, ma purtroppo in caso di reset o mancata alimentazione del circuito, la perdita del conteggio. Quindi quando il nostro progetto ha bisogno di avere una fonte temporale sicura è consigliato l’uso di un circuito RTC. Per tutte le applicazioni di test possiamo invece utilizzare il conteggio interno del microcontrollore.

Libreria Time

E’ la libreria principale che permette di creare e manipolare date e orari. Internamente la libreria Time utilizza la funzione millis() di Arduino per tenere traccia del tempo trascorso.
La libreria espone diversi metodi che permettono di impostare ed ottenere informazioni sulla data e sul tempo.
La prima operazione da effettuare è quella di impostare la data e l’orario tramite la funzione setTime():

setTime(h,m,s,D,M,H) Imposta l’ora e la data corrente

Per recuperare informazioni di data e di tempo possiamo usare le seguenti funzioni:

second() Restituisce il numero di secondi dell’orario corrente (da 0 a 59)
minute() Restituisce il numero di minuti dell’orario corrente (da 0 a 59)
hour() Restituisce il numero di ore dell’orario corrente (da 0 a 23)
day() Restituisce il giorno della data corrente (da 1 a 31)
month() Restituisce il mese della data corrente (da 1 a 12)
year() Restituisce l’anno della data corrente

Nel codice di esempio seguente imposto un orario e una data per poi leggerne il valore ed inviarlo al pc tramite serial monitor:

Nel codice precedente l’orario e la data sono impostati qualche secondo prima del 1 gennaio 2016, in questo modo potete osservare che la il dato viene incrementato correttamente passando dal 31 dicembre al 1 gennaio.

Altra funzione utile è la adjustTime() che permette di aggiungere o sottrarre dei valori alla data/ora corrente. Inserendo un numero di secondi positivo, incrementeremmo il valore di data ora, viceversa inserendo un valore in secondi negativo decrementeremo il valore di data e ora.
Nell’esempio seguente incremento di un giorno il valore impostato:

Utilizzare time_t

La variabile time_t è tipica dei sistemi Unix e rappresenta il numero di secondi trascorsi dal 1 gennaio 1970. La funzione now() restituisce il valore in time_t dei secondi trascorsi tra il 1/1/1970 rispetto alla data corrente impostata con la funzione setTime(). In pratica now() esegue una sottrazione tra la data e ora corrente e il valore di default.

Se escludiamo dal codice la funzione setTime() la data e l’ora corrente verrà automaticamente impostata al 1/1/1970 00:00 e now() inizierà il conteggio partendo da zero.

 

E’ possibile settare una data ed un orario usando i secondi trascorsi dal 1/1/1970 ma questo è alquanto scomodo, perciò è disponibile la struttura TimeElements in abbinamento con la funzione makeTime e setTime():

Usare TimeAlarms

TimeAlarms permette di eseguire funzioni in corrispondenza di orari preimpostati o anche ad intervalli regolari.

Per eseguire una funzione in uno specifico orario utilizzeremmo il metodo alarmRepeat() inserendo come parametro data, orario e il nome della funzione da richiamare. Per eseguire in modo corretto la funzione alarmRepeat() è necessario inserire nel blocco loop la funzione Alarm.delay() che crea un ritardo e verifica quando richiamare la funzione inserita nell’alarmRepeat():

 

Nel codice precedente la funzione ledBlink() viene richiamata non appena l’orario corrente corrisponde a quello specificato nella alarmRepeat().

La funzione ledBlink viene richiamata ogni giorno alle 15:30:00. Volendo possiamo specificare nella funzione alarmRepeat() solo un giorno della settimana utilizzando uno dei parametri seguenti:

dowSunday Domenica
dowMonday Lunedi
dowTuesday Martedì
dowWednesday Mercoledì
dowThursday Giovedì
dowFriday Venerdì
dowSaturday Sabato

ad esempio per eseguire la funzione ledBlink solo il lunedì il codice dovrà essere modificato in questo modo:

 

La libreria permette anche di eseguire la funzione specificata solamente una sola volta utilizzando il metodo alarmOnce(). Anche in questo caso è possibile specificare sia giorno della settima sia solo l’orario.

 

Come scritto precedentemente è anche possibile eseguire un timer che ripete costantemente una particolare funzione. Il metodo da usare è timerRepeat(). Ad esempio il codice seguente permette di eseguire ogni 30 secondi la funzione Allarme()

 

è possibile anche creare un timer che viene eseguito solo una volta impiegando la funzione timerOnce():

 

Time e TimeAlarms sono due librerie molto utili che prima o poi dovremmo utilizzare per creare applicazioni che devono essere sincronizzate con la data e l’ora. Gli esempi visti fino ad ora sono si funzionali ma non permettono di tenere traccia del conteggio del tempo anche quando si verifica un reset della scheda. La soluzione per evitare questo problema è l’impiego di un circuito esterno chiamato RTC (Real Time Clock).

La libreria DS1307RTC

Questa libreria viene utilizzata in abbinamento ad un circuito RTC esterno. Questi circuiti sono composti da un integrato (nel nostro caso il DS1307) da un quarzo e da una batteria tampone che garantisce il conteggio del tempo anche quando avviene un reset del microcontrollore o una mancanza di energia.
Il loro costo è contenuto, sono disponibili in commercio diversi modelli che soddisfano molte tipologie di installazione. Quello in mio possesso è prodotto da SeedStudio e potete visualizzare le sue caratteristiche seguendo questo link.

Questo circuito si collega all’Arduino UNO usando il bus I2C. La libreria DS1307RTC ha quindi bisogno di interagire con questo bus richiedendo l’inserimento nel codice della libreria Wire.

L’RTC deve essere dotato di batteria tampone CR2032 per poter garantire il conteggio del tempo anche in assenza di alimentazione (proveniente da Arduino). Inoltre abbiamo bisogno, la prima volta che usiamo l’RTC, di impostare la data e l’ora correnti. Lo sketch seguente mostra come fare questo settaggio:

 

Possiamo usare anche un altro metodo per settare data e ora, piuttosto che impiegare il metodo set() possiamo utilizzare il metodo write() in abbinamento con la struttura TimeElement:

 

A questo punto l’RTC incrementerà autonomamente il valore di data e ora . Il codice di esempio seguente va infatti a leggere il valore di data e ora, precedentemente impostato, e lo invia sul serial monitor (il valore è espresso in secondi trascorsi dal 1/1/1970):

 

Il codice precedente non è di certo esplicativo, possiamo quindi convertire il dato (secondi trascorsi dal 1/1/1970) in valori comprensibili utilizzando il metodo get() ed elaborando il valore restituito con le funzioni della libreria Time:

 

Oppure possiamo utilizzare il metodo read() per popolare la struttura TimeElements ed ottenere lo stesso risultato ma con meno righe di codice.

 

Utilizzando le librerie di questo tutorial avrete pieno controllo su data ed ora per realizzare progetti dove il riferimento temporale è il requisito principale.