Monday, June 06, 2011

Motor Drivers: 1A Dual TB6612FNG Part 1

It's time to wipe the Cheetos dust from your mouth because we're gunna get that Arduino rollin' tonight.

Maybe later...

Unlike a servo which has separate wires for the control signal and voltage supply, DC motors only have two terminals available. Try plugging one of those in to a digital output pin and you'll fry the Arduino. Plug them into the 5V output and GND pins and the wheels are just going to spin and you'll have no control over the speed or direction. So, what do we with these two you ask?

Your motors are going to require more current than any micro-controller can safely handle, so were going to need some extra circuitry for a motor controller. You can use an IC H-bridge such as the L293D ($2.95 at Jameco) for a motor driver if your motors do not have a peak current over 600mA. The L293D allows you to either control two motors bidirectionally or four motors in a single direction. Each output pin already has built in back-EMF protection for when you reverse directions or suddenly stop the motor and it even has a separate input for the power supply and logic voltage. But, if you are planning on using any larger motors whose current exceeds 600mA  you will need to use another motor driver or you will melt the chip. I've read that you can just piggyback and solder two chips on top of one another to double the max current, but there is a cleaner alternative if you're willing to spend an extra $3.

The motor driver I'll be using for my robot buddy is a breakout board for the Toshiba TB6612FNG chip from Sparkfun. http://www.sparkfun.com/products/9457

This bugger is a lot smaller than you'd think
I really need to start using a camera to take pictures. I assure you there's text printed on it.
Size comparison against two 16-pin IC

This board can control two motors requiring a supply voltage up to 15V and constant current of 1.2A with a peak current up to 3.2A. There is also a separate voltage supply for the motors and logic. This chip allows you to not only control the direction of each motor, but you can also control the speed of your motors using the PWM input pins. Neat! Below is a table from the chip's datasheet showing how to control the direction of your motor.

Courtesy of Toshiba's TB6612FNG Data sheet
So, you already got two motors and a driver? Well then, let's get coding.

Being the environmentally responsible person that I am, I built a test platform for our motor driver using an old Sparkfun box I had lying around. It ain't pretty, but it will do for this post. Since the platform only has two wheels, I'll be using a nub thingy(guitar pick) to keep it balanced for the time being until I get some sort of castor wheel. If it weren't 4am, I'd go to the hardware store. Maybe I'll get one tomorrow if I'm not feeling overwhelmingly lazy.

Inside sits two geared DC motors.
Just to test the code, right?
The motor driver is well labeled, so the wiring is pretty self explanatory. Here's a quick sketch I wrote that allows you to control the speed and direction of your motors. It includes functions for driving forward and reverse, turning, and braking. Check the code's define section for how I wired it. The logic supply voltage can be connected to the Arduino's 5V supply. I would highly suggest having a separate battery pack for the motor voltage supply. You can control your supply voltage and you don't risk damaging the Arduino.

Depending on how you have your motors set-up, this code might not work as intended for you. All you need to do to fix this is change the #define values for the incorrect directions.

//  Noah Stahl
//  6/5/2011
//  http://arduinomega.blogspot.com
//  Arduino Mega 2560
//This sketch is used to control the TB6612FNG Motor Driver.
//The Motor Driver is controlling two bidirectional DC Motors, A and B.
//There are four states for each motor in this code: STANDBY, BRAKE, CW, CCW.
//The speed of the motors can be controlled through PWM. 0 for stopped and
//255 for full-speed.

//!!!READ-ME!!!
//Depending on the placement and wiring of your motors, this code may not work
//as intended on your project. You can fix any of the wrong directions by
//changing the FORWARD, REVERSE, RIGHT, and LEFT define values below.
//You will also have to do a little experimenting to determine a good delay
//value for turning. This value is going to change depending on your motor speed,
//torque, surface material, battery voltage, and a whole bunch of other variables
//that you will probably be unable to account for. Just use a good guess.

#define PWMA 2
#define AIN1 53
#define AIN2 52
#define BIN1 51
#define BIN2 50
#define PWMB 3
#define STBY 49
#define motor_A 0
#define motor_B 1
#define FORWARD 1
#define REVERSE 0
#define RIGHT 1
#define LEFT 0

