Arduino Frequency Counter

Hi DigiKey,

Hope you are doing well.

I need some help and guidance on building a pulse frequency counter with an Arduino or any other cheap microcontroller under $50. I have an analog pulses 486 mV in amplitude and 100 ns wide that are coming from my photodiode TIA at frequency of around 60 Hz. I would like to feed these pulses into a microcontroller and have their frequency displayed on an OLED screen. But given the Arduinos UNO and Nano clock speed and minimum input voltage requirement, I think I would have to stretch the pulse and make them larger. I tried using the TL714 comparator to see if it is capable of processing nanosecond wide pulses from my oscilloscopes function generator, it works fine, and the pulse is 4 V in amplitude, but the majority of the pulse is below 0 V. I was thinking of stretching the pulse to 1 microsecond using a LMC555 timer, it has minimum trigger voltage of 400 mV and 20 ns. I can use the LMC to stretch the 4 V pulse that is coming from the comparator. Or I could use the timer first and then use the comparator. The entire purpose of using the comparator and timer is to condition my pulse for a microcontroller like the Audino because they are relatively short and small (500 mV and 100 ns). My main goal is to just make a portable pulse/frequency counter for these pulses using an OLED and a microcontroller. If you know of any microcontrollers that can count my pulses in their original form, I will prefer to use that. I hope this is enough information for someone to guide me. I was not able to upload images of the pulse to this forum. Thank you.

With Arduino, frequency counters are pretty straight forward.

You could use an Op Amp to bump that signal up and read the frequency on an analog pin with a library, like This one for example by ArminJo

Otherwise a comparator would certainly work and you could use a digital pin like this one from author Paul Stoffregen

That’s a great project, we’d welcome any updates on your progress.

1 Like

Thank you for the reply, Kristof,

I tried using a second stage Op-Amp for amplification but there was too much signal degradation. That is why I switched to a comparator. If I use the digital pin on the Arduino, will it work for counting the 4 V 100 ns pulses as is, no need for stretching them? The pulse frequency is 60 Hz so there is plenty of time between the pulses.

One would need to read the specs of the actual microcontroller on the “arduino” chosen to determine if it would be capable of recognizing pulses as narrow as 100 ns. As a general guideline, most MCUs don’t play well with signals that are faster/narrower than their own clock cycle.

TL714 would not be my choice of comparator, because its input common mode range won’t let you run it single-supply and process inputs that are in the 500mV range. Something like a TLV3501AIDR doesn’t cost much more and would seem a lot more convenient.

As an alternative, there are microcontrollers with built-in linear comparators that are pretty speedy. PIC24EP32GP202-I/MM might be one example that 'aint expensive.

An alternative if one doesn’t wish to leave the cozy confines of the arduino ecosystem or buy the latest hot-rod board might be to take the output from one’s comparator and pipe it into the clock of a flip flop such as a 74LVC1G74DP,125 that one sets up to toggle state on each clock input. Now that train of narrow pulses at 60 Hz looks like a 30Hz square wave, which should be measurable using most any micro controller that doesn’t squeak when chewed on by the dog…


Hi Rick,

Thank you for the explanation.

The Arduino has a clock speed of 16 MHz, so it is not fast enough to process my pulses in their raw form.

The TL714 has a common-mode input voltage of -1.4 to +1.4 V, doesn’t 500 mV fall with in this range. I powered it with 5 V and grounded the other terminal. Am I missing something? If you say the TLV is better, I can try that out.

Regarding you last comment about the 30 Hz, I need to increase the duty cycle of these pulses without changing the frequency. Maybe I can try another microcontroller board like the Teensy 4.0. It has a 150 MHz clock speed on the input pins, but I would still need a comparator to make a larger square pulse. I need to figure out the most efficient way to count the pulses so I can get pulses/second on an OLED .

The datasheet I’m looking at indicates that a common-mode input closer than 1.4v to either supply rail is not recommended. Assuming your input signal is ground-referenced, it’d be very much outside of the happy zone in a 5v single-supply environment.

It doesn’t appear that you’re quite understanding the suggestion. By converting each pulse to an edge, you’d “stretch” them by the maximum amount possible. Frequency being the inverse of period and whatnot, by measuring the time between edges on that converted signal and doing a bit of math, a 16 MHz clock should be sufficient to offer something like ~19bit resolution on your measurements, updated on a pulse-by-pulse basis and basically as accurate as your oscillator. Note that you’ll probably want to apply some sort of digital filtering to the results in order to be able to read the display…


