Go Down

Topic: Bug nell' esempio BlinkWithoutDelay (Read 953 times) previous topic - next topic

acik

Nell' esempio "BlinkWithoutDelay" il codice originario e' :
Code: [Select]
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:

Code: [Select]
currentMillis = millis()
if(currentMillis - previousMillis > interval)
    previousMillis = previousMillis + interval;





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

Federico Vanzati

#1
Jul 22, 2012, 10:47 am Last Edit: Jul 22, 2012, 10:50 am by Federico Vanzati Reason: 1
L'unico modo per cui potrebbe verificarsi una differenza tra le due istanze è questo:
Code: [Select]

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:

Code: [Select]

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.
F

acik

No, perche':
il timer va sempre avanti ed il codice pure...
Code: [Select]
if(currentMillis - previousMillis > interval)
viene eseguito quando la differenza tra i due e' superiore a mille.
quindi
Code: [Select]
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.




acik


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.

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

Testato

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
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

acik


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:
Code: [Select]
previousMillis = previousMillis + interval;

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

acik

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)


Code: [Select]
  if(currentMillis - previousMillis > interval) {
    int diff = (currentMillis - previousMillis);
    previousMillis = currentMillis;
    Serial.println(diff); 

PaoloP

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.
--> http://code.google.com/p/arduino/issues/list

uwefed



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:
Code: [Select]
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 ;) ;) ;) ;)

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

Go Up