Author Topic: Cheap PIC Frequency Counter Module (eBay / China)  (Read 5435 times)

0 Members and 1 Guest are viewing this topic.

Online horo

  • Regular Contributor
  • *
  • Posts: 66
  • Country: de
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #25 on: March 22, 2021, 12:35:00 pm »
@Martin,
Well, I don’t really use Github as a blog for discussions. Maybe this should instead be moved to the software related section of the EEVblog?  No idea how to do that apart from creating a new topic.

In the mean time and just to put minds at rest...  :) The comment you quote is true but only applies in the range below 2Hz.  Let me explain:

The basic restriction is that the PIC is edge triggered. You can select whether you want the rising or falling edge initially during setup but that is it. The original frequency counter simply counted the number of edges within the gate time (e.g. 1s). For RPM measurements that is way to coarse, so I implemented a reciprocal measurement of the period at low frequencies.  In that mode, my software needs to see at least 2 (say falling) edges = 1 period within the measurement time which is 1 second as the longest gate time used for very low frequencies. That condition is only guaranteed if the frequency is >= 2Hz, hence at frequencies below 2Hz to 1Hz the display flips between showing the correct value, e.g. 1.23Hz and 1Hz, depending if 1 or 2 falling edges were detected within the measurement period. The closer you get to 1Hz the more likely is it that you just see 1 instead of 1.xx. From 1Hz and below you just see zero. This is what the comment meant. It starts working from 1Hz onward but for a fully steady display you need 2Hz or more.

Ok, let's keep the discussion here as it is really covered by "Projects, Designs, and Technical Stuff".
I see the limitation below 2 Hz, but this was not my idea. Instead I want to understand how you solved it in the higher Hz ranges. You explained your reciprocal measurement with an example for 50.123 Hz:

If the frequency is above 1Hz and below 200Hz, reciprocal measurement is used where my software measures the time from the start of the first period all the way to end of the last full period within the measurement period, and counts the number of full periods, it saw. Example, at 50.123Hz, a period is 19.95ms and 49 full periods fit into 1 second, So the total accumulated time measured would be 0.9775s. 49 would then be divided by this to get the frequency.  Crucially these are not 49 separate measurements where each could be affected by missing an edge. Instead this is is one continuous measurement period and all edges are detected. 

In reality, the time within this software is measured in 20us increments and is stored as a 16bit integer. So 0.9775s equates to the value of 48879. This simplification introduces an error of up to 20us. The poor 8-bit PIC is then doing a 32-bit multiplication of 49 * 50000*1000 and then divides that huge number in another 32-bit operation by 48879 to get the result of 50123. This is the frequency in milliHertz which is then rounded to 2 decimals and shown as 50.12Hz. Should the PIC see only 48 instead of 49 full periods, because of just missing the first edge, it simply uses the values for 48 periods and comes to the same result.  Its slightly more complex than that but in principle this is how things work.

This algorithm works up to 255Hz but I decided to draw the line at 200Hz and switch back to the original mode, because in reciprocal mode the accuracy gets rapidly worse the higher the frequency because the 20us is just too coarse for measuring smaller periods. Sadly changing the 20us inherited from the original firmware without a complete redesign of the software is not possible.

Maybe we can reuse some of your effort, so let me put my thoughts step by step:

- If you measure e.g. 1000.0 Hz for one second (i.e. 50000 ticks of 20 µs) then you will get a period length of 1000 µs and 999 full periods.
Total accumulated period time is 999000 µs, giving 49950 ticks, the reminder to the 50000 ticks (=1 second) is 50 ticks.

- If you measure e.g. 1000.1 Hz then you will get a period of 999.9 µs and 999 full periods.
Total accumulated period time is 998900 µs, giving 49945 ticks, reminder 55.

- If you measure e.g. 1000.2 Hz then you will get a period of 999.8 µs and 999 full periods.
Total accumulated period time is 998800 µs, giving 49940 ticks, reminder 60.

So the reminder to the full 1 second period of 50000 ticks increases with increasing sub-Hz frequency.

