Go Down

Topic: itoa - millis() (Read 787 times) previous topic - next topic

ecrock

La funzione millis() dovrebbe restituire il numero di millesecondi dall'avvio di Arduino.
Ora, come è possibile che la millis sulla mia scheda Uno restituisca dei "millesecondi" più corti di un millisecondo vero?!?

Questo è un codice veloce di prova che ho fatto, ogni 10 secondi reali ne conto 12 a monitor...possibile che il colpevole possa essere itoa? In che modo fisicamente ciò influenza, accelerando, il processore?

grazie in anticipo per l'aiuto, purtroppo anche con il cerca non ho trovato una soluzione...

Code: [Select]
char test[2]; //text has to end with '\0' !!!!!!
int seclamp=8;
unsigned long tempo;
int secondi=60;
int minuti=0;
int x=1;

/* -----------------------------------------------------------------  */
/** MAIN program Setup
*/
void setup()                    // run once, when the sketch starts
{
    Serial.begin(9600);
  tempo=millis();
  seclamp=8;
}

/* -----------------------------------------------------------------  */
/** MAIN program Loop
*/

void loop()                     // run over and over again
{

if(millis()>tempo+1000 && minuti>=0){
      secondi--;  //decremento i secondi
      tempo=millis();
        itoa(secondi,test,10);
              Serial.println(secondi);

    if(secondi==0)
    {
        secondi=60;
        minuti--;
    }
}

else if(minuti<0 && millis()>=tempo+1000 && seclamp>0)
    {
      tempo=millis();
  Serial.println("kaboom");
      x=!x;
      seclamp--;
    }
}

leo72

L'Atmega328 non è un RTC, un orologio in tempo reale. Inoltre il clock è fornito da un risonatore ceramico, la cui tolleranza è normalmente maggiore rispetto a quella di un quarzo. Sommando queste variabili ottieni una misura temporale di massima.
Se prendi 2 Arduino qualsiasi e gli carichi sopra il Blink, avviandoli contemporaneamente noterai come, trascorsi un po' di secondi, i lampeggi dei 2 led integrati iniziano a divergere.
Se in un giorno il tuo Arduino "sbarella" di 1 minuto e la tua applicazione ha bisogno solo di un'idea di massima del tempo trascorso, allora puoi ignorare questa differenza. Se invece cerchi una maggiore precisione, devi rivolgerti ad altro.

uwefed

#2
Jan 11, 2013, 11:30 pm Last Edit: Jan 11, 2013, 11:32 pm by uwefed Reason: 1
Vedo 3 problemi di cui uno grosso:

Perché devi convertire il numero in una stringa? Per stamparla sulla seriale puoi farlo anche senza. La conversioe ti ruba tempo e ti fa la sketch piú grande.

Metti un numero a 2 cifre in un array di 2 elementi e vuoi aggiungere pure un /0 finale. Sovrascrivi la memoria.

La variabile tempo viene aggiornata solo quando i minuti sono contati fino minore a 0.

Se vuoi far decrementare i secondi ogni 1000 millisecondi devi aggiornare ogni secondo la variabile tempo.

L'inprecisione che trovi non é data dalla inprecisione del clock del Arduino ma dal Tuo sketch che per pura fortuna fa qualcosa di simile a quello che vuoi fare.

Ciao Uwe

ecrock

#3
Jan 12, 2013, 06:57 am Last Edit: Jan 12, 2013, 07:06 am by ecrock Reason: 1

Vedo 3 problemi di cui uno grosso:

Perché devi convertire il numero in una stringa? Per stamparla sulla seriale puoi farlo anche senza. La conversioe ti ruba tempo e ti fa la sketch piú grande.

Metti un numero a 2 cifre in un array di 2 elementi e vuoi aggiungere pure un /0 finale. Sovrascrivi la memoria.

La variabile tempo viene aggiornata solo quando i minuti sono contati fino minore a 0.

Se vuoi far decrementare i secondi ogni 1000 millisecondi devi aggiornare ogni secondo la variabile tempo.

L'inprecisione che trovi non é data dalla inprecisione del clock del Arduino ma dal Tuo sketch che per pura fortuna fa qualcosa di simile a quello che vuoi fare.

Ciao Uwe


