ELEC 201
Professors Bennett & Young
13 December 1997
Three Crazy Bastards – Thursday Group #3
How to Build Your Very Own
Fully Robotic Execution Device
1.0 STRATEGY
Our robot has been placed on Mars, and has been presented with the task of collecting samples of Martian soil, specifically Unobtainium (Un). Our goal is to collect as many samples of the soil (which will hopefully contain several Un samples) as possible in 90 seconds and return them to a special collection bin. To accomplish this goal, we have implemented three different strategies:
2.0 ROBOT STRUCTURE
Start with a bin of parts. See Figure 1.

Figure 1. In the beginning, there was a bucket of parts, and it was good.
Then came Three Crazy Bastards, and the madness began.
2.1 Frame
F.R.E.D.’s frame consists of a series of parallel beams running from the rear of the robot to the front. Along the rear runs a double-wide beam across the tops of the ends of these beams. F.R.E.D.’s structure resembles more than anything else a dune buggy, with the forward tires more compressed toward the center than the aft tires. The battery is placed low and in the middle above the gear box which powers the forward wheels. See Figure 2.

Figure 2. This is probably the most important picture we’ve taken. It shows the drive system, the shaft encoders, the frame, and the start light detector, all in one easy snapshot.
2.2 Wheels & Drive System
The robot is powered by driving the two middle wheels. These wheels are powered independently to allow for steering control. One Johnson motor was used to power each wheel, and the motors were mounted near the rear of the robot, 1 2/3 FLU’s above the axle to be driven. Attached to each motor head is an 8-toothed gear. The motor drives a 40-tooth gear at the same altitude as the motor mounting. On this shaft is a 16-tooth gear, which drives a 40-tooth gear on the next shaft. This shaft is mounted 1 2/3 FLU’s down from the previous shaft, so that it is at the same altitude as the axle to be driven. On this shaft is an 8-tooth gear, driving a 40-tooth gear on the axle with the wheel. The total gear reduction is given by (40:16)(40:8)(40:8) = 62.5:1.
The wheels driven have bigfoot tires attached, as do the two non-driven wheels at the rear of the robot. The schematic illustrates the relative placements of all wheels and gears.
On the shaft before each of the two driven axles, we have implemented shaft encoders, using "narrow wheels" as described in the text on page 83. For every 5 turns of the shaft encoder wheel, the tires turn once. Each encoder wheel has 6 holes in it, so the motherboard counts 12 ticks per revolution. Thus, it takes 60 ticks for one revolution of the tire, or 6 degrees per tick.
Because the tires are controlled independently, a function to make F.R.E.D. move in a straight line is necessary. We used the shaft encoders for this purpose, and the function go_straight() ensures that the number of ticks counted by the encoders stays the same on both tires, increasing or decreasing the speed on either motor as necessary. The encoders also are useful for tracking distances and the angle swept out when F.R.E.D. is turning by simply counting ticks. The constants that determine the number of ticks per inch or ticks per degree will be stored as persistent floats. F.R.E.D. can move forward and backward in a straight line, and he can perform stationary turns, simply by rotating the wheels in opposite directions.
The gear box, shaft encoders, and motors can all be seen in Figure 2.
2.3 Block Acquisition
The ROtational Component (ROC) of F.R.E.D. is mounted on the bow of the robot. The ROC has an associated subsystem for block acquisition (BAD-ASS). (Actually, we just wanted to write BAD-ASS on our report.) In less complicated terms, the BAD-ASS is a system of two arms which grabs the block, and the ROC flips the BAD-ASS (and hopefully the block) over the body of the robot onto a conveyor belt which leads to our onboard storage bin located on the aft of the robot.
2.3.1 BAD-ASS
The BAD-ASS is designed to snap up blocks with the haste of a crocodile snapping up the legs of innocent tourists. Its jaws consist of two arms linked by gears in a condensed gear box surrounding a Mabuchi motor (see Figure 3). An even number of gears separate the two shaft-mounted arms so that one motor can drive both arms in opposite directions. Two touch switches were used to determine the open or closed state of the arms. These switches are visible in Figure 3, with the open sensor located just above the arm on the right and the closed sensor located behind the arm on the left.

