Wireless Motor Driver Shield Hookup Guide

Pages
Contributors: Nick Poole, Shawn Hymel
Favorited Favorite 2

Understanding the Example Code

The example code is designed to let you control the H-Bridge, as well as a servo attached to pin 11, using serial communication. Let's walk through a few excerpts from the code and see if we can understand a little better what's making it work. As with most sketches, it starts with some basic setup:

language:c
#include <Servo.h>

Servo swivel;

int pwm_a = 3; // Channel A speed
int pwm_b = 6; // Channel B speed
int dir_a0 = 4; // Channel A direction 0
int dir_a1 = 5; // Channel A direction 1
int dir_b0 = 7; // Channel B direction 0
int dir_b1 = 8; // Channel B direction 1

char inbit; // A place to store serial input
int swivelpos = 90; // Servo position

void setup()
{
Serial.begin(9600); // Pour a bowl of serial

swivel.attach(11); // Attach servo to pin 11
swivel.write(swivelpos);

pinMode(pwm_a, OUTPUT); // Set control pins to be outputs
pinMode(pwm_b, OUTPUT);
pinMode(dir_a0, OUTPUT);
pinMode(dir_a1, OUTPUT);
pinMode(dir_b0, OUTPUT);
pinMode(dir_b1, OUTPUT);

draw(); // Draw the driving instructions to the serial terminal

}

As you can see, we started out by including the servo library and creating a servo object called "swivel". Next, we declare a handful of variables to keep track of which pins are responsible for which functions, and also variables for the servo position and incoming serial characters. The setup() function is where serial communication is initialized, the servo object is attached and the control pins are all set as output devices. Finally, we call the function draw(), which we'll look at in a minute.

language:c
void loop()
{
if(Serial.available()){ // Wait for serial input
    inbit = Serial.read();
    switch(inbit){ // Switch based on serial in
        case 'w': // Move Forward
    forward(200);
    delay(30);
    shutoff();
    break;
        case 's': // Move Backward
    reverse(200);
    delay(30);
    shutoff();
    break;
        case 'q': // Turn Left while moving forward
    turnL(200);
    delay(30);
    shutoff();
    break;
        case 'e': // Turn Right while moving forward
    turnR(200);
    delay(30);
    shutoff();
    break;
        case 'a': // Spin Left in place
    spinL(200);
    delay(30);
    shutoff();
    break;
        case 'd': // Spin Right in place
    spinR(200);
    delay(30);
    shutoff();
    break;
        case 'x': // Short brake
    brake();
    break;
        case 'z': // Spin servo (on pin 11) left
    servoL();
    break;
        case 'c': // Spin servo (on pin 11) right
    servoR();
    break;
    }
}
}

The main loop of the example code just waits to see input on the serial line and then stores the incoming value and compares it against a list of cases. By scrolling through the switch/case statements, you can see the behavior associated with each serial character. The rest of the code is composed of the various procedures that are called in the main loop. Let's look at a few of these:

language:c
void draw() // Serial Instructions
{
Serial.println("                           ");
Serial.println(" ------------------------- ");
Serial.println(" |       |       |       | ");
Serial.println(" |   Q   |   W   |   E   | ");
Serial.println(" | turnL |forward| turnR | ");
Serial.println(" ------------------------- ");
Serial.println(" |       |       |       | ");
Serial.println(" |   A   |   S   |   D   | ");
Serial.println(" | spinL |reverse| spinR | ");
Serial.println(" ------------------------- ");
Serial.println(" |       |       |       | ");
Serial.println(" |   Z   |   X   |   C   | ");
Serial.println(" |servo L| brake |servo R| ");
Serial.println(" ------------------------- ");
Serial.println("                           ");
}

This one is pretty straightforward! The draw() procedure is just a bunch of print statements that tell you which keys are attached to which functions.

Finally, there are a bunch of procedures that actually set the speed and direction of the motors. These are the functions that you'll want to borrow for your own code because they wrap up all of the control pin stuff we talked about in the last section into intuitive commands like "forward," "turn," and "brake." All of the motion commands are basically structured the same. For example:

language:c
void forward(int speed) // Move Forward
{
digitalWrite(dir_a0, 0);
digitalWrite(dir_a1, 1);
digitalWrite(dir_b0, 0);
digitalWrite(dir_b1, 1);

analogWrite(pwm_a, speed);
analogWrite(pwm_b, speed);
}

The brake() and shutoff() functions are structured the same as the motion procedures except that in the case of brake(), all of the pins are written high, and in the case of shutoff(), all of the pins are written low. The brake() procedure actually shorts the motor so that it resists turning. The shutoff() function simply shuts off power to the motors so that they come to a rolling stop. Try referring to the example code that was copied from Simple Motor Control for more details on how these functions were defined.

Finally, there are the servo control functions, which increment or decrement the servo position variable before writing it to the servo:

language:c
void servoL() // Spin servo (on pin 11) left
{
if(swivelpos>10){
swivelpos = swivelpos-10;
swivel.write(swivelpos);
}
}

The only kind of clever thing going on here is that we check ahead of time whether we've reached the limits of the servo so we can't increment beyond its range of motion.