Accurate Frequency Counter (0 - 65MHz)


Senior Member
Dear Picaxe enthousiasts,

Since I am in need of a frequency counter for an analog electronics project I googled around and quickly ran into a nice PICAXE implementation (0 - 65MHz) that seemed to satisfy my requirements very well. Its design was published in 2006 (!) by Jeremy Leach, who has been a prolific contributor to this forum (but he has not been hanging around anymore lately I think). The thread and the original program can be found in the PICAXE archives here: Link to Jeremy's implementation

Since this implementation is really old now and on deprecated PICAXE hardware (08M) I decided to modernize it (whilst keeping Jeremy's concept and most of the implementation intact as it seems to be very well designed). I have now built it, did several tests and it appears to perform wonderfully, with a frequency (relative) accuracy of close to 0.1% (but I need to test more).

The hardware setup consists of a 28X2 (with a 16MHz crystal i.s.o. the usual resonator), running at maximum frequency (64MHz), and a 74HC4040 binary ripple counter.

The key changes I made compared to Jeremy' implementation are (as copied from the code implementation):
  • Jeremy's concept & code largely retained (>95%)
  • Adapted 08m to 28x2 with very accurate crystal (the 28X2 is the smallest PICAXE allowing the use of a crystal as its time base) -> no calibration needed anymore!
  • Significantly shorter sample times (4x - 16x) without compromising accuracy (this required a change in the divisor output selection)
  • Addition of SERTXD PC-output for testing or use (in parallel to LCD display like AXE133)
  • Minor comments changes + clarifications
All credits really go to Jeremy, I have merely polished the program towards the current hardware standards and made some performance improvements because of that.
The code is strongly documented (but also check the 2006 thread) and includes detailed information on the hardware setup needed.
I also attached a simple 08M2 frequency generator program for quick testing of the frequency counter using 4 frequencies (4KHz - 4MHz)

PS1: There is still room for significant improvement (theoretically a tenfold increase in accuracy, and the 28X2 has many more inputs to make that happen) and I am working on that right now, but for most practical applications the current program will serve very well.
In case anyone sees an issue or improvement then I am happy to be informed!

PS2: I tested using the SETXD output, as I currently do not have an AXE033/133 LCD display at hand. But I did not make any changes to Jeremy's part of the LCD code ...



Last edited:


Senior Member
Thanks Kranenborg, for the update of a real “classic” PICaxe project.
I have also used the 28X because of its external oscillator capability.
In one instance where I required very high precision, I actually employed the 10 Mhz signal from a GPS disciplined oscillator.


Senior Member
Here is a version that should be more accurate because:
  1. It uses more 74HC4040 lines, resulting in smaller intervals (avoiding potential rounding errors due to low count figures at the lower end of an interval)
  2. #counts maximized by aligning interval boundaries with multiples of 2^16 (resulting in max count numbers registered (i.e. close to 65536) near the upper end of each interval)
The electrical circuit is documented in the code. It does not suffer from the COUNT accuracy issue as discussed > here <
I do not have equipment to validate my statement on "beautiful accuracy" , though :ROFLMAO:



Senior Member
Thanks for that. I'm trying to get it working properly.
When I used the PWMgenerator program, I found that the PWM is reset every 10 seconds or so, giving a jittery output as it restarts each time it checks the input settings. I modified the program so the PWMOUT command is only executed if the settings have changed.
REM This is a simple frequency generator
REM Four freqs are generated by a 08M2
REM ---
REM Jurjen Kranenborg, 08-09-2020
REM Modified Derek 18/2/21
' From

#picaxe 08m2

REM Connect the following input (C.1, C.3 or C.4) to ground and you will see
REM the resulting frequency as PWM output on pin C.2:
REM     C.1 low -> 4KHz
REM      C.3 low -> 40KHz
REM     C.4 low -> 4000KHz
REM   no connection -> 4MHz (all inputs are high due to pullups!)
REM You may change the inputs while the circuit is running, after a few (max 4) seconds
REM the frequency response will follow ...

SYMBOL datain    = b0
SYMBOL lastin    = b1

SYMBOL inmask    = %00011010
INPUT C.1, C.3, C.4
PULLUP inmask

GOSUB Alter            ' Start off checking the setting

    datain = pinsC AND inmask
    IF datain<>lastin THEN
        GOSUB Alter    ' The setting changed so change the frequency

' A change occurred. Find it and act on it.
    lastin = datain
    IF pinC.1 = 0 THEN
        PWMOUT pwmdiv16, C.2, 124, 249 ;    4000Hz (4KHz) at 50% @ 32MHz (C.1)
    ELSEIF pinC.3 = 0 THEN 
        PWMOUT C.2, 199, 399 ;             40000Hz (40 KHz)at 50% @ 32MHz (C.3)
    ELSEIF pinC.4 = 0 THEN
        PWMOUT C.2, 19, 39 ;             400000Hz (400 KHz) at 50% @ 32MHz (C.4)
        PWMOUT C.2, 1, 3 ;             4000000Hz (4MHz) at 50% @ 32MHz ( - )