Figure 3. Dentist’s view of the Block Acquisition system.
2.3.2 ROC
The BAD-ASS is mounted between two turrets so that it can rotate along the common axis. The purpose of the ROC is to rotate this axis, thereby rotating the entire BAD-ASS, moving a collected block 135o from its initial location in front of the robot to the waiting conveyor belt in the back of the robot.
The ROC consists of a Johnson motor geared well down so that it could overcome the heavy friction inherent to our design. Experimentation revealed that we could successfully rotate the BAD-ASS from only one side (see Figure 3), leaving the other side available for touch switches (see Figure 4), which we used to determine the angular position of the system.

Figure 4. Side view of the Block Acquisition system.
2.3.3 Conveyor
After a block has been collected, it needs to be transported to the bin in the rear of the robot. We used a conveyor belt to move the block from the rotated BAD-ASS arms to the bin. The conveyor was driven by a Mabuchi motor mounted just above F.R.E.D.’s primary drive system (see Figure 5). We used a large gear ratio because of the weak motor and the desired slow speed of the conveyor.
The belt itself is constructed of 40-tooth gears and a strip of wide belt link surrounded on each side by a strip of chain link.

Figure 5. A too-close-up of the conveyor system.
The gear box is on the left side of the figure.
The motor is located directly under the left track of the chain link
2.3.4 Storage Bin
The storage bin was built to be flexible so that it could start the round flush against the back of the robot. We tied it off using a LEGOÒ rubber band wrapped around one of the rotating shafts of the conveyor system. When the round begins, the conveyor spins and releases the bin. The bin has a plate on the robot side of the bin to prevent the many collected blocks from interfering with our gear systems.

Figure 6. Storage bin in mid-flight.
2.4 RoboBoard
A RoboBoard was constructed in the exact manner described in the Course Notes for ELEC201, Fall 1997, and was mounted vertically on the port side of F.R.E.D. Figure 7 displays a closeup of the RoboBoard and battery system, and Figure 8 displays the mounting schema of the RoboBoard.

Figure 7. The Rice RoboBoard V4.0. And battery. Nice soldering job, guys.
Note the message on the LCD screen.

Figure 8. Side view of the completed robot.
2.4 Sensors & the Outside World
F.R.E.D. has an IR beacon tower (visible in Figure 8) that emits a frequency of either 100 or 125kHz, depending on the position of dipswitch 1 on the RoboBoard. He also has two IR receivers on the tower, facing fore and aft, which measure the intensity of the beacon of the other robot. The stronger the reception, the closer the other robot.
F.R.E.D. will continually run a process called outside_world() that updates the readings of the sensors and stores them in arrays called digital_values[8] and analog_values[8]. outside_world() is a while loop that never returns false and thus runs forever, or until the process is killed at the end of execution. In addition to these two arrays, a third array called motor_speeds[6] is maintained with the function move_robot(int motor, speed), which is always called when a motor speed is to be changed. move_robot will first change the value of the appropriate motor, and then it will update the value in the array to the new speed. outside_world() also maintains the number of encoder ticks from the shaft encoders and saves them as constants.
A single IR reflectance sensor on the center of the underside of F.R.E.D. detects the start light. It is visible in Figure 2.

Figure 9. Front view of completed robot and Jim’s hand. Looks like it’s time for a manicure.