void setup()
{
  pinMode(PWMA,OUTPUT);
  pinMode(AIN1,OUTPUT);
  pinMode(AIN2,OUTPUT);
  pinMode(PWMB,OUTPUT);
  pinMode(BIN1,OUTPUT);
  pinMode(BIN2,OUTPUT);
  pinMode(STBY,OUTPUT);
 
  motor_standby(false);        //Must set STBY pin to HIGH in order to move
}

void loop()
{
  motor_brake();               //STOP for 1s
  delay(1000);
  motor_drive(FORWARD, 255);   //Move FORWARD at full speed for 1s
  delay(1000);
  motor_brake();               //STOP for 1s
  delay(1000);
  motor_drive(REVERSE, 150);   //REVERSE at about half-speed for 1s
  delay(1000);
  motor_brake();               //STOP for 1s
  delay(1000);
  motor_turn(RIGHT, 255, 255); //Spin RIGHT for 0.5s
  delay(500);
}

//Turns off the outputs of the Motor Driver when true
void motor_standby(char standby)
{
  if (standby == true) digitalWrite(STBY,LOW);
  else digitalWrite(STBY,HIGH);
}

//Stops the motors from spinning and locks the wheels
void motor_brake()
{
  digitalWrite(AIN1,1);
  digitalWrite(AIN2,1);
  digitalWrite(PWMA,LOW);
  digitalWrite(BIN1,1);
  digitalWrite(BIN2,1);
  digitalWrite(PWMB,LOW);
}

//Controls the direction the motors turn, speed from 0(off) to 255(full speed)
void motor_drive(char direction, unsigned char speed)
{
  if (direction == FORWARD)
  {
    motor_control(motor_A, FORWARD, speed);
    motor_control(motor_B, FORWARD, speed);
  }
  else
  {
    motor_control(motor_A, REVERSE, speed);
    motor_control(motor_B, REVERSE, speed);
  }
}

//You can control the turn radius by specifying the speed of each motor
//Set both to 255 for it to spin in place
void motor_turn(char direction, unsigned char speed_A, unsigned char speed_B )
{
  if (direction == RIGHT)
  {
    motor_control(motor_A, REVERSE, speed_A);
    motor_control(motor_B, FORWARD, speed_B);
  }
  else
  {
    motor_control(motor_A, FORWARD, speed_A);
    motor_control(motor_B, REVERSE, speed_B);
  }
}

void motor_control(char motor, char direction, unsigned char speed)
{
  if (motor == motor_A)
  {
    if (direction == FORWARD)
    {
      digitalWrite(AIN1,HIGH);
      digitalWrite(AIN2,LOW);
    }
    else
    {
      digitalWrite(AIN1,LOW);
      digitalWrite(AIN2,HIGH);
    }
    analogWrite(PWMA,speed);
  }
  else
  {
    if (direction == FORWARD)  //Notice how the direction is reversed for motor_B
    {                          //This is because they are placed on opposite sides so
      digitalWrite(BIN1,LOW);  //to go FORWARD, motor_A spins CW and motor_B spins CCW
      digitalWrite(BIN2,HIGH);
    }
    else
    {
      digitalWrite(BIN1,HIGH);
      digitalWrite(BIN2,LOW);
    }
    analogWrite(PWMB,speed);
  }
}


I would highly suggest that you power your motors with their own battery source, perhaps a few rechargeable NiMH AA's. If you use the 5V supply from the Arduino for the motor supply voltage, you might damage the Arduino by drawing too much current. 

Once again, your mileage may vary with the code. Depending on how you have your motors set-up, this code might not work as intended for you. All you need to do to fix this is change the #define values for the incorrect directions. Also, depending on your power supply's voltage and amperage ratings, the timing delays for turning are going to be different.  Do a few test runs and figure out the optimal delay values for your project.

3 comments:

  1. hello !!
    I succeeded in building a project with one motor but I would like to add a second motor to my tb6612fng, and I would appreciate if you could give me the the cabling scheme.

    regards

    ReplyDelete
  2. hi,

    Thanks for your blog post, great to see how you are using the sparkfun motor breakout board. I just wondered how you actually wired up the motors? I have 2 wires coming from each motor but your pin setup in the sketch says there are other inputs to plug in? Which of the motor wires need to go where and what are the other pins for? Any help much appreciated.

    ben

    ReplyDelete