Line Tracker code

Can someone email a copy of the Easy C code they wrote for the line Tracker? I have looked in the help section of Easy C and looked in the inventors guide but it does not help. If I had a copy of something that someone has that works then I could learn from that.

Thank you,
Dave

Here is some working line tracker code. This is EasyC 2.0 code with user derived functions. If you have EasyC 1.0, then whereever you see, for example “TurnLeft()”, copy the code from the TurnLeft function (at the bottom) into that spot. This will also work with the straight MPLAB compiler, which is how I do my programs.

Some notes: I programmed the code to turn 180 degrees and re-aquire the line if it comes to the end. I’ve also added some code that only activates when all three line sensors are hit at once. In my robot, putting a line of tape at right angles to the main line causes the robot to turn 180 degrees and activates a dump mechanism that dumps out whatever is in the hopper (a plastic “in box” type tray) This allows this robot to deliver documents around the office by following lines. I use masking tape over dark gray carpet, so the sensing may be backwards for you if you use electrical tape over tile. Anyway, the logic is:

If left sensor active, go left to center on the line
if right sensor active, go right
if center sensor active, go straight
if no sensors, turn in the direction of the last sensed area. (lastLine variable) This works very well to re-aquire the line and allows the robot to make sharp turns. This same behavior causes the robot to turn 180 degrees if it comes to the end of the line.
This code works better if the sensors are mounted in the front of the robot instead of near the middle.

My robot is a 4-motor tank tread unit, so the right side is motors 1 and 8, which turn backwards, and the left side is 2-7. (this matches the default VEX wiring)

This robot also includes two IRPD (Infrared proximity detectors, Sharp GP2D12 from Acroname Robotics) that work just fine as an analog input. These detect obstacles in the path of the robot. They provide a distance reading.

I also have a button (bumper switch) on the top of the robot labeled “STOP”. Pushing the button switches between radio control mode and autonomous mode. The robot starts in R/C mode and won’t move untill the button is pushed – a very good feature.

#include “UserAPI.h”

#define OUTPUT 0
#define INPUT 1

void GoLeft(void);
void GoRight(void);
void AllStop(void);
void GoForward(void);
void goDump(void);

void IO_Initialization(void)
{
DefineControllerIO ( 5, INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,INPUT ,OUTPUT ,OUTPUT ,OUTPUT ,OUTPUT ,OUTPUT ,OUTPUT ) ;
}
int flag; // 0 = auto, 1=RC
int i; // loop counter
int rcInput; // Input from Radio ch 6
int LeftLine; // Input from left line sensor input1
int rightLine; // Input from right Line sensor input 3
int centerLine; // Input from center line sensor
int CamTilt; // Camera Tilt RC
int CamPan; // camera Pan RC
int FWD = 200; // Forward PWM value
int STP = 127; // Stop PWM value
int REV = 55; // Reverse PWM value
int SLOW = 185; // SLOW PWM MODe
int REVSLOW = 80;
int lastLine = 0; // Last Direction of line detected
int min = 200; // lowest IR level detected
int max = 500; // highest IR level detected
int avg = 300; // min-max/2 = trigger IR level
int DumpFlag = 0; // 1 = time to dump!
int IRleft ; // IR Prox detector left
int IRright ; // IR Prox detector right

