[Back to Home Page]
www.RomanBlack.com
Zero-error 1 second Timer
A very versatile Zero Cumulative Error timing system with PIC source code
Roman Black - orig June 2001 - updated Aug 2006.
What is it?
Bresenham's Algorithm is a system where 2 imperfect periods can be
alternated to produce an average that matches any "perfect" period.
With most modern micros the easiest time period to generate is an
overflow of the internal timer, generally 256 ticks or 65536 (256x256)
ticks. Unfortunately, since most of these Micros run at crystal speeds
like 4MHz and 20MHz, these overflow timed periods generated are binary and
cannot be evenly divided into 1 second or any easily usable
real-world clock value.
Brilliant programmer Bob Ammerman recognised this fact and mentioned
his use of a Bresenham-type system for PIC micros.
Later I did a little work on the
idea to speed-optimise it for the PIC timer0 overflow which is available on all
PICs and release the results as public domain open source. It should also
work on any other micro with a binary-multiple internal timer.
Basic Theory
Bresenham's algorithm was originally designed for speedily calculating
imperfect periods in grid movement on a 2 dimensional matrix like an
X-Y Plotter. A similar system can be used for generating one average timed
period from multiples of a smaller imperfect timed period (like the PIC
timer0 overflow period).
So we can generate a "perfect" average 1 second
period from the imperfect PIC timer0 overflow in a way which
is very fast and leaves the PIC with a lot of free time for other tasks.
The big advantage is that the 2 periods are completely independant, so
ANY crystal speed can be used to generate ANY timed period. For hobby use
this means a real time 1 second clock can be built with any old crystal in
the parts junkbox. For commercial use it means a real time
1 second clock can be added to any existing design no matter what crystal was
originally chosen, independant of other timed processes, and requires very
little processor timeslice to implement.
The basic theory is shown above.
A 20 unit period is needed, but the closest period the PIC can
generate is 17 or 24 units (for example). Athough each generated period
is imperfect, the overall average period is perfect because this
is a Zero Cumulative Error system.
In other words, the cumulated error after every generated period
is added on to the next period so over any significant amount of time
the average error must be zero.
In the exaggerated example above there is a high percentage of jitter
per generated period. In real life the jitter can be small enough that it is
not a problem, as in the actual PIC implementation below the real jitter
maximum is only 0.0256% (about 1/40th of a percent) on a 1 second period.
Obviously the long term average error is ZERO and it will make an accurate
real world clock.
Theory using the PIC timer0
Basic procedure to generate a 1 second period;
(assuming a 4MHz crystal, and 1000000 timer0 ticks/second)
Every timer0 overflow; subtract 256 from our Period variable
When Period variable gets less than zero; generate the 1 second event
and ADD another 1000000 to it
Because we ADD the next 1000000 ticks to the next second,
the cumulated error is still
contained within the Period variable. This means that the NEXT second will
be adjusted by the error that was left in the variable. Every period
will self-adjust it's length so over time there is Zero Cumulative Error.
Optimisation for the PIC timer0;
Using a 3 byte Period variable means it can subtract 256 simply by decrementing
the MID byte
Instead of going BELOW zero, event is generated on HIGH and MID bytes both equal zero,
which is easier to test and avoids handling negative values
When event is detected, HIGH and MID bytes must equal zero, so the 24-bit add
becomes many times faster than a "proper" 24-bit add
To summarise, it is extremely quick and easy to subtract the 256 ticks for
every timer0 overflow, and it is extremely quick and easy to ADD the 24-bit
value for the next timed period.
PIC source code
This first source code generates a 1 second event from a PIC with 4MHz
crystal and the timer0 overflow interrupt. As it uses the timer0
interrupt it cannot be used on PIC's that have no interrupts
like the cheap 12c508 and 12c509. This is the code that is easiest
to use for most designs.
Code example for a PIC using timer0 interrupt;
Right-click here to download the one_sec.asm source code.
(text 11 kb)
This next source code generates a 1 second event from a PIC with 4MHz
crystal and timer0, but does not require an interrupt so it will
still work with the cheapest PICs. I have also corrected a minor bug in the
no-interrupt code.
Code example for a PIC using NO interrupts;
Right-click here to download the one_sec2.asm source code.
(text 11 kb)
Notes
You can use the 2 code examples above on any PIC and with any crystal.
Just adjust the 24-bit period value bres_ to the number of timer0 ticks
per second
and it will generate a 1 second period. You can also generate
longer or shorter periods than 1 second simply by changing that value.
You can also run timer0 (or another PIC timer) at a prescale value so
it does the interrupt less often. This slightly increases the jitter per
second but can free up some processor time. For example using an interrupt
every 65536 ticks (256x256) and a 4MHz crystal the MAXIMUM jitter possible
per second is still less than 7% of a second, and the timer code uses 256
times less processor time. Important. If doing this you must
modify the code to suit the new timer setup, and also the subtraction.
Other microprocessors like the AVR, Atmel, Motorola, TI etc
will also work with this system but I don't have source code for these
micros unless someone emails the code to me.
Tools
You will need to convert large decimal numbers (like 1000000) to a 24-bit
hex value for the PIC to use, so I have provided a simple decimal-hex converter;
Click here for HexCon 1.0
- end -
[Back to Home Page]