PIC Projects

A simple 15MHz Frequency Counter

This is a shortened translation from Russian of my article published in Радио (Radio) magazine, no. 11 (2008) 18-21. The goal of this project was to design a simple, reliable, and easily repeatable device. Also, some drawbacks of the previous model are fixed.

Device features

  • Frequency range: 10Hz - 15MHz (*)
  • Amplitude range: 200mV - 15V
  • Resolution: 4 decimal digits
  • Guaranteed accuracy: 3 decimal digits
  • Counting cycle: 0.1sec or 1sec; automatic/manual selection
  • Power sources: single AA battery or external 7 - 15VDC
  • Total price of components: about $20
Counting 14.318MHz
(*)without any changes in hardware it can be easily extended up to 20 - 25MHz depending on AC characteristics of the concrete exemplar of the microcontroller.

Operation modes and accuracy

There are two widely used principles of frequency measurement. The classical one is based on counting of the number of periods in a fixed time interval (e.g. 1sec). This methods was used for years and implemented by using various families of ICs. Its advantage is obtaining a final value of frequency which is ready for displaying. However, in some cases when several frequency measurements in a row are needed (for example by adjusting the frequency of a signal oscillator) this methods noticeably slows down the work.

Another method, which gained popularity relatively recently after making digital processors widely available, is based on measuring the period T of a waveform. The frequency f and the period T are related according to the equation f = 1 / T. Hence, one division is needed to convert the period into the corresponding value of the frequency. But the advantage is that the measurement time is practically equal to the waveform period, which is less than 0.1sec for frequencies above 10Hz.

However, in reality the period T is measured in discrete time units which leads to a finite resolution of the measurement. In our device the unit (hence, the resolution) of the period measurement is t = 200nsec. This is a limitation of the used family of microprocessors, whose maximum clock frequency is 20MHz and each instruction takes at least 4 clock cycles. Therefore, the instruction frequency is 20/4 = 5MHz, which corresponds to a 200nsec period. Since only an integer number of units is used to measure the period T, the measured value by the nature of the method is smaller or equal than the actual value. Most of the time it is strictly less, so the difference between the measured value and the real one is about 1 unit, that is 200nsec. The consequence of this is that the computed value of the frequency, assuming that the waveform period is n units, is between 1 / (n+1)·t and 1 / n·t. In our case, the computed frequency is between 5,000,000 / (n+1) and 5,000,000 / n. The difference between these values is the absolute error of the entire measurement, and it depends on n. The following graph shows the absolute error (the vertical axis) as a function of the waveform frequency (horizontal axis):

error

As it follows from this graph, the absolute error exceeds ±10Hz for input frequencies above approx. 7KHz. Hence, this method is suitable for measuring low frequencies only. In order to combine the advantages of both methods by keeping the absolute error reasonable, the device uses the period-based method for frequencies not exceeding 7KHz and the first (classic) method for higher frequencies. Since the display has only 4 digits, the frequency resolution is in any case above ±10Hz for frequencies above 10KHz. But the measurement time does not exceed 0.1sec in the entire frequency range, which is a great advantage in some applications. To make the frequency resolution consistent, the values between 7KHz and 9.999KHz (for which we only have 3 decimal digits by counting for 0.1sec) are simply multiplied by 10 for displaying. The switching point 7KHz is set up in software and switching between the modes is automatic. If desirable, one can disable the period measurement mode by pressing a button. In this case the frequency counting time becomes 1 sec for frequencies below 10KHz. Another hit of this button enables the period measurement mode again. The left photo below shows an error caused by the measuring the period about the switching point (in this version the switching posing was 10KHz), while the low frequencies are computer exactly, see the right image. In the later case the frequency is provided by dividing the 500KHz clock frequency of another PIC.

Counting error Errorless counting

In addition to the method limitations, another source of inaccuracy is the crystal oscillator. All timing intervals are obtained by dividing its frequency, hence rely on the oscillator. For more information on this the readers are forwarded to the corresponding discussion from the first model description. The 20MHz crystal I use has accuracy of 10ppm, which leads to the entire device accuracy of ±1 least significant digit for frequencies above 10KHz. If the period measurement is disabled, then the inaccuracy in the frequency range 10Hz - 10KHz does not exceed ±1.

