Arduino: Motors

May 2013 Note: this will be updated soon: I have a new motor shield design that will make hooking up motors much easier.

Motors pull a lot of current, so you can't drive them directly from the Arduino's output pins. You need a separate power supply for the motors.

To drive a motor, we're going to use a chip called an "H bridge" (or "half bridge") that takes power from a battery pack and signals from the Arduino to figure out when to spin the motors. Specifically, we'll use a chip called an SN754419. It costs just under $2 from Jameco.

[Dual motor control with half-bridge chip]

The H-bridge chip requires a lot of wires, so it's already been wired up for you, as shown in the diagram. But you still need to make connections to the Arduino and to the motors:

the light green wires go to Arduino digital pins 2 and 3, to control the direction of motor 1 -- they're called the motor 1 logic pins. To make the motor go one direction, you set pin 2 high and pin 3 low; to make it go the other direction, set 2 low and 3 high.

the dark green wires go to pins 4 and 5, for the direction of motor 2 (the motor 2 logic pins).

the white wires go to pins 9 and 10, to control the speeds of the two motors. They're called the enable pins for motors 1 and 2.

Software

Okay, how do you control one of these chips in software?

I've written a library called HalfBridge you can use to make the direction setting easier. Just create a Motor object and call setSpeed() on it, passing in a speed between -255 and 255. Pass 0 to stop the motor. Here's some sample code:

#include <HalfBridge.h>

Motor motors[2] = { Motor(9, 2, 3), Motor(10, 4, 5) };

void setup()
{
    motors[0].init();
    motors[1].init();
}

#define FAST 200
#define SLOW 130

void loop()
{
    if (motors[0].mSpeed == 0 ) {
        motors[0].setSpeed(SLOW);
        motors[1].setSpeed(-SLOW);
    } else if (abs(motors[0].mSpeed) >= FAST) {
        motors[0].setSpeed(0);
        motors[1].setSpeed(0);
    } else {
        motors[0].setSpeed(FAST);
        motors[1].setSpeed(FAST);
    }

    delay(2000);
}