Ciao,
converto il numero in una stringa perchè ho bisogno (non in questo sketch) che i caratteri vengano stampati come ascii. Difatti qui quell'itoa potrei anche rimuoverlo perchè non viene utilizzato.
Ovviamente il "problema" era la dimensione della stringa, grazie. Nonostante l'avessi pure scritto, non avevo considerato lo \0 finale. Ma la domanda vera è: perchè accelera? non sarebbe più logico pensare ad un rallentamento?

La variabile tempo viene utilizzata sia per il countdown che per un evento (lampeggio) finale (cioè minuti<0).
La variabile tempo di fatto è aggiornata ogni volta che si verifica la condizione millis()>=tempo+1000


ecrock

#4
Jan 12, 2013, 07:00 am Last Edit: Jan 12, 2013, 07:21 am by ecrock Reason: 1

L'Atmega328 non è un RTC, un orologio in tempo reale. Inoltre il clock è fornito da un risonatore ceramico, la cui tolleranza è normalmente maggiore rispetto a quella di un quarzo. Sommando queste variabili ottieni una misura temporale di massima.
Se prendi 2 Arduino qualsiasi e gli carichi sopra il Blink, avviandoli contemporaneamente noterai come, trascorsi un po' di secondi, i lampeggi dei 2 led integrati iniziano a divergere.
Se in un giorno il tuo Arduino "sbarella" di 1 minuto e la tua applicazione ha bisogno solo di un'idea di massima del tempo trascorso, allora puoi ignorare questa differenza. Se invece cerchi una maggiore precisione, devi rivolgerti ad altro.


Si, so di questa cosa, però qui parliamo del 20% di differenza...mi sembra esagerato!
Come ho scritto sopra, era un overflow nella stringa di caratteri causata dall'itoa, ma non capisco quale principio ci sia dietro a un'accelerazione.

PaoloP

Esegui questo sketch e controlla i risultati dell speedtest.
Vedrai che a volte 1000 millisecondi vengono contatti come 999 o 1001, se non peggio.
--> http://playground.arduino.cc/Main/ShowInfo

uwefed


La variabile tempo di fatto è aggiornata ogni volta che si verifica la condizione millis()>=tempo+1000


Hai ragione. Non l'ho visto.

Non so dove é il problema dell'imprecisione.

Comunque contare ogni secondo i millisecondi non é la via giusta per migliorare la precisione.
È meglio che lavori tutto il tempo con i millis() e fai la conta alla rovescia principale con quelli. Per la visualizzazione calcoli il tempo rimanente dai milliseconi in secondi e minuti e lo visualizzi in minuti e secondi.

Ciao Uwe

ecrock


Hai ragione. Non l'ho visto.

Non so dove é il problema dell'imprecisione.

Comunque contare ogni secondo i millisecondi non é la via giusta per migliorare la precisione.
È meglio che lavori tutto il tempo con i millis() e fai la conta alla rovescia principale con quelli. Per la visualizzazione calcoli il tempo rimanente dai milliseconi in secondi e minuti e lo visualizzi in minuti e secondi.

Ciao Uwe


L'imprecisione di 1-2 millisecondi ogni 1000 non è assolutamente un problema per quello che devo realizzare, però con quell'overflow dato dall'itoa l'imprecisione era di circa 200 millisecondi ogni 1000!
Ora funziona tutto bene, con la precisione preventivabile. Proverò comunque anche la tua strada.

Grazie ancora

uwefed


Ovviamente il "problema" era la dimensione della stringa, grazie. Nonostante l'avessi pure scritto, non avevo considerato lo \0 finale. Ma la domanda vera è: perchè accelera? non sarebbe più logico pensare ad un rallentamento?

Risposta.

Avendo dimensionato l'array troppo piccolo il /0 (3o elemento array[2]) viene comunque memorizzato nella cella di memoria ma dietro alle celle di memoria dove viene memorizzato l' array. Su quella cella di memoria sará memorizzato un valore di un alta variabile che memorizzando il /0 nel Array sovvrascrivi col valore 0. Adesso dipendente dallo Sketch e dal compilatore dopo l'array c'é una precisa variabile ma non so dirti quale sia (non ho la conoscenza necessaria da poterlo dire, forse qualcun altro).

Ciao Uwe
 

Go Up