Output format

The LCD I used can only display four 7-segment characters. In order to indicate the frequency units (Hz, KHz, or MHz) I used a 3-color LED. If the LED is green, then the displayed frequency corresponds to Hz. Similarly, the yellow color corresponds to KHz, and the red one to MHz (like in traffic lights). The table below shows how the frequency readings look like. The yellowish boxes indicate (invisible) digit place holders on the LCD. The non-meaningful leading zeros are not displayed and the values of KHz and Hz, and also MHz and KHz on display are separated by decimal points.

LCD reading LED color Frequency range Counting time
0. 0. 0. 0    0 - 9 Hz 0.1 sec
0. 0. 1. 2    10 - 99 Hz 0.1 or 1 sec
0. 1. 2. 3    100 - 999 Hz 0.1 or 1 sec
1. 2. 3. 4    1 - 9.999 KHz 0.1 or 1 sec
1. 2. 3. 4    10 - 99.99 KHz 0.1 sec
1. 2. 3. 4    100 - 999.9 KHz 0.01 sec
1. 2. 3. 4    1 - 9.999 MHz 0.01 sec
1. 2. 3. 4    10 - 14.99 MHz 0.001 sec
0. H. F.0.    > 15 MHz 0.001 sec

The frequency values having more than 4 decimal digits are rounded off to the nearest integer having only 4 non-zero higher order digits. For example, the value 12,345,678 is rounded off to 12,346,000 (and 12.35 will be displayed), whereas 12,345,456 is rounded off to 12,345,000 (and 12.34 will be displayed).

Hardware

The counting frequency first comes to a preamp built on a JFET T4 and high-speed comparator U3 of type LT1719. According to the data-sheet it can flip at 60MHz when powered from a single 5V source. This is a little brother of the comparator that I used in my first frequency counter design. The package contains just one comparator, which drops the power consumption down to about 4mA when idle. This time I decided to do it right and prevent any self-oscillating. Several issues have contributed to this. First, the circuitry connected to the inputs has to have resistance possibly below 1K. Second, inverting input should be used. Third, the positive feed resistor R5 increases the internal hysteresis up to about 20mV. Last, but not least, a capacitor between the inputs is needed. The value of this capacitor does not influence on device functionality up to 20MHz, but kills all unwanted self-oscillating.

Schematic Board layout

The voltage at the source of T4 is about 50mV below the one at the joint point or resistors R3 and R4. This way the device sensitivity is very high and is about 50mV. The signal amplitude at the source pin of the source follower T4 is about 0.85 of the input voltage. The comparator prototype is built on a small PCB (the right photo below) and it works just fine in the entire frequency range. The PCB contains the decoupling capacitors C4 and C9. The bottom side of the PCB is used as a ground plane, which significantly improves its stability to self-oscillating. The left photo shows the comparator output by converting a 125Hz sine wave. No oscillation is observed, which is not the case in my first device. The comparator has a shut down control and is turned on 1msec prior to a measurement (wake-up time). This reduces the drawing power in about of factor of 2, which is very important for the battery operation.

Comparator output Counting 14.318MHz

The output of the comparator is connected to the timer TMR1 input of the microcontroller. This unit determined the higher working frequency. According to the data-sheet, the input waveform period should be at least 60nsec (16.6MHz) in the asynchronous mode. However, concrete exemplars work fine up to 20 and some even up to 25MHz. This way the upper frequency limit can be easily extended by respectively modifying the constant HF in the code and recompiling it. The timer can work in the frequency counting mode and in the period measuring mode. In the first case it should be not synchronized with the CPU frequency, since it slows it down significantly. As experiments show, running it in a synchronous mode leads to an error of several megahertz by counting a 15MHz frequency. This mode is used for measuring high frequencies.

The period is measured by reconfiguring TMR1 to work with the CCP block (Capture, Compare, PWM) inside the PIC. This is done by embedded software. In this mode, however, the timer must work in synchronous mode and gets the CPU instruction frequency (5MHz).

