Bug nell' esempio BlinkWithoutDelay

Nell' esempio "BlinkWithoutDelay" il codice originario e' :

currentMillis = millis()
if(currentMillis - previousMillis > interval)
    previousMillis = currentMillis;

Ma non va bene ! in quanto passano sicuramente dei ms per processare quell' if e poi settare il valore di previousMillis.

Il codice corretto dovrebbe essere:

currentMillis = millis()
if(currentMillis - previousMillis > interval)
    previousMillis = previousMillis + interval;

PS. Mi mettete una nota nel codice ? "modified 22 Lug 2012 by Alex Limbeck" XD

L'unico modo per cui potrebbe verificarsi una differenza tra le due istanze è questo:

if(millis() - previousMillis > interval) {
    previousMillis = millis();
    //codice
}

quell'if ad essere processato ci mette infinamente meno di un millisecondo. Quindi di fatto anche se è concettualmente sbagliato, l'errore che produci non è sostanziale.

Un approccio sbagliato potrebbe essere:

if(millis() - previousMillis > interval) {
    //tanto codice
    previousMillis = millis();
}

dove aggiornando previousMillis come ultima istruzione, sicuramente hai lasciato passare del tempo, probabilmente anche nell'ordine dei millisecondi, tutto sta alla quantità e complessità di codice che viene eseguito prima.

No, perche':
il timer va sempre avanti ed il codice pure...

if(currentMillis - previousMillis > interval)

viene eseguito quando la differenza tra i due e' superiore a mille.
quindi

previousMillis = currentMillis

verra' eseguito ancora piu' tardi.

Quindi il ritardo sara' superiore a 1000.
Questo ritardo sara' tanto piu' grande, quanto piu' bassa e' la frequenza del microcontroller.

Il fatto e' che l' errore c'e' ed io lo voglio correggere XD

interessante concetto,
dipende sia dal tempo che impiega il codice interno all'if, come dice federico, sia dalla precisione che a te serve.

Nei casi in cui questo crea problemi, potresti usare il leOS di leo, dovresti essere immune da questi ritardi visto che lavora su un secondo timer del micro

Testato:
interessante concetto,
dipende sia dal tempo che impiega il codice interno all'if, come dice federico, sia dalla precisione che a te serve.

Io ho gia' risolto il problema.
Basta modificare il codice in:

previousMillis = previousMillis + interval;

Funziona con qualsiasi velocita' del micro...
Funziona indipendentemente dalla quantita' di codice...
Oltre ad essere concettualmente la soluzione giusta.

Ecco un esempio :
Il sottostante codice sballa di 1 o 2 ms su un Arduino UNO cloccato a 16MHz.
Da notare che il Serial.print l' ho messo dopo, per non indurre altri ritardi !
(guardare con il serial monitor l' effettivo delay)

  if(currentMillis - previousMillis > interval) {
    int diff = (currentMillis - previousMillis);
    previousMillis = currentMillis;
    Serial.println(diff);

Apri un "ticket" descrivendo il problema e la soluzione, in inglese. Gli sviluppatori valuteranno la questione e, se del caso, la inseriranno nella prossima release.
--> Google Code Archive - Long-term storage for Google Code Project Hosting.

acik:

Testato:
interessante concetto,
dipende sia dal tempo che impiega il codice interno all'if, come dice federico, sia dalla precisione che a te serve.

Io ho gia' risolto il problema.
Basta modificare il codice in:

previousMillis = previousMillis + interval;

Funziona con qualsiasi velocita' del micro...
Funziona indipendentemente dalla quantita' di codice...
Oltre ad essere concettualmente la soluzione giusta.

per dire una cattiveria: Il millis() viene aggiornato ogni millisecondo. Percui posso avere un errore fino a 0,999mS. Siccuramente questo no é preciso e percui non ammissibile :wink: :wink: :wink: :wink:

In poche parole:
@acik devi valutare la necessitá di precisone che devi ottenere. Se un LED lampeggia con 1 Hz oppure con 1,001 Hz a nessuno frega qualcosa e nessuno si accorge.
Se hai necessitá di tempi piú precisi Ti consiglio di usare i timer del ATmega.

Ciao Uwe