Line following robot using PID

I am making a Line following robot using PID.
Hardware: L298N motor driver, arduino uno, 8 IR sensor array and two motors.
Problem: Bot is not working. I unable to know whether my code is right or wrong. Please help...


// PID constants
float Kp = 0.2; // Proportional gain
float Ki = 0.0; // Integral gain
float Kd = 1.0; // Derivative gain

int baseSpeed = 150; // Base speed for motors
int maxSpeed = 255; // Max motor speed

QTRSensors qtr; // Use QTRSensors with the latest QTR library
const uint8_t SensorCount = 8;
const uint8_t SensorPins[] = {10, 11, 12, A0, A1, A2, A4, A5}; // Define pins connected to each sensor
uint16_t sensorValues[SensorCount];

const int ENA = 5; // PWM for left motor
const int ENB = 6; // PWM for right motor
const int leftMotorForward = 3;
const int leftMotorBackward = 9;
const int rightMotorForward = 8;
const int rightMotorBackward = 7;

int lastError = 0;
float integral = 0;

void setup() {
  Serial.begin(9600);
  
  // Initialize QTRSensors
  qtr.setTypeRC();
  qtr.setSensorPins(SensorPins, SensorCount);
  qtr.setTimeout(2500);
  
  // Motor pins
  pinMode(leftMotorForward, OUTPUT);
  pinMode(leftMotorBackward, OUTPUT);
  pinMode(rightMotorForward, OUTPUT);
  pinMode(rightMotorBackward, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);

  // Set PWM to 0 initially
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}

void loop() {
  // Read sensor values
  qtr.read(sensorValues);

  // Calculate weighted position of the line
  int position = calculateLinePosition(sensorValues);

  int error = position - 3500; // Calculate error (3500 is center)
  
  integral += error; // Accumulate the integral
  int derivative = error - lastError; // Calculate the derivative

  int controlSignal = (Kp * error) + (Ki * integral) + (Kd * derivative); // PID formula

  // Calculate motor speeds
  int leftSpeed = baseSpeed + controlSignal;
  int rightSpeed = baseSpeed - controlSignal;

  // Constrain speeds
  leftSpeed = constrain(leftSpeed, 0, maxSpeed);
  rightSpeed = constrain(rightSpeed, 0, maxSpeed);

  // Move motors
  moveMotors(leftSpeed, rightSpeed);

  lastError = error; // Update lastError
  delay(10); // Small delay for stability
}

int calculateLinePosition(uint16_t *sensorValues) {
  int position = 0;
  int totalValue = 0;

  for (int i = 0; i < SensorCount; i++) {
    position += sensorValues[i] * i * 1000; // Weighted position
    totalValue += sensorValues[i];
  }

  if (totalValue > 0) {
    position /= totalValue; // Normalize
  } else {
    position = 3500; // Default to center if no line is detected
  }

  return position;
}

void moveMotors(int leftSpeed, int rightSpeed) {
  if (leftSpeed > 0) {
    digitalWrite(leftMotorForward, HIGH);
    digitalWrite(leftMotorBackward, LOW);
  } else {
    leftSpeed = abs(leftSpeed);
    digitalWrite(leftMotorForward, LOW);
    digitalWrite(leftMotorBackward, HIGH);
  }

  if (rightSpeed > 0) {
    digitalWrite(rightMotorForward, HIGH);
    digitalWrite(rightMotorBackward, LOW);
  } else {
    rightSpeed = abs(rightSpeed);
    digitalWrite(rightMotorForward, LOW);
    digitalWrite(rightMotorBackward, HIGH);
  }

  analogWrite(ENA, leftSpeed);
  analogWrite(ENB, rightSpeed);
}

What function does your PID perform for the robot? Speed, line position, etc?

line position

Please explain what that means: what do you expect to happen and what happens instead.

Also, where did these values come from? The bot has to be "working" before reasonable values for Kp, Kd and Ki can be selected.

// PID constants
float Kp = 0.2; // Proportional gain
float Ki = 0.0; // Integral gain
float Kd = 1.0; // Derivative gain

Ok, please show the actual values you are feeding the PID and what is returned.

Is this function working as you designed it to work?

Note that:

In the likely event that you did not write this code, please post a link to where you found it.

The question posted by @DaveX above is a very strong hint: the function probably won't work on an Arduino Uno due to integer overflow of the variables named position and totalValue.

Also, sensor zero won’t contribute any information.

Oh, Pololu's 8 sensor RC-mode thingy, QTR-MD-08RC,does a certain sort of digital outputs:

and the example code in

...says the return values are 0-2500.

...so the maximum may be as large as 2500*1000*7*8/2 =70000000.

The code looks bogus.

i don't know from where did i took the code but i modified it using chatgpt

It maybe, cause i didn't wrote the the code. could you please provide me the code or help how to write the code for the same?

Also i didn't bought the sensor array from pololu website. I took it from a local shop.

Sorry to hear that, as it is not likely to work.

ChatGPT doesn't know the coding rules for microprocessors, and like many beginners, just guesses.

what can i do now?

You can learn to code like everyone else. Start small, run the built in tutorials in the Arduino IDE and learn the basics. Files>Examples> ...

If you have questions about C/C++, there are on line tutorials covering every aspect of the programming language.

Then look at some of the thousands of tutorials on line showing how to build and write code for a line following robot.

There might be a robot club or competition in the town where you live! Meet people and collaborate.

I know how to code in C and C++

what, i didn't understood

I don't know

That is a great start! You should be able to recognize the stupid mistakes made by ChatGPT.

All you have to do now is learn about the special functions used with Arduino, and the theory of robot navigation. Line following is one of the simplest approaches.

Well, wrap it in a test script and see if the results look sane. If it gives garbage then everything downstream is garbage-in-garbage-out until it is fixed.