precisione arduino

astrobeed:

jacock:
l' ho fatto andare per un ora attaccato a un carica-usb (quindi non dovrebbero esserci quegli effetti di rallentamento dovuti all' uso con l' usb del pc) e il risultato è che DOPO UN ORA, HA PERSO GIA' 5 SECONDI..... uso arduino 2009 è normale? è il quarzo che è rovinato o di scarsa qualità?

Mettendo da parte per un attimo le considerazioni sulla reale precisione del quarzo/risuonatore montato sulla 2009/UNO, si va da +/- 50 ppm fino a +/-250 ppm (ovvero un errore reale compreso tra +/- 2 minuti/mese e +/- 10 minuti/mese), il vero problema è che la millis non è 1 ms esatto.

In Wiring.c viene definita in questo modo:

// the prescaler is set so that timer0 ticks every 64 clock cycles, and the

// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))




Ovvero il Timer0 è settato con un prescaler 1:64 in modo da ottenere un count ogni 4us, dato che la millis funziona contando gli overflow abbiamo 256*4 = 1024 us per ogni count della millis e non 1000 come porta a pensare il nome della funzione.
Tradotto in tempi, ipotizzando che il quarzo sia da 16 MHz precisi, vuol dire che quando la millis segna 1024 ms in realtà sono passati solo 1000 ms.

chissà se di questa particolarità ha tenuto conto Leo nel suo SWrtc (o RTCsw, ora non ricordo bene...)?

Leo usa una sua routine per calcolare l'overflow del timer, non quello integrato nel codice di Arduino quindi soffre meno (anzi non soffre proprio) di questo problema.
Il problema è che si vuole aumentare la precisione l'unica cosa è passare ai quarti termo-compensati... ma costano.
20mhz 0,2ppm --> http://it.rs-online.com/web/p/oscillatori/7293338/

jacock:
salve a tutti....

l' ho fatto andare per un ora attaccato a un carica-usb (quindi non dovrebbero esserci quegli effetti di rallentamento dovuti all' uso con l' usb del pc) e il risultato è che DOPO UN ORA, HA PERSO GIA' 5 SECONDI..... uso arduino 2009 è normale? è il quarzo che è rovinato o di scarsa qualità?

5 secondi all'ora sono una mostruosita per qualsiasi quarzo di solito ci si mettono vicino dei condensatori variabili di qualche pf e si "ritocca" la frequenza del quarzo alla temperatura operativa, al max un quarzo deve spostarsi di 1 secondo a giorno

altro sistema per mantenere la precisione in maniera incredibile e quella di mantenere il quarzo a una temeratura elevata stabile es 50 gradi con un termostato

Ciao

Quarzo o risuonatore c'entrano fino ad un certo punto.
La funzione millis lavora con un interrupt che viene generato dal timer di cui ha già detto astrobeed.
Può darsi che questo interrupt non venga eseguito sempre (ci sono funzioni che disabilitano gli interrupt e altre funzioni basate su interrupt che potrebbero influire, tipo la seriale)

Se si vuole precisione bisogna usare un RTC

m

Mamma mia che onore... massimo in persona che scrive in un mio topic :open_mouth: :open_mouth: :open_mouth: :open_mouth:

astrobeed:

jacock:
l' ho fatto andare per un ora attaccato a un carica-usb (quindi non dovrebbero esserci quegli effetti di rallentamento dovuti all' uso con l' usb del pc) e il risultato è che DOPO UN ORA, HA PERSO GIA' 5 SECONDI..... uso arduino 2009 è normale? è il quarzo che è rovinato o di scarsa qualità?

Mettendo da parte per un attimo le considerazioni sulla reale precisione del quarzo/risuonatore montato sulla 2009/UNO, si va da +/- 50 ppm fino a +/-250 ppm (ovvero un errore reale compreso tra +/- 2 minuti/mese e +/- 10 minuti/mese), il vero problema è che la millis non è 1 ms esatto.

In Wiring.c viene definita in questo modo:

// the prescaler is set so that timer0 ticks every 64 clock cycles, and the

// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))




Ovvero il Timer0 è settato con un prescaler 1:64 in modo da ottenere un count ogni 4us, dato che la millis funziona contando gli overflow abbiamo 256*4 = 1024 us per ogni count della millis e non 1000 come porta a pensare il nome della funzione.
Tradotto in tempi, ipotizzando che il quarzo sia da 16 MHz precisi, vuol dire che quando la millis segna 1024 ms in realtà sono passati solo 1000 ms.

ok... ma c'è un modo per contare 1000ms precisi, senza incappare in millis che ogni 1024 ne conta uno (ovviamente tenendo come accettabili gli errori +/- del quarzo ecc, che comunque se uno deve realizzare un timer ecc di magari 10 minuti o 1h non gliene frega niente se perde anche 10 secondi a mese)
forse con micros???? (che però va a zero dopo 70h sempre secondo il reference...)

EDIT:

sciorty:
Secondo me quello contribuisce non poco!

dato che scrivi questo, per imparare a scrivere codice in modo migliore, potresti dirmi come l' avresti fatto te????

jacock:
ok... ma c'è un modo per contare 1000ms precisi, senza incappare in millis che ogni 1024 ne conta uno

Dov'è il problema ?
Devi solo moltiplicare il valore di millis per 1024 per sapere i secondi reali.

AHAHAHAAHAHHA, che mona... hai ragione..... scusa, ma sto facendo 7 robe contemporaneamente, e pensare risulta di troppo... :smiley:

per snellire il codice invece? voi come lo avreste fatto?

sciorty:
Secondo me quello contribuisce non poco!

No, millis è gestito tramite un timer in free run e il relativo interrupt sull'overflow, puoi fare il codice complicato quanto ti pare, ma stai pur certo che ogni 1024 us, con un eventuale jitter di qualche us a seconda delle operazioni pendenti, c'è una interruzione per aggiornare millis.
Unico rischio di perdere dei count, citato anche da Massimo, è se nel tuo codice disattivi gli interrupt per un tempo maggiore di 1 ms, in questo caso è possibile perdere degli overflow del timer con relativo mancato aggiornamento del contatore, però è un caso limite in cui è difficile incappare a meno di non mettersi a pasticciare con gli interrupt senza sapere quello che si fa.

grazie 10000000000000000000000000000000

Come ha detto pablos, ne ho tenuto conto.
A seconda del clock, io uso un valore iniziale che assegno al contatore per far sì che l'overflow avvenga esattamente 1000 volte al secondo. Poi, come ha detto astrobeed, non è una formula esatta al 100% perché si verificano fluttuazioni stesse del risonatore/quarzo ma anche blocchi delle routine di reset per cui non si ottiene mai una precisione assoluta. Per sistemare un po', ho messo un deltaT, ossia una correzione da applicare sul calcolo dei secondi per far durare 1 secondo più o meno di 1000 ms, in modo da riavvicinare il conteggio del tempo al valore reale.

Tornando a millis, in realtà non è vero che il team di Arduino non ha previsto che il timer 0 va in overflow con un'accuratezza differente dalle 1000 volte al secondo. Anzi, mi permetto di contraddire astrobeed perché la formula da lui citata dà come risultato 976. Difatti per calcolare il tempo di 1 overflow si usa la formula
CLOCK/PRESCALER/RISOLUZIONE CONTATORE
Nel caso di Arduino, con clock a 16 MHz, prescaler a 64 e contatore ad 8 bit 8256), si ha
16000000/64/256=976.5625

La correttezza dei miei calcoli è provata anche dal fatto che il PWM usato dall'Arduino, Phase Correct PWM, dà come frequenza la metà del tempo di overflow, e difatti 976/2=488.28, che sono infatti i 490 MHz circa che citiamo sempre come frequenza del PWM.

Per ovviare a ciò, il team di Arduino introduce questo:

// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)

