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

PID line follower won't follow curves


I made a line follower. It definetly seems like it is trying to follow the line but it wont do the curves correctly. It cant make a close turn and that causes it to lose the line.

The track seems like it could be followable by a line follower.

I’ve been tuning the Kp and the motor speeds for some days and I haven’t gotten any closer to a solution

Here’s a photo of the track:

As for my motor circuit, it is an L293B HBridge. The PWM pins go to the enable pins and the m1b and m2b go to the inputs

Here’s my code:

#include <QTRSensors.h>

#define KP               0.20    
#define KD               0      
#define KI                 0     

#define M1_DEFAULT_SPEED    70
#define M2_DEFAULT_SPEED    70
#define M1_MAX_SPEED  120
#define M2_MAX_SPEED  120

#define NUM_SENSORS    8                   
#define TIMEOUT        2500                  
#define EMITTER_PIN    12                   
#define DEBUG          0                    

//Crea objeto para 8 sensores QTR-8RC, en los pins 2-9. (PORTD, entradas)
QTRSensorsRC qtrrc((unsigned char[]) {
  2, 3, 4, 5, 6, 7, 8, 9
unsigned int sensorValues[NUM_SENSORS];

int pwmA = 10;
int pwmB = 11;

int m2B = A5;
int m1B = A3;

int lastError = 0;
int lastProportional = 0;
int integral = 0;

void set_motors(int motor1speed, int motor2speed)
  if (motor1speed > M1_MAX_SPEED)
    motor1speed = M1_MAX_SPEED;

  if (motor2speed > M2_MAX_SPEED)
    motor2speed = M2_MAX_SPEED;

  if (motor1speed < 0)
    motor1speed = 0;

  if (motor2speed < 0)
    motor2speed = 0;

  digitalWrite(m1B, HIGH);
  digitalWrite(m2B, HIGH);
  analogWrite(pwmA, motor1speed);
  analogWrite(pwmB, motor2speed);

void calibration()
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);   
  for (int i = 0; i < 100; i++)  

  digitalWrite(13, LOW);     


void setup()
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);


  set_motors(0, 0);

void loop()

  int position = qtrrc.readLine(sensorValues, QTR_EMITTERS_ON, 1);   

  int error = position - 3500;

  int turn = (KP * error) + (KI * integral) + (KD * (error - lastError));
  integral += error;
  lastError = error;

  int leftMotorSpeed = M1_DEFAULT_SPEED + turn;
  int rightMotorSpeed = M2_DEFAULT_SPEED - turn;

  set_motors(leftMotorSpeed, rightMotorSpeed);



I suspect most of your trouble boils down to tuning your PID coefficients. Some of the turns on your course look challenging, particularly the sharp turns. It will likely be difficult to tune your robot to reliably complete those turns with only a proportional term. The derivative term is typically very important for stability when tuning a line follower, especially at higher speeds. I suggest reading through Ben’s posts in this thread about PID tuning; there is a lot of good information there you might find helpful.