Line Follower Complications

Hello everyone I have been having difficulties with this project (should have been simple).

It is just a line follower program who needs to cover about 6 meters in the least amount of time possible.

It is kinda slow and after the first half of the track (it is a rectangle with gentle curves at its edges) where it needs to turn, it starts to form a path of a sine wave between the black lines.

I did indeed try google but it didn’t really help me in this instance.

I’m not in any way an experienced person with Arduino, in fact I am fairly new. Sorry for any mistakes. I thank anyone in advance who responds to this post.

Anyway here is the code:

// Pins of Motors
int vRIGHT = 5; // Velocity Motor RIGHT
int vLEFT = 6; // Velocity Motor LEFT
int dRIGHT = 7; // direction Motor RIGHT
int dLEFT = 8; // direction Motor LEFT

// Pins of the sensors
int line = 11;
int line2 = 12;
int light = A0;

int sensorLEFT;
int sensorRIGHT;

void velRIGHT(int vel)
{
if(vel >= 0) // MOTOR
{
digitalWrite(dRIGHT,HIGH);
analogWrite(vRIGHT,vel);
}
else
{
digitalWrite(dRIGHT,LOW);
analogWrite(vRIGHT,abs(vel));
}
}

void velLEFT(int vel)
{
if(vel >= 0)
{
digitalWrite(dLEFT,HIGH);
analogWrite(vLEFT,vel);
}
else
{
digitalWrite(dLEFT,LOW);
analogWrite(vLEFT,abs(vel));
}
}

void setup(void)
{
pinMode(dRIGHT, OUTPUT);
pinMode(dLEFT, OUTPUT);
pinMode(line, INPUT);
Serial.begin(9600);
Serial.println(“Sensor Testing”);
}

void loop(void)
{
while(analogRead(light) < 800)
{
Serial.print("Sensor light = “);
Serial.print(analogRead(light));
Serial.print(” Sensor line = “);
Serial.print(digitalRead(line));
Serial.print(” Sensor line2 = ");
Serial.println(digitalRead(line2));
}
velLEFT(255);
velRIGHT(255);
delay(600);
while(1)
{
sensorLEFT = digitalRead(line);
sensorRIGHT = digitalRead(line2);

if(sensorLEFT && sensorRIGHT) //LEFT = BLACK e RIGHT = BLACK
{
velLEFT(255); //
velRIGHT(115);//
}

if(!sensorLEFT && !sensorRIGHT) //LEFT = WHITE e RIGHT = WHITE
{
velLEFT(110);//
velRIGHT(255);//255
}

if(sensorLEFT && !sensorRIGHT) //LEFT = BLACK e RIGHT = WHITE
{
velLEFT(255);
velRIGHT(255);
}

if(!sensorLEFT && sensorRIGHT) //LEFT = WHITE e RIGHT = BLACK
{
velLEFT(0);
velRIGHT(255);
}

}
}

Sono_un_inglese_di_Londra.ino (1.77 KB)

You should post your code in </> tags.
When you say the track is a rectangle with gentle curves at it edges do you mean it is a rectangled with rounded corners?

Try to explain what your code is supposed to do.

In this case is the follower not in the middle of the black line, if so why does it try to turn right instead of going at full speed?

 if(sensorLEFT && sensorRIGHT)  //LEFT = BLACK e RIGHT = BLACK
    {
      velLEFT(255); //
      velRIGHT(115);//
    }

Here should it not be trying to turn left instead of going straight?

    if(sensorLEFT && !sensorRIGHT)  //LEFT = BLACK e RIGHT = WHITE
    {
      velLEFT(255);
      velRIGHT(255);
    }

Yes the track is exactly like you think it is.

About the code you are right, the values are inverted (old save of the file) but that is not the end of the problem because it keeps making that sine wave which keeps slowing the robot.

The robot does the track 6 meters in 10,8 seconds, 0,55m/s (very slow, with actually good motors).

Thanks

You should put comments in the code to say what each section does turn left turn right and so on.
You should also put print statements so that as you watch the follower you can keep one eye on the output to see what it is doing and why.

Your program really has only four input states;

BLACK BLACK
WHITE WHITE
BLACK WHITE
WHITE BLACK

and it has four fixed responses to these inputs.

It has no memory, it does not know what it was doing last or how long it was doing it for.
That is what is causing your oscillations.

If the follower has been BLACK BLACK for a long time it must be going fast along a straight.
If it then goes WHITE BLACK then either it is on the straight and drifting of it to the left or it has reached a right hand bend. It should make a small turn to the right. If that gets it back to BLACK BLACK then it was drifting off the line and it should start going straight again. On the other hand if it continues to be WHITE BLACK then it must be on a corner and it needs to make a sharper right turn. If it quickly goes WHITE BLACK, BLACK BLACK, BLACK WHITE it turned too quickly.

So you need to build some memory and timing into your program.
If the track is fixed and you are allowed to know the layout then after a few trials you could more or less hard code the speed of turning the follower needs to make to get round the corner, however that is cheating and not really following the line.

Thank you. You have helped me very much.

If I could ask one more thing, how do I go for searching “adding memory to my Arduino program” because only what I find is increasing its flash memory, which I don’t believe that is what you mean.

The Arduino board is modified with more flash and an embedded “motor controlling Arduino shield”.

If anyone wondered it is powered by 8 1,5V batteries and it has an aluminum chassis (I didn’t have a say in this), to prevent the Arduino from killing itself it has a plastic sheet preventing it from touching the metal, I don’t really know the RPM of the motors but I know they are powerful enough, two black & white sensors at the front and one in the center.

I will add the suggestions you have given me in this thread and hopefully well implement them. If I am able to finish this project, the end product will be here.

You are correct I don’t mean adding physical memory. I mean getting your sketch to remember what it did last, at the moment it only lives in the present.

Imagine you are the line follower. You look at the sensors and they say BLACK WHITE what are you going to do?
To make a good decision you really need more information like I see BLACK WHITE now but just before that I was seeing BLACK BLACK for 10s and going at full speed.

A couple of other things about your program. The funtion loop() does what it says it loops it is called again and again.
Within loop() you have a never ending while statment

while(1)
{
...
}

Get rid of that while statement and let loop() do the looping for you.

You will need to move the stuff that only needs to get done once out of loop() and into setup()
i.e. move this stuff;

while(analogRead(light) < 800)
  {
    Serial.print("Sensor light = ");
    Serial.print(analogRead(light));
    Serial.print(" Sensor line = ");
    Serial.print(digitalRead(line));
    Serial.print(" Sensor line2 = ");
    Serial.println(digitalRead(line2));
  }
  velLEFT(255);
  velRIGHT(255);
  delay(600);

You can use the millis() fuction to work out how long you have been doing something;
https://www.arduino.cc/reference/en/language/functions/time/millis/

When @ardly said ‘add memory’, the reference is to the logical construct in your program, not the physical memory that is part of the arduino.

It means, keep track of the last state (or the last several states).
Then you can use the current state of the sensors AND the previous state of the sensors to make better decisions about what to do now.

Edit: which @ardly just clarified. :slight_smile: