millis o unixtime?

Buon giorno,

vorrei realizzare un controllo che mi permetta di eseguire determinate operazioni a intervalli regolari, senza però bloccare il programma con il delay; guardando in rete ho trovato una soluzione basata sulla funzione millis(): questa soluzione prevede l'utilizzo di variabili unsigned long che, presto a tardi, andranno in overflow. La domanda è: quando questo accadrà cosa ne sarà di tutti i controlli basati su queste variabili? L'overflow porterà ad un azzeramento della variabile?
Per ovviare a questo "inconveniente" pensate che sia implementabile qualcosa basato sul now.unixtime()?

Grazie

Millis va in overflow dopo 49,7 giorni.

Io ho sviluppato alcune alternative che non soffrono di questo inconveniente:
libreria secTimer: un semplice contasecondi che utilizzi come milis(), ma che va in overflow dopo 136 anni!
swRTC: una libreria per implementare un RTC software: con essa puoi avere il tempo in oo:mm:ss e la data in gg:mm:aa per poter programmare eventi anche a distanza di anni
leOS: un semplice scheduler che esegue azioni in background indipendenti dal loop principale, a cadenza impostabile

Trovi tutto qui:
http://www.leonardomiliani.com/?page_id=374

grazie per il suggerimento! me li spulcio e vedo come utilizzarli :slight_smile:

ma cosa accade se la variabile definita come unsigned long va in overflow? si ri-azzera?
grazie

zioTonino:
ma cosa accade se la variabile definita come unsigned long va in overflow? si ri-azzera?

Semplicemente riparte da 0 o dal valore in eccesso dovuto all'operazione matematica, esempio pratico con una variabile di tipo byte, per semplicità di calcolo, ma valido con tutti i tipi di variabile.

byte A;
A = 250;
A += 8: // ora A vale 2 perché 250 + 8 = 258 però è in eccesso a 256 quindi 258 - 256 = 2

Oppure :

byte A;
A = 255;
A++;
// ora A vale 0, siamo in overflow perché un valore byte non può rappresentare il valore 0x100 e tutti i bit in eccesso vengono eliminati.

A++; // ora A vale 1

zioTonino:
ma cosa accade se la variabile definita come unsigned long va in overflow? si ri-azzera?

Sì. Riparte il conteggio da zero.

EDIT:
preceduto

leo72:

zioTonino:
ma cosa accade se la variabile definita come unsigned long va in overflow? si ri-azzera?

Sì. Riparte il conteggio da zero.

EDIT:
preceduto

di solito millis si usa assegnandone il valore temporaneo a due diverse variabili, a distanza di tempo, e poi confrontandole tramite un IF, per stabilire se è passato un tot tempo o meno; questo è il pochissimo che so e che potrebbe amche essere sbagliato; cosa succede se vado a fare la differenza tra una lettura fatto subito dopo l'overflow ed una fatto subito prima? ottengo un valore negativo?

Ottieni un valore incoerente. Ci sta che il tutto passi inosservato, come no. Dipende dal tuo codice.
Esempio.

(2^32)-1=4294967295
Questo è il valore massimo che può contenere un unsigned long (4 byte, 32 bit).
Mettiamo cheil prossimo io faccia un test poco prima dell'overflow, quando cioè millis contiene ad esempio 4294967000, e che il codice che uso sia questo:
if (millis()>tempMillis) {
......ecc....
tempMillis = millis() + 1000;
}

Entro nell'if, eseguo il mio codice, poi prima di uscire imposto la prossima ripetizione a 1000 ms di distanza.
Però millis() diciamo che ora valga 4294967050 (ho impiegato 50 ms per eseguire i miei compiti), quindi tempMillis() dovrebbe valere 4294967050+1000= 4294968050. Ma il massimo è 4294967295, per cui tempMillis contiene 4294968050-4294967295=755.
Il controllo riparte, poi millis va in overflow e riparte da zero. Però siccome il check è fatto con millis > tempMillis, arriva dopo 1000 ms il controllo 756 > 755.
Qui vedi che l'overflow non ha dato problemi.

Se invece il controllo è:
if ((millis() + 1000)) > tempMillis) {
....ecc.....
tempiMillis() = millis();
}

Allora il problema può saltar fuori.
Prendiamo i valori di prima. All'uscita dell'if tempMillis vale 4294967050 perché memorizzo millis(). Al successivo check faccio:
(4294967051 + 1000) > 4294967050?
Eseguiamo 4294967051+1000, dà come risultato 756. Ma siccome 756 non è maggiore di 4294967051, il ciclo if non viene ripetuto finché millis() + 1000 non diventa maggiore, cioè dopo quasi 49,7 giorni

zioTonino:
Per ovviare a questo "inconveniente" pensate che sia implementabile qualcosa basato sul now.unixtime()?

e cosa succede quando va in overflow la now.unixtime()? ]:smiley:

