Crepton the Coasterbot

May 2nd, 2010

Here’s my entry for the Make: Magazine Robot Build:

More pics in my Flickr set:

http://www.flickr.com/photos/simplebot/sets/72157623775333657/

Coasterbot entry thoughts, goals, info

May 2nd, 2010


Project Goals:
- To build my first programmable robot
I’ve built several BEAM robots in the past, but have never built a programmable bot, and have always wanted to.
- to use only materials on hand
I knew I had everything I’d probably need to build a robot in my bins, since I’ve been wanting to build one for quite a while and had stocked up parts, but never built anything.
-make an aesthetically finished lookiing robot
I’m an artist by trade, so I wanted to build something that looks nice, even within the narrow time constraints that I had to do this project
- leave considerations for future expansion
I’d like this thing to become something I can let just “live” in my house without having to always wonder where it might be, so it’ll need more than just the two touch sensors it has now.
-work within my current time constraints.
I’m in crunch time at work doing 50-60 hours a week, so finding time to build robots is hard to come by.
have fun!
if it’s not fun, what’s the point?
Environment considerations:
This robot is to exist primarily in my house. THe floor is all VCT tile, and is flat and smooth. Since the robot was going to be pretty small, I wanted it to sit as close to the floor as possible so that even small things will be encountered as obstacles.


Construction:
Materials:
2 CD rom spindle spacers… no recordable media
2 surplus wheels from All Electronics (purchased about 8 years ago)
1 pololu baby orangutan-b 168 robot controller
2 Solarbotics GM6 gear motors.
1 lipo battery from a broken RC helicopter (that I still hope to salvage more parts from)
1 pololu ball caster wheel for the front wheel
sintra expanded PVC for the bumper and battery holder
2 salvaged switches from some old electronics
bits of shapelock thermoplastic for the nut caps.
4 screws and nuts
aluminum pipe cut to length for the chassis spacers
bits of wire from salvaged electronics
bits of foam I had around for the bumper mount
door weather stripping for the bumper top guides
2 transparent CDROM spindle spacers
2 surplus toy wheels from All Electronics
2 GM6 gear motors from Solarbotics
2 micro switches from salvaged electronics
1 lipo battery salvaged from broken RC helicopter
strip of sintra expanded PVC
bits of Shapelock thermoplastic
weatherstripping
bits of wire from salvaged electronics
bits of sponge
scrap perfboard
aluminum pipe
pololu baby orangutan-b 168 robot controller
pololu ball caster wheel
double sided fabric waterproofing tape
4 screws and nuts size 6-32
Tools:
I used only hand tools for the construction of the robot parts. The CDs were cut using a jewler’s saw and a small finger drill for pilot holes. All other holes were drilled with the small drill and then reamed to size.
expanded PVC bumper was cut with a utility knife then thermoformed to shape by placing the sheet into boiling water and then bending into shape by hand while still soft.
Soldering was done with my hakko 936 solder station.
chassis:
I used transparent spacers from the CD spindles that I already had on hand. Once the shapes were cut and test fit, I used 600 grit sandpaper to give a dull finish to the CDs, for a translucent effect instead of purely transparent .
Motors:
I used the Solarbotics motors mostly for the form they come in. The have squared off sides that I knew I could use to help add some structural rigidity to the chassis.
Bumper:
The bumper works pretty well. I used sponge for attaching the bumper to the frame of the robot. This kept it rigid enough to stay in place while still soft enough to trigger the switches when an obstacle is encountered. I left enough space inside so that I can add 2 IR proximity detectors to the back side of the bumper. I will cut two holes into the bumper to allow the prox sensors to peek through while still not protruding from the surface of the bumper.
The bumper fails to detect low lying objects that only strike the lower quarter inch or so of the bumper. I’m still trying to refine this so that it will always trigger the switches.
Programming:
I used a Rodney Brooks style behavior based method for programming this robot. I drew heavily from the book: Mobile Robots: Inspiration to Implementation. I combined this with my lousy programming knowledge to cobble something together. I’m sure my programming style leaves much to be desired.
My program is written in C, and compiled and programmed with gcc through Atmel’s AVR Studio software. I used the programming libraries that Pololu provides to interface with the Baby Oragutan, which were a tremendous help. This greatly simplified figuring out how to set up the pins as digital input, as well as providing functions for driving the motors without getting into all the nitty gritty of dealing with PWM.
Things learned:
I really need to learn more programming. One of the biggest challenges that I faced was making my robot turn after a bumper strike. I was trying to implement a timer that would count down while still cycling through the sensor checking. I thought my timer wasn’t working, but it was just ticking through the timer too quickly. Once I switched my variable type to something that could handle larger numbers I could make the bot turn for a while before starting off in a new direction.
CDs aren’t a very good building material.The CDs I used are already cracking in the holes for the screws.

Next time I’d use connection headers for the controller instead of hard wiring everything to the header pins. It’ll get pretty sloppy looking by the time I use up all the pins on the controller board.

Foolproof touch sensors are difficult to make. I guess that’s why even my roomba will get stuck from time to time.

BONUS:  The robot still fits into a CDROM spindle. So I guess I have storage for the robot taken care of.

Things to do In order of importance.
-Add voltage sensor behavoir to monitor battery voltage. Since I’m using a lipo battery, I need to make sure that I don’t drain the battery down too far.

