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.


Sunday, April 4, 2010

Servo Modification for Continuous Rotation

Things are moving along for me on my robot build for the Make: Robot Build Contest.  I'm having a blast!

So, my next step is to modify a servo for continuous rotation.  Most servos are designed to allow only a limited degree of freedom in rotation and the Hitech HS-322HD that comes in the Jameco build kit is no different.  Since we're going to mount wheels to each servo, we'd really like for them to be able to turn (and keep turning) 360 degrees in either direction.

I'm going to use a couple special tools.  The first is a desoldering vacuum, or "solder sucker" as some might call it.  This will help remove solder when I desolder the servo's controller board from the motor.  The second tool is a micro cutter.  This is basically a small pair of snips.



Here is our unmodified servo, a Hitech HS-322HD.


First, we're going to remove the four screws from the bottom of the servo and lift off the bottom cover.


Next, we'll desolder the motor from the controller board.  We do this primarily so that we can remove the potentiometer in a later step without damaging it.  To desolder the motor, heat the two solder lugs on the motor (the two big solder joints at the opposite end of the servo from where the control wires enter), one at a time, and use the desoldering vacuum to pull the solder from the lugs.  Once all the solder is removed, use a small, flat screwdriver to lift the controller board away from the motor.


One you have the controller board free from the motor, you will see three wires running from the board to a potentiometer.  There is a small screw holding the potentiometer in place.  Remove the screw, free the potentiometer, and pull the entire controller unit free from the servo.


So, now we have separated the controller from the servo.  In the future we can reinstall it back into the servo for another project, use it separately in another project, or raid it for its parts!


Our next step will be to solder two wires to our motor.  You could use the original control wires from the servo, but I chose to just add a couple of my own.  I fashioned a small hook in the end of each wire to loop through the lugs of the motor.  This will help avoid having the wires easily pulled out of the servo.


Once we have the wires hooked through the lugs, crimp them with a pair of needle-nosed pliers to help hold them in place.  Then solder the wires to the motor lugs.


Our motor is all set now, so we need to concentrate on the gears next.  There is a small tab on the main drive gear that was originally designed to keep the servo from rotating completely.  We need to remove the tab, so remove the top cover of the servo to expose the gears, starting by removing the screw and wheel on top of the servo.


Let's take a profile picture of the gears so that we can remember how they were assembled!  Then we'll remove the main gear (large white gear) and separate the bearing sleeve from it.


In the close-up picture, you can see the small tab that we need to remove so that the gear will be able to rotate fully.  There are some options regarding how to remove the tab.  I opted to use a pair of micro snips to avoid getting sawdust in the grease.  However, you could likely use a small dremel cutter to saw it.  I also read about someone melting the tab to remove it.  The danger in using the snips is that it could cause the gear shaft to split.  I read about this possibility in a number of online posts where folks had accidentally split the gear or gear shaft when cutting.  To try to minimize this possibility, I decided to make my first cut parallel to the gear shaft and then make my second cut perpendicular to the shaft.  To further minimize the risk, I made sever small cuts in this fashion as opposed to trying to remove the tab with only two large cuts.


Once the tab has been removed, it should be nice and flush with the gear so that it does not catch the stop that is built into the case of the servo.


We can now reassemble the gears.  Don't forget to place the bearing sleeve back onto the main drive gear.


You can now replace the top and bottom covers of the servo and mount the wheel to the main drive gear instead of the original white horn disk.


Now we can test the servo to make certain it turns continuously in both directions.  If you have your voltage regulator built, you can connect the servo wires to the power bus of your breadboard.  Once you are sure it turns in one direction, flip the polarity of the wires and try it the other direction.  This isn't quite the way the servos will be powered in our final robot, but it is a good test to make sure our modification was successful.