Azz, Leo, non pretendevo così tanta attenzione :sweat_smile:, mi bastava capire se i miei timori fossero fondati, però ora capisco anche che fondamentalmente il timore è reale ma anche frutto della mia ignoranza in materia di programmazione, basta usare correttamente la funzione e il problema non si pone più. Grazie, risposta spettacolare e chiara :wink:

Azz, Leo, non pretendevo così tanta attenzione , mi bastava capire se i miei timori fossero fondati, però ora capisco anche che fondamentalmente il timore è reale ma anche frutto della mia ignoranza in materia di programmazione, basta usare correttamente la funzione e il problema non si pone più. Grazie, risposta spettacolare e chiara

@Menniti
@leo72

Seguo sempre i vostri messaggi ed imparo ogni volta qualcosa in più e,come dici tu (Menniti) ,riuscite entrambi a dare spiegazioni semplici,precise ed anche con esempi che aiutano tutti quelli che come me hanno tanto da imparare......continuate sempre così :grin:

lesto:

zioTonino:
Per ovviare a questo "inconveniente" pensate che sia implementabile qualcosa basato sul now.unixtime()?

e cosa succede quando va in overflow la now.unixtime()? ]:smiley:

Dai, davvero, hai unix sul Arduino?

uwefed:
Dai, davvero, hai unix sul Arduino?

ROFTL XD

leo72:

uwefed:
Dai, davvero, hai unix sul Arduino?

ROFTL XD

Eccolo ]:smiley:

stavo per dire "occhio che portebbe anche essere, magari non un linux ma un *nix", ed eccomi preceduto con tanto di link

Lí non devi contare i millisecondi ma le ore :wink: :wink: :wink:
Ciao Uwe

[OT]
quella shell non permette quasi nulla. Allora meglio Bitlash
http://bitlash.net/wiki/start
[/OT]

leo72:
Millis va in overflow dopo 49,7 giorni.

Io ho sviluppato alcune alternative che non soffrono di questo inconveniente:
libreria secTimer: un semplice contasecondi che utilizzi come milis(), ma che va in overflow dopo 136 anni!
swRTC: una libreria per implementare un RTC software: con essa puoi avere il tempo in oo:mm:ss e la data in gg:mm:aa per poter programmare eventi anche a distanza di anni
leOS: un semplice scheduler che esegue azioni in background indipendenti dal loop principale, a cadenza impostabile

Trovi tutto qui:
Arduino – Leonardo Miliani

ciao Leo,

purtroppo questo percorso non esiste

``your-arduino-IDE-folder/hardware/tiny/cores/tiny/
e inoltre il file, core_build_options.h, non esite..

nella cartella hardware ho solo altre due cartelle:
arduino e tools
nella prima c'è una cartella cores (percorso esatto: G:\Antonio\progetti\arduino-1.0.1\hardware\arduino\cores\arduino all'interno di questa cartella sono contenuti alcuni file, tra i quali:
Arduino.h, Binary.h

che faccio?

nella swRTC non è implementata qualche funzione per andare in avanti o indietro nel tempo?

con la libreria dell'adafruit e con i pulsanti posso impostare l'ora dal display attraverso il codice:

      if (buttons == BUTTON_RIGHT){

        DateTime future (now.unixtime() + 1 * 3600L );

        RTC.adjust(DateTime(future.year(), future.month(), future.day(), future.hour(), future.minute(), future.second()));

        lcd.setCursor(0,1);  
        lcd.print("ORA +1          ");
        delay(400);

senza paura che sballi la data o altro...

si può fare anche con la tua? thanks

Il percorso che ti ho dato è corretto, forse hai avuto un problema di idle del sito.
La swRTC implementa un RTC software e poi impostare la data e l'ora nonché leggerli. Siccome si basa sull'HW dell'Arduino, non ha la precisione di un RTC hardware ma se devi programmare delle azioni nel futuro ti può essere sufficiente.
Cmq se vuoi solo contare il tempo, usa la secTimer, e fai un controllo su seconds come se lo facessi su millis.

PS:
your-arduino-IDE-folder/hardware/tiny/cores/tiny/
questo percordo ce l'hai se hai installato il core Tiny per programmare gli Attiny.

ciao Leo,
io ho un Arduino UNO R3, che monta un Atmega 328P-PU

********************************************************************
REQUIREMENTS

* The secTimer library needs Arduino IDE version 002x or 1.0x to work with Atmega48/88/168/328/328P, Atmega640/1280/1281/2560/2561 and Atmega8/8A.
* To work with Attiny24/44/84, Attiny25/45/85 and Attiny2313 you need the Tiny Core libraries that you can download from:
http://code.google.com/p/arduino-tiny/
* To work with Atmega644/1284 you need a speciale core that you can download from:
http://www.leonardomiliani.com/?page_id=374

Directions to install and use the Tiny and 644/1284 cores are provided from their respective authors.

********************************************************************

ma quale Tiny Core devo montare? (IDE 1.0.1)
Nel punto due e tre la mia versione non è comprsa...

Grazie