-I’d like to make the bump behavior turn the bot for a random amount of time instead of fixed. This way it’s less likely to get stuck in a repetitive loop in certain situations.

-Make an “I’m bored” behavior that switches the robots direction after a certain amount of time without another sensor being activated.
-Add proximity sensors that can detect when the bot is close to something, and turn away from it.  It will work in a similar way to the bump function, but will arc away from the stimulus instead of pivoting. I have some proximity sensors that I can install.
-add a PIR sensor and play with non-navgation issues, like responding to human presence.

sorry for the mess.

May 2nd, 2010

I just set up this site so bear with me as I get it all working… I’ll be putting more information than is in my flickr set here.

coasterbot code

May 2nd, 2010

/*
coasterBotSubsumption.c
by Darrell Johnson simplebot AT google’s email service DOT com

com port in makefile is set to com3
Subsumption code based on the code found in:
Mobile Robots: Inspiration to Implementation
by Joseph Jones and Anita Flynn

It’s a fixed priority arbitration scheme to pick from the various behaviors that are
coded.

I’m new to programming so this is probably lousy code.
******************************************************************************

right bumper is IO_C0
left bumper is IO_C5
*/

// Includes

#include

// Constants

//drive constants
#define STOP 0
#define FORWARD 1
#define BACKWARD 2
#define LEFT_TURN 3
#define RIGHT_TURN 4

// Global variables
volatile uint16_t timer_cnt = 0;
volatile uint8_t timer_on = 0;
volatile long distance = 0;
volatile long angle = 0;

//DJ my global variables
//DJ behavior flags: initial states
volatile uint8_t cruise_active = 1;
volatile uint8_t bump_active = 0;
volatile uint8_t panic_active = 0;

//DJ behavior commands
volatile uint8_t cruise_command = 0;
volatile uint8_t bump_command = 0;
volatile uint8_t panic_command = 0;
volatile uint8_t avoid_command = 0;

// globals for the bump behavior function

volatile long turn_angle = 0;
volatile uint8_t turn_dir = 1;
volatile uint8_t turning = 0;
volatile uint8_t backing_up = 0;

// Functions
void initialize(void);
void moveRobot (uint8_t operation);

//DJ behavior prototypes
void cruise(void);
void bump(void);

//DJ arbitration prototype
void motor_control (void);

//main program
int main (void)
{ //set up the controller
initialize();
// Stop just as a precaution

moveRobot(STOP);

// STARTUP DELAY
delay_ms(9000);

// THIS IS THE MAIN LOOP
while(1)
{
// cycle through the behaviors and the motor control
bump();
cruise();
motor_control(); //this is where the subsumption priority happens
}
}

// Initialize the ATmega168 microcontroller
void initialize(void)
{

set_digital_input(IO_C0, PULL_UP_ENABLED); // left bumper
set_digital_input(IO_C5, PULL_UP_ENABLED); //right bumper

}

// movement commands used by behaviors
void moveRobot (uint8_t operation)
{
if(operation == STOP)
set_motors(0,0);
if (operation == FORWARD)
set_motors(100, 113);
if (operation == BACKWARD)//{
set_motors(-50, -50);

if (operation == LEFT_TURN)//{
set_motors(75, -75);

if (operation == RIGHT_TURN)//{
set_motors(-75, 75);
set_motors(50, 350);
}

//DJ function working area
/////////////////////////////////////////////////////////////////////

//DJ cruise behavior Always active
void cruise()
{
cruise_command = FORWARD;
cruise_active = 1;
}

//bump behavior
void bump()
{
if(turning)
{
if(backing_up)
{
if(distance >turn_angle)
{
backing_up = 0;
}
bump_command = BACKWARD;
distance ++;

}
else
{
if(turn_dir)
{
if(angle > turn_angle)
{
turning = 0;
bump_active = 0;
}
else{
angle ++;

bump_command = RIGHT_TURN; //pivot CCW
}
}
else
{
if(angle > turn_angle)
{
turning = 0;
bump_active = 0;
}
else{
angle ++;
bump_command = LEFT_TURN; //pivot CW
}
}
}
}
else if ((is_digital_input_high(IO_C0))==0 || (is_digital_input_high(IO_C5))==0) //check for a bump

{
// Set the turn parameters and reset the angle
if ((is_digital_input_high(IO_C0))==0 && (is_digital_input_high(IO_C5))==0)
{
backing_up = 1;
turning = 1;
distance = 0;
angle = 0;

bump_active = 1;
}
else if ((is_digital_input_high(IO_C0)==0) && (is_digital_input_high(IO_C5)))
{
turn_dir = 1;
turning = 1;
bump_active = 1;
angle = 0;
turn_angle = 100000;
}
else if ((is_digital_input_high(IO_C5)==0) && (is_digital_input_high(IO_C0)))
{
turn_dir = 0;
turning = 1;
bump_active = 1;
angle = 0;
turn_angle = 100000;
}

}
else
turning = 0;

}

// DJ this is the main subsumption loop
void motor_control ()
{

if (bump_active)
moveRobot(bump_command);
else if (cruise_active)
moveRobot(cruise_command);
else
moveRobot(STOP);
}

/////////////////////////////END/////////////////////////////////////

coasterbot

May 2nd, 2010