void main ( void )
{
i = 0 ;
flag = 1; ; // start in autonomous mode
Wait ( 1000 ) ;
while ( i == 0 ) // infinite loop
{

        if ( flag == 0 ) // if autonomous mode
        {
              rcInput = GetDigitalInput ( 9 ) ; // Switch modes
              if ( rcInput == 0 ) // switch mode
              {
                    flag = 1 ; // switch to RC mode
                    AllStop();
                    Wait ( 500 ) ; // Debounce the switch
              }
			  IRleft = GetAnalogInput(4);
			  IRright = GetAnalogInput(5);
				if (IRleft > 200 || IRright > 200) // we see an obstacle
				{
					//AllStop();
					//Wait(1000);
				}
              LeftLine = GetAnalogInput ( 3 ) ;
              centerLine = GetAnalogInput ( 2 ) ;
              rightLine = GetAnalogInput ( 1 ) ;
              if ( rightLine < min )
              {
                    min = rightLine ;
              }
              if ( rightLine > min )
              {
                    max= rightLine ;
              }
              avg = min + ((max-min) / 2) ;
              avg = min+200 ;
              if ( LeftLine <avg && rightLine < avg && centerLine < avg ) // all sensors activated at once
              {
                    DumpFlag = 1 ;
                    GoForward();
                    Wait ( 400 ) ;
                    continue;
              }
              if ( centerLine < avg )
              {
                    GoForward();
                    if ( DumpFlag == 1 )
                    {
                          goDump();
                    }
                    continue;
              }
              if ( rightLine  < avg ) // if value < 100 then we are over line
              {
                    GoRight();
                    lastLine = 1 ; // Last Detected Right Turn
                    continue;
              }
              if ( LeftLine < avg ) // if value > 100 then we are over line
              {
                    GoLeft();
                    lastLine = 0 ; // last detected left line
                    continue;
              }
              if ( lastLine == 0 ) // last line detected
              {
                    SetMotor ( 1 , SLOW ) ;// this is a more agressive turn than a line correction
                    SetMotor ( 8 , SLOW ) ;
                    SetMotor ( 2 , FWD ) ;
                    SetMotor ( 7 , FWD ) ;
                    continue;
              }
              else
              {
                    SetMotor ( 1 , REV ) ;// more agressive turn
                    SetMotor ( 8 , REV ) ;
                    SetMotor ( 2 , REVSLOW ) ;
                    SetMotor ( 7 , REVSLOW ) ;
                    continue;
              }
        }// end of IF FLAG==0 block i.e. autonomous mode
        else // // rc mode
        {
              Arcade4 ( 0 , 2 , 1 , 1 , 2 , 8 , 7 , 0 , 0 , 0 , 0 ) ;
              MotorRcControl ( 0 , 6 , 6 , 0 ) ;
              ServoRcControl ( 0 , 4 , 4 , 0 ) ;
              ServoRcControl ( 0 , 3 , 3 , 0 ) ;
              rcInput = GetDigitalInput ( 9 ) ; // switch modes
              if ( rcInput ==0 )
              {
                    flag = 0 ; // switch to autonomous mode
                    Wait ( 500 ) ; // Debounce the switch
              }
        }
  }

}

void GoLeft()
{
SetMotor ( 2 , SLOW ) ;
SetMotor ( 7 , SLOW ) ;
SetMotor ( 1 , 127 ) ;
SetMotor ( 8 , 127 ) ;
return;
}

void GoRight()
{
SetMotor ( 1 , REVSLOW ) ;
SetMotor ( 8 , REVSLOW ) ;
SetMotor ( 2 , 127 ) ;
SetMotor ( 7 , 127 ) ;
return;
}

void AllStop()
{
SetMotor(1,127);
SetMotor(2,127);
SetMotor(7,127);
SetMotor(8,127);
return;
}
void GoForward()
{
SetMotor(1,REV);
SetMotor(8,REV);
SetMotor(7,FWD);
SetMotor(2,FWD);
}
void goDump()
{
int enc = 0; // encoder value
DumpFlag = 0 ;
AllStop();
SetMotor ( 6 , 0 ) ;
StartEncoder(1);
enc = 0;
PresetEncoder(1,0);
while (enc <= 25)
{
enc = GetEncoder(1);
}
SetMotor ( 6 , 127 ) ;
Wait(2000); // hold still, wait for paper to dump out
SetMotor ( 6 , 255 ) ;
enc = 0;
StartEncoder(1);
PresetEncoder(1,0);
while (enc <= 25)
{
enc = GetEncoder(1);
}
SetMotor ( 6 , 127 ) ;
StopEncoder(1);
return;
}