IIRC this 499xx value (the full period tick sum) is always available even for higher frequencies.
All we have to do is to calculate the length of one period (in ticks), in my 1000 Hz example i.e. 50 ticks.
This value is calculated by "one_period = 50000 / int( frequency )"
And if you calculate finally "x = reminder - one_period" you will get x = 0, 5, 10, 15,... i.e. 1/50 Hz resolution.

Same calculation for 2000,x Hz gives 0, 3, 5, 8, 10,... so even in higher ranges we have the possibility to get down to 0.1 Hz resolution.

For 9999 Hz the resolution drops to 0.2 Hz.

But in the range 200..999 Hz we could for sure get one valid decimal digit.

I never considered extending the counter the other way, i.e.  below 1Hz operation. The only way to do that would be to extend the gate time / measurement time. That would be fairly easy but having to wait 10 or 100s for each display update seems not very useful.

I totally agree!
 

Online horo

  • Regular Contributor
  • *
  • Posts: 66
  • Country: de
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #26 on: March 24, 2021, 04:11:26 pm »
I had some time to think about my proposal:


Maybe we can reuse some of your effort, so let me put my thoughts step by step:

- If you measure e.g. 1000.0 Hz for one second (i.e. 50000 ticks of 20 µs) then you will get a period length of 1000 µs and 999 full periods.
Total accumulated period time is 999000 µs, giving 49950 ticks, the reminder to the 50000 ticks (=1 second) is 50 ticks.
...
So the reminder to the full 1 second period of 50000 ticks increases with increasing sub-Hz frequency.

IIRC this 499xx value (the full period tick sum) is always available even for higher frequencies.

My idea so far:

Check resolution extension for DL4YHF – Range 200..2500 Hz   
   
   Calculate number of "deci-periods" as correction sum and add it to 10 * pcnt -> result = 10*freq
   The calculation does not exceed the uint16_t range (for the targeted frequency range 200..2500)
   
Input (integer values)   
   
   total (50000 ticks)
   pcnt (total number of full periods)
   sum_of_p (cumulated length of all full periods, measured in ticks)
   
Calculation (expressed in meta-language)   
   
   reminder = total – sum_of_p; // length of not fully captured periods before and after pcnt
   tmp =  reminder/2 * freq + 1250;
   // divide reminder by two to keep the product below 65535, prepare rounding
   correction = tmp / 2500; // rounded number of additional deci-periods
   result = 10 * pcnt + correction; // total number of deci-periods per second = frequency in deci-hertz

NOPE!  |O

I looked again into the source and saw your comments as well as the code:

Code: [Select]
        ; Note 2: This method could create a pcnt that can get too high for the subsequent 32-bit maths
        ;         Therefore there is a check to stop accumulating periods and incrementing pcnt if
        ;               80 (in frequency mode) or 140 (in RPM) mode is reached
...
        ;
        ; check if pcnt has reached maximum. If yes, don't add amy further periods
        ;
...
        goto    P_done          ; [64+1]  stop if pcnt >= 80 (freq) or >= 140 (rpm)


So my idea does not work unless I add a 2nd 16-bit period accumulator and a 2nd 16-bit period counter without compromising the loop timing -> shifted to low priority.

Nevertheless I'm happy with 1 Hz resolution for 256..99999 Hz and the increased resolution below.
 

Online horo

  • Regular Contributor
  • *
  • Posts: 66
  • Country: de
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #27 on: March 27, 2021, 08:59:01 pm »
Next try, at least the range 256.0 .. 999.9 got 1 decimal digit:
https://github.com/Ho-Ro/DL4YHF-Source-Code/commit/7d89af60f1ee40d7922c779da5db1bbfb0862f31

Remarks?
 

