3. Simple Code to Drive the Motors

If we don’t want to worry about variable motor speed, we can simply make use of the truth table values in the previous section to figure out how to drive our motors. The code to do this becomes simple AVR digital I/O manipulation:

Initialize the motor control pins

#include <avr/io.h>

// use Data Direction Registers (DDRx) to
// set the four motor control pins as outputs
DDRD |= (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD6);
DDRB |= (1 << PORTB3);

Motor 1 forward at full speed

PORTD &= ~(1 << PORTD5);    // drive pin PD5 low
PORTD |= (1 << PORTD6);    // drive pin PD6 high

Motor 1 reverse at full speed

PORTD |= (1 << PORTD5);    // drive pin PD5 high
PORTD &= ~(1 << PORTD6);    // drive pin PD6 low

Motor 1 brake low

PORTD |= (1 << PORTD5) | (1 << PORTD6);    // drive pins PD5 and PD6 high

Motor 2 forward at full speed

PORTD &= ~(1 << PORTD3);    // drive pin PD3 low
PORTB |= (1 << PORTB3);    // drive pin PB3 high

Motor 2 reverse at full speed

PORTD |= (1 << PORTD3);    // drive pin PD3 high
PORTB &= ~(1 << PORTB3);    // drive pin PB3 low

Motor 2 brake low

PORTD |= (1 << PORTD3);    // drive pin PD3 high
PORTB |= (1 << PORTB3);    // drive pin PB3 high

To achieve variable speeds, we can rapidly alternate between driving and braking a motor, but doing this in software can be taxing on the CPU. Fortunately, AVRs come with hardware timers that can rapidly toggle the motor driver states for us while leaving the CPU free for our higher-level computations.