Introduction: Clusterbot!

About: Electronics are a newly re-found hobby for me. I'm not an engineer - I'm an ordinary guy who likes to tinker with electronics in his free time. You can see more about my projects at www.meanpc.com.
What is Clusterbot?  He is a small, affordable, autonomous Arduino-powered robot.  He can move, see, avoid obstacles, and makes a melodic chirping sound sometimes.

Clusterbot was my first Arduino project, and I think he makes a great project for a beginner.  While building Clusterbot you will learn how to use motor controllers, ultrasonic rangefinders and how to program an elementary robotic platform.  The most important thing I learned from building Clusterbot was the importance in planning the location of things like your Arduino board, battery packs, wiring, etc.  

Why is it called Clusterbot?  The more I worked on Clusterbot, the more I found my form following function than design.  I ended up with wires everywhere, the battery pack extended off the back to maintain balance and a mess of erector set odds and ends.  The end result was a cluster%#&@ of parts really, so I named him Clusterbot.  No matter what the rest of him looks like, the ultrasonic sensors gave him a good looking face, and at least you could tell where the front was.

You don't have to follow every step of the physical build, but I do recommend you pay close attention to the motor controller hookup and ultrasonic programming sections.

Let's get started!

Here's a video of  a finished Clusterbot:


Step 1: Bill of Materials

1. Arduino Uno - get an eBay knockoff for around $15 shipped.
2. Pololu round robot chassis kit - $24 at http://www.robotshop.com/pololu-round-robot-chassis-kit-solid-blue-2.html
3. Pololu dual 1A motor driver - $8.45 at http://www.robotshop.com/productinfo.aspx?pc=RB-Pol-110&lang=en-US
4. Protoshield - $14.95 at http://www.robotshop.com/productinfo.aspx?pc=RB-Spa-303&lang=en-US
5. HC-SR04 Ultrasonic sensor - Buy these on ebay.  You can get them for around $4 apiece instead of the $30 Parallax charges for their PING sensors.
6. Hookup wire and solder.
7. Battery holder for motor batteries.  I bought a 2 AA pack from Radio Shack for a couple of bucks.
8.  Two AA batteries and one 9 volt battery.
9. Various nuts, bolts, zipties and pieces of wood,plastic, etc.  I used parts from an old erector set.  Whatever you have laying around will be fine. 
10.  Optional - I added a big diffused green LED and a piezo buzzer to my Clusterbot to pimp it out a little.  Buy a few noisy and shiny things to make your bot more interesting.

The Pololu round robot chassis referenced above contains the motors,gearbox,axles,wheels,tires,caster and round plastic chassis.  This is a pretty awesome deal for a first robot.  The kit actually comes with two casters too.

The protoshield is not essential - you may substitute your own breadboard instead.  I used a protoshield because I had one sitting around.  It does make your design a little cleaner however.

If you already have an Arduino and either don't use or already have a protoshield, you can build Clusterbot for around $35.  Buying everything listed above will come to around $70.

Step 2: Assemble the Gearbox

Follow the instructions for the Tamiya gearbox assembly.  I used the lower gear ratio instructions for my build.  You can use the video below for reference.

Step 3: Assemble the Ball Caster

Two of them come in the kit - you only have to put one together.

Step 4: Solder Headers to the Motor Driver

Solder the header pins to the motor driver breakout board.  An easy way to do this - use a breadboard to hold everything together as shown in the video.

Step 5: Assemble Chassis

Time to attach the wheels and tires and mount the gearbox and ball caster to the chassis.

Step 6: Solder Hookup Wire to Motors

Solder hookup wire to the two terminals on each motor.  Leave plenty of slack - these wires will connect to the motor driver on top of the robot.  Strip, make a little hook in the wire, squeeze it to the terminal and solder.  I used zipties for cable management.

Step 7: Mount Arduino, Protoshield and Motor Driver to Chassis.

Use your imagination in this part.  I used erector set parts to build a little platform to mount my electronics to.  Motherboard type standoffs can be helpful.  Be aware of the balance of your bot when you place your components, especially the AA battery pack.  You will also need to find somewhere to mount the 9V battery that will power the Arduino.

Step 8: Understanding Your Motor Driver!

It took a few hours of research and trial and error for me to figure out how to use the Toshiba TB6612FNG with my Arduino, but I finally figured it out.  Hopefully I can save someone some trouble by posting all of the information here.

