Randy D’Souza, Brian Petrowicz

Prof.  Fred Martin

Robotics 1

Little Stewey

 

            This is a formal description of the evolution of our egg-hunting robot, which we ultimately named on the day of the contest, Stewey.   The main function of this robot was to search for two types of eggs, teal-colored that scored 1 point each and black-colored eggs which were worth -4 points.  It was built using Technic Legos, and powered by the Handy Board (which was made by professor Martin), based off a Motorola 6811 chip.   We programmed the robot using the Interactive C language and compiler.  The dimensions of the robot were not to exceed a square foot.  The contest consisted of one-on-one match-ups, each lasting three minutes, using double elimination.  The robot with the most points in their goal at the end was the winner of the match-up.  In the end, we were unable to get Stewey to work properly, but it was the challenge and the experience of creating him that was the enjoyable part.  The whole experience, including our successes and misfortunes, has given us a process that we can apply to future robotic projects. 

            We first started off wanting a robot that was actually more violent and petulant than one that actually accomplished the already difficult goal of autonomously searching for an egg.  That was soon thwarted by the rules of the contest, and our lack of design implementation (it was too hard).  Our initial design was completely problematic in actuality.  We wanted a carriage that was divided into two parts, one for each type of egg, and once three of one type of egg was collected, Stewey would return the egg to the appropriate nest for our scoring convenience.  To collect the eggs, we had a mouth with two rods that acted as protruding teeth to scoop the eggs.  We then had a mandible that came down from up above that, if timed correctly, came down to the back of the egg to hold it in place to be scooped into the mouth of our robot.  The mouth was about three inches wide, and five inches high.  We had an optic sensor that would see an egg, and would activate the single mandible and two scoop teeth.  We then needed a way to sort the eggs.  We wanted to develop a conveyer belt that brought the egg to the base of our carriage where it would be sorted.  While on the belt we had two line-following sensors, one on each side of the belt, to see either black, or [other color], to be sorted.  Once the egg reached the top of the belt, there was a dividing servomotor that would divide the colors of eggs, to the left if it was teal, to the right if it was black.  The carriage was approximately thirteen Lego units high, and towards the top of the covered bin, we had line-breaking sensors.  If the beam was broken on either side, then it was time to return the eggs.  The last step was to get rid of the eggs once a bin was full.  There were two doors, one for each side of the bin.  We put another optic sensor on the back, and once it saw white (denoting a goal) the appropriate door would open, which was operated by a servomotor (Fig 3, 4). 

            Navigation was the next step now that the robot was built.  First there was figuring out which goal we needed to go to.  This was done by two polarized light sensors (one sensing horizontal light, the other sensing vertical light) that were raised up by Lego bars on the front of the robot, above the mouth.  One of the goals had horizontally polarized light, while the other had vertically polarized light.  By switching the two wires on our handy board we could decide which goal we wanted the robot to return to.  We now had a base-point on which we could guide the robot.  Before we could use that, we would need to find either three eggs of the same color. 

            The process of finding the eggs was a little bit more difficult.  We essentially had random motion.  We used a sonar sensor on the front of the robot that constantly compared vales to see where the greatest open space was, and naturally, it would attempt to go toward the center of the ring.  It would go straight for a few seconds, check for values on the front optic sensor to see if there had been any change, and if so, stop and grab the egg.  The robot would do this until we had three eggs of one color.  Unfortunately, this never worked well enough.  If Stewey was stuck in a corner, we used some basic emergence code to spin out of it.  Keep turning left or right until there was free space.

            That was the basic layout.  Did it work even with thorough tweaking? No, it did not.  There was a lot that went wrong, and for the most part, in order for the initial robot to find an egg, we had to manipulate its environment significantly, i. e.  place the egg right in front of the robot to even find the egg.  We tried giving it arms to make it easier to place eggs in front of the two teeth, but that turned out to violate the maximum allowed size.   It was frustrating.  The two teeth that were to lift the egg onto the conveyer belt were glued, not mechanically attached, so when coming back down to reset, one out of three times they would brake off.  Then there was the conveyer belt, which was probably not smart from a design point of view.  It was carrying an egg, which definitely had a tendency to wobble all the time up at a 30-degree angle, against gravity.  So, constantly, if it ever found an egg, there was a good chance it had fallen down.  The next problem with our implementation was the sorting of black and teal eggs.   Using our original code and original robot design, the eggs were sorted flawlessly.   After changing our design and code, it was not so consistent. 

 

 

 

