Algoritmo per la differenza tra due secondi

Io ho due variabili, che rappresentano due secondi:

a: rappresenta quando è successo l'evento
b: rappresenta "ora"

c'è da tener conto però della differenza tra minuti.. (ad esempio a = 10, b = 12; ma a è successo 3 minuti fa... quindi la differenza e' notevole...)
a me interessa tener conto di una differenza superiore a 30 secondi... (nell'esempio di prima mi basta sapere che tra a e b sono intercorsi più di 30 secondi)

l'unica cosa certa è che a è successo "prima" di b (es: a = 10, b = 2; sono passati più di 30 secondi)

non so bene come spiegare il mio problema... ho provato varie cose ma nessuna torna...
es:
(60 + a - b) % 60 >= 30;
(60 + ABS(a-b)) % 60 >= 30;
(60 + ABS(a-b)) % 60 <= 30;

non mi vengono altre idee.... se non
(60 + a - (b < a ? b + (60 - a) : b)) % 60 >= 30
(60 + a - (b < a ? b + (60 - a) : b)) % 60 <= 30

che però non va...

Diciamo che tu hai 2 variabili che tengono il valore di 2 "istanti".

E vuoi che il tuo codice faccia qualcosa se la differenza fra le 2 sia superiore ad un tot. Devi usare la funzione millis(), che restituisce i ms passati dall'avvio dell'Arduino.

Potresti provare con:

unsigned long, tempoA, differenza;

void setup() {
differenza=30000; //30 sec. espressi in ms
}

void loop() {
if (EVENTO) {
tempoA=millis();
}
if ((millis()-differenza)>tempoA) {
AZIONE;
tempoA=millis();
}
}

non volevo usare millis(), dato che ho un DS1307

e poi, ad una rapida occhiata, non funziona più quando millis() torna 0

Beh, potevi dirlo prima che avevi un RTC :cold_sweat:

Cmq era una bozza di codice, se hai un orologio, il procedimento è lo stesso: se non ricordo male il DS1307 trasmette l'orario in formato byte, che poi alcune funzioni riportano ad un'orario "umano". Lavora quindi con l'ora grezza al posto di millis. Oppure trasmorma i secondi/minuti/ore in frazioni di ore e fai i calcoli con quelli.

Buon lavoro.

hai ragione, sono fuso... è tre giorni che sto cercando di far funzionare una cosa che ovviamente non va.. non capisco perché, il codice è lo stesso, ma da una parte non va...

tornando al discorso...
io faccio restituire (non ti dico ogni volta il prof cosa dicono alla traduzione return = ritornare :P) i valori umani...

solo con questo non riusciresti a darmi una mano? vorrei usare i secondi per usare un uint8_t... e non oltre :grin:

Brig:
solo con questo non riusciresti a darmi una mano?

Più di così? Ti ho già scritto il codice... :stuck_out_tongue_closed_eyes:

vorrei usare i secondi per usare un uint8_t... e non oltre :grin:

Non bastamo, devi lavorare con le frazioni di ore perché se leggi 00:59, quindi secondi = 59, e poi leggi 01:40, (40-30=) 10 è minore di 59 ma in realtà sei già 40 secondi dopo.

Metti orefraz=ore+(minuti/60)+(secondi/3600) e confronta con questo.

e quindi usare float?
non c'è un'altro modo "più economico"??
magari con qualche magheggio... :grin:

oppure trasformi tutto in secondi e non hai decimali :wink:
però dovresi usare un long, quindi
seconditot=ore3600+minuti60+secondi e confronta con questo.

Oppure nell'istante della prima lettura, inizializzi a 0 una variabile, ed ogni secondo la incrementi di 1. Quando diventa >=30 sono passati 30 secondi e fai quel che devi fare.

però bisognerebbe avere un interrupt ogni secondo in modo che il valore sia molto attendibile :wink:

insomma prima regola della programmazione:
logica e inventiva :wink:

allora, se trasformi tutto in secondi (o in ore) poi hai lo stesso problema della millis(), ovvero prima o poi un overflow (dipende dalla dimensione della variabile), anche se usando unsigned long con i secondi è molto più raro che usando solo i millesimi come la millis()

In realtà il problema overflow ce l'ha anche l'RTC, ma si presenta dopo anni, se non millenni. (dipende dalla dimensione massima della varibile "anno" all'interno dell'rtc)

Per utilizzare tutta la precisione possibile, il metodo è creare un array (o meglio una classe) che nelle sue celle contiene anno, mese, giorno, ora, minuti, secondi
il confronto a questo punto diventa un poco più complicato, conviene usare una funzione, o nel caso di una classe un metodo pubblico

(non ti dico ogni volta il prof cosa dicono alla traduzione return = ritornare smiley-razz)

beh il mio diceva sfrugulate l'array... eppure si capiva cosa bisognava fare. Per esempio in questo caso nella funzione devi sfrugulare con gli array, ovvero farne una copia dell'array contenente il tempo memorizzato (in questo caso tempoA), sommarci il valore(differenza), normalizzarlo (finché i secondi sono > 60 allora secondi -=60 e incrementare di 1 i minuti, etc..), e controllare se è più grande dell'array appena letto dall'RTC...

et voilà, hai un sistema per contare il tempo che andrà in overflow molto dopo la nostra departura dal mondo terreno 8)

ps. prima scrivi il codice funzionante, POI ottimizzalo con uint_8 e tutto quello che vuoi. Altrimenti non capirai mai se è il principio o l'ottimizzazione ad essere errata...

@superlol: l'interrupt ogni secondo è necessario solo se il loop dura più di un secondo o una sua frazione molto grossa. Ma salvo delay o codice astruso, il loop() non dura più di qualche millisecondo. Senza contare che all'interno dell'interrupt non puoi fare chiamate a funzioni esterne, quindi niente interrogazioni all'RTC, nel caso ce ne fosse il bisogno

leo72:
Oppure nell'istante della prima lettura, inizializzi a 0 una variabile, ed ogni secondo la incrementi di 1. Quando diventa >=30 sono passati 30 secondi e fai quel che devi fare.

era troppo difficile perché ci potessi arrivare io :roll_eyes: :roll_eyes:

via... come al solito grazie!!!

superlol:
però bisognerebbe avere un interrupt ogni secondo in modo che il valore sia molto attendibile :wink:

Non serve, dato che lui ha un RTC e può leggere quello. E cmq non credo che se invece di 20 secondi sono passati 20,5 secondi possa partire il missile nucleare :stuck_out_tongue_closed_eyes:

233600+5960+60=82800+3540+60=86400
un lo0ng arriva a 2^63 non credo tu abbia problemi :wink:

esatto non dovrebbe mai andare in overflow.

uint_8

giusto -> uint8_t
ma sono la stessa cosa del tipo byte utilizzabile con arduino (te lo scrive in arancione...l'occhio potrebbe ringraziare)

@Brig: non ci hai spiegato bene (oppure sono io quello ottuso) ma non basta far partire in conteggio dei 30 secondi dopo che è successo l'evento A?
Ti risparmi una variabile e n-mila conversioni, fai solo il confronto con i secondi:

  • accade l'evento -> salvo nell'array ora_evento
  • ora_allarme = ora_evento + 30 secondi (più eventuali riporti sui minuti ecc)
  • SE ora_allarme == rtc[] (confronti i minuti e i secondi)
    -> si: scatta allarme
    -> no: non fare niente, non sono ancora passati i 30 secondi dall'evento

E' quello che ho detto anch'io 5 post qui sopra....