Jason Bagnall Kayla Plancon Kevin Carree BE 1200 Midterm Report Objectives Build a robot and program it to follow a black line, go around an obstacle, re-find and follow the black line after going around the obstacle, and stop on green. Constraints What is provided in the Lego Mindstorms kit and what can be done using the NQC software. Functions The robot starts right near the green square and then follows the right edge of the line until it hits the can and the touch sensor is triggered. The line following function has stopped at this point, after which the robot backs up for half of a second. If the arm is touching the can, the robot will move away from the can by turning left, then moving forward slightly. When the arm isn’t touching the can, the bot turns right while moving forward slightly. The robot uses this functionality to move around the can. After the timer runs out, the bot stops, and line following is restarted. The robot follows the line until it reaches the green square, where it stops. Design Specifications The robot must follow the line, detect the obstacle, and then circumvent it, and finally have a way to detect the green square. Generate Alternatives After completing quiz 6/7, line following was easy to accomplish. Having had the program associated with Linebot 3 as an overall framework for line following, only one light sensor was needed. The initial design of the robot (which was designed for exceptional turning radius), was a poor line follower. This robot design had two large wheels in front and one smaller wheel in the rear. In addition to having too tight of a turning radius (and thus a poor straight line tracking ability), this design resulted in the robot moving too fast for conventional line following. The decision was made to return to a design which relied upon treads instead of wheels, and rather than spend our time generating a new kind of line following program, to instead focus on achieving as many points in the rapidly impending Midterm trial. A touch sensor was placed on the front of the robot (in a normally inactivated position) to act as a bumper which would detect the can. A second touch sensor (in a normally activated position) was mounted in such a way that a “finger” while contacting the can, wouold deactivate the sensor, and in such a way form the basis for “wall” following behavior. Macros EYE BUMP GRAZE LEFT RIGHT LINE_EVENT1 Global Variables Description Light sensor: SENSOR_1 Touch sensor 1: SENSOR_3 Touch sensor 2: SENSOR_2 OUT_A OUT_C tells the bot which direction it last looked to find the tape and to look in the opposite direction this time Description int lineValue int stopValue int sweepDir = 1 int AVE, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 Functions The calculated value for which the robot “sees” the tape and simply moves forward. The calculated value at which the robot will stop the “find()” inline function, and return to moving forward on the tape. This tells the bot to sweep back and forth to look for the tape for a fixed time. The set of variables used for the averaging inline function Description setup() Sets sensors, and sets up light sensor with line follow thresholds. start follow Line follow based on Linebot 3. watch_bump() void setup() Waits for front bumper (sensor 3) to be pressed on can contact and reorients the bot to prepare for a timed wall following task. Sets the sensors and the line values. void find() This will cause the line follow to stay on the tape. void watch_bump() This waits for the front bumper (sensor 1) to be pressed (when the bot hits the can) then backs the bot up, and turns it to the left in preparation to wall follow the can. This is used to continuously average the light sensor values after the can has been circumnavigated. This value then drives a conditional statement which waits for green to be “seen.” Description void average() Tasks main follow can Runs setup() which sets sensors, and sets up light sensor with line follow thresholds, starts line follow, and starts watch_bump(). Line following task. Goes forward when on the tape, otherwise starts the code block from above to find it. A timed wall following task. The sensor "graze" (sensor 2) is designed to always be pressed unless the bot is in contact with the can. This function will follow a wall (or curve in our case) indefinitely (or as long as the timer is set to allow it). In this way the following is dynamic, but re-finding the line (when the task is complete, and line following restarted) is a function of time (and therefore a constant, rather than variable function). Testing and Evaluating the Design Line Following Light sensor on the front of Robot follows the track line consistently. the robot. Detecting the Obstacle Robot bumps into obstacle At first, the programming for going around the can interfered with the arm, backs up, turns, then moves forward. It goes around the object by using two touch sensors. Finding Green Square Once the robot goes around the obstacle, the robot uses an average time to stop on the green square. with the line following. After properly integrating the inline function of “watching the bumper” into the line follow, it was just a matter of finding the correct timing sequence which would place the robot close enough to the line that upon restarting line following, the line would be found. Finding the green square proved to be troublesome. When we finally got it to stop on green, it would also stop on black sometimes. We tried using a timer and eventually had to test every part by itself. Despite trying three separate methods of stopping on green, and consulting with Garan for almost an hour, a way to stop on green could not be found. Changes in the Design The final design ended up completely different than the initial design. More gears were added along with treads being used instead of actual wheels to make the robot travel more slowly. The arm was also redesigned. Code // MidTerm Jason, Kevin, Kayla // sensor and motors #define EYE SENSOR_1 #define BUMP SENSOR_3 #define GRAZE SENSOR_2 #define LEFT OUT_A #define RIGHT OUT_C #define LINE_EVENT 1 // global variables //variables for line follow int lineValue; int stopValue; int sweepDir = 1; //variables for average int AVE, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; task main() { setup(); //sets sensors, and sets up light sensor with line follow thresholds start follow; //line follow based on linebot 3 watch_bump(); //waits for front bumper (sensor 3) to be pressed on can contact and reorients the bot to prepare for a timed wall following task } void setup() { SetSensor(EYE, SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_PERCENT); SetSensor(BUMP, SENSOR_TOUCH); SetSensorMode(SENSOR_3,SENSOR_MODE_BOOL); SetSensor(GRAZE, SENSOR_TOUCH); SetSensorMode(SENSOR_2,SENSOR_MODE_BOOL); lineValue = EYE; stopValue = lineValue - 3; lineValue += 3; SetEvent(LINE_EVENT, EYE, EVENT_TYPE_LOW); LowerLimit(LINE_EVENT) = lineValue; } void find() //used by line follow to stay on the tape { SetPower(LEFT+RIGHT, 3); //while finding the line, the bot runs slower if (sweepDir > 0) //this next block tells the bot to sweep back and forth to look for the tape for a fixed time { Rev(LEFT); } else { Rev(RIGHT); } int sweepTime = 20; monitor(EVENT_MASK(LINE_EVENT)) //this block a)tells the bot which direction it last looked in to find the tape, and b)tells it to look in the opposite direction this time { while(true) { Wait(sweepTime); sweepTime *= 2; sweepDir *= -1; Toggle(LEFT+RIGHT); } } Fwd(LEFT+RIGHT); SetPower(LEFT+RIGHT, OUT_FULL); } task follow() //line follow. Goes forward when on the tape, otherwise starts the code block from above to find it. { Wait(100); while (true) { if (BUMP==0) { OnFwd(LEFT+RIGHT); while(EYE > stopValue) { if (EYE > lineValue) { find(); } } Off(LEFT+RIGHT); } } } void watch_bump()//this waits for the front bumper (sensor 1) to be pressed (when the bot hits the can) then backs the bot up, and turns it to the left in preparation to wall follow the can { while (true) { if (BUMP==1) { stop follow; OnRev(LEFT+RIGHT); Wait(50); OnRev(LEFT);OnFwd(RIGHT);Wait(30); OnFwd(LEFT+RIGHT);Wait(100); start can; } } } task can()// a timed wall following task. The sensor "graze" (sensor 2) is designed to always be pressed unless the bot is in contact with the can. This function will follow a wall (or curve in our case) indefinitely (or as long as the timer is set to allow it). In this way the following is dynamic, but re-finding the line (when the task is complete, and line following restarted) is a function of time (and therefore a constant, rather than variable function) { ClearTimer(1); do { if (GRAZE==0) // if the bot is touching the can the bot moves away from it by turning left, while moving forward slightly. { OnRev(LEFT);OnFwd(RIGHT);Wait(25); OnFwd(LEFT+RIGHT);Wait(15); } else if (GRAZE==1)// if the bot isn't touching the can (during this task only) the bot turns right, while moving forward slightly. { OnFwd(LEFT);OnRev(RIGHT);Wait(20); OnFwd(LEFT+RIGHT);Wait(15); } } while (Timer(1)<110); //the above is carried out until this timer runs out, at which point the bot stops, and line following is restarted PlaySound(1); Off(LEFT+RIGHT);Wait(50); start follow; start average; //starting the average, which finds green after the can so as to give the bot less time to see green falsely. } task average() // This averaging function is an attempt to have the bot stop on green. { ClearTimer(2); while(true) { x1 = SENSOR_1; Wait(3); x2 = SENSOR_1; Wait(3); x3 = SENSOR_1; Wait(3); x4 = SENSOR_1; Wait(3); x5 = SENSOR_1; Wait(3); x6 = SENSOR_1; Wait(3); x7 = SENSOR_1; Wait(3); x8 = SENSOR_1; Wait(3); x9 = SENSOR_1; Wait(3); x10 = SENSOR_1; Wait(3); AVE = (x1+x2+x3+x4+x5+x6+x7+x8+x9+x10) / 10; PlaySound(3); if ((AVE >= 49 && AVE <=55 )&&Timer(2)<=400) // waits for the conditions expected of green, and also 17.6 seconds to have elapsed { Off(LEFT+RIGHT); stop follow; stop main; PlaySound(4);Wait(400); } } }