Offline theHWcave

  • Contributor
  • Posts: 32
  • Country: gb
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #28 on: March 28, 2021, 01:34:54 pm »
I understand what you mean and agree that this would be great, but unfortunately The PLJ-8LED needs a 13 MHz clock, so a simple 10 MHz GPSDO wont be any good. Also, simple GPS-derived frequency standards don't actually adjust a local oscillator, instead they contain a programmable divider that is normally set to produce the 1Hz aka 1PPS signal. Popular GPS chips like the NEO 7N for example allow you to set the divider to anything you like to change the 1PPS signal to 10 MHz for example. You can also set it to 13 MHz although that is actually outside the spec. The problem is that in the case of the NEO 7N (and probably similar chips) that frequency is full of jitter. If you set it to 10 MHz, you get a precise 10 million pulses in exactly 1 second, in other words 10 MHz, but the width of each pulse is not a constant 50ns, instead some are only 41ns and others 62ns.  This happens only at some frequencies, unfortunately 10MHz (and 13 MHz) are such frequencies. I made an investigation about this here:   Those GPS-based references are still very useful to verify the accuracy of counters. A properly aligned counter should show exactly 10.000.000 because it gets exactly 10 million pulses per second. The fact that the pulses have different length does not matter. However, I don't think using such a signal as a clock would be very good.  The alternative would be a proper GPSDO that uses a PLL to adjust a local TCXO. The mini GPS ref. clock from Leo Bodnar is such a thing that can produce a very accurate and clean signal from 400Hz to 800 MHz. I have one of these and it works very well, but I have not tried using it to replace the oscillator in the PLJ-8LED. To be honest, I don't use the PLJ-8LED much because its horrible pre-amps mangle any input signal all the way to the source so inserting it to measure frequency in a circuit usually means that that circuit stops working or behaves strangely.

 

Offline cdev

  • Super Contributor
  • ***
  • Posts: 6412
  • Country: 00
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #29 on: March 28, 2021, 10:25:43 pm »
I understand what you mean and agree that this would be great, but unfortunately The PLJ-8LED needs a 13 MHz clock, so a simple 10 MHz GPSDO wont be any good. Also, simple GPS-derived frequency standards don't actually adjust a local oscillator, instead they contain a programmable divider that is normally set to produce the 1Hz aka 1PPS signal. Popular GPS chips like the NEO 7N for example allow you to set the divider to anything you like to change the 1PPS signal to 10 MHz for example. You can also set it to 13 MHz although that is actually outside the spec. The problem is that in the case of the NEO 7N (and probably similar chips) that frequency is full of jitter. If you set it to 10 MHz, you get a precise 10 million pulses in exactly 1 second, in other words 10 MHz, but the width of each pulse is not a constant 50ns, instead some are only 41ns and others 62ns. 

IS IT REALLY THAT BAD???

This happens only at some frequencies, unfortunately 10MHz (and 13 MHz) are such frequencies. I made an investigation about this here:   Those GPS-based references are still very useful to verify the accuracy of counters. A properly aligned counter should show exactly 10.000.000 because it gets exactly 10 million pulses per second. The fact that the pulses have different length does not matter. However, I don't think using such a signal as a clock would be very good.  The alternative would be a proper GPSDO that uses a PLL to adjust a local TCXO. The mini GPS ref. clock from Leo Bodnar is such a thing that can produce a very accurate and clean signal from 400Hz to 800 MHz. (But with lots iof jitter, Ive heard this a lot but didn't know how bad it would be for my own applications. Not infrequently this issue comes up for me where I could do something that I want or need ONLY if I could generate this (insert stable time clock signal frequency here, its almost always ithin the range 9-28 MHz. )
I have one of these and it works very well, but I have not tried using it to replace the oscillator in the PLJ-8LED. To be honest, I don't use the PLJ-8LED much because its horrible pre-amps mangle any input signal all the way to the source so inserting it to measure frequency in a circuit usually means that that circuit stops working or behaves strangely.
[/quote]
"What the large print giveth, the small print taketh away."
 

Offline cdev

  • Super Contributor
  • ***
  • Posts: 6412
  • Country: 00
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #30 on: March 28, 2021, 10:49:08 pm »
What is the music you're playing near the end? Its perfect for this subject matter.

