Monday, May 10, 2010

Final Photos and Videos

Here are my final photos and videos for the Make: Robot Build Contest.  Click on the pictures for a lager image.  Sorry for the poor exposure on both the pictures and videos.


Here are some videos of Twitch:
  • Good Run - Shows a pretty good run with a few obstacles.
  • Out of Tough Corner - Shows Twitch successfully navigate a pretty tough area.
  • Brave Soldiers 3 - Shows the good sensitivity of the bumper assembly against a small, unanchored Legos model.  Those are some brave soldiers!
  • Brave Soldiers 4 - Shows the good sensitivity of the bumper again.  Wondering what happened to Brave Soldiers 1 & 2?  Maybe they weren't so lucky... or maybe George Lucas had something to do with the progression of the story (ok, by the looks of the video, probably not).
  • Head-on 1 - Shows how Twitch handles a head-on collision by reversing.
  • Head-on 2 - Shows how Twitch handles another head-on collision.
  • Stuck - Shows Twitch get stuck... it happens.
What a blast this has been!  Hope we do it again.

Parts List

Part of the requirement for the Make: Robot Build Contest is to provide a parts list.  Here it is:

Parts List (OpenOffice Spreadsheet)
Parts List (PDF)

Microcontroller

Now that I have the physical form of the robot, I guess it is time to work on the controller and get something going.  Initially, this was a bit more difficult than I first thought.

I encountered a bit of confusion over the difference between the pin numbers on the controller chip (Ardweeny with an ATmega328) and the "pins" in the Arduino development environment.  My brother, Steve, later explained to me that this is because the Arduino environment pins are the pins on the Arduino board as opposed to the pins on the actual microcontroller chip.  At any rate, I eventually figured it out with the help of the small pin lables on the Ardweeny circuit board and some online research.

Once I had the pins straight, my control circuit using the TI L293D worked very well.  I simply tied the EN1,2 and EN3,4 pins to +5v through a current-limiting resistor, tied the A pins to the Ardweeny, and tied the Y pins to the servos.

I interfaced the bumper switches through current-limiting resistors and draw-down resistors so that when the switches were closed they would trigger a HIGH state on the input pins.

By the way, after playing with the robot for a while, modifying the code, and coming up with a reasonable navigation routine, I decided to call the robot "Twitch."  Here is the schematic:  Twitch Robot Schematic.

The code is fairly simple.  One aspect that might not seem straight-forward to some is that I used Pulse Width Modulation (PWM) to calibrate the servos while the bot was moving forward and backward.  I am not sure why, but the bot moves in an arc if supplying full voltage to the servos by triggering the Ardweeny pins digitally (HIGH/LOW).  To compensate for this, I use PWM (or Analog output as it is called in the Arduino) on the servos to gain a finer control over how much they rotate during any given time period.  With PWM, you can make a servo move at an 8-bit resolution (256 values) of speed instead of simply off or on.

Here is a link to the code:  Twitch Controller Sketch

Here is the code text:

/*
 Twitch3

 Twitch Robot Control

 2010 by Karl Demuth - use as you like!

 This control program allows Twitch to navigate by checking input from left and
 right bumpers and turning accordingly.  The servo control is done with two modified
 servos (left and right) driven by a Texas Insruments L293D h-driver.

 */

int pin_LED = 13;             // LED connected to digital pin 13
int pin_RightServo_1A = 5;    // Right Servo pin output to 1A on L293D
int pin_RightServo_2A = 6;    // Right Servo pin output to 2A on L293D
int pin_LeftServo_3A = 9;     // Left Servo pin output to 3A on L293D
int pin_LeftServo_4A = 10;    // Left Servo pin output to 4A on L293D
int pin_LeftBumper = 12;      // Left Bumper Switch
int pin_RightBumper = 1;      // Right Bumper Switch
int state_LeftBumper = 0;     // Intermediate holder of left bumper state
int state_RightBumper = 0;    // Intermediate holder of right bumper state

int calibration_LeftServo = 255;    // calibration of PWM output so that when going
                                    // forward or backward, the robot goes straight
