10MHz frequency counter - Page 1
Forum section: electronics / general

author: Cloud
author_rank: Regular Contributor
timestamp: April 09, 2017, 02:06:47 pm
content: I have made DCF77 frequency reference and for testing it I would like to have a resolution of readings 0,1Hz. Well the frequency counters at school don't go that low. Other possibility is Philips frequency counter (I would use it with GPS 10MHz reference) but the problem is that you can get data out of it only via GPIB. So I was thinking about using a microcontroller where a 32bit counter would be counting rising edges and every 10seconds (GPS 1pps divided by 10) would interrupt and send data over serial port and restart counter to zero. Would this work? I assume the mcu with 48MHz clock wouldn't be fast enough to execute all these things between two 10MHz pulses.

author: Gibson486
author_rank: Frequent Contributor
timestamp: April 10, 2017, 12:29:52 pm
content: What are you actually trying to do? I mean...they makes devices that do they very thing you are trying to do (measure frequency) and there is one device that actually will display the waveform (an oscope).To do this with a micro would suck because....100 ns....think about that. They do have ns response digital inputs, but then you need to take into account the amount of time it takes you to add, store, and break out of a loop. Is it possible? Maybe, but you would probably need to not use your typical MCU library (sure as hell not the Arduino one). You need to figure out how many clock cycles you can spare. Seeing as how you are only 4.8 times faster than your intended signal, you do not have much to spare.

author: CJay
author_rank: Super Contributor
timestamp: April 10, 2017, 12:46:33 pm
content: Well, kinda, but no.Plenty of 60MHz frequency counters out there that use the CCP module in a PIC microcontroller that runs at, for instance, 10MHz, they're relaible and accurate.What we need is a little more information about what frequencies the OP wants to measure

author: Kleinstein
author_rank: Super Contributor
timestamp: April 10, 2017, 03:00:13 pm
content: Using a µC is a very viable way to make an medium quality frequency counter. Today the usual way is a reciprocal counter, using µC internal timers to do time-stamping. The upper frequency limit is more limited by an often external prescaler, that divides down the signal frequency to a range the µC can manage well. For the reciprocal counter way the external prescaler has no significant negative effect and thus an output frequency can be chosen suitable for the µC to handle. Most of the counting is done with the timer hardware in the µC - so no need for a super high speed µC.

