Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Line follower not following the line

I made a line follower using Arduino nano,qtr-8rc ,tb6612fng,micro gear motor and 7.2v battery i tried to upload a code ;the bot is working (motor are spinning in right direction) but it is not following the line just running here and there randomly i have been trying to fix this thing from past 3-4 days and didn’t find any thing and now i m very frustrated so please someone help me one thing i noticed when i tried to upload any other code is that once calibration is done then the motor starts to glitch (1sec moving forward and another sec moving backward) and then one motor starts to spin in opposite direction with respect to other motor and after a 1 both motor starts to move in correct order (moving forward but still doesn’t follow line)

#include<QTRSensors.h>
#define Kp 0.1 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
#define Kd 4// experiment to determine this, slowly increase the speeds and adjust this value. ( Note: Kp < Kd) 
#define MaxSpeed 255// max speed of the robot
#define BaseSpeed 255 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define NUM_SENSORS  8     // number of sensors used

#define speedturn 180

#define rightMotor1 A2
#define rightMotor2 A1
#define rightMotorPWM 11
#define leftMotor1 A4
#define leftMotor2 A5
#define leftMotorPWM 10
#define motorPower A3

QTRSensorsRC qtrrc((unsigned char[]) {2,3,4,5,6,7,8,9} ,NUM_SENSORS, 2500, QTR_NO_EMITTER_PIN);

unsigned int sensorValues[NUM_SENSORS];

void setup()
{
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotor2, OUTPUT);
  pinMode(rightMotorPWM, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);
  pinMode(leftMotorPWM, OUTPUT);
  pinMode(motorPower, OUTPUT);
  
  delay(3000);
  
  int i;
  for (int i = 0; i < 100; i++) // calibrate for sometime by sliding the sensors across the line, or you may use auto-calibration instead
  {
   //comment this part out for automatic calibration 
    if ( i  < 25 || i >= 75 ) // turn to the left and right to expose the sensors to the brightest and darkest readings that may be encountered
    {
      move(1, 70, 1);//motor derecho hacia adelante
      move(0, 70, 0);//motor izquierdo hacia atras 
    }
    else
    {
      move(1, 70, 0);//motor derecho hacia atras
      move(0, 70, 1);//motor izquierdo hacia adelante  
    }
    qtrrc.calibrate();   
    delay(20);
  }
  wait();
  delay(3000); // wait for 2s to position the bot before entering the main loop 
}  

int lastError = 0;
unsigned int sensors[8];
int position = qtrrc.readLine(sensors);

void loop()
{  
  position = qtrrc.readLine(sensors); // get calibrated readings along with the line position, refer to the QTR Sensors Arduino Library for more details on line position.
  
  if(position>6700){
    move(1, speedturn, 1);//motor derecho hacia adelante
    move(0, speedturn, 0);//motor izquierdo hacia adelante
    return;    
  }
  if(position<300){ 
    move(1, speedturn, 0);//motor derecho hacia adelante
    move(0, speedturn, 1);//motor izquierdo hacia adelante
    return;
  }
  
  int error = position - 3500;
  int motorSpeed = Kp * error + Kd * (error - lastError);
  lastError = error;

  int rightMotorSpeed = BaseSpeed + motorSpeed;
  int leftMotorSpeed = BaseSpeed - motorSpeed;
  
  if (rightMotorSpeed > MaxSpeed ) rightMotorSpeed = MaxSpeed; // prevent the motor from going beyond max speed
  if (leftMotorSpeed > MaxSpeed ) leftMotorSpeed = MaxSpeed; // prevent the motor from going beyond max speed
  if (rightMotorSpeed < 0)rightMotorSpeed = 0;    
  if (leftMotorSpeed < 0)leftMotorSpeed = 0;
    
  move(1, rightMotorSpeed, 1);//motor derecho hacia adelante
  move(0, leftMotorSpeed, 1);//motor izquierdo hacia adelante
}
  
void wait(){
  digitalWrite(motorPower, LOW);
}

void move(int motor, int speed, int direction){
  digitalWrite(motorPower, HIGH); //disable standby

  boolean inPin1=HIGH;
  boolean inPin2=LOW;
  
  if(direction == 1){
    inPin1 = HIGH;
    inPin2 = LOW;
  }  
  if(direction == 0){
    inPin1 = LOW;
    inPin2 = HIGH;
  }

  if(motor == 0){
    digitalWrite(leftMotor1, inPin1);
    digitalWrite(leftMotor2, inPin2);
    analogWrite(leftMotorPWM, speed);
  }
  if(motor == 1){
    digitalWrite(rightMotor1, inPin1);
    digitalWrite(rightMotor2, inPin2);
    analogWrite(rightMotorPWM, speed);
  }  
}

FBGZY3IITOW9BOV (1).ino (3.6 KB)

Hello.

I think we should start by establishing that your sensor array and program are establishing the position of the line correctly. Can you upload a program that calibrates your sensors in the setup phase, then during the loop just calls readLine and prints the line position value to Arduino’s Serial Monitor? Then you can test that function is doing what you expect by just manually moving your robot over a line. If that does not behave as you expect, then you might try printing your individual sensor values too so you can see what is going on, and you can post here if you do not understand the results you get.

- Patrick

Hey Patrick,
Thanks for your quick reply you got it right sensors are reading value properly i mean like sensor readings are 1000 for black line and 10-40 for white background as you said to use readline in loop so i directly printed position (did i do it right?) So the value that i got from position=qtrrc.readline(sensors) is upto 8000 max early i didn’t how to understand this reading so i check pololu site for qtrrc commands there i found that this readline command gives the value from sensor which is just above the black so i compared to my results and they are way more different then i expected . And one thing i didn’t understand is that when i uploaded code this time the motor reacted strange again like right hand side motor is going clockwise and then going anticlockwise ,i suspect that my motor driver is fault i guess… Here are some video for your understanding (https://drive.google.com/folderview?id=1btnNLZgt1ZJHBa_rbjqGSlfkdPQ3taiR)

The readLine function should never return a value of 8000 with an 8-channel reflectance sensor array; its range should be 0-7000. The values I saw in your video matched my expectation about what should be happening. Can you explain how they are different from what you are expecting?

- Patrick

Yeah you are right the position or readline function is working correctly I couldn’t figure out that early until I looked full details about the sensor function. Till now we know that sensors are functioning correctly .motor driver , Arduino nano and motors are new so I can’t understand what’s happening with my bot every when I try to upload the very same code ,I have been seeing new behavior like in last video bot is going reverse and now this time when I again connected the battery it followed a line for a bit (https://drive.google.com/folderview?id=1btnNLZgt1ZJHBa_rbjqGSlfkdPQ3taiR)

I cannot access your videos. The forum does not allow users to post very large videos, but it does work well with videos linked from YouTube. Could you upload your videos on YouTube (unlisted if you prefer) and link to them here?

Since your readLine function is working as expected your problem probably has to do with your PID tuning and the conditional statements in your program. I suggest you simplify your original program by taking out the if statements that use position (the ones to prevent your motors from exceeding MaxSpeed or turning backwards are probably okay), reduce your BaseSpeed and MaxSpeed values, and set your derivative coefficient (Kd) to zero. Then, using only your proportional coefficient (Kp) just try to get your robot to steadily oscillate about the line.

After you get your robot to steadily oscillate about the line, you should have an easier time working from there to get a smooth line follower, at which point you can then try to repeat the process for running your robot at higher speeds. You might consider researching some PD controller tuning methods, such as the Ziegler-Nichols method.

- Patrick