int calibration_RightServo = 190;   // 0 = no output, 255 = full output

// setup() runs one time when the sketch begins and initializes pins and variables

void setup()   {               
  // initialize the digital pin as an output:
  pinMode(pin_LED, OUTPUT);
  pinMode(pin_RightServo_1A, OUTPUT);
  pinMode(pin_RightServo_2A, OUTPUT);
  pinMode(pin_LeftServo_3A, OUTPUT);
  pinMode(pin_LeftServo_4A, OUTPUT);
  pinMode(pin_LeftBumper, INPUT);
  pinMode(pin_RightBumper, INPUT);

}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                    
{
  state_LeftBumper = digitalRead(pin_LeftBumper);
  state_RightBumper = digitalRead(pin_RightBumper);
 
  if ((state_LeftBumper == HIGH) && (state_RightBumper == HIGH)) {
    // both bumpers are triggered meaning that Twitch hit something headon
    digitalWrite(pin_LED, HIGH);
    reverse();
  }
  else if ((state_RightBumper == HIGH) && (state_LeftBumper == LOW)) {
    // hit something on the right, so we'll turn left a bit (avoid_right)
    digitalWrite(pin_LED, HIGH);
    avoid_right();
  }
  else if ((state_LeftBumper == HIGH) && (state_RightBumper == LOW)) {
    // hit something on the left, so we'll turn right a bit (avoid_left)
    digitalWrite(pin_LED, HIGH);
    avoid_left();
  }
  else {
    // we're not hitting anything, so let's proceed forward
    digitalWrite(pin_LED, LOW);
    forward();
  }
}

// forward() - activate both servos to go forward
//  - uses the calibration values set toward the top of this program so Twitch
//    actually goes somewhat?? straight
void forward()
{
  analogWrite(pin_RightServo_1A, calibration_RightServo);
  digitalWrite(pin_RightServo_2A, LOW);
  analogWrite(pin_LeftServo_3A, calibration_LeftServo);
  digitalWrite(pin_LeftServo_4A, LOW);
}

// backward() - activate both servos to go backward
//  - uses the calibration values set toward the top of this program so Twitch
//    actually goes somewhat?? straight
void backward()
{
  digitalWrite(pin_RightServo_1A, LOW);
  analogWrite(pin_RightServo_2A, calibration_RightServo);
  digitalWrite(pin_LeftServo_3A, LOW);
  analogWrite(pin_LeftServo_4A, calibration_LeftServo);
}

// rotate_right()
//  - activates the left servo forward and the right servo backward to rotate
//    Twitch right
void rotate_right()
{
  digitalWrite(pin_RightServo_1A, LOW);
  digitalWrite(pin_RightServo_2A, HIGH);
  digitalWrite(pin_LeftServo_3A, HIGH);
  digitalWrite(pin_LeftServo_4A, LOW);
}

// rotate_left()
//  - activates the right servo forward and the left servo backward to rotate
//    Twitch left
void rotate_left()
{
  digitalWrite(pin_RightServo_1A, HIGH);
  digitalWrite(pin_RightServo_2A, LOW);
  digitalWrite(pin_LeftServo_3A, LOW);
  digitalWrite(pin_LeftServo_4A, HIGH);
}

// avoid_right() - turn left a bit
//  - activates only the right servo to turn left a bit
//  - left turning is done by turing left wheel backward
void avoid_right()
{
  digitalWrite(pin_RightServo_1A, LOW);
  digitalWrite(pin_RightServo_2A, LOW);
  digitalWrite(pin_LeftServo_3A, LOW);
  digitalWrite(pin_LeftServo_4A, HIGH);
}

// avoid_left() - turn right a bit
//  - activates only the left servo to turn right a bit
//  - right turn is done by turning right wheel backward
void avoid_left()  // by turning right
{
  digitalWrite(pin_RightServo_1A, LOW);
  digitalWrite(pin_RightServo_2A, HIGH);
  digitalWrite(pin_LeftServo_3A, LOW);
  digitalWrite(pin_LeftServo_4A, LOW);
}

