The most intuitive method is simply to change the overflow value of a
timer. This approach works to an extent, but it is not well suited for
precise frequency control. The problem is because
,
in which
is frequency, and
is period. In our case,
is always quantized by the divider of the timer clock.
Most stepper motors can step at 500Hz. This translates to a period of exactly 2ms. But how about 499Hz? It translates to a period of about 2.004ms. It may seem to make sense to set up the timer so we can control its period at 0.004ms intervals. But this is not true. At 333Hz, the period is 3.333ms, which is not a multiple of 0.004ms!
Using the period of a timer to directly control stepper also has other disadvantages. For example, a differentially driven robot will need two timers to control its two motors. As we will discuss later, acceleration control also needs its own frequency control. Does this mean that we need to use two more timers to control acceleration and deceleration? Soon, we are left with no timer to provide the basic monotonic tick for time keeping and other periodic logic.
This is why we need a different scheme for generating a variety of frequencies. We will use one single timer to do this.
The basic idea is that we begin with a timer overflow period that is much shorter than the shortest stepping period. In our example, let's assume that a stepper steps at a maximum speed of 500 steps per second. In this case, we can assume a 5kHz timer interrupt frequency for relatively smooth stepping.
But 5kHz is not divisible by 499Hz, is it? You are correct! With a 5kHz base frequency, the 499Hz stepping will be slightly uneven. This is what happens in one second:
The period is
in milliseconds. Is this terrible? Not really. Since the variance
of the long versus short steps is only off by 10%, most stepper motors
will work fine.
This pattern is generated using the following code:
In this code, step_freq is the stepping frequency (499Hz), whereas
base_freq is the base frequency (5000Hz).
Intuitively, this code should work. As step_freq increases,
it takes fewer iterations to overflow sum. To generate a 499Hz
frequency (for stepping), this code should be executed at 5kHz (5000
times per second).
To make this logic cleaner, one can always make use of structures. The following code makes this frequency division logic flexible:
The only tricky part in this code are the use of the
cb_func and cb_param. cb_func is a
``call back'' function whenever there is an overflow.
cb_param is just a pointer to something that is
passed to the callback function. This way, the call back function
can have its own very complex structure for storing parameters
and non-volatile state information.
Also, note that base_freq is not specific to the structure.
This is because typically, all mechanisms that rely on frequency
division can rely on the same timer, hence having the same base
frequency.
Copyright © 2006-02-15 by Tak Auyeung