Follow line robot 90º turn help

Good afternoon, I am building a line-following robot for a school project using PID and 8 QTR RC sensors that use the "qtrSensors.h" library.
The PID cannot make 90-degree turns very well, sometimes it even goes off the line. My idea would be to detect if more than 3 sensors on the respective side are detecting the line. If so, using the gyro sensor it will make a 90-degree turn. However, I do not know how to do the part where the detection of when the sensors are detecting the line on only one side to make the turn, using it as a conventional sensor without calculating the error to center the robot. Is it possible to do this?

    //variaveis da biblioteca do sensor de refletancia
    #include <QTRSensors.h>
    
    QTRSensors qtr;
    
    //variaveis de quantidade e de leitura dos sensores
    const uint8_t sensores = 8;
    uint16_t leituras[sensores];
    
    //***************************************************************************************************************************************************
    //variaveis do PID
    
    //ganhos proporcionais,integrais e derivados
    float kp = 0.65;
    float ki = 0;
    float kd = 0.9;
    
    uint8_t multiP = 1;
    uint8_t multiI = 1;
    uint8_t multiD = 1;
    //variaveis de calculo de erro e PID
    int erro;
    int erroAnterior;
    int P;
    int I;
    int D;
    
    //variaveis usadas na multiplicacao dos valores
    float Pvalue;
    float Ivalue;
    float Dvalue;
    
    //***************************************************************************************************************************************************
    //***************************************************************************************************************************************************
    
    //***************************************************************************************************************************************************
    //variaveis dos motores
    #include <AFMotor.h>
    
    //define os motores
    AF_DCMotor motorD(1);
    AF_DCMotor motorE(2);
    
    //***************************************************************************************************************************************************
    //variaveis de velocidade base,minima e maxima
    int leftbasespeed = 100;
    int rightbasespeed = 100;
    
    int leftmaxspeed = 210;
    int rightmaxspeed = 210;
    
    int leftminspeed = 0;
    int rightminspeed = 0;
    
    //***************************************************************************************************************************************************
    // variaveis de cores rgb
    //***************************************************************************************************************************************************
    // calibragem da cor branca e preta em aproximadamente 10 seg
    void calibragem() {
      for (uint16_t i = 0; i < 400; i++) {
        qtr.calibrate(); {
        }
      }
    }
      //***************************************************************************************************************************************************
      //acoes executaveis ao iniciar
      void setup() {
    
        //define o tipo de sensor como digital (RC) e define as portas
        qtr.setTypeRC();
        qtr.setSensorPins((const uint8_t[]) {22, 24, 26, 28, 30, 32, 34, 36 }, sensores);
    
        //ativa o monitor serial
        Serial.begin(9600);
    
        calibragem();
      }
    
      //***************************************************************************************************************************************************
      /* leitura dos sensores tanto minima quanto maxima*/
      void monitor() {
    
        //mostragem minima
        for (uint8_t i = 0; i < sensores; i++) {
          Serial.print(qtr.calibrationOn.minimum[i]);
          Serial.print(' ');
        }
        Serial.println();
    
        //mostragem maxima
        for (uint8_t i = 0; i < sensores; i++) {
          Serial.print(qtr.calibrationOn.maximum[i]);
          Serial.print(' ');
        }
        Serial.println();
        Serial.println();
        delay(1000);
      }
    
      //***************************************************************************************************************************************************
      //calculo do pid
      void PID() {
    
        //calculo da posicao do robo com isso definindo o erro
        uint16_t position = qtr.readLineBlack(leituras);
        erro = 3500 - position;
    
        //calculo do PID
        int P = erro;
        int I = I + erro;
        int D = erro - erroAnterior;
    
        //erro vira o erro anterior
        erroAnterior = erro;
    
        //calculo do PID
        Pvalue = (kp / pow(10, multiP)) * P;
        Ivalue = (ki / pow(10, multiI)) * I;
        Dvalue = (kd / pow(10, multiD)) * D;
    
        //calculo da velocidade dos motor
        float motorspeed = Pvalue + Ivalue + Dvalue;
    
        //separando a velocidade esquerda e direita
        int leftspeed = leftbasespeed + motorspeed;
        int rightspeed = rightbasespeed - motorspeed;
    
        //limitando o minimo e maximo da velocidade
        if (leftspeed > leftmaxspeed) {
          leftspeed = leftmaxspeed;
        }
        if (rightspeed > rightmaxspeed) {
          rightspeed = rightmaxspeed;
        }
        if (leftspeed < leftminspeed) {
          leftspeed = leftminspeed;
        }
        if (rightspeed < rightminspeed) {
          rightspeed = rightminspeed;
        }
        //executando o PID nos motores
        motorD.run(FORWARD);
        motorD.setSpeed(rightspeed);
        motorE.run(FORWARD);
        motorE.setSpeed(leftspeed);
      }
    
      //***************************************************************************************************************************************************
      //funcao de parada dos motores
      void stop() {
    
        //para os motores esquerdos e direitos
        motorD.run(RELEASE);
        motorE.run(RELEASE);
      }
    
      //***************************************************************************************************************************************************
      //funcao executada repetidamente
      void loop() {
        PID();
      }

This is my code, if you know of anything that can be improved in addition to all this, it would be very helpful.

some parts of the code are in portuguese for example erro = error, erroAnterior = lastError, sensores = sensors, leituras = detection, calibragem = calibration

There are probably hundreds of line-following robot projects. Some will be in the Arduino.cc Project Hub and even more via Google.

The library has functions to read individual sensor values, so you can count results any way you like.

How did you choose the K values for the PID algorithm? They are critical to best performance.

Check if sensors on one side detect black. Update your loop() like this:

void loop() {
  qtr.read(leituras); // Read raw sensor values
  int leftCount = 0;
  int rightCount = 0;

  // Threshold to determine if sensor is detecting the line
  const uint16_t threshold = 700; // adjust based on calibration

  for (int i = 0; i < sensores; i++) {
    if (leituras[i] > threshold) {
      if (i < sensores / 2) {
        leftCount++;
      } else {
        rightCount++;
      }
    }
  }

  // Detect if a 90-degree LEFT turn is needed
  if (leftCount >= 4 && rightCount == 0) {
    makeLeftTurn();  // Use gyro or timed motor rotation
  }
  // Detect if a 90-degree RIGHT turn is needed
  else if (rightCount >= 4 && leftCount == 0) {
    makeRightTurn(); // Use gyro or timed motor rotation
  }
  else {
    PID(); // Normal PID tracking
  }
}

I selected these values ​​testing to see which value takes less time to align in the center, it's my first time setting up line followers with PID so I don't have much experience with it. If you know anything that I can improve in the code I would be very grateful.

Wouldn't using the readCalibrated() function be better than using read in this case?

For PID control to work at all, the PID constants must be chosen carefully. A web search for "PID tuning" will turn up tutorials and discussions.

But for special cases that are easy to recognize, like 90 degree turns, where there is no need to employ PID steering control, your code should switch between "turn" and "line following" modes, as suggested by @ahsrabrifat above.

readCalibrated() is definitely better than read(), which is intended primarily for sensor calibration.