// reverse()
//  - this routine reverses Twitch by backing up a bit, then
//    rotating right a bit
//  - this routine is used when Twitch hits something headon
//    so that the robot reverses direction
void reverse()
{
  backward();
  delay(1500);
  rotate_right();
  delay(1500);
}

Bumper Assembly

Ok, time for some brutal honesty... this is going to be a bare-bones bot, just to get through this.  Yeah, I have a TON of ideas which I cannot wait to implement, but time is moving along and the deadline draws near.  What made me think that family life and a bot-building contest were compatible is beyond me!!

So, I thought the chassis was the hump.  GEEZ!... I hadn't even really given much thought to how I would mount my sensors (bumper switches in my case)!  So, I had a look at the micro-switches that came in the Jameco pack.  They both have two small mounting holes.  Great!  No problem!... except I couldn't find anything in my parts bins small enough to fit through the holes.  My brother, Steve, who is also an entrant in this contest and obviously way brighter than me, read the spec sheet for the switches and found that they require a 2M screw (two millimeter metric).  After searching the typical local DIY stores, I came up empty.  Time to reconsider my mounting plan.

My next thought was that I could mount the switches to some perfboard by soldering the switches directly to the board.  This ended up being the way I fabricated the final bumper assembly.  I soldered the switches to the perfboard and then mounted some bumpers cut from CDs in such a manner that the bumpers would bend and activate the switches.  My final assembly accounts not only for side strikes, but for headon strikes as well.  Later on, after testing the robot, it was obvious there were some weaknesses in this design.  First, the bot can get hung up under overhangs.  Second, sometimes when the bot tries to back a bit to avoid an obstacle, the bumpers can get caught on something, actually prying the bumper away from the switch.  Not ideal, but it will work for a first pass.

First, I got the parts together and cut some more angle brackets to mount the bumper assembly to the bot.  Then I checked placement of the switches.


Then I cut the CDs and mounted one to the assembly to see how it worked.  It worked, but it really needed some more leverage.


Seeing that the bumpers needed a bit more leverage, I drilled two holes a little closer to the center of the perfboard, cut the CDs flush in the center, and ended up getting much better results.  By the way, those are 4-40 x 1" screws.  Oh, and please ignore how my home made angle brackets aren't square!!


After making sure the bumpers would activate the switches, I wanted to mount a current-limiting resistor to the assembly.  I am not real sure now why I did not do this on the protoboard, but at the time it seemed like a good idea.  Yeah, it was kind of painful.  I hate perfboard, as you can see by my horrible-looking solder job!


Here are some pictures of the test-fit on the bot.  I later re-cut different bumpers to get them a bit more even and re-drill the holes so that they were mounted a bit more square.

Building the Chassis

This is the part of the build which concerned me the most.  The physical aspect of getting things put together in a way that would work is primarily what has kept me from building a bot in the past, so this was also one of the more exciting aspects... the hump, so to speak.

The first matter of business was to fashion some manner of mounting the servos.  I found some servo brackets that I could order online, but I really did not want to spend the money nor wait the time to receive them.  I can do this, right?  Looked at the typical stores like Home Depot and Lowe's for some angle brackets that would work.  Nothing.  Finally, I settled on a three-foot length of 1" x 1" x 1/16" aluminum angle and decided that I could cut and drill my own brackets.  I used a cheap mitre box and a hacksaw to cut the brackets 3/8" wide.  Then I placed the servos onto the brackets and marked where to drill the holes.



One important aspect to remember is to mount your servos reverse from each other.  Once this was accomplished, I marked and drilled the base CD so that I could attach the servos and other mechanical parts.  The pictures here were my first pass.  After dealing with a serious lack of prior design and the many factors that followed, such as not easily being able to remove the battery holder while the robot was assembled, I eventually re-fit and re-drilled my parts placement.  As you will see in a later post, I saved some holes by running the layer standoffs vertically from the servo brackets.  This worked very nicely.  Also, I later decided to drill two through-holes for the wires instead of trying to run them all through the center holes of the CDs.


Once the base was built, I placed the controller protoboard on top and had a look to see if everything fit.  Basically, I think we're off to a good start and at this point, I felt like I was past the hardest part.