Timer prescaler fractionalization

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I needed to solve a problem in developing my Crazy Clock firmware, and I think it's a useful enough technique that I'll describe it in case anyone else runs across a similar problem.

 

The circuit was designed with a 4 MHz crystal (the current version uses a 32.768 kHz one, but the principle remains the same), but to reduce power consumption, I set the prescaler to divide by 128, so the system clock is 31.25 kHz. What I wanted to have happen was for the controller to sleep most of the time, but a timer interrupt to wake it up at 10 Hz. So timer 0 is set up with a divide-by-64 prescaler and CTC mode. But the counting frequency as a result is 488.28125. In other words, the counter needs to count to 48.8828125 to result in a 10 Hz interrupt. Obviously, fractional counts aren't going to work.

 

I happened to remember some work I had done a long time ago on hardware PLL circuits. Some of the sophisticated ones had a special bifurcated counting system that would count to one value, then toggle one output, then continue counting to another value and then pass the resulting frequency to the phase comparator. The intermediate output was designed to go to a divide-by-n / divide-by-n-plus-one prescaler. The concept was that the intermediate count allows you to define a fractional divisor.

 

So what is 48.828125 expressed as a fraction? Turns out that's 48 + 53/64. What does that do for us? Well, if we set the counter to count to 49 for 53 cycles, then to 48 for 11 (64 - 53) cycles, that's 3125 cycles total. Recall that the clock frequency is 3125 times 10 times 64. Q.E.D.

 

So what you wind up with is an interrupt handler that needs to keep track of which interrupt within a 64 interrupt cycle is happening. On the first, you set the CTC register to 48 (recall that it's zero-based AND inclusive, so that means 49 counts), and on the 54th, set it to 47. The interrupts will happen nominally at 10 Hz. Some intervals will be one cycle shorter, of course. That works out to be 2.048 msec. For my application, that was insignificant, but it's something to consider.

 

I had other applications for this technique within the same project. Some of the firmware loads call for ticking a clock very slightly faster or slower - for example, for Martian Sol time, Sidereal time or lunar tidal time. This same fractional counting technique is used to add or subtract tenths-of-a-second between ticks to effect this change.

 

EDIT: 32.768 kHz crystal, not 32 MHz.

 

 

Last Edited: Wed. Aug 9, 2017 - 03:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your message makes no sense.     I doubt if any Mega or Tiny would oscillate at 32MHz.    An Xmega might.     However a 32MHz HF crystal will be less accurate than a 32kHz watch crystal.     And it will certainly take a lot more current / power.

 

Explain which AVR you are using and why.

Creating a 10Hz interrupt should not be difficult.    Why do you want this to be accurate?

 

I can understand that you want a 1Hz (or 2Hz) interrupt to be accurate for a RTC clock.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Goodness sakes.

 

1. 32 kHz, not Mhz. I'm sorry I mis-typed.

2. It's got to be accurate because it's a clock.

3. It's an ATTiny85, if you must know. But the entire purpose of what I posted was to share a useful technique in the abstract. I don't need any help because it's a completed, working project.

4. I want a 10 Hz accurate interrupt source because this clock ticks in freakish, crazy ways (hence the name Crazy Clock), and having higher granularity abets that mission. But in any event, this technique still can be used for all sorts of purposes where you need to mark fractional time, and it's easy to do. It's just non-obvious enough that I thought it would be nice to write it down.

 

 

[Profanity removed by Moderator jgmdesigns]

Last Edited: Wed. Nov 26, 2014 - 04:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does your Crazy Clock have a random-but-within-ten-minutes mode? Having know people who ran their clocks ten minutes fast in order to not be late, but then compensated for the offset, I had the idea a long time back that such a feature would be useful. All you know is that your clock could be up to ten minutes fast, but it could be spot-on.

 

By the way, I agree that the idea of fractional dividers is interesting enough to warrant writing down, although as you say, it is more often used in PLLs, were the dynamics of the loop tend to smooth out the jitter.

Four legs good, two legs bad, three legs stable.

Last Edited: Mon. Nov 24, 2014 - 03:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Such a mode could be done. The closest at present is a mode that runs 10% fast for 12 hours and 10% slow for another 12 (you give that one to your boss). You could just adjust up the 12 hour range to make it shorter. 20% faster over the course of 50 minutes is 10 minutes fast. And I think 20% may just be on the outer limits of imperceptible - particularly if you sandwich a minute of normal ticking to hide the transition.

 

The fundamental obstacle is that the controller has no idea what time it actually is or where the clock hands are pointing. So synchronizing special features like that can really only be done immediately when the battery is installed.

 

Your idea is a good one, though. A procrastinator's special. :D I'll see what I can do.

 

EDIT: It's now available as an option in the store. :)

 

Last Edited: Tue. Nov 25, 2014 - 09:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes. He has a very valid technique here. Remember about a year ago I was making a clock, and we got down to "add one count to the time if the bottom 8 bits of the second counter is > 186? You can REALLY get an accurate timepiece that way, assuming temperature drift won't goof things up.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some quartz watch manufacturers buy cheap crystals and calibrate them using frequency counters to set a software compensation factor. I've considered doing this for my boards, but I don't have a hyper-accurate frequency counter, and, I dunno, it's a bit like swatting a fly with a sledgehammer.

 

EDIT: In the end, and completely ironically, I did wind up making a hyper accurate GPS disciplined oscillator and am using this exact technique to trim my clock boards. This became necessary once I realized that the ±10 ppm frequency tolerance of the crystal didn't mean that it was necessarily within 10 ppm of the actual center frequency. Rather, it meant that if you bought a thousand of them, they'd all be within 10 ppm of each other. So now I sample manufacturing batches and compute a "standard" trim factor, and offer individual trimming (with a 100 ppb granularity) as a value-add.

Last Edited: Mon. Nov 23, 2015 - 06:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nsayer wrote:

So what is 48.828125 expressed as a fraction? Turns out that's 48 + 53/64. What does that do for us? Well, if we set the counter to count to 49 for 53 cycles, then to 48 for 11 (64 - 53) cycles, that's 3125 cycles total. Recall that the clock frequency is 3125 times 10 times 64. Q.E.D.

 

Yes, this choice-of-two divisors is a very good way to get low ppm errors on average times.

Google also

 Egyptian Fraction - for when a simple single fraction does not 'fit'

&

 Rate Multiplier - for modulation decisions to lower the jitter , In the example above, those 11 can be spread 'evenly' amongst the 64, rather than all grouped at one end, if you want to  use a higher-rate interrupt, with less jitter.

If you only react at 3125 cycles, then it does not matter how the 11 is inserted into the 64.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The old N... N+1 technique

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reminds me of a bit-banged serial routine I wrote a long time ago. The overall baud rate was pretty accurate, but the bit periods weren't all the same length.

 

Four legs good, two legs bad, three legs stable.