Thank you very very much.

Dave

wow thats long code. mine was much shorter and was mainly:

If (leftsensor > right sensor)
{
turn right
}
if (right sensor > left sensor)
{
turn left
}
else
{
go straight
}

Wow this is great. Keep it coming.

Dave

The code that does “min / max” was an attempt to get the robot to adjust to different light levels and contrast between the line and the floor. It did not work very well.

You do have to have some sort of code to re-aquire the line once it is lost. I look for the last sensor that had contact, and turn that direction but more agressively.

I noticed that changing the center of gravity of the robot (putting a heavy book in the “hopper”) also changed the turning behavior by moving the center of rotation back, which sometimes caused the robot to miss the line and wander off. I had to “tone down” the turning speed to keep on the line.

Have fun!

Francis Govers

I’ve posted pictures of this robot to the gallery

Francis Govers

Ok, can someone tell me what I did wrong here. I tried to create the line tracker code but it does not go.:frowning: Can someone advise? I want to keep it simple. But I am working on the longer code above. But I need to fix this one first. Again trying to keep it short and sweet.

#include “UserAPI.h”

int leftsensor;
int rightsensor;
int centersensor;

void main ( void )
{
SetMotor (1,0);
SetMotor ( 2,255)
leftsensor=GetAnalogInput (1);
centersensor=GetAnalogInput (2);
rightsensor=GetAnalogInput (3);
if (leftsensor>rightsensor)
{
Setmotor (1,255);
}
if (rightsensor>leftsensor)
{
SetMotor (2,0);
}
else
{
MotorRcControl (0,1,1,0)
MotorRcControl (0,1,2,0)
}
}

The line sensors’ don’t really work like that. They provide an analog value that shows how much the signal is reflecting from the surface. If the surface is dark, the value will be low. If it is bright, the value will be high.

There are three sensors placed about 1/2" apart. The line will be under at most 2 sensors at a time. If the right sensor is over the line, you need to turn right to center the line. If the left sensor is over the line, you need to turn left. If only the center sensor is over the line, go straight.

This works fine untill you run off the line, which will take about 1/2 a second. What I used was to keep the value of the last sensor that saw a line (either right or left) and then turn more sharply in that direction. This will get the robot back to the line. The robot moves too fast to keep over the line otherwise–you’ll run off faster than you can correct. This has the added effect that if the robot reaches the end of the line, it will automatically turn 180 degrees and find the line again in the other direction.

So you have to figure out what your background value is (I use the “online” mode to do this) and your line value, and see if what you are getting out of the sensor is closer to one value (background, line) or the other. The values will be hundreds apart. I get about 700 for the background, dark gray carpet, and about 100 for the line, masking tape.

The background and foreground reflections are going to “jitter” quite a bit (10-20) as the robot moves (due to variations in the material and lighting), and these false indications will cause your code to result in very erratic behavior.

Hope this helps.

Another quick word of advice for line tracker. SLOW DOWN. The vex robot can jump off the line completly very quickly. Start with the robot moving very slowly, get the code working, and then increase speed in small increments. I found that I could not turn at full speed and keep on the line.

Cheers,
Francis Govers

I tried here to strip out the line tracker code for a two motor robot without all my extras.

int flag; // 0 = auto, 1=RC
int i; // loop counter
int LeftLine; // Input from left line sensor input1
int rightLine; // Input from right Line sensor input 3
int centerLine; // Input from center line sensor
int FWD = 200; // Forward PWM value
int STP = 127; // Stop PWM value
int REV = 55; // Reverse PWM value
int SLOW = 185; // SLOW PWM MODe
int REVSLOW = 80;
int lastLine = 0; // Last Direction of line detected

int avg = 300; // level of line sensor to between over line / not over line