author: Luminax
author_rank: Regular Contributor
timestamp: April 12, 2017, 09:29:20 am
content: I'm currently building one too for my company's testing equipment.Utilizing PIC18F's 64MHz internal oscillator (yes, I know, not really spot-on accurate) to measure two or three type of frequencies :1) 256Hz LCD 'beat' signal derived from clock crystal 32.768kHz divided by 128. Margin for error is 256 ± 0.010 Hz2) IR "carrier" frequency at 37.9kHz ~ 40kHz (DUT dependant) with ± 0.1~0.3 kHz3) Ceramic Oscillator ranging from 2MHz~8MHzwith base frequency 64MHz, the fastest the Capture/Compare/PWM module can timestamp the timer (in this case TMR1) is FOSC/4 since running TMR1 at FOSC runs the risk of causing improper edge detection (though I might want to try this... hmmmm).Regardless, CCP, and TMR1 running in state machine mode gets me down to quite a nice resolution and accuracy.for F = 256 Hz, if I use "every rising edge" option on CCP, it'll give me T= 1/F = 3.90625 mswith F reference at FOSC/64 = 16 MHz, the TRef = 1/FRef = 62.5 nsgiving you 62500 counts for a one period, well within the 16-bit of TMR 1 (65536 count).In this particular case, a one out count up and down will give me :* miscount/error up : 62501 count. 1 Period of the counted Frequency -> 62501 * 62.5ns = 3.9063125 msgiving Fin = 1/3.9063125ms = 255.9959 Hz (rounded to 4 decimal points)* miscount/error down : 62499 count. 1 Period -> 62499 * 62.5ns = 3.9061875 msgiving Fin = 1/3.9061875ms = 256.0041 Hz (rounded to 4 decimal points)Well within my plus-minus range.Dividing the source frequency down to 16 using the CCP divide-by-16 prescaler helps increase the resolution, but you have to prepare to go into the land of Timer and CCP interrupt management (which can be done, as I believe the timer keeps counting regardless of whether you're in interrupt or not, unless you stop it) and adds a counter to count how many of '16-bit' have you overflowed by.In this particular frequency example, dividing by 16 gives you 16 Hz, with period = 1/16 = 62.5ms. this gives you a nice 1,000,000 counts for a 'one period' (which is essentially 16 periods prescaled down to 1).</endrant>

author: Kleinstein
author_rank: Super Contributor
timestamp: April 12, 2017, 04:08:58 pm
content: Handling timer overflow in time stamping mode is possible, though it can be tricky. It might need extra care for the case of an timer overflow and capture event happen very close together. This is nothing magic, but needs some attention to details.Once the frequency handled with time stamping is reasonable low (e.g. <10- 1000 kHz, depending on the µC) the µC can also take care of the number of capture evens in software. So no more need to divide down lower in hardware. In many cases one can get a way with a single switchable divider in front of the µC. Up to something like 100 kHz the µC can directly handle the signal by time-stamping. A divider by 512 stage would extend the range up to about 50 MHz and it can still be used for frequencies down to a few kHz without getting a sluggish update rate. So there is plenty of tolerance in whether to use the divider or not.

author: Luminax
author_rank: Regular Contributor
timestamp: April 12, 2017, 04:48:49 pm
content: My first consideration when I started the project was to use synchronized 4-bit counters in an 8-bit, 16-bit or even more configurations. That was before I came across CCP/ECCP in PIC.I might re-visit this idea since those counters (classic 74XX161/163/191/193 etc) are veeeery cheap and compact these days. On top of the more precisely calibrated and controlled 10MHz or so reference frequency (after all, a counter is only as accurate as its reference), add in some phased reference frequency and some charge time unit to measure any 'discrepancy' between the start of the input signal and the reference signal (interpolation) and... yeah, that's still a long way off but eh, 16-bit counters only take 4 chips, and 64-bit only take 16 chips

author: Kleinstein
author_rank: Super Contributor
timestamp: April 12, 2017, 05:27:16 pm
content: When using the reciprocal counter mode, there is no need to read out external counters. One only needs an external divider. Usually something like a factor of 128 to 1024 should be OK. If the µC allows to chose the input for the capture function, one can even get away without an external switch / MUX to chose with and without divider. So it is the µC and one chip like 74HC4020 or similar.If you really get it fast (ASM) the PIC16 might be able to keep pace with an 500 kHz signal without the divide by 16 mode thus an 8 MHz signal even without an external divider. However I am not sure about the exact limit, and programming in ASM can be tricky.Having an separate timing clock makes things way more complicated. So if possible run the µC with the accurate clock or one derived from it. So either a µC with internal PLL or one that can run timers directly on the speed of an external clock (e.g. Ateml AVR) would be an advantage.

author: Luminax
author_rank: Regular Contributor
timestamp: April 13, 2017, 07:43:02 am
content: What I'm trying to say Kleinstein, is to relegate the whole counting process to a dedicated circuitry, with the UC controlling the start/stop timing etc, and maybe adding some interpolation.To be totally truthful, though, I'm just dying to design some old-fashioned digital logic based system and get 'em jazzing with the PICs

author: Rerouter
author_rank: Super Contributor
timestamp: April 13, 2017, 11:57:05 am
content: many timer peripherals allow a clock divider on the external input, meaning you can still do your reciprocal counting for higher frequencies (now implementing that into my own code base) e.g. 8Mhz input, divide it by 16, and do your reciprocal on the timer overflow interrupts.

author: Luminax
author_rank: Regular Contributor
timestamp: April 13, 2017, 03:53:18 pm
content: That is exactly what I'm doing right now. Although unfortunately the one I'm using, PIC18F45K22, only have a divide by 16 prescaler maximum but eh, external prescaler is not too hard to slap in combined with some multiplexing to choose what's the prescale I'm going to use.Going back to prescaling, as I've mentioned in my previous post, one of the frequency I'm measuring is 256, and divided by 16 that's 16Hz.F = 16 Hz, T = 1/16 = 62.5msgiven our minimum reference to be 16Mhz using the internal FOSC/4 of the PIC18F, we have :Count = (1/16)/(1/16,000,000) = 1,000,000 counts.Given a 16-bit timer, we'll find that if we reset properly (or even if we don't as long as we keep count) :1,000,000 / 65536 = 15+ overflow.Now, what about the resolution ? given that a spot on 16Hz counts 1,000,000 thus giving us x16 Frequency of 256 Hz,We have :Up count = 1,000,001 * 62.5ns = 62.5000625ms; F = 15.999984000015999984000015999984 Hz (yay for copy paste)Let's cut that to 15.999984 (Although I'm kinda suspicious about the whole floating point operation)Giving us x16 of : 255.999744Down count = 999,999 * 62.5ns = 62.4999375ms; F = 16.000016000016000016000016000016 HzCutting to 6 decimals we get 16.000016, giving us x16 of : 256.000256On the up count, one miscount, or just generally a 'step' (btw, up count mean lower Frequency, which I'm sure you all know, just reminding) is equal to :255.999744/256 = 0.999999 or a 99.9999% out from the supposed/assumed 256 Hz, giving us the resolution of 0.0001%While on the down count we have :256.000256/256 = 1.000001 or a 100.0001%, again a deviation of 0.0001%Now all this would be pretty meaningless if we have an inaccurate Reference Frequency, or we do not properly handle the signal in external prescaling causing all sorts of stray inductance/capacitance affecting the reading, but that's par for the course.</endrant>

author: Kleinstein
author_rank: Super Contributor
timestamp: April 13, 2017, 05:26:49 pm
content: One the signal is slow enough to do reciprocal counting, the µC can also measure the time for more than one period, just by counting periods in software. This usually is that in the capture interrupt the time for the even is measured and checked if the time from the start is long enough to calculate a good result. If not, one is just counting the interrupt calls. So the relative resolution is largely independent from the input frequency. So with 16 MHz timer clock one would get 7 digits of resolution after a little less than 1 second.Besides classical reciprocal counting, there is also another option with the same hardware. Instead of looking at only the first and last timing event, one can also use all the timer event in between. This can give an even higher resolution. The typical method proposed here is calculation a linear regression of the times. This is equivalent to calculating an weighted average on the frequency calculated form the first and last, the 2nd and 2nd last and so on. Ideally this gives an much higher resolution, usually higher than actual accuracy. This method is called continuous time stamping counter. However proponents of this method usually don't tell you that it depends on the type of frequency noise present which method gives better (lower noise) results. With noise that is more like a phase noise (e.g. errors from the trigger circuit) the continuous time stamping is indeed better - with noise more like a kind of FM modulation (e.g. noise intrinsic to the oscillator) the simple reciprocal counting can be better. In intermediate cases other combinations of the captured times can give better results than both extremes.So depending on the signal to measure it might be better to increase the timing resolution, e.g. with a fast µC (many ARM based µC could use something like a 100 MHz timer clock) or with analog interpolation for the time stamps.

author: newbrain
author_rank: Super Contributor
timestamp: April 13, 2017, 08:54:21 pm
content: Quote from: Cloud on April 09, 2017, 02:06:47 pmUp to 20MHz (tested, maybe more with some care)?Just get yourself a PSoC5:Ultra cheapdevelopment boardProgrammable HW, just design what you need.Decent IDESimple driver library, APIs are automatically generated from the design, easy interrupt handling, no hassle clock definitions etc...By coincidence, I was just given a goodish OXCO -not trimmable, but precalibrated (-2ppb), and +/-50ppb at 1.5 years- and decided to do a simple reciprocal frequency counter.Everything in the attached schematic is on chip, the custom ProgDivider component is just a chain of /10 dividers and a multiplexer.The SW is about 300 lines, including many comments.Here's the core interrupt handler to read the period, to give a taste of the generated APIs (e.g.PeriodCounter_ReadCapture())Code:void Count_Interrupt_InterruptCallback(void){// Only act on a capture interruptif (!(PeriodCounter_ReadStatusRegister() & PeriodCounter_STATUS_CAPTURE))return;// Disable this interrupt to avoid flooding if input frequency is too high// for the current range, will be re-enabled after some ms.Count_Disable();static uint32_t lastCount;uint32_t thisCount = PeriodCounter_ReadCapture();// Only report period if main loop is freeif (!countReady){period = lastCount - thisCount;// Signal new measurement to main loopcountReady = true;}// preserve last count for next capturelastCount = thisCount;// Calculate IRQ inter-arrival time for auto ranginguint32_t newTicks = GetTicks();delta = newTicks - lastTicks;lastTicks = newTicks;// Signal we have a measuredeltaReady = true;// And restart the missing trigger timeouttoNoTrigger = 0;}

author: Luminax
author_rank: Regular Contributor
timestamp: April 19, 2017, 06:27:48 am
content: Just out of curiosity newbrain, what's that program you're using for the schematic? seems kind of familiar...

author: newbrain
author_rank: Super Contributor
timestamp: April 19, 2017, 03:33:23 pm
content: Quote from: Luminax on April 19, 2017, 06:27:48 amThat's PSoC Creator 4.0, the PSoC specific IDE: it includes a simple but effective schematic editor for the PSoC internal FPGA-like programmable HW.Basic stuff such as gates and FF or pre-built components for more complex things can be used; one can define their own component (e.g. my "ProgDivider") or macros. Verilog can also be used.There are also analog parts: PGA, Opamps, comparators etc.A small library of passive and active components is available, to complete the schematic with circuitry external to the PSoC, if desired.For a complete list of the internal components, search the forum for danadak posts.The code editor is what I'd call decent, but not really advanced (e.g.: no git integration).I normally use an external one (VS Code), saving a file auto updates it -both ways- if I happen to have it open in both programs.Written and generated code is compiled with gcc, so it's easy to set up external compilation (as I did with VS Code), but there is no way* to describe the internal HW setup without the Creator tool.* One can find some attempt on the web, with very limited success.

author: NorthGuy
author_rank: Super Contributor
timestamp: April 19, 2017, 07:14:59 pm
content: If you want to measure up to 10MHz with 0.1 Hz precision, you need to distinguish 9.9999999 MHz from 10 MHz. This requires at least 0.01ppm precision clock source. I don't think you can get any clock source which would be so precise over the 10 sec range.Otherwise, most small PIC16F1* have asynchronous counters (timers) which won't have any problems counting the exact number of pulses for a period defined by your clock source.

author: Luminax
author_rank: Regular Contributor
timestamp: April 21, 2017, 07:44:25 am
content: Northguy : that would be direct counting method.I've taken to using reciprocal counting method these days.Assuming you have 10 MHz precision reference oscillator and you want to count a 10MHz input signal,Dividing by 2^16 barely gets you 4 digits down the MHz (9,999 kHz with plus minus after that)In many cases that should be enough I'd say.In this case the multiplier/divider is 65536 and you'd get a "frame" of 6.5ms more or less.I have never understood how exactly does the high end frequency counter employs reciprocal and works the 'gate' time into their calculation.My guess is that they use divider, and then average out the results for the time gate, or close to the time gate? hmmmEither way, it's a long way down the rabbit hole

author: Kleinstein
author_rank: Super Contributor
timestamp: April 21, 2017, 09:05:36 am
content: With a 10 MHz Signal there is not that much difference in resolution from direct counting to low end reciprocal counting. The reciprocal counting has the advantage of getting the high resolution at low input frequencies too.Reciprocal counters don't have a fixed gate time. The setting is more like an approximate value: The simple method is to get a start timing and than count signal periods and use the time for the last edge before the end of nominal gate time as the stop time. The frequency is than number of periods divides by stop time minus start time.Modern better counters use a kind of analog interpolation or similar tricks to get higher resolution (e.g. 1 ns to 100 ps range) time measurements. In addition they can look at more than just the first and last edge.AFAIK some of the PIC18 already include hardware that can be used to get an analog interpolation to get resolution in the ns range. Also ARM based µC are fast enough to directly get a better than 10 ns counting resolution and have enough computing power to do the multi stop interpolation method in real time. So a high resolution counter is not that large anymore.For short time stability a crystal oscillator is not that bad. So 0.01 ppm over something like 1 hour is possibly even for a low end one if the temperature is stable.

author: NorthGuy
author_rank: Super Contributor
timestamp: April 21, 2017, 02:23:31 pm
content: Quote from: Luminax on April 21, 2017, 07:44:25 amEither way you count a number of pulses in your signal and the number of pulses on your time base. Then you divide one by the other.The maximum achievable resolution (not talking about accuracy) depends on the maximum of these two counts. To achieve the 0.01ppm resolution, you need to count at least 100M pulses. You can count 100M pulses either on your signal, or on your time base. Either way, you get the desired resolution.To get 100M pulses on the 10 MHz signal you need 10 seconds and you can do this with $0.50 PIC16F1501 using what you call direct counting (if you count for 100 seconds you get 0.001ppm resolution).Reciprocal counting at 10 MHz will require the same amount of time.You can do reciprocal counting with 100 MHz time base. Then you can get your desired resolution in 1 sec. This can be done with a high end $20 MCU.You can go further. You can get $50 FPGA (or ASIC), build a delay ladder and possibly space your taps as close as 100ps apart (may be even better if you can control jitter), which is the same effect as if your time base had pulses coming at 10 GHz. Then you can count 100M "pulses" and get your desired resolution in 10ms.The latter approach may be good for commercial frequency counter, but the $0.50 direct approach is certainly better for one-time job.At any rate, to achieve 0.1Hz accuracy, you need an accurate time base. And 0.01ppm time base is hard to get.