"What the large print giveth, the small print taketh away."
 

Online horo

  • Regular Contributor
  • *
  • Posts: 66
  • Country: de
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #31 on: March 30, 2021, 09:16:47 am »
Also, simple GPS-derived frequency standards don't actually adjust a local oscillator, instead they contain a programmable divider that is normally set to produce the 1Hz aka 1PPS signal. Popular GPS chips like the NEO 7N for example allow you to set the divider to anything you like to change the 1PPS signal to 10 MHz for example. You can also set it to 13 MHz although that is actually outside the spec. The problem is that in the case of the NEO 7N (and probably similar chips) that frequency is full of jitter. If you set it to 10 MHz, you get a precise 10 million pulses in exactly 1 second, in other words 10 MHz, but the width of each pulse is not a constant 50ns, instead some are only 41ns and others 62ns.  This happens only at some frequencies, unfortunately 10MHz (and 13 MHz) are such frequencies. ...
The NEO manual restricts possible frequencies. They shall be even divisions of 48 MHz and shall be < 24 MHz, so 12, 8, 6, 4, 3, 2, 1 MHz are quite free of jitter, as well as 4.8, 2.4, 1.2 and 0.96 MHz; I used the last one to calibrate my DL4YHF with origial FW, because the last digit (=10 Hz) was almost exact to 10 ppm. Now I use the "calibration zoom" function of my own FW to come down to 1 ppm (short term).
Also some NEO modules (e.g. the NEO-M8N I use) provide a TCXO as system clock that gives quite stable output even without GPS-lock.
 

Online beanflying

  • Super Contributor
  • ***
  • Posts: 5968
  • Country: au
  • Toys so very many Toys.
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #32 on: March 30, 2021, 09:28:10 am »
Slightly randomly I just finished a case for my cheapy and the filter material for the poorly chosen Blue LED arrived yesterday. I did tweak it a while ago against my GPSDO as is the Siglent. I gave them both a good warmup yesterday and ran the Siglent from 30Meg down across a range to about 100k. Worst case was 1-2 counts off the Siglents set point.

There is a problem with the Neo GPSDO chips they have horrid jitter unless you pick off certain multiples. My quoted post below. EDIT SNAP to Horo  :) Post here https://www.eevblog.com/forum/testgear/test-equipment-anonymous-(tea)-group-therapy-thread/msg2246022/#msg2246022

Quote
It only generates 'reasonable' non horrible jitter at the following frequency steps. 12, 8, 6, 4.8, 6, 3, 2.4, 2, 1 MHz which are all integer divisible from 24MHz. U-Center only allows whole number frequency steps to be sent to the device so it is limiting for higher frequencies without jitter. **Full Bandwidth shown on the Micsig with all the other gear and the screen is 20M filtered.

« Last Edit: March 30, 2021, 10:41:15 am by beanflying »
Coffee, Food, R/C and electronics nerd in no particular order. Also CNC wannabe, 3D printer and Laser Cutter Junkie and just don't mention my TEA addiction....
 

Offline theHWcave

  • Contributor
  • Posts: 32
  • Country: gb
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #33 on: April 02, 2021, 10:21:11 pm »
@cdev:
All music tracks came from the YouTube - copyright-free music library. I'm not sure which piece you mean but the tracks used were "Ether", "Stale Mate" and "Procession" (not necessarily in that order).
Hope that helps
 

Offline theHWcave

  • Contributor
  • Posts: 32
  • Country: gb
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #34 on: April 02, 2021, 10:39:20 pm »
Yes, this matches my findings (as in that video). All frequencies that produce a whole integer when 24 MHz is divided by that frequency are jitter free. At very low <=100 KHz or so, it does not matter too much because any jitter, if it occur, is is very small. But for example 10 MHz jitters between 8 and 12 MHz.

No good to be used as a replacement for a 10 MHz xtal time-base, but as a frequency standard connected to the input of the counter for testing accuracy, it is still ok, even with jitter, because when selecting 10 MHz, the number of pulses per second delivered by the NEO 7N is exactly(*) 10,000,000 and this is what a frequency counter actually measures.   
(*) limited to GPS accuracy of course.
 

