Description
The ATmega48/168/328P used on all four controllers discussed in this app note has two eight-bit timers: Timer0 and
Timer2. Each of these timers has two PWM output pins. The Timer0 PWM output pins are OC0A on PD6 and
OC0B on PD5; these are the control lines for motor 1. The Timer2 PWM output pins are OC2A on PB3 and OC2B
on PD3; these are the control lines for motor 2. Our general motor control strategy is as follows:
1. Configure Timer0 and Timer2 to generate inverted PWM outputs on all four motor control lines. An
inverted PWM is a signal that is low for the specified duty cycle and high the remainder of the period. As
such, a duty cycle of 0% produces a constant high output and a duty cycle of 100% produces a constant low
output.
This is accomplished by setting the Timer/Counter Control Registers (TCCRxx) to select the appropriate
timer mode and timer clock (note that these registers are defined in <avr/io.h>, so you must first include this
before the code below will work):
// see the ATmega48/168/328P datasheet for detailed register info
// configure for inverted PWM output on motor control pins
TCCR0A = TCCR2A = 0xF3;
// use the system clock / 8 (2.5 MHz) as the timer clock
TCCR0B = TCCR2B = 0x02;
These register values configure Timer0 and Timer2 to run in fast PWM mode using the system clock divided
by 8, setting output pin OCxx when the timer counter matches the value in register OCRxx and clearing
output pin OCxx when the timer counter exceeds its maximum value of 255 and overflows.
This gives us four inverted PWM outputs, one on each of our motor control lines. Each PWM is running at a
frequency of 20 MHz/8/256 = 9.8 kHz and each has a duty cycle determined by the value in its associated
eight-bit OCR0A, OCR0B, OCR2A, or OCR2B register. For example, if OCR0B = 127, the duty cycle of
the PWM output on pin OC0B (PD5) is 128/256 = 50%. For the fast PWM mode used in the above code, the
relationship between the OCRxx value and the PWM duty cycle is given by:
duty cycle of PWM on pin OCxx (%) = ((OCRxx + 1) / 256) * 100%
Note that one consequence of this formula is that you can never achieve a clean 0% duty cycle; the closest
you can come to 0% when using a fast PWM is 1/256 = 0.4%, which we approximate as 0% in this
document. If you use phase-correct PWMs, you can achieve both clean 0% and 100% signals at the expense
of halving your PWM frequency. Please see the ATmega48/168/328P datasheet for more information if you
wish to use phase-correct PWMs.
2. For each motor, you can select rotation direction by holding one of its control PWMs fixed at 0% duty cycle
(i.e. holding the control line high) while PWMing the other control line at some arbitrary duty cycle. The
duty cycle of this second control line determines the speed of the motor, with 100% resulting in full speed
(since now one motor input is a constant high while the other is a constant low).
details: if you need an urgent delivery order, please feel free to contact us, and we will do our best to meet your needs.
Price problem: if you find that other suppliers offer cheaper prices for the same product, we are also willing to provide you with reference prices and give you further discounts.