I think that the most frustrating problem we had, had to do with a while loop in our code, which resulted in our robot driving straight, searching for an egg, and then when it thought it found an egg, it would go into an infinite loop of turning either right or left (which it ultimately did in the contest by accident).  This lasted literally for a couple of days of testing.  In fact, we had this problem right up until the preliminary round on Friday, October 31st, where the robot was supposed to be able to pick up at least one egg, and bring it back to goal.  We augmented the code to only search for one egg, just for the test.  At this time, this was the most efficient the robot got.  The night before we had gotten fed up, and, as a result, stopped caring.  So right before class we tweaked the code to just perform the task at hand; limited searching, minimal use of servos, just grabbing the egg.  We manipulated the environment, to just have the sonar aim the robot towards low echo spaces, which it assumed was the egg.  We tried this out and it actually worked for a little bit, picking up the egg, pulling straight in reverse, and dropping it off, only it dropped it off in the wrong spot.  We went for a formal test.  It got stuck and failed. 

            Part of the failing was due to a lack of traction on the rear wheels.  They barely touched the ground, causing out robot to maneuver poorly.  To get the teeth low enough to the ground, we had to use flat supports (medium sized Lego sprockets that were connected through holes in the front by the front optic sensor) that gave the robot an even level balance.  We could not use actual wheels because they created too much friction, which made it impossible for the robot to turn.  Along with the uneven colored floor of the lab, which wreaked havoc in identifying color for guidance, these supports often tripped on an uneven level surface, which caused the robot to trip, and things that were gently attached to fall off.  This in whole made us frustrated.

 

Fig. 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


            On Sunday, November 2nd, the day before the contest, we went into the lab to try to get the robot to work one last time.  We played with code for an hour or so, and the teeth as well as optic sensors kept falling off, again.  We decided to make a drastic change.  We literally gutted our robot.  We removed the whole conveyer belt powered by one motor, the two line following sensors on either side of the conveyer belt, and the bin.  We then removed the flimsy, thin mandible that even after being glued would constantly brake off, as well as the two front teeth, which also always broke off.  Our new design was much simpler and less irritating.  The logic was this: we have a hollow opening; we find an egg; we still sort the color; we have the dividing servo steer an egg to the left if it was teal, and to the right if it was black.  We removed the door so if it went to the right it would just fall out, essentially, ignoring the egg (which was how we coded it).  So at this point it was just searching for 1 egg at a time.  It was still guided by the sonar, and the polarized lights.

 

 


                                                                                                                                     Fig. 3

 

 

 

                                                                                                                             Servo

 

 

                                                                                                                                     Fig. 4

 

 

           

 

We ended up saving the essential parts of out initial code, and just modifying it where necessary to accommodate our needs (Figs. 1, 2).

int left_motor = 1;
int right_motor = 3;
int left_touch = 2;
int right_touch = 3;
int left_light = 5;
int right_light = 6;
int count = 0;
int value = 0;
int x=1;
int val = 70;
int average;
int current;
int color = 0;
int black = 0;
int r;
float r2;
int front_d;
int goal1, goal2;
float time, time2, tottime = 0.;
int greatest = 0;
int z, direction;
 
void main()
{
    init_expbd_servos(1);
    servo5 = 1500;
    servo2 = 2500;
    reset_system_time();
 
    while (1) {
        while (!start_button()){}
        while (!stop_button())
          {
            time = seconds();
            servo2 = 2400;
            printf("%d\n", (int)time);
            front_d = sonar();
 
              while (x == 1)
              {
                while (front_d > 120)
                  {
                    forward(60);
                    sleep(1.);
                    front_d = sonar();
 
                    average = (analog(6) + analog(5)) / 2;
 
                    if ((average < 220) && (average > 130))
                      {
                        color++;
                        servo5 = 1500;
                        sleep(.6);
                    }
                    else {servo5 = 100;}
 
                    if(seconds() >= 180.) done();
 
                    if (color == 2)
                      {
                        found_egg();
                        x = 0;
                        front_d = 100;
                    }
              printf("%d\n", (int)seconds());
              if (seconds() >= 180.)
                 done();
                }
 
 
                    if (analog(16) > 100)
                      {
                        stop();
                        reverse();
                        sleep(1.);
                    left();
                    sleep(1.);
                    }
                   else if (analog(18) > 100)
                      {
                        stop();
                        reverse();
                        sleep(1.);
                    right();
                    sleep(1.);
                    }
                  else
                    {
                      right();
                      sleep(2.);
                  }
 
            if (seconds() >= 180.)
              done();
            }
        }
        stop();
        init_expbd_servos(0);
    }
 
}
void found_egg()
{
    stop();
    color = 0;
    goal1 = analog(22);
    right();
    sleep(.2);
 
    for (z = 1; z <= 5; z++)
      {
        right();
        sleep(.4);
        if (analog(22) > greatest)
          {
            greatest = analog(22);
            direction = z;
        }
    }
 
    if(seconds() > 180.) done();
 
    if (direction == 1) {left(); sleep(.4); stop();}
    if (direction == 2) {left(); sleep(.8); stop();}
    if (direction == 3) {left(); sleep(1.2); stop();}
    if (direction == 4) {left(); sleep(1.6); stop();}
    if (direction == 5) {left(); sleep(1.8); stop();}
 
    while (sonar() > 120)
      {
        forward(60);
        sleep(.2);
    }
 
    right();        
    sleep(2.);       
    reverse();
    sleep(1.);
    stop();
    servo2 = 3500;
    sleep(1.);
    forward(60);
    sleep(1.5);
    stop();
    //search out goal; turn 180; reverse until analog(23) > 240;
}
 
