Figure 5. Modified RJ11 cable connector.
on the 754410 chip while we use the direction inputs
(1A/2A and 3A/4A) to set direction and PWM the bridge.
However, in order to do this we need to invert the sense of
the PWM signal when we change directions.
Remember that in an H-bridge, if both direction
lines are the same (both high or both low), our bridge is
disabled. So, if one direction line is high then the PWM’s
active cycle is logic low; if one direction line is low, then the
LISTING 1. Motor speed and direction function.
void SetMotorSpeed(int speedL, int speedR)
SetMotorSPeed() works with +/- 255 as values.
static int lastSpeedL = 0;
//Only change speed when it is different
static int lastSpeedR = 0;
//When we change direction, we also need
// to change the sense of the PWM line.
if (speedL != lastSpeedL)
lastSpeedL = speedL;
if (speedL >= 0)
L_DIR = FWD;
TCCR0A &= ~L_NORMALPWM;
LEFTMOTOR = speedL;
16 SERVO 07.2009
Figure 6. Quadrature phase relationship and direction.
PWM’s active cycle is logic high. While this may seem like
a lot of effort just to save one I/O line, let’s remember
that the ATMEGA168 only has 28 pins, so saving one pin
I now have a way to set the motor speed from my
robot board. Next, I want to use the quadrature encoder to
take odometry readings. Dealing with a wheel encoder is
best done in an interrupt routine. This allows speed and
direction measurement to happen in the background
while the main program happily does its own thing. The
ATMEGA168 has two external interrupt lines: INT0 and
L_DIR = REV;
//Set COM0B0 which reverses PWM sense
TCCR0A |= L_NORMALPWM;
LEFTMOTOR = -speedL;
if (speedR != lastSpeedR)
lastSpeedR = speedR;
if (speedR >= 0)
R_DIR = FWD;
TCCR0A &= ~R_NORMALPWM;
RIGHTMOTOR = speedR;
R_DIR = REV;
//Set COM0A0 which reverses PWM sense
TCCR0A |= R_NORMALPWM;
RIGHTMOTOR = -speedR;