Improving Frequency Measurement Resolution & Gremlins

Hacking multi-tool. Get one for $30, including worldwide shipping.

Improving Frequency Measurement Resolution & Gremlins

Postby mrmr » Mon Nov 19, 2012 2:13 pm

Hi All,

I've been playing with my bpv4 recently and I noticed while measuring frequency results were unexpected.

I addressed one of the problems observed as a printing error with bpWlongdecf(). Please see
http://dangerousprototypes.com/track/view.php?id=66

The other problem appeared to be a resolution issue. As an example, while measuring a 2Hz frequency, the measurement was often 1Hz. So I decided to take a stab at improving frequency measurements. I decided to use the prescaler only when necessary. I also decided to measure the period and divide for low frequencies.

I updated AUXpin.c bpFreq() with:

Code: Select all
void bpFreq(void){
        //static unsigned int j,k;
        long l;

        if(AUXmode==AUX_PWM){
                //bpWline(OUMSG_AUX_FREQ_PWM);
                BPMSG1037;
                return;
        }

        //bpWstring(OUMSG_AUX_FREQCOUNT);
        BPMSG1038;
        //setup timer
        T4CON=0;        //make sure the counters are off
        T2CON=0;       

        //timer 2 external
        AUXPIN_DIR=1;//aux input
       
        RPINR3bits.T2CKR=AUXPIN_RPIN; //assign T2 clock input to aux input
        // should be good on bpv4

        T2CON=0b111010; //(TCKPS1|TCKPS0|T32|TCS); prescale to 256
        // counter only seems to be good til around 6.7MHz,
        // use 4.2MHz (nearest power of 2 without exceeding 6.7MHz) for reliable reading
        l=bpFreq_count();// all measurements within 26bits (<67MHz)
        if(l>0x3fff){//if >4.2MHz prescaler required
                l*=256;//adjust for prescaler
        }else{// get a more accurate reading without prescaler
                //bpWline("Autorange");f
                BPMSG1245;
                T2CON=0b001010; //(TCKPS1|TCKPS0|T32|TCS); prescale to 0
                l=bpFreq_count();
        }
        if(l>0x3ff){//if it's less than 1KHz, get a more accurate reading by measuring period
             bpWlongdecf(l); // this function uses comma's to seperate thousands.
   }else{// counting tics is inferior to measuring period for low frequencies
                BPMSG1245;
           l=bpLFreq_count();
      if(l<0) BPMSG1244; // " UNKNOWN ERROR", no timeout but not count either.
           else if(l==0) bpWline("Frequencies < 1Hz not supported");
      else{
         bpWlongdecf(l/100);
         UART1TX('.');
         l = l % 100;
         if (l < 10) UART1TX('0');
         bpWdec(l);
      }
        }

        if(l>0) bpWstring(" Hz");                               

        bpWBR;

        //return clock input to other pin
        RPINR3bits.T2CKR=0b11111; //assign T2 clock input to nothing
        T4CON=0;        //make sure the counters are off
        T2CON=0;
}


which uses a new function bpLFreq_count():

Code: Select all
long bpLFreq_count(void){
        static unsigned int j;
        static long l;

        //timer 4 internal, measures interval
        TMR5HLD=0x00;
        TMR4=0x00;
        T4CON=0b1000; //.T32=1, bit 3

        //one second of counting time
        PR5=0xf4;//most significant word
        PR4=0x2400;//least significant word
        IFS1bits.T5IF=0;//clear interrupt flag
       
        //timeout on timer4 (timer 5 interrupt) while looking for rising edge
   j=IOPOR & AUX;
        //start timer4
        T4CONbits.TON=1;
   // timeout on interrupt
        while(IFS1bits.T5IF==0) {
      // break on rising edge
      if((IOPOR & AUX) && !j) break;
      j=IOPOR & AUX;
   };
        //stop timer4
        T4CONbits.TON=0;

   // rising edge never found, no support for <1Hz
   if(IFS1bits.T5IF) return 0;

        //timer 4 internal, measures interval
        TMR5HLD=0x00;
        TMR4=0x00;
        T4CON=0b1000; //.T32=1, bit 3
        IFS1bits.T5IF=0;//clear interrupt flag
       
        //timeout on timer4 (timer 5 interrupt) while looking for rising edge
   j=IOPOR & AUX;
        //start timer4
        T4CONbits.TON=1;
   // timeout on interrupt
        while(IFS1bits.T5IF==0) {
      // break on rising edge
      if((IOPOR & AUX) && !j) break;
      j=IOPOR & AUX;
   };
        //stop timer4
        T4CONbits.TON=0;

   // rising edge never found, no support for <1Hz
   if(IFS1bits.T5IF) return 0;

        //spit out 32bit value
        j=TMR4;
        l=TMR5HLD;
        l=(l<<16)+j;
   
   // convert to 1/100 of a Hz
   if(l) return(0x00f42400*100/l);
   // error, no timeout interrupt but count still 0.
   return -1;
}


This code seemed to work good for the two high end ranges; however, for the low frequency range (when bpLFreq_count was called) Gremlins went to work.

For an unknown reason this function returned a frequency of f/N where N can be 1 to 4. When N=1the results are exactly what I expect.

Does anyone have any idea what might be going on?
Do I have "special" hardware? Could someone repeat this and confirm the results I see?

Thanx.
mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm

Re: Improving Frequency Measurement Resolution & Gremlins

Postby mrmr » Mon Nov 19, 2012 3:35 pm

It occurred to me that the hardware may not be double sampling on the read. I altered the code loops to do it in firmware:

Code: Select all
        //timeout on timer4 (timer 5 interrupt) while looking for rising edge
   j=IOPOR & AUX;
        //start timer4
        T4CONbits.TON=1;

        IFS1bits.T5IF=0;//clear interrupt flag
   // timeout on interrupt
        while(IFS1bits.T5IF==0) {
      // break on rising edge
                k=IOPOR & AUX;
      if(IOPOR & AUX && k && !j) break;
      j=k;
   };


This revised loop code now functions properly. Patch to follow.
mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm

Re: Improving Frequency Measurement Resolution & Gremlins

Postby mrmr » Wed Nov 21, 2012 2:57 am

I have found edge detection logic in the PIC hardware that, pending testing, may add yet another auto range:
http://ww1.microchip.com/downloads/en/DeviceDoc/39701a.pdf

Unfortunately it appears limited to 16bit timer captures, i.e. the firmware synchronization will likely be retained for the lowest frequencies.
mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm

Re: Improving Frequency Measurement Resolution & Gremlins

Postby ian » Wed Dec 05, 2012 2:47 am

Tyank you so much. Added to the tracker and will test for the next release.
User avatar
ian
Crew
Crew
 
Posts: 10535
Joined: Mon Jul 06, 2009 6:14 am

Re: Improving Frequency Measurement Resolution & Gremlins

Postby mrmr » Fri Jan 04, 2013 8:58 pm

mrmr
Newbie
Newbie
 
Posts: 8
Joined: Mon Nov 19, 2012 1:37 pm


Return to Bus Pirate Support