void done()
{
    while (1)
      {
        stop();
    }
}
 
void forward(int value)
{
    motor(left_motor, value); motor(right_motor, value);
}
 
void reverse()
{
    bk(left_motor); bk(right_motor);
}
 
void left()
{
    fd(right_motor); bk(left_motor);
}
 
void right()
{
    fd(left_motor); bk(right_motor);
}
 
void stop()
{
    off(left_motor); off(right_motor);
}

 

  We spent most of Sunday trying this out, and it marginally worked.  The main problem was that it tested fine in the lab, but not upstairs in the contest arena.  The search values for the sensors up there were much different, due to the floor being a greenish-grayish color, instead of being a mix or white, gray, and black.  Our main commands were to go forward, turn towards the strongest readings of the servo, and attempt to collect the egg.  We attached two horizontal arms that ran perpendicular to the robot along its axis, although again, to abide size restrictions, were set a little aback from the very front of the mouth.  So the arms could catch eggs, but not force them into the mouth.  We should have just made the mouth much wider, and just swallow up whatever we could get. 

            This was basically the design we used for the contest.  Again, we ran into a “while” loop problem, and during the contest, the robot would start off going in circles.  If the sonar determined it saw something, it would rush right toward it.  The only problem was that most of the time it would see the other robots and just ram them (as it ended up doing in the contest, although, again due to poor traction, it would get over-powered by an apposing robot).  This was funny to watch, and neglected others from getting eggs, but not our intention.  In the long run it ended up helping us out, and as a result we were able to win a round in the contest.  Our new code can be seen below:

int left_motor = 1;
int right_motor = 3;
int left_touch = 2;
int right_touch = 3;
int left_light = 5;
int right_light = 6;
int count = 0;
int value = 0;
float time;
int average;
int color = 0;

void main()
{
   int val = 70;

   init_expbd_servos(1);
   servo5 = 1500;
   servo2 = 2500;
   reset_system_time();

   while (1){
       while (!start_button()){}
       while (!stop_button())
         {
           time = seconds();
           forward(val);
           if (analog(18) > 100) {left(); sleep(1.5);}
           if (analog(16) > 100) {right(); sleep(1.5);}
           if (sonar() > 120) {left(); sleep(1.5);}

           forward(val);

           average = (analog(6) + analog(5)) / 2;

           if ((average < 220) && (average > 130))
             {
               color++;
               servo5 = 1500;
               sleep(.6);
           }
           else {servo5 = 100;}

           if (color == 2)
             {
               while (analog(2) < 180)
                 {
                   forward(val);
                   if (analog(18) > 100) {left(); sleep(1.5); }
                   if (analog(16) > 100) {right(); sleep(1.5); }
                   if (sonar() > 120) {left(); sleep(1.5); }

                   forward(val);
sleep(2.); forward(60);
                   if (seconds() > 180.) done();

               }
               release();
               servo2 = 2500;
           }

           if (seconds() > 180.) done();
       }
       stop();
       init_expbd_servos(0);
   }
}

void release()
{
   stop();
   right();
   sleep(3.);
   stop();
   servo2 = 3500;
   sleep(1.);
   forward(60);
   sleep(2.);
}

void done()
{
   while (1)
     {
       stop();
   }
}

void forward(int value)
{
   motor(left_motor, value); motor(right_motor, value);
}

void reverse()
{
   bk(left_motor); bk(right_motor);
}

void left()
{
   fd(right_motor); bk(left_motor);
}

void right()
{
   fd(left_motor); bk(right_motor);
}

void stop()
{
   off(left_motor); off(right_motor);
}

            All in all it was a fun and enlightening experience.  We really got a great hands-on experience of design versus implementation complexity.  We learned the valuable lesson that even thought it works on paper, and maybe even a lab setting, that doesn’t mean it will work in the real world.   If we were to build another robot to accomplish a similar function, I am sure we would use a more reliable, and time-effective approach.  The robot was a great idea to pursue; it’s just that the design process was tedious.  In the future it would be great if our class could explore similar ideas to obtain a greater understanding of robotics.