6.25 Nanosecond Resolution Timer for Any Microcontroller!


Introduction: 6.25 Nanosecond Resolution Timer for Any Microcontroller!

While designing a solid state replacement for a vacuum-tubes-and-CRT radar display subsystem, I was stuck at getting a suitable system to time the period between the synch pulse and the echo pulse. The synch pulse and echo pulse were being captured on two pins of an Arduino Due. The Arduino Due has a MCLK/2 clock of 42 MHz, which would give me a resolution of 23.81 nanoseconds (ns) which, for the speed of light, would translate to a distance of 6.86 meters. I wanted a better resolution.

After looking into solutions using high speed oscillators and discrete logic ICs (counters, shift registers), FPGAs and off the shelf solutions costing in the range of USD 2,000/-, I decided to examine the ESP8266 for some solution to my timing problem.

To my delight, I discovered two functions in the Arduino ESP8266 API, namely ESP.getCycleCount() and ESP.reset()

ESP.getCycleCount() counts the instruction cycles since start, in an internal unsigned 32-bit variable, liable to overflow every 28 seconds or so. A one microsecond period will give 160 instruction cycles. Now to measure the software overhead required by your software, you need to only count the instruction cycles your routine counts for a 1 microsecond delay and subtract 160 from that count, to give you the software overhead in acquiring the count. For 1 microsecond delay, I got a count of 213. Which worked out to 213-160 = 53 counts (53 x 6.25 = 331.25 nanoseconds) software overhead to acquire the count. Subtracting 53 from every count gives me a count accurate to within a few tens of picoseconds, for periods from 30 microseconds to about 500 microseconds.

Step 1: Setup the ESP8266

Open the Arduino IDE.

Select the appropriate ESP8266

Select the speed, 160 MHz.

Step 2: Write a Program to Trap a START and a STOP Interrupt

Setup two pins to respond to RISING or FALLING interrupts. Within the START ISR, capture the instruction count. Within the STOP interrupt capture the instruction count and raise a transmit flag. Reset the CPU to obviate a counter overflow. For interrupts that may be far in between, an automatic periodic reset or an overflow handler could be written.

Within the loop() function, transmit the count over the I2C bus. The slave should be setup to receive from the I2C slave.

Check out the program. It is quite self-explanatory.

I am now able to time the period between two events, to a resolution of 6.25 ns, which with the speed of light, resolves to a resolution of about 1.8 meters.

Profiling the count acquisition instructions for the software overhead, which will be a constant, is very important.



    • Casting Contest

      Casting Contest
    • Microcontroller Contest

      Microcontroller Contest
    • Woodworking Contest

      Woodworking Contest

    We have a be nice policy.
    Please be positive and constructive.




    Hey, is it possible to expand this to 4 input signals and measure the time between them with nanosecond resolution?

    1 reply

    Sorry, I've just seen this query...

    Yes, you could potentially time as many events as there are pins, using interrupt service. All of the ESP8266 pins can be configured for interrupt capture.

    First of all that's a lovely solution you spread here! Thanks.

    Two short question:
    1. What are you using to generate the 1 microsencond pulse (train)? Can a function generator be omited?
    2. Isn't there a chance for counter overflows when having small duty cycle (short single pulses followed by long silence) ? I propose a reset right in the start Interrupt Routine so you definitly start your conting with a small count.
    (Checking if the stop cycle is lower than the start cycle and in this case adding the counter maximum could also solve the problem.)

    Hello ! I repeated your code on esp12 - 160 mhz mode, ports 12, 13 are connected to one synchronization source, but i2c counter always sends 116 value. if I understood correctly, then my tick was 116 * 6.5 = 754 nanoseconds.But why, if the start-stop triggers I synchronized with one source?

    1 reply

    Use a variable to store the current count when the first event occurs. Then, to time the period between the first and second events, just subtract the stored count from the current count and multiply by 6.5ns.

    Hello ! I repeated your code on esp12 - 160 mhz mode, ports 12, 13 are connected to one synchronization source, but i2c counter always sends 116 value. if I understood correctly, then my tick was 116 * 6.5 = 754 nanoseconds.

    I use timer based controller like this in a lot of my Arduino projects.