Operazioni con l'orario

Ciao,
sono nuovo di Arduino, ho da poco collegato l’RTC DS1307 che funziona a meraviglia con la relativa libreria.
Adesso lo step successivo è di sfruttarlo per fare di arduino un timer (tra le altre cose).
Mi chiedevo se esiste una libreria o qual’è la maniera più semplice per “giocare” con i vari controlli sull’ora.
All’inizio mi sembrava banale poter dire al codice “if, orario è maggiore o uguale a quello stbilito, accendi le luci”, ma in realtà non è proprio così.
Quindi mi sono fatto una tabella booleana con una serie di casistiche e il tutto adesso è riassunto in questa if:

if ( (RTC.get(DS1307_MIN,false) >= MinAccensLuci && RTC.get(DS1307_HR,false) >= OraAccensLuci) || (RTC.get(DS1307_MIN,false) < MinAccensLuci && RTC.get(DS1307_HR,false) > OraAccensLuci))

Sono curioso di sapere se questa è la maniera migliore, perché su internet non ho ancora trovato niente, ma magari sono io che mi sto legando su una cosa che magari si poteva fare meglio…
Ad ogni modo il suddetto comando mi serve per far accendere delle luci (credo si capisca dai nomi delle variabili). Per lo spengimento invece, dovendo creare prima l’effetto “fade out”, ho necessità di fare prima dei calcoli sull’orologio (cosa che in excel si farebbe credo velocemente, ma non in C).
Ad esempio se voglio che le luci siano spente alle 22.00, ma il fade dura mezz’ora, in pratica devo sottrarre 00.30 dalle ore 22.00 e quindi a partire dal risultato (21.30), far partire il fade out fino allo spengimento.

Spero di essere stato chiaro.

Se non richiedi una precisione spaccata al 100° potresti provare a trasformare tutto in frazioni di giorno, come si usa ad esempio in astronomia.
Ovvero, prendiamo il caso di adesso:
giorno 09:
ore: 21
minuti: 49
secondi: 00

Diventa 9+(ore/24)+(minuti/1440)+(secondi/86400) = 9.909027778
In questa maniera con un solo if risolvi il problema, basta farti una funzione tipo
float frazione_giorno(byte giorno, byte ore, byte minuti, byte secondi)
che ti restituisca la conversione, così sei a posto.

Se devi togliere ad un orario 30 minuti non devi far altro che fare
orario = frazione_giorno(giorno,ore,minuti,secondi) - (30/1440)

Grazie, mi sembra un'ottima idea: pensi che nel mio caso posso anche tener conto solo delle ore e dei minuti? Mi servirebbe quasi un semplice timer giornaliero, quindi potrei anche convertire tutto a minuti e sarei a posto?

Guarda, per come sono i calcoli potresti in teoria tener conto anche dei secondi. C'è un "però": l'Atmega non è un controllore che esegue nativamente calcoli in virgola mobile (float) per cui potresti avere dei problemi con gli arrotondamenti. Sicuramente una precisione ai minuti potresti avercela. Fai comunque delle prove.

Il sistema che ti ho dato è comodo perché se devi ad esempio calcolare l'accensione, che so, dopo 12h da un preciso istante, basta che tu faccia valore_attuale+(15/24). Ad esempio mettiamo che l'indicazione che hai adesso sia: 10.75678563 Tra 12 ore sarà esattamente 11.25678563

Il bello del metodo è che il cambio del giorno te lo fa la matematica :D Devi solo tener conto della fine o dell'inizio del mese. Cioè devi farti un piccolo calcolo per vedere di quanti giorni finisce il mese attuale (più che altro febbraio bisestile). Se ad esempio ottieni 32.2 e sei a marzo, sai che devi togliere 31 ed ottieni 1.2, cioè il 1° del mese dopo.

Non é meglio calcolare con i secondi e non avere delle frazioni? Con interi puoi usare un unsignet long che é piú preciso di un float con decimali. Con un unsignet long puoi programmare tempi per i prossimi 136 anni oppure 125 se fai coincider anno 0 con il 2000. Oltre questo se Ti serve solo un orario di stop potresti usare un RTC che ha la funzione Di alarme. Ciao Uwe