void main ( void )
{
i = 0 ;

Wait ( 1000 ) ; // wait 1 second before we go
while ( i == 0 ) // infinite loop
{

LeftLine = GetAnalogInput ( 3 ) ;
centerLine = GetAnalogInput ( 2 ) ;
rightLine = GetAnalogInput ( 1 ) ;

avg = 300

if ( centerLine < avg ) //center sensor is over line
{
setmotor(1,FWD)
setmotor(2,FWD) // go straight
}
if ( rightLine < avg ) // if value < avg then we are over line
{
setmotor(1,FWD)
setmotor(2,STP)
lastLine = 1 ; // Last Detected Right Turn
continue; // you will need to use “user code” module for this command
// continue causes the program to jump to the “end while” statement
}
if ( LeftLine < avg ) // if value < avg then we are over line
{
setmotor(1,STP)
setmotor(2,FWD)
lastLine = 0 ; // last detected left line
continue;
}
if ( lastLine == 0 ) // last line detected was the left sensor
{
SetMotor ( 1 , FWD) ;// this is a more agressive turn than a line correction
SetMotor ( 2 , REVSLOW ) ;
continue;
}
else // if lastline is right
{
SetMotor ( 1 , REVSLOW) ;// more agressive turn
SetMotor ( 2 , FWD) ;
continue;
}
}

Ok, we tried to set it up in Easy C. But it gives me an error code on the “i==0” infinite loop. I am really getting frustrated here. Why can’t this be easy ?? I just want to program the line follower (tracker).

Thanks Dave

Make sure that the while code says:

while (i==0) //infinite loop

I tried it and did not have a problem. Look at the statements above and below this one. You don’t need the “avg = 300;” line – its redundant.

Good luck

Francis Govers

Below is what I typed in Easy C 1.1. Lines 3 thru 14 I set as variables. And I then used the easy c output statements to setup the software. But it just wont work. Is there a way that I can have the easy c version of this emailed to me? I can then look at how it was created and learn from that. This is very important to me. I really want to learn how to do this. But if it stays this difficult then I will just move on.

Thank you for your patience and Help.

1 #include “UserAPI.h”
2
3 int flag; // 0=auto, 1=RC
4 int I = 0; // loop counter
5 int Leftline; //Input from left Line sensor input1
6 int Rightline; //Input from Right Line sensor input3
7 int Centerline; //Input from Center Line sensor input2
8 int FWD = 200; // Forward PWM value
9 int STP = 127; // Stop PWM value
10 int REV = 55; // Reverse PWM mode
11 int SlOW = 185; // Slow PWM mode
12 int REVSLOW = 80;
13 int lastline = 0; // last direction of line detected
14 int avg = 300; //Level of line sensor to between over line/not over line
15
16 void main ( void )
17 {
18 i=0
19 Wait (1000); // wait for light sensors to initiate
20 while(I==0) //infinite loop
21 {
22 Leftline = GetAnaloglnput ( 3 ) ;
23 Centerline = GetAnaloglnput ( 2 ) ;
24 Rightline = GetAnaloglnput ( 1 ) ;
25 avg = 300
26 }
27 if ( Centerline < avg ) // center sensor is over line
28 {
29 SetPWM ( 1,200 );
30 SetPWM ( 2,200 );
31 }
32 if ( Rightline < avg ) // if value < avg then we are over line
33 {
34 SetPWM ( 1 , 200) ;
35 SetPWM ( 2, 127) ;
36 lastline = 1 //Last detected right line
37 continue
38 }
39 if ( Leftline < avg ) // if value < avg then we are over line
40 {
41 SetPWM ( 1,127);
42 SetPWM ( 1,127);
43 lastline = 0 // last detected left line
44 continue
45 }
46 if ( lastline == 0 } // last line detected was the left sensor
47 {
48 SetPWM ( 1 , 200 );
49 SetPWM ( 2 , 80 ) ;
50 continue
51 }
52 else // if lastline is right
53 {
54 SetPWM ( 1,80);
55 SetPWM ( 1,200);
56 continue
57 }
58}

You are going to probably laugh when you read this…

You have mixed up “I” and “i” variables in your code – the Easy C Compiler is case sensitive – you need to make sure that all the “i”'s are the same – either all upper case or lower case. So change the “while(i==0)” to "while(I==0) and change line 18 to be “I=0” and you should be OK.

Francis Govers

do this

while (1) //infinite loop
{
}

Ok I changed to upper case and I still have this message

Error[yy] line#20 : syntax error … which is the while statement.

Am I out of luck ??

Thank you guys for your help.

If you are Never going to change the value of “I” or “i”, write the While like:

while(1)

The KISS principle

I am sorry to keep complaining but I still have the same error. I changed the while to While (1).

If you use the Code Tags, you can place Code Inline, including the Indenting.

So your below program has these issues:
Your “i = 0” in line #18 has Not been Declaired and has no ending Semicolon ‘;’. It Should be Deleted since “I = 0” is Declaired and Initilized in line #4, and the Refferenced Variable in the "while (I == 0) in line #20.

Your “avg = 300” in line #25 has no ending Semicolon ‘;’

Your “lastline = 1 //Last detected right line” in line #36 has no ending Semicolon ‘;’

Your “continue” in line #37 has no ending Semicolon ‘;’

Your “lastline = 0 //Last detected right line” in line #43 has no ending Semicolon ‘;’

Your “continue” in line #34 has no ending Semicolon ‘;’

Your “continue” in line #50 has no ending Semicolon ‘;’

Your “continue” in line #56 has no ending Semicolon ‘;’

Your “while(I==0) //infinite loop” will only Loop:
{
Leftline = GetAnaloglnput ( 3 ) ;
Centerline = GetAnaloglnput ( 2 ) ;
Rightline = GetAnaloglnput ( 1 ) ;
avg = 300
}

The rest of the Program (below that point) will be “Unreachable”, and “never execute”.

#include “UserAPI.h”

int flag; // 0=auto, 1=RC
int I = 0; // loop counter
int Leftline; //Input from left Line sensor input1
int Rightline; //Input from Right Line sensor input3
int Centerline; //Input from Center Line sensor input2
int FWD = 200; // Forward PWM value
int STP = 127; // Stop PWM value
int REV = 55; // Reverse PWM mode
int SlOW = 185; // Slow PWM mode
int REVSLOW = 80;
int lastline = 0; // last direction of line detected
int avg = 300; //Level of line sensor to between over line/not over line

void main ( void )
{
    i=0
    Wait (1000); // wait for light sensors to initiate
    while(I==0) //infinite loop
    {
        Leftline = GetAnaloglnput ( 3 ) ;
        Centerline = GetAnaloglnput ( 2 ) ;
        Rightline = GetAnaloglnput ( 1 ) ;
        avg = 300
    }
    if ( Centerline < avg ) // center sensor is over line
    {
        SetPWM ( 1,200 );
        SetPWM ( 2,200 );
    }
    if ( Rightline < avg ) // if value < avg then we are over line
    {
        SetPWM ( 1 , 200) ;
        SetPWM ( 2, 127) ;
        lastline = 1 //Last detected right line
        continue
    }
    if ( Leftline < avg ) // if value < avg then we are over line
    {
        SetPWM ( 1,127);
        SetPWM ( 1,127);
        lastline = 0 // last detected left line
        continue
    }
    if ( lastline == 0 } // last line detected was the left sensor
    {
        SetPWM ( 1 , 200 );
        SetPWM ( 2 , 80 ) ;
        continue
    }
    else // if lastline is right
    {
        SetPWM ( 1,80);
        SetPWM ( 1,200);
        continue
    }
}

Sorry, don’t have time to type this into EasyC 1.x right now…