Offline JimRemington

  • Regular Contributor
  • *
  • Posts: 191
  • Country: us
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #35 on: April 11, 2021, 11:02:15 pm »
I had a use for the basic kit and wondered how hard it would be to get my old PIC stuff working again, so I bought a couple on eBay.  It was a surprisingly pleasant experience, and I was astonished to discover that MPLAB8 still works with my ancient PICSTART PLUS programmer!

The free XC8 compiler associated with MPLABX supports the 16F628A, so here is a simple XC8 program that simply counts up and displays a 16 bit number.

The code leaves two pins (RA5 and RA4) free for I/O, which plenty to allow the module to be used as a dedicated 5 digit, 7 segment display.  I borrowed the definitions in the frequency counter assembly code to drive the segments.

Demo program:
Code: [Select]

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */

// display data buffer
unsigned char digits[5]={0};

// digit drive table (left=0 to right=4)
unsigned char digit_drive[5]={0x07, 0x0B, 0x0E,0x0D,0x0F};
// digit drive table (right=0 to left=4)
// unsigned char digit_drive[5]={0x0F,0x0D,0x0E,0x0B,0x07};

// bitmask for segment A , etc ..
#define _A  0x40     
#define _B  0x80
#define _C  0x04
#define _D  0x01
#define _E  0x08
#define _F  0x10
#define _G  0x20
#define _DP 0x02
#define BLANK_PATTERN 0
// blank display pattern (7-segment code)

//translate to seven-segments

unsigned char symb[] =
{
 (_A+_B+_C+_D+_E+_F   ), // ABCDEF. = '0'    ( # 0  )
 (   _B+_C            ), // .BC.... = '1'    ( # 1  )
 (_A+_B   +_D+_E   +_G), // AB.DE.G = '2'    ( # 2  )
 (_A+_B+_C+_D      +_G), // ABCD..G = '3'    ( # 3  )
 (   _B+_C      +_F+_G), // .BC..FG = '4'    ( # 4  )
 (_A   +_C+_D   +_F+_G), // A.CD.FG = '5'    ( # 5  )
 (_A   +_C+_D+_E+_F+_G), // A.CDEFG = '6'    ( # 6  )
 (_A+_B+_C            ), // ABC.... = '7'    ( # 7  )
 (_A+_B+_C+_D+_E+_F+_G), // ABCDEFG = '8'    ( # 8  )
 (_A+_B+_C+_D   +_F+_G), // ABCD.FG = '9'    ( # 9  )
 (_A+_B+_C   +_E+_F+_G), // ABC.EFG = 'A'    ( # 10 )
 (      _C+_D+_E+_F+_G), // ..CDEFG = 'b'    ( # 11 )
 (         _D+_E   +_G), // ...DE.G = 'c'    ( # 12 )
 (   _B+_C+_D+_E   +_G), // .BCDE.G = 'd'    ( # 13 )
 (_A      +_D+_E+_F+_G), // A..DEFG = 'E'    ( # 14 )
 (_A         +_E+_F+_G), // A...EFG = 'F'    ( # 15 )
 (_A   +_C+_D+_E+_F   ), // A.CDEF. = 'G'    ( # 16 )
 (   _B+_C   +_E+_F+_G), // .BC.EFG = 'H'    ( # 17 )
 (            _E      ), // ....E.. = 'i'    ( # 18 )
 (BLANK_PATTERN       ), // ....... = ' '    ( # 19 )
 (0xFF                ), // all segments on  ( # 20 )
 (_A+_B      +_E+_F+_G), // AB..EFG = 'P'    ( # 21 )
 (            _E   +_G), // ....E.G = 'r'    ( # 22 )
 (      _C+_D+_E   +_G), // ..CDE.G = 'o'    ( # 23 )
 (_A+_B+_C      +_F+_G), // ABC..FG = 'Q'    ( # 24 )
 (      _C+_D+_E      ), // ..CDE.. = 'u'    ( # 25 )
 (         _D+_E+_F+_G), // ...DEFG = 't'    ( # 26 )
 (_A   +_C+_D   +_F+_G), // A.CD.FG = 'S'    ( # 27 )
 (_A+_B   +_D+_E   +_G), // AB.DE.G = 'Z'    ( # 28 )
 (            _E+_F   ), // ....EF. = 'I'    ( # 29 )
 (   _B+_C+_D         ), // .BCD..  = 'J'    ( # 30 )
 (         _D+_E+_F+_G), // ...DEFG = 'k'    ( # 31 )
 (         _D+_E+_F   ), // ...DEF. = 'L'    ( # 32 )
 (_A+_B+_C   +_E+_F   ), // ABC.EF. = 'N'    ( # 33 )
 (      _C+_D+_E+_F   ), // ..CDEF. = 'V'    ( # 34 )
 (         _D      +_G), // ...D..G = '='    ( # 35 )
};

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/
#define _XTAL_FREQ 20000000

