Higher resolution timer / ticker

Is there any way to achieve sub-microsecond timing resolution on a Ticker or other timer like functions?

I have a project which requires me to generated a 100Hz clock output in sync to an external source.

I have a system in place that can read the incoming source and generate my synchronized output at what I think is the correct rate using a Ticker running at a period of 5000us. But due to clock speed differences the two drift out of sync over time.

Right now I monitor this drift and when the error gets over a certain threshold (currently 200 us) I introduce a single long or short cycle to bring things back into alignment.

It works but it’s not ideal. It would be far better to run the Ticker at the correct rate to start with.
I can average the incoming signal over a reasonable length of time and so measure the clock differences between the incoming signal and my internal clock. This can give me the relative clock differences very accurately. If I was to set the ticker period taking this error into account it would be possible to virtually eliminate this drift and so greatly reduce the need to correction cycles.
However since I am seeing a clock error of around 5 ppm this gives me a required ticker period of 4999.975 us.

Is there any way short of directly configuring one of the hardware timers (not very portable) that I can get this sort of resolution?

Hello Andy,

The only sub-microsecond function I could find in Mbed OS 6 API is the wait_ns() function which is implemented in

mbed-os/platform/include/platform/mbed_wait_api.h
mbed-os/platform/source/mbed_wait_api_no_rtos.c

Best regards, Zoltan

I’ve managed to work around it a little.

I estimate the clock error in parts per million averaged over 30 seconds or so and every second add that much to my estimated clock error. If the total estimated clock error at the start if the second is then over 4us I run a cycle that is a couple of us off the nominal time and remove that much from the accumulated error.
It’s not perfect since it is based on estimated clock errors rather than measured time errors. I still drift relative to the input and have to maintain the higher level code that monitors the error and makes an adjustment if it’s over 200 us. But it does drop my drift rate from over 5 ppm to under 0.5 ppm making the large adjustments a lot rarer.

One thing that is a little annoying is that there seems to be an overhead when rescheduling the ticker.
If in the ticker interrupt I re-attach the same function with a different period the timing shifts by around 18 us. It’s easy to compensate for this but irritating to have to and I suspect not very portable since that time is almost certainly related to some internal processing delays.

Andrew

This is a problem very well suited for hardware timers – trying to do timing code by hand is always going to give you overhead. Using a hardware timer, you could have the timer count incoming clock edges, then fire an output/interrupt every X clocks to generate the slower clock signal. It’s guaranteed to be drift free! Note that this will only work if the input clock speed is evenly divisible by the output clock speed (but there may be ways around this).

I don’t know what MCU you’re using, but with an LPC1768 you could set it up like this:

  • Configure Timer0 CTCR to operate in counter mode, counting rising edges on CAP0
  • Configure Timer0 MR0 with half the correct match value to generate 100Hz from the input clock
  • Configure Timer0 MCR to reset when Match 0 is triggered
  • Configure Timer0 EMR to toggle the match output IO pin each time Match 0 is triggered

Unfortunately the input and output clocks are not neat multiples.
In fact the input clock can be any one of 10 different rates, all lower than 100Hz and only a couple of them neat multiples.

So without adding a PLL to boost the input clock rate up the only option is to use the main CPU clock as the timer source and set the period correct after calculating the clock rate differences.

Since the relative clock rates are going to drift over time due to temperature changes etc… some correction system is always going to be needed, my aim is to get the rate as close as possible to correct and so minimize how often this happens.