This information is referring to the Toshiba TB6612FNG , sold on breakout boards as the Sparkfun Motor Driver 1A Dual TB6612FNG and the Pololu Dual DC Motor Driver 1A.  Refer to the picture for the rest of this step for pinout information. 

A few TB6612FNG links:
TB6612FNG Motor Driver carrier overview at Robotshop.com
Toshiba TB6612FNG Datasheet
Forum post at the Pololu forum regarding using the TB6612FNG with Arduino.

At first I was under the impression that you just hooked up AO1 and AO2 to one motor, BO1 and BO2 to the other motor, and PWMA to one PWMA to one PWM output and PWMB to another PWM output.  It turns out, you have to make every connection on the TB6612FNG chip to get it to work properly.   I'll cover them one by one.

From the top left of the diagram, working counter-clockwise:
GND - Connect to the ground terminal on the Arduino board
VCC  - Connect to the 5V VCC on the Arduino board.
AO1 - Connect to the negative lead of motor A.
AO2 - Connect to the positive lead of motor A.
BO2 - Connect to the positive lead of motor B.
BO1 - Connect to the negative lead of motor B.
VMOT - Connect to the positive side of the power source you are using to power the motors.
GND - Connect to the negative side of the power source you are using to power the motors.
PWMA - Connect to PWM pin on the Arduino.  On the Arduino Uno, this would be either pin 3,5,6,9,10,or 11.
AIN2 - Connect to a digital pin on the Arduino.
AIN1 - Connect to a digital pin on the Arduino.
STBY - Connect to a digital pin on the Arduino.
BIN1 - Connect to a digital pin on the Arduino.
BIN2 - Connect to a digital pin on the Arduino.
PWMB - Connect to a PWM pin on the Arduino.  On the Arduino Uno, this would be either pin 3,5,6,9,10,or 11.
GND - Connect to the ground of the Arduino.

Now that you have the connections made, it is easy to use the controller to make your motors go.  Basically, you make motor A move clockwise by setting AIN1 to HIGH, AIN2 to LOW, and sending a value between 1 and 255 to PWMA.  STBY will need to be set HIGH also for any motor control to happen.

Also, your mileage may vary, but I found that my motors would not function reliably unless I used a minimum PWM value of 35.  This is probably a function of motor size, power source, robot weight, etc.

So, to go forward you would need to program:
STBY - HIGH
AIN1 - HIGH
AIN2 - LOW
PWMA - 255
STBY - HIGH
BIN1 - HIGH
BIN2 - LOW
PWMB - 255

Backwards would be the same as the above, except AIN1 and BIN1 would be LOW while AIN2 and BIN2 would be high.

So, the IN1 and IN2 pins determine direction, while the PWM pins control speed.  You should be able to use this information to figure out how to do all sorts of turns and maneuvers.

Don't forget the STBY pin must be high for the chip to work!

Step 9: Wire Up the Arduino and Code for Your First Test Run

Connect the jumper wires and from your Arduino to the mini breadboard on your protoshield.  Use the picture from the previous step to help accomplish this.

As for the I/O pins on the Arduino, connect them to the motor driver as follows:

PWMA will connect to pin 3 on the Arduino.
AIN1 will connect to pin 0 on the Arduino.
AIN2 will connect to pin 1 on the Arduino.
PWMB will connect to pin 5 on the Arduino.
BIN1 will connect to pin 2 on the Arduino.
BIN2 will connect to pin 4 on the Arduino.
STBY will connect to pin 6 on the Arduino.

In the code below, I wrote up a few functions to make it easier to control the robot.  The main code section looks a lot like the old Logo programming language.

I had to spend a little time getting ClusterBot to track straight.  I've got no physical way to do a front-end alignment on the robot, so I tweaked the goForward() and goBackward() functions by changing the PWM values until the bot tracked relatively straight.  It's not crucial that it's perfect with this robot, but when I first ran ClusterBot, he would move in arcs instead of lines.  I'm not sure if the robot is not tracking straight because it is physically crooked, the weight is unevenly distributed, the PWM signals are different from the two pins on the Arduino, or if it's simply a matter of different performance characteristics of the two cheap-o motors.  Probably a combination of all of the above.

I also took some rough measurements of the angular distance travelled when rotating left and right so I could easily make the robot turn roughly 90 degrees, 180 degrees, etc.  The problem with this is that as the batteries discharge, the angular travel will decrease also.  It's just a rough estimate.  It might not be on this bot, but I will have to have encoders on my wheels at some point, or just use stepper motors.  Encoded wheels will probably be the answer though.