Concordo con Uwe, è molto più semplice, oltre che molto meglio per il micro, gestire il tutto tramite numeri interi a 32 bit. Basta scrivere preventivamente un paio di funzioni che trasformano l'orario fornito dal RTC in secondi e l'orario scritto nel formato classico sempre in secondi, dopo di che si ragiona su questi, e la precisione è totale. Un giorno dura 24*3600 = 86400 secondi, con 32 bit (unsigned long) è possibile rappresentare fino a 49710 giorni pari a oltre 136 anni, credo che bastino per qualunque applicazione :) Una volta che si ha il solo orario, oppure l'orario più la data, convertito in secondi diventa molto semplice fare conti per determinare azioni di avvio, o fine, di determinate azioni.

Come sempre in campo informatico, non esiste un solo modo per ottenere un risultato. XD

Volendo potrebbe essere migliorato anche il metodo suggerito da voi. Potrei stabilire un "punto 0" da cui iniziare a contare, ad esempio l'inizio di un anno, ed inserire il valore dell'anno nei primi 8 bit di un unsigned long: con 8 bit, posso contare fino a 256 anni quindi ho un range che va dall'anno scelto "anno 0" fino ad (anno 0)+255. A questo punto, ho i restanti 24 bit da usare come contatore di secondi per avere il momento all'interno di un anno. Quando il contatore dei secondi raggiunge il max per un anno (86400+365 oppure 86400+366 per i bisestili), azzero ed incremento il contatore degli anni. Così gestisco fino a 256 anni.

leo72: Potrei stabilire un "punto 0" da cui iniziare a contare, ad esempio l'inizio di un anno, ed inserire il valore dell'anno nei primi 8 bit di un unsigned long: con 8 bit, posso contare fino a 256 anni quindi ho un range che va dall'anno scelto "anno 0" fino ad (anno 0)+255.

La matematica non è un'opinione :) Il limite di 160 anni è dato dal valore a 32 bit, se mi usi 8 bit per conteggiare gli anni non te ne rimangono abbastanza per conteggiare un singolo anno, infatti 86400, secondi in un giorno, moltiplicato per 365 fa 31.560.000 che è un numero maggiore di 24 bit. Ovviamente si può usare come base per conversione il minuto, dipende dalla risoluzione richiesta, e in questo caso si arriva a qualche millennio.

Hai ragione, ho perso 1 bit per strada :*

astrobeed: Concordo con Uwe, è molto più semplice, oltre che molto meglio per il micro, gestire il tutto tramite numeri interi a 32 bit. Basta scrivere preventivamente un paio di funzioni che trasformano l'orario fornito dal RTC in secondi e l'orario scritto nel formato classico sempre in secondi, dopo di che si ragiona su questi, e la precisione è totale. Un giorno dura 24*3600 = 86400 secondi, con 32 bit (unsigned long) è possibile rappresentare fino a 49710 giorni pari a oltre 136 anni, credo che bastino per qualunque applicazione :) Una volta che si ha il solo orario, oppure l'orario più la data, convertito in secondi diventa molto semplice fare conti per determinare azioni di avvio, o fine, di determinate azioni.

Scusate, abbiate pazienza la mia ignoranza, vi seguo a malapena: sull'orario penso di aver capito il concetto ma tenendo in considerazione anche i giorni come funziona il tutto? In particolare nel mio caso se ad esempio accendo delle luci ad un determinato oradio di un giorno e voglio che si spengano ad un orario del giorno dopo?

Devi semplicemente riconvertire da secondi a orario e controllare se l'orario è uguale al momento in cui vuoi accendere/spengere le luci.

ciao mechrekt Un giorno ha 86400 secondi Se vuoi spegnere domani dopo 26 ore e 10 minuti devi aggiungere ai tempo in secondi di adesso (timestamp) 10 minuti, 2 ora e 1 giorno che sono: 10 * 60 + 2*60*60 + 1*24*60*60 secondi. Ciao Uwe