A nice feature of the used microcontroller is the built-in LCD block. It generates all waveforms needed to run the LCD, runs in its own thread, and does not use the CPU time. The LCD has 20 pins, out of which only 15 are used. It works in 1:3 multiplex mode and I run it with waveform of type A. Theoretically, waveform B provides a better contrast, but is not recommended with that PIC because of some internal hardware issues (?!) Anyway, I tried it and noticed no contrast improvement. It should be mentioned that the LCD contrast is high enough, even with waveform of type A. Although it is specified as a "high-voltage" one, by some reason no definition of the high voltage is given in the data-sheet. Varitronix manufactures two versions of such LCD which differ in the driving voltage. After my first frequency meter device I am very careful with those voltages and hoped that this one will indeed work from 5V. It turned out not to be the case again. The optimal voltage turned out to be about 4V. This is provided by R12 in the voltage divider on resistors R12 - R15. The other resistors are used to compose the three levels of bias voltages needed for driving the LCD in mode A.

A little challenge was to control the bi-color LED D1. Although it can be controlled directly from a PIC pin, there is no two free pins available. In order to use 1 pin to select 3 LCD states (green, yellow, red) the circuit around transistors T1 and T2 is used. When the voltage on pin 14 of PI is 0V, T1 is open and T2 is closed, so the LED is green. When this voltage is 5V, T1 closes and T2 opens, so the LED is red. When pin 14 is turned to the high-impedance state (reconfigured for input), both transistors open due to the base current of bipolar transistors through resistors R10 and R11. This way both LEDs (red and green) are on, which results in a yellow color. It turns out that not all bi-color LEDs provide a good yellow color. The best mixture of colors (green and red) is in rectangular 2x5mm LEDs. In the round ones that I have, both 3mm and 5mm, one can see two color spots, whereas the rectangular one provides a clean yellow color with no noticeable spots if one looks on it orthogonally to its surface. The photo below (sorry not in focus) demonstrate this issue.

Round LED Rectangular LED
round LED rect LED

The device can be powered from a single AA battery of from an external power supply. In the first case the needed 5V voltage is provided by the step-up DC/DC converter MAX856. The Schottky diode D2 has extremely low direct voltage drop (below 0.3V), which benefits for saving the battery life. The inductor I used is Sumida CRDH5D18 series with a maximum current of 540mA. The current through the inductor according to my measurements does not exceed 100mA. After about 3min and 20sec of inactivity (showing 0 at the display) the unit turns off when powered from the battery. To turn it on again one should press button S2. This way the negative pole of the battery is connected to the ground through the power jack switch J2. The DC/DC converter activates and turns on the PIC. It, in turn, posts 5V on pin 7, which leads to opening of the power MOSFET T3. This transistor short cuts the button and at this time it can be released. This process takes about 1sec. Note that the LED D1 turns on faster than the PIC. One needs to hold the button for about 1 sec, otherwise the device won't turn on. This prevents it from undesirable turning on if the power button is hit incidentally. After the timeout of inactivity, the PIC puts 0V on pin 7, which leads to closing of T3. The battery disconnects from the unit and the leak current through it is below 0.5μA. Diodes 4 and D5 can be omitted, but then the current leak increases up to 14μA. When the device is ON, the voltage drop on T2 is about 20mV, which practically does not introduce any power loss.

If the device is powered from an external poser supply, the battery and the MOSFET are disconnected from the ground, so the button S2 does not turn on the DC/DC converter. In this case the 5V voltage is provided by the linear LDO U4. Diode D3 is needed to exclude the current through pin 1 of U4 when the unit is powered by the battery.

The counter is assembled on a 2-sided PCB. One side of it is connected to the ground, whereas the other one is used for wiring. The LCD, LED, and the buttons are assembled on the ground side of the PCB. Those are the only "through hole" components. The PCB is designed for resistors and capacitors in the 0603 package, however, the ones in a slightly larger one, 0805, can be used too. All transistors are in the SOT23 package.

Prototype Assembled PCB

Software design

After all necessary initialization the program falls into an infinite loop. In this loop we first check whether the button S1 is on and setup the corresponding variable. After this we get a quick frequency count within a time interval of 0.001sec. The maximum value of the TMR1 counter obtained this way is 25000 for input frequencies below 25MHz. The time interval is generated by simply executing a loop with 5000 instructions. Since the timer does not take the CPU time, the delay is accurate. It is important to mention that the obtained TMR1 counter value does not exceed 65536 - the maximum unsigned number representable on 16 bits. Since TMR1 is a 16-bit counter, no overflow occurs and, respectively, no overflow interrupt is requested. This is important because interrupt processing takes some CPU time which would affect the time delay.

If the first quick sample value is above 15000 we display "HF" on display and the measurement cycle is over. Otherwise, we compare the value with 10000. If the counter value is above 10000, that is, it has 5 digits, we round it off to 4 digits and display. Otherwise, the frequency is too low and we start another measurement interval of length of 0.01sec. The processing in this case is quite similar to the above. We round a value off to 4 digits and display, or request a longer measurement interval.

In a similar we proceed with longer and longer measurement intervals, if necessary. Let us mention again, that no overflow of TMR1 occurs, so the produced delays by running the CPU for a certain number of instruction clocks are accurate. Therefore, we make up to 3 frequency samples - within time intervals of 0.001sec, 0.01sec, and 0.1sec. If the obtained value after the last sampling is below 700 (so that the input frequency is below 7KHz), we switch to the period measurement or compose one more time measuring interval of length 1sec depending on the mode.

In the period measurement mode the timer TMR1 is reconfigured to be used for the CCP1 block and is updated with the instruction frequency of 5MHz. The first rising signal edge starts the timer and the next one stops it. In either case a CCP1 interrupt is generated and processed. Within each interrupt we capture the timer value and save it. After the second interrupt the first captured value is subtracted from the second one, this giving the number of 200nsec units in the waveform period. Next, a 3-byte division of 5000000 over the value of the difference is performed, which results in the frequency value. Note that this value is at most 14 bits.

If the waveform period is too large, the timer TMR1 overflows in about 3sec and in this case we report 0 as the frequency value. The timer overflow is caught by the timer interrupt. The program uses the Watchdog timer to process any unexpected events. For example, what happens if we prepared to measure a low frequency and it suddenly raised up? To simply the analysis of what may happen, the Watchdog timer simply resets the code after about 1sec of hanging and the computations start over. To make this working, the Watchdog timer is periodically cleared by the software. In my experiments no Watchdog reset was observed, however.

Summarizing, in our approach with multiple frequency samples we never get a value exceeding 16 bits in binary. This tremendously speeds up all computations, in particular a conversion of the value to display into the BCD representation. It turns out that the the device updates the display so fast that it is often impossible to read it, particularly if the signal source is not very stable. So, our initial goal to speed up the measurements is achieved. In fact, a 0.2sec delay is introduced between any two measurements to slow the device down and give the user a chance to read the display. Remember that the CPU runs at 20MHz clock frequency (provided by the NDK NX2520SA 10ppm crystal) and I recall the time when the first generations of PCs were that fast (PC XT).

Final assembly

The frequency counter is assembled in Hammond 1593Q enclosure. The manufacturer also offers a battery holder kit, but I just used a standard one from Radioshack and glued it to the front cover. The right side of the enclosure has a hole for accessing the external power supply jack. The BNC connector is a low profile Molex part no. 73171-0700. It mounts practically in the middle of the project enclosure height. In order to drill holes in the enclosure I used a mask made from paper (available for download below). One needs to cut off 4 holes for the PCB posts. After that the mask can be placed to the bottom of the face cover from the inner side and used for marking the positions of the holes and LCD opening.

Back view Side view

Although the schematic shows 2N5485 JFET as T4 which I used on the prototype, I did not find one in SOT-23 package. Instead, I used a more widely available JFET MMBFJ112. In this case the resistance of R2 should be about 8.2K in order to get 1.4V at the source of T4.

Downloads


Last modified:Mon, Jan 23, 2023.

12334