The code:

#define PWMA 3
#define AIN1 0
#define AIN2 1
#define PWMB 5
#define BIN1 2
#define BIN2 4
#define STBY 6


/* Robot does 27 rotations in one minute and
10 feet in 25 seconds.  Current straight tracking is 233 left, 255 right. */


void setup() {
  // put your setup code here, to run once:
pinMode(PWMA,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(BIN2,OUTPUT);
pinMode(STBY,OUTPUT);


}


void loop() {

  startUp();
  goForward();
  delay(5500);
  turnAround();
  goForward();
  delay(5500);
  turnAround();
  goBackward();
  delay(5500);
  rotateLeft();
  delay(560);
  rotateRight();
  delay(560);
  goForward();
  delay(3000);
  applyBrakes();
  delay(2000);
  }


void goForward ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,234);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}


void goBackward ()
{
  digitalWrite (AIN1,LOW);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,233);
  digitalWrite (BIN1,LOW);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}


void rotateRight ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,LOW);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}


void rotateLeft ()
{
  digitalWrite (AIN1,LOW);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}


void veerLeft ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,190);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}


void veerRight ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,190); 
}


void applyBrakes ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}


void startUp ()
{
  digitalWrite(STBY,HIGH);
}


void turnAround()
{
  rotateLeft();
  delay(1370);
}


void shutDown ()
{
  digitalWrite(STBY,LOW);
}

Step 10: Attach and Hookup the HC-SR04 Ultrasonic Sensor

There are four pins on the HC-SR04 sensor.  They are labelled VCC,TRIG,ECHO and GND.  I soldered hookup wire to each pin.  Connect the VCC lead up to the 5V pin on your Arduino, then connect the ground lead of the sensor to a ground pin on the Arduino.  TRIG will connect to pin 10 and ECHO to pin 11.


Step 11: Pimp Your Robot, Upload the Code and Unleash the Clusterbot!


I attached an LED to pin 7 on the Arduino.  I did not use a resistor!!!  But you should.

I attached a Piezo buzzer to pin 9 on the Arduino.  I did not use a resistor.  But you should.

You will need to download the HC-SR04 library and save it to your Arduino library folder.  Get it here.

The code:

#include "Ultrasonic.h"
Ultrasonic ultrasonic( 10, 11);

#define PWMA 3
#define AIN1 0
#define AIN2 1
#define PWMB 5
#define BIN1 2
#define BIN2 4
#define STBY 6
#define LED 7
#define SPEAKER 9
#define FREQ 1000

/* Robot should continue straight until an object is within the distance threshold */
/* Sorry for the superflous code at the bottom - I need to get those functions */
/* into a header file  */

/* The robot should move forward and have a steady green LED until something is 7 inches in front of the sensor.
   Then the robot should stop and rotate left until there is not an object within 7 inches anymore               */

void setup() {

pinMode(PWMA,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(BIN2,OUTPUT);
pinMode(STBY,OUTPUT);
pinMode(LED,OUTPUT);

}

void loop() {

  startUp();
  while(ultrasonic.Ranging(INC) < 9) {
    rotateLeft();
    digitalWrite(LED,HIGH);
    tone(SPEAKER,FREQ);
    delay(20);
    digitalWrite(LED,LOW);
    noTone(SPEAKER);
    delay(20);
  }
  goForward();
  digitalWrite(LED,HIGH);


}
void goForward ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,233);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}

void goBackward ()
{
  digitalWrite (AIN1,LOW);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,233);
  digitalWrite (BIN1,LOW);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}

void rotateRight ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,LOW);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}

void rotateLeft ()
{
  digitalWrite (AIN1,LOW);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}

void veerLeft ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,190);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,255); 
}

void veerRight ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,LOW);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,LOW);
  analogWrite(PWMB,190); 
}

void applyBrakes ()
{
  digitalWrite (AIN1,HIGH);
  digitalWrite (AIN2,HIGH);
  analogWrite(PWMA,255);
  digitalWrite (BIN1,HIGH);
  digitalWrite (BIN2,HIGH);
  analogWrite(PWMB,255); 
}

void startUp ()
{
  digitalWrite(STBY,HIGH);
}

void turnAround()
{
  rotateLeft();
  delay(1370);
}

void shutDown ()
{
  digitalWrite(STBY,LOW);
}