Questo correttore viene usato all'interno della ISR che intercetta l'overflow del timer 0 per "addirizzare" il conteggio: infatti non viene incrementato direttamente millis ma un contatore differente. 976/1000 dà 0.976, che è la durata dell'overflow sul timer 0 di Arduino Sommando 1024 volte 0.976 si arriva al valore corretto di 1000 overflow per secondo. Ed ecco che la correzione del timer settato incorrettamente porta ad un valore corretto (relativamente alla precisione del risonatore).

quindi non ho capito... devo mettere 1024 o 976??????

jacock:
quindi non ho capito... devo mettere 1024 o 976??????

Non devi mettere niente. Se millis dice che sono passati 1000 ms, sono passati 1000 ms.
L'imprecisione è dovuta ai fattori che io ed altri ti hanno elencato.

Se vuoi una precisione maggiore, devi usare un RTC esterno.
Se vuoi un sistema software, puoi provare la mia swRTC che gestisce il tempo mediante l'uso del timer 2 e permette la correzione della discordanza fra tempo reale e tempo misurato medianto un delta.

ok.... quindi mi elimino dalla testa il fatto di dover dividere per 1024 per avere 1s....

Se vuoi te lo ribadisco :wink:
Sì. levatelo dalla testa. A livello di software o modifichi il core di Arduino inserendo il delta come ho fatto io nel caso della mia swRTC oppure ti affidi ad un RTC. L'alternativa è un chip in standalone con un quarzo da 32768 Hz esterno collegato in modo asincrono al timer 2 ed usando il modulo Real Time Counter dell'Atmega328, come ho fatto io nel mio progetto Micrologio. Dove si raggiunge una buona precisione.
Ma sei legato al fatto che: il chip deve essere in standalone; usi il timer 2; se il progetto usa librerie di terzi che usano il timer 2, potresti avere conflitti.

        1. bastava parlare chiaro.... :smiley:

vabbè... i miei progetti, per un pò, finchè non mi servirà più precisione, tipo per un cronometro, continueranno ad avere 5 secondi di ritardo ogni ora...

Se il tuo progetto prevede la Ethernet o il Wifi puoi sempre sincronizzarti ogni ora con i server NTP.
Altrimenti
--> DS1307 Real Time Clock breakout board kit : ID 264 : $7.95 : Adafruit Industries, Unique & fun DIY electronics and kits
--> http://www.robot-italy.com/product_info.php?products_id=763
per la massima precisione
--> http://www.robot-italy.com/product_info.php?products_id=2602 o ChronoDot - Ultra-precise Real Time Clock [v3] : ID 255 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits

PaoloP:
Se il tuo progetto prevede la Ethernet o il Wifi puoi sempre sincronizzarti ogni ora con i server NTP.
Altrimenti
--> DS1307 Real Time Clock breakout board kit : ID 264 : $7.95 : Adafruit Industries, Unique & fun DIY electronics and kits
--> http://www.robot-italy.com/product_info.php?products_id=763
per la massima precisione
--> http://www.robot-italy.com/product_info.php?products_id=2602 o ChronoDot - Ultra-precise Real Time Clock [v3] : ID 255 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits

mi piacerebbe un sacco utilizzare le shield ethernet, per mettere online i dati di alcuni miei progetti........
ma sfortunatamente da 5 mesi non ho pìù un mio collegamento internet in casa =( =( =( =(

ho abbandonato anche tutte quelle cose a controllo remoto per questo motivo...

jacock:
ma sfortunatamente da 5 mesi non ho pìù un mio collegamento internet in casa =( =( =( =(

E a casa del vicino? :roll_eyes:

secondo te adesso da dove sto scrivendo?
poi abito in un condominio separato dagli altri dove per beccare una rete, posso farlo solo con il pc mettendo la chiavetta fuori dalla finestra con una prolunga... no c'è la stabilità e la velocità di trasferimento che avevo prima...

1 mega di download al secondo =( =( =( =( =( =( =( =( =( =(