#include <xc.h>

unsigned int counter=0;
 
// separate out the digits of "counter" into display buffer

void update_display(void) {
    digits[4] = counter%10;
    digits[3] = (counter/10)%10;
    digits[2] = (counter/100)%10;
    digits[1] = (counter/1000)%10;
    digits[0] = counter/10000;
}

void main(void) {
    TRISB = 0; //RB as Output
    PORTB = 2; //turn on DP
    TRISA = 0; //RA as Output
    PORTA = 0x0F;  //turn on 5th (rightmost) digit
    __delay_ms(1000); //test display/DP
   
    unsigned char i,j,k;
    // display test, all segments
            PORTB = 0xFF; //all segments on
            for (j=0; j<5; j++) {
            PORTA = digit_drive[j];
            __delay_ms(400);
            }
            PORTB = 0;
           
    while(1) //count up and display result
    {
        update_display();
        for (k=0; k<50; k++) {
        for (j=0; j<5; j++) {
            PORTA = digit_drive[j];
            PORTB = symb[digits[j]];
                __delay_ms(1);
              }
        }
        counter++;
    }
}
Note: exposure caught the display while the last digit was changing.
« Last Edit: April 12, 2021, 02:50:18 pm by JimRemington »
 

Online MikeK

  • Frequent Contributor
  • **
  • Posts: 769
  • Country: us
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #36 on: April 12, 2021, 02:09:05 am »
I still think it needs a proper preamp...I don't like the idea of feeding an unknown signal directly to the PIC pin.
 

Online ledtester

  • Super Contributor
  • ***
  • Posts: 1428
  • Country: us
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #37 on: April 12, 2021, 02:31:25 am »
I still think it needs a proper preamp...I don't like the idea of feeding an unknown signal directly to the PIC pin.

There's one sketched out in this PDF:

http://www.iw1axr.eu/radio/BiTx/Frequenzimetro%20a%20led%20con%2016F628.pdf

(see pages 4 and 6 and 8 )
 

Online MikeK

  • Frequent Contributor
  • **
  • Posts: 769
  • Country: us
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #38 on: April 12, 2021, 12:28:28 pm »
I still think it needs a proper preamp...I don't like the idea of feeding an unknown signal directly to the PIC pin.

There's one sketched out in this PDF:

http://www.iw1axr.eu/radio/BiTx/Frequenzimetro%20a%20led%20con%2016F628.pdf

(see pages 4 and 6 and 8 )

I did what theHWCave detailed...using the kit parts meant for the "crystal tester" to construct a pre-amp.  I just meant that JimRemington should consider a pre-amp.
 

Offline JimRemington

  • Regular Contributor
  • *
  • Posts: 191
  • Country: us
Re: Cheap PIC Frequency Counter Module (eBay / China)
« Reply #39 on: April 12, 2021, 02:11:18 pm »
In my application, "known" serial commands will be used to control the display, so no preamp is needed.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf