Pagina 1 di 3

Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 15:39
da thexeno
Buongiorno a tutto EY!

Premetto che se ho sbagliato sezione di farmelo subito notare! :-)
Ho realizzato un programmino di prova, che gira sul Pierin, per misurare la frequenza teorica del quarzo del modulo interno RTCC e magari farci quindi qualche autoaggiustamento in SW. Il mio difetto è che poi mi voglio andare ad impegolare per capire a fondo gli aspetti di quel che ho fatto. Oggi sono interessanto alla sua precisione, qualcosa di istruttivo tutto sommato.
Il programma funziona correttamente e il quarzo da misurare, di 32768Hz teorici, senza condensatori di carico il PIC mi dice che è a 32770Hz e con due condesatori da 12pF diventano 32768Hz "precisi", con risoluzione di 1Hz nel mio caso. Se li aumento, scende di un altro paio di Hz al massimo. Quindi è coerente con la misura e la teoria che sta dietro al quarzo.

Quello che vi voglio chiedere è come farsi un'idea corretta di quel "preciso". Ho semplicemente implementato il Timer3 che incrementa ad ogni fronte positivo della frequenza del RTCC, squadrata e buttata fuori da un pin del micro (RB1), avendo il timer3 come ingresso T3CKI sul pin RA5 che riceve i 32768Hz. Quindi collegati con un filo esterno.
La misura dura un secondo "preciso"(?) contato da un altro timer, Timer0.

Ragionando con il codice sottomano, capisco che può dipendere dal momento in cui accendo e spengo la base tempi del timer0 e la precisione del quarzo. Quindi qualcosa come (1/TCY * n_istruzioni + ppm_12MHz) dove le n_istruzioni sono tutte quelle istruzioni che sono in eccesso rispetto all'effettivo spegnimento del Timer0 e TCY è la frequenza di una istruzione; per ridurle al minimo ho spento i timer nella ISR. I ppm_12MHz è l'imprecisione del quarzo di sistema espressa in parti per milione.
Ma non vi chiedo di partire da questo perché potrebbe essere sbagliato, quanto in realtà vorrei sapere come si stima l'imprecisione di un'applicazione del genere.

Qualcuno mi sa dare una mano a ragionare su questo? Sicuramente è pieno di esperti a riguardo. :ok:


Ecco il codice, riporto per semplicità solo le parti essenziali, senza gli header vari e tutte le sotto funzioni usate:

main.c
Codice: Seleziona tutto
/******************************************************************************/
/* Main Program                                                                      */
/******************************************************************************/
uint16_t start = 0;
uint16_t end = 0;
volatile uint8_t ovflw = 0;
volatile uint8_t passed = 0, measure = 0;
uint16_t period, totale;
int i;


void main(void)
{

    /* Configure the oscillator for the device */
    ConfigureOscillator();

    /* Initialize I/O and Peripherals for application */
    InitApp();
    lcd_init();


    write_comm4(LCD_ENTRYMODESET|LCD_ENTRYLEFT|LCD_ENTRYSHIFTDECREMENT);
    while (write_comm4(LCD_BUSYCHECK) != 0);

    while(1)
    {
        printf("Press start.");
        for (i= 0; i<1500; i++) __delay_ms(1);
        ovflw=0;
        TMR3H = 0;
        TMR3L = 0;
        TMR0H = 0x48; // attesa 1 secondo, 1 step = 1/46875Hz
        TMR0L = 0xe5;
        T0CONbits.TMR0ON = 1;
        T3CONbits.TMR3ON = 1; // via con misura
        printf(".");
        while(passed==0){
         //   printf("T0: %u", TMR0);
           // write_comm4(LCD_CLEARDISPLAY);
            //while (write_comm4(LCD_BUSYCHECK) != 0);
        }
        T3CONbits.TMR3ON = 0; // stop con misura
        T0CONbits.TMR0ON = 0;
        passed = 0;
        printf(".");

        // Calcola!
        period = TMR3L;
        period |= TMR3H << 8;
        write_comm4(LCD_CLEARDISPLAY);
        while (write_comm4(LCD_BUSYCHECK) != 0);
        write_comm4(LCD_SETDDRAMADDR | 0x40);
        while (write_comm4(LCD_BUSYCHECK) != 0);
        printf("T: %x - ovf=%d", period, ovflw);
       totale = period*(ovflw+1)/1; // Sample 1 secondo
        write_comm4(LCD_RETURNHOME);
        while (write_comm4(LCD_BUSYCHECK) != 0);
        printf("f = %u Hz", totale);
        for (i= 0; i<3500; i++) __delay_ms(1);
        write_comm4(LCD_CLEARDISPLAY);
        while (write_comm4(LCD_BUSYCHECK) != 0);
    }

}


interrupts.c
Codice: Seleziona tutto
/******************************************************************************/
/* Interrupt Routines                                                         */
/******************************************************************************/

/* High-priority service */

#if defined(__XC) || defined(HI_TECH_C)
void interrupt high_isr(void)
#elif defined (__18CXX)
#pragma code high_isr=0x08
#pragma interrupt high_isr
void high_isr(void)
#else
#error "Invalid compiler selection for implemented ISR routines"
#endif

{

   
      /* This code stub shows general interrupt handling.  Note that these
      conditional statements are not handled within 3 seperate if blocks.
      Do not use a seperate if block for each interrupt flag to avoid run
      time errors. */

#if 1
   

      if(PIR2bits.TMR3IF)
      {
          // hai overflow!
          ovflw++;
          PIR2bits.TMR3IF = 0;
      }
     
     
     
#endif

}

/* Low-priority interrupt routine */
#if defined(__XC) || defined(HI_TECH_C)
void low_priority interrupt low_isr(void)
#elif defined (__18CXX)
#pragma code low_isr=0x18
#pragma interruptlow low_isr
void low_isr(void)
#else
#error "Invalid compiler selection for implemented ISR routines"
#endif
{

      /* This code stub shows general interrupt handling.  Note that these
      conditional statements are not handled within 3 seperate if blocks.
      Do not use a seperate if block for each interrupt flag to avoid run
      time errors. */

#if 1

   if (INTCONbits.TMR0IF)
      {
         T0CONbits.TMR0ON = 0;
          passed = 1;
          T0CONbits.TMR0ON = 1;
          INTCONbits.TMR0IF = 0;
      }
     

#endif

}


e infine le altre funzioni, inizializzazioni timer incluse:
Codice: Seleziona tutto
    void InitApp() {

    //************************************** Porte digitali
  ANCON0 = 0xff;
  ANCON1 = 0b00011111;



 
  //************************************************* Interrupt esterni e debug led

// TRISDbits.TRISD5 = 1;  // pulsanti
// RPINR1 = 22; // RD5 - usa HW esterno e polling in INT per usare piu pulsanti
  INTCON2bits.INTEDG1 = 0;
  INTCON3bits.INT1IP = 0; //  prior
  INTCON3bits.INT1IE = 0; // attiva no
  INTCON3bits.INT1IF = 0;

  TRISDbits.TRISD7 = 0; //LED
  PORTDbits.RD7 = 0;
  TRISDbits.TRISD6 = 0;
  PORTDbits.RD6 = 0;

  //************************** RTCC module config
  TRISCbits.TRISC0 = 1;
  TRISCbits.TRISC1 = 1;
  TRISBbits.TRISB1 = 0;
  EECON2 = 0x55;
  EECON2 = 0xAA;
  RTCCFGbits.RTCWREN = 1;
  // HALFSEC stato del secondo
  RTCCFGbits.RTCOE = 1;
  RTCCFGbits.RTCEN = 1;
  PADCFG1 = 0b00000101; // 2^16 su RTCC pin

  //******************************* LCD port config
  TRISD = 0b00000000; //8 bit data
  TRISBbits.TRISB5 = 0; // RS
  TRISBbits.TRISB3 = 0; // E
  TRISDbits.TRISD4 = 0; // R/#W
  PORTBbits.RB5 = 0;
  PORTBbits.RB3 = 0;
  PORTDbits.RD4 = 0;

  //*************************** timer3 config
  /* pin esterno, presc 1, sincro, 16bit, off
   */
  TRISAbits.TRISA5 = 1;
  RPINR6 = 2; // T3CKI su RA5
  T3CON = 0b10000010;
  PIE2bits.TMR3IE = 1;
  IPR2bits.TMR3IP = 1;

  //******************************* timer0 config
      /* include anche i suoi interrupt*/
    /* off
     * 16bit
     * fosc/4
     * 256 prescaler
     *
     *
     *
     */
   
    T0CON = 0b00000111;

    /* abilita il timer int, bit 2 IF timer 0, low prior*/

    INTCONbits.TMR0IE = 1;
    INTCON2bits.TMR0IP = 0;

      //***************************************** Priorità e int
    /* interrupt enable di tutto il resto, PIE*/

    /* interrupt priority per ogni periferica IPR*/

    /*The RCON register contains bits used to determine the
    cause of the last Reset or wake-up from Idle or Sleep
    mode. RCON also contains the bit that enables
    interrupt priorities (IPEN).*/


  RCONbits.IPEN = 1;
  INTCONbits.GIEH = 1;
  INTCONbits.GIEL = 1;

}

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 19:29
da Candy
In tutta questa storia, assumendo esatto il programma, in grado di misurare e compensare le latenze interne, hai considerato l'oscillatore del PIC come riferimento di tempo "perfetto".
Forse 32 kHz rispetto a 20 MHz o più sono pochi ed il risultato potrebbe essere accettabile, ma già ora non hai nessun riscontro sulla reale recisione dello strumento di misura realizzato.

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 19:49
da DirtyDeeds
Se non la smettete di usare il termine precisione vi banno :mrgreen:

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 19:51
da Candy
Io mi tiro fuori... Non l'ho mai usato! :mrgreen:

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 21:27
da thexeno
DirtyDeeds ha scritto:Se non la smettete di usare il termine precisione vi banno :mrgreen:


Ah? Il termine è corretto. Io devo trovare una sua tolleranza di misura, non posso assumere che sia "precisa". In quel senso l'ho usato e mi ha infastidito un po questo commento. Pace.

ps: forse nel titolo avrei potuto mettere incertezza al posto di precisione, al massimo..

Candy ha scritto:In tutta questa storia, assumendo esatto il programma, in grado di misurare e compensare le latenze interne, hai considerato l'oscillatore del PIC come riferimento di tempo "perfetto".
Forse 32 kHz rispetto a 20 MHz o più sono pochi ed il risultato potrebbe essere accettabile, ma già ora non hai nessun riscontro sulla reale recisione dello strumento di misura realizzato.


Tornando a noi, il programma è solo quello. La compensazione non la faccio e non è implementata. Quella era un'idea del suo utilizzo.
E come faccio ad avere un riscontro? Devo in qualche modo calcolare l'errore, o i frequenzimetri hanno un errore calcolato da mago merlino? :mrgreen:
L'errore del quarzo è quasi banale da trovare, con un datasheet. Ma per il resto? E' corretta la mia ipotesi?
Perché studiando i frequenzimetri è ben spiegato l'errore, ma non si assume che l'hai fatto te e quando c'è un dT da qualche parte, è una tolleranza che da il costruttore. Ma in questo caso il costruttore sono io... :-|

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 22:09
da DirtyDeeds
thexeno ha scritto:Il termine è corretto.


Precisione vuol dire tutt'altro: la precisione è una misura della dispersione dei valori di una grandezza nel caso di misurazioni ripetute e non va confusa con altri termini, come accuratezza.

thexeno ha scritto:i frequenzimetri hanno un errore calcolato da mago merlino?


I costruttori di frequenzimetri (quelli seri) non dichiarano l'incertezza di misura, ma solo la risoluzione e la stabilità della base tempi. Se uno ha bisogno di una misura accurata, invece di usare il campione di frequenza interno allo strumento, utilizza un campione atomico di frequenza.

Ciò che tu stai facendo è misurare la frequenza del RTC rispetto alla frequenza generata da un altro oscillatore al quarzo, di cui però non puoi conoscere la frequenza.

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 22:22
da thexeno
DirtyDeeds ha scritto:
thexeno ha scritto:Il termine è corretto.


Precisione vuol dire tutt'altro: la precisione è una misura della dispersione dei valori di una grandezza nel caso di misurazioni ripetute e non va confusa con altri termini, come accuratezza.



Uhm, mi informerò. Potrebbe anche essere che quel termine sia stato usato per distrazione da chi spiegava certe cose e forse nei libri, a riguardo, neanche si usa.

Non per diffidenza, ma non ti conosco come gli altri utenti e non so se posso fare questa domanda, al massimo ignorala: nella vita lavori in cose del genere? Ovvero, sei specializzato in qualche ramo o tutto quel che sai è derivato da passione che non concilia i tuoi studi pregressi?


Per il resto, adesso vedo un attimo perché mi hai ricordato delle cose che mi son scordato completamente.
A me comunque interessa anche un errore relativo e quello non mi puoi dire che non esiste nelle misure di questo tipo. Non torna qualcosa altrimenti..

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 22:27
da DirtyDeeds
thexeno ha scritto:nella vita lavori in cose del genere?


Mi guadagno il pane con cose del genere.

thexeno ha scritto:Ovvero, sei specializzato in qualche ramo o tutto quel che sai è derivato da passione che non concilia i tuoi studi pregressi?


Sono specializzato e quel che so concilia con i miei studi pregressi.

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 23:20
da MassimoB
Da Treccani...
precisione /pretʃi'zjone/ s. f. [dal lat. praecisio -onis "taglio, troncamento"]. - 1. a. [l'essere preciso, spec. nel fare qualcosa: eseguire un compito con molta p.; lavoro di grande p.] ≈ accuratezza, attenzione, cura, diligenza, esattezza, meticolosità, (non com.) minuziosaggine, scrupolo, scrupolosità. ↑ pignoleria, rigore. ↔ approssimazione, disattenzione, imprecisione, (non com.) pressappoco. ↑ incuria, negligenza, noncuranza, sciatteria. ▲ Locuz. prep.: per la precisione [perché si sappia veramente come stanno le cose: io, per la p., sono il primo della fila] ≈ (fam.) per la cronaca, per la verità, per l'esattezza. b. [capacità di esprimere bene ciò che si vuole dire: parlare con p.] ≈ chiarezza, correttezza, proprietà (di linguaggio). ↔ approssimazione, imprecisione, vaghezza. c. [minima possibilità di errore: p. di un orologio] ≈ esattezza, [di treni e sim.] puntualità. ↔ imprecisione, inesattezza.

Re: Precisione sulla frequenza

MessaggioInviato: 24 mag 2014, 23:25
da DirtyDeeds
Per i termini tecnici è meglio lasciare perdere i vocabolari generici. Qui c'è il vocabolario dei termini metrologici, ed è quello che fa testo in questo campo (sebbene abbia diverse pecche).