I understand now what you mean by the common-mode voltage now. It looks like I will have to convert the analog pulse to digital one that is on the order of 3 to 5 V.

So just to clarify, the clock speed of an Arduino is more related to the frequency of the pulses coming in rather that how short they are, If I am 60 pulses per second, it will detect all of them?

I am new to all of this, so I am trying to be careful with what I understand.

Hi @aab5544 ,

You could consider also using Arduino’s INT0 or INT1 interrupt inputs. Those interrupts are asynchronous, i.e. should be able to capture even 100ns pulses (datasheet does not say anything about that, but I guess it is fair to assume that the capturing SR-latch can handle 100ns pulses).
Alternatively could try to use the internal comparator of the Arduino (atmega328) to trigger the comparator interrupt, which is assumed to be asynchronous as well (again the datasheet is not very helpful here).

If one of these options sounds testable, but you’d need more info about how to do the implementation, kindly let us know.

Cheers, heke

1 Like

Not sure how much basic electronics/physics education you have but this may help.

Frequency and period are related by a very simple equation, f(Hertz) = 1 / T(seconds).
Your 100 ns pulse has an equivalent frequency of:
(100 ns = 0.0000001 s = 1e-7 s)
f = 1/1e-7 = 10,000,000 Hz = 10MHz

The processor has to be fast enough to read when each edge of the pulse occurs . The 16 MHz processor is only slightly faster than the pulse edge occurrence. It takes a minimum of one clock cycle to perform an instruction and some instructions take multiple clock cycles to execute. With clock speed only 1.6 times faster than the time between pulse edges this micro is too slow for accurately measuring such a short pulse.

When you are the counting the frequency of the pulses the processor only needs to be fast enough to capture one edge of each pulse. So with pulses coming in at a 60 Hz rate a 6000 Hz processor would be fast enough to execute many dozens of instructions between pulses.

It’s early and I’m still on my first coffee, so if I muddled this explanation hopefully somebody else on the forum will fix it.


Hi heke,

Thank you for you reply. What you said sounds promising and yes, I couldn’t find anything in the data sheet regarding minimum input pulse width. If you can point me in the right direction as to where I can find tutorials and information about both options it would be greatly appreciated.

Best regards,


Hi Paul,

Your explanation makes sense. Yes, I am not analyzing the whole pulse, just counting their frequency, so 16 MHz sounds fast enough to detect the waveform’s voltage that spans 100 ns. Now I just need to figure out what is the minimum voltage the pulse needs to be for the arduino to detect it. 500 mV is not small, but if I use a comparator to make a square wave from it, It would be need to know what voltage. Thank you for the frequency and period explanation. That really helped.

Best regards,


I’d start with the comparator trip point for 1/2 the expected amplitude to give 50% margin on the high and low sides. Test how well it performs and adjust as needed.


Sounds good, I was tripping it at 400 mV. I’ll reduce it to 200 mV, run the output to the Arduino and see if it works. Thank you.

Hi Aamer @aab5544,

Actually there are quite many ways that you can take to implement this. The simplest one is to e.g. enable INT0 interrupt as rising edge triggerable and poll the interrupt flag of the INT0 in a software loop. Once the flag is set, just increment a pulse count variable, clear the flag and read the variable value once per second to get the frequency. A bit more complex setup is to have an interrupt routine that is launched when the edge is detected at INT0. The routine then increments the count variable.
See this document:
Yet another way is to use the Arduino’s counters. They can be clocked from external source (T0, T1 pins). Just configure a counter to count the input pulses and readout+reset the count every second to get frequency in Hertz.
Yet more another way is to make the input signal edge to trigger a counter capture. That is, you can set a counter to count system clock pulses (through prescaler if needed) and use your input pulse edge to capture the counter value. That way you can get more accurate frequency measurement (count value is inversely relative to the input pulse frequency). However, the pulse capture feature may be synchronous to system clock, thus may not be able to react to 100ns pulses reliably.
Take a look at here:

I wonder, could you show to the forum your TIA circuit? Perhaps there is a chance to increase the signal swing already at the TIA, removing the need for comparator or additional gain stages.
Cheers, heke



The interrupt method sounds better than the trigger. I think it would be easier for the Arduino to only flag a pulse when it arrives rather than constantly spinning its wheels looking for one. I’m going to read up on the coding that is involved with this method and later purchase an Arduino.

Regarding the TIA, it is on a breadboard so I will just tell list the parameters:

  • Op-Amp: LT1226
  • Rf: 100 kOhm
  • Cf: 0.1 pF
    The is an CR-RC filter at the output to remove the DC offset. What you said about increasing the signal swing should work by increasing Rf. I started with 10k, 20k, 47k, 60k and eventually stuck with 100k because it gave me the best energy resolution. If I go above 100k, I think it was 120k, the pulse doesn’t resemble a Gaussian peak anymore. It is more of a squarish hill. It is 1 microsecond wide and 1 V high. I can mess around with Rf and see what happens. Should I aim for a 1 Volt amplitude and pulse width on the order of microseconds? What pulse is good enough for the Arduino without the use of a comparator? I can alter my TIA to match that. I have attached an image of the output pulse of the TIA (100 k Rf 0.1pf Cf).

Also, regarding the TL714 comparator. I tested it with the function generator on the scope and it is capable of converting nano second millivolt pulses to digital ones. I have also attached those images.

I think I have a lot of testing I need to do with the TIA, comparator and Arduino now. At this point I might as well take all the advice I was given and see what works. I have counted these pulses by connecting the TIA to a single channel analyzer (basically a comparator) and timer and counter. But those are bulky lab systems that cost thousands of dollars. I’m trying to a make everything cheap and potable. Thanks again.


Hi Aamer @aab5544,

Regarding the input threshold for a logic “High”, here’s the spec for the ATmega328P, which is the part used in the Arduino Uno R3.

From page 406 of ATmega328P datasheet:

So, for a 5V supply, which is typical for the Uno, your logic High input should be at least 3.0V (0.6 x Vcc). It may work with lower voltages, but it is not guaranteed, and so may not give you consistent results under all conditions.

1 Like

Hi Aamer @aab5544,

Nice waveforms!
OK. Fiddle with the Arduino’s resources to find the most suitable solution and drop here a line if you get stuck. Interrupt based read-out may be the best way to go. It is the least invasive (i.e.takes MCU cycles only when an edge iarrived).

For the TIA, there may perhaps be better alternatives these days (e.g. R-R output swing, non-BJT input stage, …). Do you have the 51 Ohm resistor from the photodiode to ground? What are your supply voltages for the TIA? What is the wavelength of the received light?
@rick_1976, @David_1528, @PaulHutch, @Kristof_2649 and @APDahlen may have more experience on photodiode preamps. Any recommendations gents?
Cheers, heke


Hi David,

Ah I see, now I know what voltage to shoot for. 3 V will be my target. Thank you for finding this information in the document. I think the UNO and Nano both use the same processor.


1 Like

Hi aab5544,

The Nano comes in multiple MCU options, so one must look at the respective datasheet for the MCU used for each to know. Obviously, the lower voltage versions will generally have lower “High” thresholds.

1 Like

Hi heke,

Thank you, I spent a good amount of time stabilizing everything on a breadboard. Sounds like a plan forward is slowly getting clear. I’ll study the coding and see what works. I’ll aim for 3 V. Is 1 microsecond good enough pulse width?

Yes, there is a lot of room for improvement for this TIA circuit. Faster op-amp, low noise components, JFET bootstrapping, etc. My breadboard set up is the first version of a prototype. I don’t have a resistor from the diode to ground. It is reverse biased with -15 V on the anode and the cathode leads straight to the inverting terminal. I am supplying the negative rail with -15 V because I am using that rail to bias the diode and the LT1226, but +2.5 V to power the positive rail of the Op-Amp. Ideally, I would want to do +/- 2.5 V for the LT1226 and - 20 V for the diode. But again, it is a breadboard and I had to make split power supply using two separate power supplies. The diode output current is caused by alpha particles from polonim-210 striking the chip, but I calculated the current signal by getting Coulombs and drift velocity from the 5.3 MeV alpha particle and -15 V bias. It was around 20 uA and 8 ns wide (Current pusle). There is no light source, I did all my measurements in a dark box.

Best regards,