Figure 10. Top view of completed robot.
3.0 CONTROL
For the sake of expediency, we divided F.R.E.D.’s code into several files, each devoted to a certain category of functionality. MAIN.c was provided; it initiates IR equipment and launches mymain() as a process, located, conveniently, in MYMAIN.c. MOTORCONTROL.c contains the functions that deal with shaft encoders and driving F.R.E.D. around. BACKGROUND.c contains the function outside_world() that is in charge of running the process that updates the variables dealing with the environment. VARIABLES.c contains the few variables that we use, and CONSTANTS.c likewise contains all the constants we use. Finally, STRATEGY.c contains the functions that deal with the strategy and the actual commands that drive F.R.E.D. around the board and hopefully win the game. A transcript of the commented code is attached to this report in Appendix C.
A-1 APPENDIX A
There is no Appendix A. Sorry about that.
B-1 APPENDIX B
Nope. Better luck next time.
C-1 APPENDIX C
fred.lis
encoders.lis
constants.c
variables.c
motorcontrol.c
background.c
strategy.c
mymain.c
main.c
constants.c
/* */
/* constants.c -- declares constants and gives them useful, wordy */
/* names... making the code more readable... and */
/* things easier to change */
/* */
/* tell FRED which way to go -- these are fed to move_robot() */
int FORWARD = 0; /* FRED goes forward */
int BACKWARD = 1; /* FRED goes backward */
int LEFT_TURN = 2; /* FRED turns left */
int RIGHT_TURN = 3; /* FRED turns right */
/* LineStatus constants: */
int GOING_LEFT = -1; /* indicates FRED veering left */
int GOING_STRAIGHT = 0; /* indicates FRED going straight */
int GOING_RIGHT = 1; /* indicates FRED veering right */
/* strategy names */
int ONE_POINT_STRATEGY = 0;
int WINNING_STRATEGY = 1;
int EMBELLISHED_ONE_POINT_STRATEGY = 2;
/* starting directions */
int LEFT_START = 0;
int RIGHT_START = 1;
/* side of board the special bin is on */
int LEFT_SPECIAL_BIN = 0;
int RIGHT_SPECIAL_BIN = 1;
/* gives names to the motor numbers */
int LEFT_MOTOR = 0; /* port drive motor port value */
int RIGHT_MOTOR = 1; /* starboard drive motor port value */
int ROC = 2; /* ROC motor port value */
int BADASS = 3; /* BAD-ASS motor port value */
int BELT = 4; /* motor that drives the conveyor belt */
/* gives the maximum and minimum speeds for motors so we can */
/* drive each motor at relative speeds, i.e. full speed for */
/* one may not be the same as full speed for another */
int LEFT_MOTOR_MAX = 5; /* maximum speed of the left motor */
int LEFT_MOTOR_MIN = 4; /* minimum speed of the left motor */
int RIGHT_MOTOR_MAX = 5; /* maximum speed of the right motor */
int RIGHT_MOTOR_MIN = 4; /* minimum speed of the right motor */
int TURN_SPEED = 8; /* turning speed of the drive motors */
int ROC_START_SPEED = 8; /* speed the ROC starts at */
int ROC_UP_SPEED = 6; /* speed of the ROC coming up */
int ROC_DOWN_SPEED = 2; /* speed of the ROC coming down */
int BADASS_SPEED = 6; /* speed of the badass */
int BELT_SPEED = 8; /* speed of the conveyor belt */
int MOTOR_SEARCH_SPEED = 4; /* searching speed of the motors */
/* gives names to the shaft encoder ports */
int LEFT_SHAFT_ENCODER = 0; /* left tire shaft encoder port value */
int RIGHT_SHAFT_ENCODER = 1; /* right tire shaft encoder port value */
/* gives names to the various digital ports */
int NOT_BADASS_OPEN = 2; /* closes when the badass is open */
int NOT_BADASS_CLOSED = 3; /* closes when the badass is closed */
int ROC_DOWN = 4; /* closes when the roc is down */
int ROC_UP = 5; /* closes when the roc is up */
int START_LIGHT = 30; /* detects the light starting the game. */
/* gives names to the various analog ports */
/* note: we never really used these on game-day */
int LEFT_LINE_SENSOR = 20; /* port bow ir reflectance sensor */
int MID_LINE_SENSOR = 21; /* middle ir reflectance sensor */
int RIGHT_LINE_SENSOR = 22; /* starboard ir reflectance sensor */
int PHOTOCELL = 23; /* photocell looks for special bin light */
/* some environmental constants we determined for the game board */
int BLACKWHITE = 220; /* threshold value for differentiating */
/* black from white */
int INCH_CONST = 30; /* encoder ticks per inch */
int LIGHT_THRESHOLD = 100; /* threshold for locating special bin */
variables.c
/* */
/* variables.c -- declares variables and provides handy reference */
/* guide to what gizmo plugs in where and gives */
/* proper plug orientation based on wire color */
/* */
/* array of 6 integers designating the current motor speeds */
int motor_speeds[6];
/* 0: port drive motor (black toward the switch)
1: starboard drive motor (purple toward the switch)
2: ROC motor (brown toward the switch)
3: BAD_ASS motor (red toward the switch)
4: belt motor (brown toward the switch)
5:
*/
/* designates the current values of the analog inputs */
int analog_values[8];
/* 20:
21:
22:
23: ... and we didn't use any of these
24: in our current code version ...
25:
26:
27:
*/
/* designates the current values of the digital inputs */
int digital_values[8];
/* 0: left shaft encoder
1: right shaft encoder
2: not_badass_open switch
3: not_badass_closed switch
4: roc_down switch
5: roc_up switch
6:
7:
30: start light IR sensor-
*/
int cnt; /* counter variable */
int left_distance; /* number of ticks on the left shaft encoder */
int right_distance; /* number of ticks on the right shaft encoder */
int LineStatus; /* either STRAIGHT, LEFT, or RIGHT */
int pidx; /* process number for outside_world() */
motorcontrol.c
/* */
/* motorcontrol.c -- a circus of functions which make the motors do */
/* various things */
/* */
/* ---------------------------------------------------------------- */
/* sets the new motor speed to the designated port and */
/* updates the values in the motor_speeds[] array */
void set_motor_speed(int port, int speed)
{
motor_speeds[port] = speed;
motor(port, speed);
}
/* ---------------------------------------------------------------- */
/* sets the tick counts on the encoders to zero */
void reset_encoders()
{
reset_encoder(LEFT_SHAFT_ENCODER);
reset_encoder(RIGHT_SHAFT_ENCODER);
}
/* ---------------------------------------------------------------- */
/* makes FRED go in a straight line by keeping the encoder counts equal */
void go_straight()
{
/* if FRED is going right, we want to go back left a bit */
if (LineStatus == GOING_RIGHT)
{
/* which we can do by making the right motor faster if possible... */
if (motor_speeds[RIGHT_MOTOR] < RIGHT_MOTOR_MAX)
{
set_motor_speed(RIGHT_MOTOR, RIGHT_MOTOR_MAX);
printf("\nGoing right...right++\n");
}
/* ... or by making the left motor slower if possible */
else if ((motor_speeds[RIGHT_MOTOR] == RIGHT_MOTOR_MAX) && (motor_speeds[LEFT_MOTOR] > LEFT_MOTOR_MIN))
{
set_motor_speed(LEFT_MOTOR, LEFT_MOTOR_MIN);
printf("\nGoing right...left--\n");
}
/* ... the inevitable backup case */
else printf("\nVeering right!\n");
}
/* same deal if FRED is going left: we want to go back right a bit */
else if (LineStatus == GOING_LEFT)
{
/* which we can do by making the left motor faster if possible... */
if (motor_speeds[LEFT_MOTOR] < LEFT_MOTOR_MAX)
{
set_motor_speed(LEFT_MOTOR, LEFT_MOTOR_MAX);
printf("\nGoing left...left++\n");
}
/* ... or by making the right motor slower if possible */
else if ((motor_speeds[LEFT_MOTOR] == LEFT_MOTOR_MAX) && (motor_speeds[RIGHT_MOTOR] > RIGHT_MOTOR_MIN))
{
set_motor_speed(RIGHT_MOTOR, RIGHT_MOTOR_MIN);
printf("\nGoing left...right--\n");
}
/* .. the inevitable backup case */
else printf("\nVeering left!\n");
}
/* if FRED isn't turning, don't correct motion. */
else if (LineStatus == GOING_STRAIGHT) printf("\n%d %d\n", left_distance, right_distance);
/* prevents continuous updates */
msleep(50L);
}
/* ---------------------------------------------------------------- */
/* this is the go_straight() code modified to drive backwards */
void go_straight_backward()
{
if (LineStatus == GOING_RIGHT)
{
if (motor_speeds[RIGHT_MOTOR] > -RIGHT_MOTOR_MAX)
{
set_motor_speed(RIGHT_MOTOR, -RIGHT_MOTOR_MAX);
printf("\nGoing right...right++\n");
}
else if ((motor_speeds[RIGHT_MOTOR] == -RIGHT_MOTOR_MAX) && (motor_speeds[LEFT_MOTOR] < -LEFT_MOTOR_MIN))
{
set_motor_speed(LEFT_MOTOR, -LEFT_MOTOR_MIN);
printf("\nGoing right...left--\n");
}
else printf("\nVeering right!\n");
}
else if (LineStatus == GOING_LEFT)
{
if (motor_speeds[LEFT_MOTOR] > -LEFT_MOTOR_MAX)
{
set_motor_speed(LEFT_MOTOR, -LEFT_MOTOR_MAX);
printf("\nGoing left...left++\n");
}
else if ((motor_speeds[LEFT_MOTOR] == LEFT_MOTOR_MAX) && (motor_speeds[RIGHT_MOTOR] < -RIGHT_MOTOR_MIN))
{
set_motor_speed(RIGHT_MOTOR, -RIGHT_MOTOR_MIN);
printf("\nGoing left...right--\n");
}
else printf("\nVeering left!\n");
}
else if (LineStatus == GOING_STRAIGHT) printf("\n%d %d\n", left_distance, right_distance);
msleep(50L);
}
/* ---------------------------------------------------------------- */
/* generic function to turn on the drive motors */
/* and move a certain distance and angle. */
void move_robot(int move_direction, int speed, int ticks)
{
float start_time = seconds();
reset_encoders();
/* moves forward a certain number of ticks. */
if (move_direction == FORWARD)
{
set_motor_speed(LEFT_MOTOR, speed);
set_motor_speed(RIGHT_MOTOR, speed);
while (left_distance <= ticks)
go_straight();
}
/* moves backwards a certain number of ticks. */
if (move_direction == BACKWARD)
{
set_motor_speed(LEFT_MOTOR, -speed);
set_motor_speed(RIGHT_MOTOR, -speed);
while (left_distance <= ticks)
go_straight_backward();
}
/* performs a stationary left turn */
if (move_direction == LEFT_TURN)
{
set_motor_speed(LEFT_MOTOR, -speed);
set_motor_speed(RIGHT_MOTOR, speed);
while (left_distance <= ticks) ;
}
/* performs a stationary right turn */
if (move_direction == RIGHT_TURN)
{
set_motor_speed(LEFT_MOTOR, speed);
set_motor_speed(RIGHT_MOTOR, -speed);
while (left_distance <= ticks) ;
}
/* ... and turn things off when we're done */
set_motor_speed(LEFT_MOTOR, 0);
set_motor_speed(RIGHT_MOTOR, 0);
reset_encoders();
}
/* ---------------------------------------------------------------- */
/* run from outside_world() process. updates left_distance, */
/* right_distance, and LineStatus. */
void watch_encoders()
{
left_distance = read_encoder(LEFT_SHAFT_ENCODER);
right_distance = read_encoder(RIGHT_SHAFT_ENCODER);
if (left_distance > right_distance) LineStatus = GOING_RIGHT;
if (left_distance == right_distance) LineStatus = GOING_STRAIGHT;
if (left_distance < right_distance) LineStatus = GOING_LEFT;
}
background.c
/* */
/* background.c -- spawned as a process from mymain.c -- continuously */
/* updates the environment variables analog_values[], */
/* and digital_values[]; runs the watch_encoders() */
/* function which keeps track of left_distance, */
/* right_distance, and LineStatus. */
/* */
void outside_world()
{ int i;
while (1){
for (i = 0; i <= 7; i++)
analog_values[i] = analog(20 + i);
for (i = 2; i <= 7; i++)
digital_values[i] = digital(i);
watch_encoders();
}
}
strategy.c
/* strategy.c -- this is the meat of our code, the functions that are */
/* called in mymain() and elsewhere */
/* implements each of our three strategies */
/* contains code for block collection and line tracking */
int sees_black(int sensor)
{
return (analog(sensor) >= BLACKWHITE);
}
void find_white_line()
{
set_motor_speed(LEFT_MOTOR, LEFT_MOTOR_MIN);
set_motor_speed(RIGHT_MOTOR, RIGHT_MOTOR_MIN);
while ((! sees_black(LEFT_LINE_SENSOR)) || (! sees_black(RIGHT_LINE_SENSOR)))
go_straight();
while(sees_black(LEFT_LINE_SENSOR) || sees_black(RIGHT_LINE_SENSOR))
go_straight();
set_motor_speed(LEFT_MOTOR, 0);
set_motor_speed(RIGHT_MOTOR, 0);
}
void grab_block()
{ long tc;
printf("\nStarting to grab\n");
/* motor 2 is ROC, 3 is BAD-ASS, 4 is belt */
set_motor_speed(BADASS, BADASS_SPEED);
printf("\nClosing badass!\n");
/*tc is time count */
/*Any operation that does not trigger a sensor */
/*(indicating completion) within 2 seconds will*/
/*be ended. */
tc = mseconds();
while (! digital(NOT_BADASS_CLOSED) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 0);
printf("\nTurning ROC\n");
set_motor_speed(ROC, ROC_START_SPEED);/*Extra boost to get going*/
sleep(0.1);
set_motor_speed(ROC, ROC_UP_SPEED);/*Real ROC Speed*/
tc = mseconds();
while (! digital(ROC_UP) && ((tc + 2000L) > mseconds())) ;
set_motor_speed(ROC, 0);
sleep(0.75);/*Let things settle down and conveyor take hold*/
printf("\nOpening badass a bit\n");
set_motor_speed(BADASS, -BADASS_SPEED);
msleep(500L);
set_motor_speed(BADASS, 0);
sleep(0.5);
printf("\nTurning ROC back\n");
set_motor_speed(ROC, -ROC_START_SPEED);
sleep(0.12);
set_motor_speed(ROC, -ROC_DOWN_SPEED);
set_motor_speed(BADASS, -BADASS_SPEED);/*Just right opening to
bring arms down*/
sleep(0.04);
set_motor_speed(BADASS, 0);
tc = mseconds();
while (! digital(ROC_DOWN) && ((tc + 2000L) > mseconds()));
set_motor_speed(ROC, 0);
printf("\nOpening badass\n");
set_motor_speed(BADASS, -BADASS_SPEED);
tc = mseconds();
while (! digital(NOT_BADASS_OPEN) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 0);
printf("\nblock grabbed\n");
}
void run_strategy(int strategy, int start_point, int special_bin)
{
long tc;
set_motor_speed(5, 4);
if (strategy == ONE_POINT_STRATEGY) { /*Beat the brick*/
/*Set ROC & Badass to start positions*/
set_motor_speed(ROC, -ROC_START_SPEED);
sleep(0.12);
set_motor_speed(ROC, -ROC_DOWN_SPEED);
tc = mseconds();
while (! digital(ROC_DOWN) && ((tc + 2000L) > mseconds()));
set_motor_speed(ROC, 0);
set_motor_speed(BADASS, -BADASS_SPEED);
tc = mseconds();
while (! digital(NOT_BADASS_OPEN) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 0);
/*Drive straight until reach block*/
tone(880.0, 0.25);
move_robot(FORWARD, LEFT_MOTOR_MIN, 260);
tone(440.0, 0.25);
/*Grab block*/
printf("\nStarting to grab\n");
set_motor_speed(BADASS, BADASS_SPEED);
printf("\nClosing badass!\n");
tc = mseconds();
while (! digital(NOT_BADASS_CLOSED) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 6);
sleep(1.0);
set_motor_speed(ROC, ROC_START_SPEED);/*Just to get off ground*/
sleep(0.1);
set_motor_speed(ROC, 0);
tone(300.0, 0.25);
tone(400.0, 0.25);
tone(500.0, 0.25);
tone(600.0, 0.25);
tone(600.0, 0.25);
/*Move into bin*/
move_robot(FORWARD, LEFT_MOTOR_MIN, 20);
tone(500.0, 0.25);
tone(400.0, 0.25);
tone(300.0, 0.25);
printf("\nTurning..\n");
sleep(1.0);
if (start_point == LEFT_START)
move_robot(LEFT_TURN, TURN_SPEED, 28);
else
move_robot(RIGHT_TURN, TURN_SPEED, 28);
tone(880.0, 0.25);
sleep(1.0);
move_robot(FORWARD, LEFT_MOTOR_MIN, 30);
printf("\nDone.\n");
ao();
} else if (strategy == WINNING_STRATEGY) {
LEFT_MOTOR_MAX += 2;
LEFT_MOTOR_MIN += 2;
RIGHT_MOTOR_MAX += 2;
RIGHT_MOTOR_MIN += 2;
/*Climb the mountain*/
move_robot(FORWARD, LEFT_MOTOR_MAX, 215);
LEFT_MOTOR_MAX -= 2;
LEFT_MOTOR_MIN -= 2;
RIGHT_MOTOR_MAX -= 2;
RIGHT_MOTOR_MIN -= 2;
/*Initialize Badass and ROC*/
set_motor_speed(ROC, -ROC_START_SPEED);
sleep(0.12);
set_motor_speed(ROC, -ROC_DOWN_SPEED);
tc = mseconds();
while (! digital(ROC_DOWN) && ((tc + 2000L) > mseconds()));
set_motor_speed(ROC, 0);
set_motor_speed(BADASS, -BADASS_SPEED);
tc = mseconds();
while (! digital(NOT_BADASS_OPEN) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 0);
grab_block();
/*Back up and stay out of the way*/
move_robot(BACKWARD, LEFT_MOTOR_MIN, 60);
sleep(10.0);
/*OK, now go down the mountain*/
move_robot(FORWARD, LEFT_MOTOR_MIN, 25);
/*Turn and drive down, picking up blocks*/
if (start_point == LEFT_START) {
move_robot(LEFT_TURN, TURN_SPEED, 60);
move_robot(FORWARD, LEFT_MOTOR_MIN, 73);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 74);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 63);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 122);
grab_block();
if (special_bin == LEFT_SPECIAL_BIN) {
move_robot(RIGHT_TURN, TURN_SPEED, 19);
move_robot(FORWARD, LEFT_MOTOR_MAX, 160);
move_robot(RIGHT_TURN, TURN_SPEED, 26);
move_robot(BACKWARD, LEFT_MOTOR_MIN, 73);
} else if (special_bin == RIGHT_SPECIAL_BIN) {
move_robot(RIGHT_TURN, TURN_SPEED, 22);
move_robot(FORWARD, LEFT_MOTOR_MAX, 341);
move_robot(RIGHT_TURN, TURN_SPEED, 45);
move_robot(BACKWARD, LEFT_MOTOR_MIN, 120);
}
} else if (start_point == RIGHT_START) {
move_robot(RIGHT_TURN, TURN_SPEED, 60);
move_robot(FORWARD, LEFT_MOTOR_MIN, 73);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 74);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 63);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 122);
grab_block();
if (special_bin == RIGHT_SPECIAL_BIN) {
move_robot(LEFT_TURN, TURN_SPEED, 19);
move_robot(FORWARD, LEFT_MOTOR_MAX, 160);
move_robot(LEFT_TURN, TURN_SPEED, 26);
move_robot(BACKWARD, LEFT_MOTOR_MIN, 73);
} else if (special_bin == LEFT_SPECIAL_BIN) {
move_robot(LEFT_TURN, TURN_SPEED, 22);
move_robot(FORWARD, LEFT_MOTOR_MAX, 341);
move_robot(LEFT_TURN, TURN_SPEED, 45);
move_robot(BACKWARD, LEFT_MOTOR_MIN, 120);
}
}
} else if (strategy == EMBELLISHED_ONE_POINT_STRATEGY) {
/*Same as beat the brick until defensive part*/
/*Initialize ROC and Badass*/
set_motor_speed(ROC, -ROC_START_SPEED);
sleep(0.12);
set_motor_speed(ROC, -ROC_DOWN_SPEED);
tc = mseconds();
while (! digital(ROC_DOWN) && ((tc + 2000L) > mseconds()));
set_motor_speed(ROC, 0);
set_motor_speed(BADASS, -BADASS_SPEED);
tc = mseconds();
while (! digital(NOT_BADASS_OPEN) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 0);
/*Drive to block*/
tone(880.0, 0.25);
move_robot(FORWARD, LEFT_MOTOR_MIN, 260);
tone(440.0, 0.25);
/*Pick up block*/
printf("\nStarting to grab\n");
set_motor_speed(BADASS, BADASS_SPEED);
printf("\nClosing badass!\n");
tc = mseconds();
while (! digital(NOT_BADASS_CLOSED) && ((tc + 2000L) > mseconds()));
set_motor_speed(BADASS, 6);
sleep(1.0);
set_motor_speed(ROC, ROC_START_SPEED);
sleep(0.1);
set_motor_speed(ROC, 0);
tone(300.0, 0.25);
tone(400.0, 0.25);
tone(500.0, 0.25);
tone(600.0, 0.25);
tone(600.0, 0.25);
/*Turn and drive into bin*/
move_robot(FORWARD, LEFT_MOTOR_MIN, 20);
tone(500.0, 0.25);
tone(400.0, 0.25);
tone(300.0, 0.25);
printf("\nTurning..\n");
sleep(1.0);
if (start_point == LEFT_START)
move_robot(LEFT_TURN, TURN_SPEED, 28);
else
move_robot(RIGHT_TURN, TURN_SPEED, 28);
tone(880.0, 0.25);
sleep(1.0);
move_robot(FORWARD, LEFT_MOTOR_MIN, 30);
printf("\nDone.\n");
ao();
/*End beating the brick*/
/*Start being a prick*/
/*Turn on the light*/
set_motor_speed(5,4);
/*Release the block*/
set_motor_speed(BADASS, -BADASS_SPEED);
sleep(0.5);
set_motor_speed(BADASS, 0);
/*Back well out of bin*/
move_robot(BACKWARD, LEFT_MOTOR_MIN, 40);
/*Begin distraction: back up and drive forward until they*/
/*lock onto us and hilarity ensues*/
while (1){ /* while (! hell_freezes_over()) */
move_robot(BACKWARD, LEFT_MOTOR_MIN, 400);
grab_block();
move_robot(FORWARD, LEFT_MOTOR_MIN, 400);
grab_block();
}
}
}
/*The end of strategy.c. Goodnight everyone.*/
mymain.c
/* */
/* mymain.c -- sets up and starts the underling peasant functions */
/* and then runs the strategy we choose with the dips */
/* */
void mymain()
{
/* declaration section and setup commands */
char nyah[];
nyah = "1c1r1c1r1a1r1e1r2c2r2a2r";
int start_point;
int strategy;
printf("3 Crazy Bastards");
enable_encoder(LEFT_SHAFT_ENCODER);
enable_encoder(RIGHT_SHAFT_ENCODER);
/* resets sensor arrays and motor array */
for (cnt = 0; cnt <= 5; cnt++)
motor_speeds[cnt] = 0;
for (cnt = 0; cnt <= 7; cnt++)
digital_values[cnt] = digital(cnt);
for (cnt = 0; cnt <= 7; cnt++)
analog_values[cnt] = analog(20 + cnt);
set_motor_speed(BELT, BELT_SPEED);
/* starts process to constantly watch the encoders and sensors */
pidx = start_process(outside_world());
/* reads start position and strategy from dip switches */
/* dip 1 is the start point */
start_point = dip_switch(1);
/* dip 2 is the strategy */
if (dip_switch(2))
{
printf("\nOne point\n");
strategy = ONE_POINT_STRATEGY;
}
if (! dip_switch(2))
{
printf("\nWinning \n");
strategy = WINNING_STRATEGY;
}
/* dip 3 enables an additional embellish routine */
if (dip_switch(3))
{
printf("\nEmbellished\n");
strategy = EMBELLISHED_ONE_POINT_STRATEGY;
}
/* displays where it thinks it's going to start */
if (start_point == LEFT_START)
printf("left..\n");
else if (start_point == RIGHT_START)
printf("right..\n");
else printf("start point?\n");
/* and now we GO! based on the strategy. */
run_strategy(strategy, start_point, 0);
/* kills our background environment process */
kill_process(pidx);
}
main.c
/* */
/* main.c -- required code given to all participants */
/* */
/* main.c handles setup routines such as board */
/* postition, IR frequency, and the start light */
/* then calls the mymain.c code (the 'real' code) */
/* as a process and enforces the time limit. */
/* */
/* revision 12.13.97 CLJ: the 'else' statement */
/* under the if (dip_switch(1)) section set tx and */
/* rx ir to the same frequency (100). now it has */
/* the correct tx/rx values to complement the values */
/* in the if() section above. wonder if jkb & crew */
/* realized this??? */
/* */
int color;
int main()
{
int pid;
printf("\nWaiting for start..\n");
/* determines ir frequency based on dip settings */
if (dip_switch(1))
{
color = 1;
ir_transmit_on();
set_ir_transmit_frequency(100);
set_ir_receive_frequency(125);
}
else
{
color = 0;
ir_transmit_on();
set_ir_transmit_frequency(125); /* CLJ changed from 100 */
set_ir_receive_frequency(100);
}
/* when the start light comes on... */
while(!digital(START_LIGHT) && !choose_button());
/* starts the robot's own code as a process */
pid=start_process(mymain());
/* ninety second time limit... */
sleep(45.);
sleep(45.);
/* ... and shut down when time expires */
kill_process(pid);
ao();
beep();
}