Moving Line Follower During Calibration HELP

Im trying to get my line follower to move back and fourth across the line during calibration to save me from manually sliding it across the line. Im using the QTR-8RC and a sample line follower code I found online. Below you can see the snipet of code whcih concerns my question.

  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

   if ( i  < 25 || i >= 75 )
   { 
    digitalWrite(rightMotor1, LOW);   
    digitalWrite(leftMotor1, HIGH);       
    analogWrite(rightMotorPWM, 50);   //PWM Speed Control
    analogWrite(leftMotorPWM, 50);   //PWM Speed Control  
   }
     else
   {  
    digitalWrite(rightMotor1, HIGH);   
    digitalWrite(leftMotor1, LOW);       
    analogWrite(rightMotorPWM, 50);   //PWM Speed Control
    analogWrite(leftMotorPWM, 50);   //PWM Speed Control
   }
   qtrrc.calibrate();   
   delay(20);

It is not clear what kind of advice or help you are looking for. Can you be more specific about what you are having problems with? Did you have some question about the code?

Brandon

Sorry Brandon,

Yes I need help with the code, so the robot will move back and fourth across the line during calibration, the code above is my best attempt but it when I run it, it will just spin one wheel indefinitely, I need help writing a code to make make the wheels spin in opposing directions until the the last sensor on the array sees the line, then do the opposite so the other side gets exposed, and keep repeating until the calibration is over!

It sounds like the code you found probably uses different hardware or different connections than your robot. The if statement used in that code is essentially separating the for loop into three section. The first section (when i is less than 25) turns the robot in one direction, the second section (when i is between 25 and 75) turns the robot in the other direction, and finally, the third section (when i is between 75 and 100) rotates the robot to face forward again.

If you need help modifying that code to work with your robot, can you post more information about your system (e.g. what motor driver are you using, what Arduino pins are connected to it, what Arduino are you using)? Also, could you post your complete code?

Brandon

That makes sense and is exactly what I want to do but yes I need help modifying it to work with my components. Im using the DFRobot Uno R3 and a DFR 2A Motor Shield, the pins connected are M1=12 M2=13 E1=10 E2=11.

The complete code:

#include <QTRSensors.h>

#define Kp 6 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
#define Kd 70 // experiment to determine this, slowly increase the speeds and adjust this value. ( Note: Kp < Kd) 
#define RIGHT_MAX_SPEED 90 // max speed of the robot
#define LEFT_MAX_SPEED 90 // max speed of the robot
#define RIGHT_BASE_SPEED 80 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define LEFT_BASE_SPEED 80  // 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 TIMEOUT       2500  // waits for 2500 us for sensor outputs to go low
#define EMITTER_PIN   QTR_NO_EMITTER_PIN     // emitter is controlled by digital pin 2

#define rightMotor1 12 
#define rightMotorPWM 10
#define leftMotor1 13
#define leftMotorPWM 11

QTRSensorsRC qtrrc((unsigned char[]) {2, 3, 4, 5, 6, 7, 8, 9} ,NUM_SENSORS, TIMEOUT, EMITTER_PIN); // sensor connected through analog pins A0 - A5 i.e. digital pins 14-19

unsigned int sensorValues[NUM_SENSORS];

void setup()
{
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotorPWM, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotorPWM, OUTPUT);
  
  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

  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
   { 
    digitalWrite(leftMotor1, LOW);
    digitalWrote(rightMotor, HIGH);
    analogright(leftMotorPWM, 80)
    analogright(rightMotorPWM, 80)   
   }
     else
   {  
    digitalWrite(leftMotor1, HIGH);
    digitalWrote(rightMotor, LOW);
    analogright(leftMotorPWM, 80)
    analogright(rightMotorPWM, 80)   
   }*/

   qtrrc.calibrate();   
   delay(20);
 
 delay(2000); // wait for 2s to position the bot before entering the main loop 
    
    /* comment out for serial printing
    
    Serial.begin(9600);
    for (int i = 0; i < NUM_SENSORS; i++)
    {
      Serial.print(qtrrc.calibratedMinimumOn[i]);
      Serial.print(' ');
    }
    Serial.println();

    for (int i = 0; i < NUM_SENSORS; i++)
    {
      Serial.print(qtrrc.calibratedMaximumOn[i]);
      Serial.print(' ');
    }
    Serial.println();
    Serial.println();
    */
} 

int lastError = 0;

void loop()
{
  unsigned int sensors[8];
  int 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.
  int error = position - 3500;

  int motorSpeed = Kp * error + Kd * (error - lastError);
  lastError = error;

  int rightMotorSpeed = RIGHT_BASE_SPEED - motorSpeed;
  int leftMotorSpeed = LEFT_BASE_SPEED + motorSpeed;
  
    if (rightMotorSpeed > RIGHT_MAX_SPEED ) rightMotorSpeed = RIGHT_MAX_SPEED; // prevent the motor from going beyond max speed
  if (leftMotorSpeed > LEFT_MAX_SPEED ) leftMotorSpeed = LEFT_MAX_SPEED; // prevent the motor from going beyond max speed
  if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep the motor speed positive
  if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep the motor speed positive
  
   {
  digitalWrite(rightMotor1, HIGH);
  analogWrite(rightMotorPWM, rightMotorSpeed);
  digitalWrite(leftMotor1, HIGH);
  analogWrite(leftMotorPWM
  , leftMotorSpeed);
}
}

There seems to be some typos in your code; are you sure that is the exact code you are using (I would be surprised if it compiles without any errors)? For example, in the part of the code that is supposed to do the calibration, you use “digitalWrote” instead of “digitalWrite”, as well as “analogright” instead of “analogWrite”. It also looks like one of your variable names doesn’t match the rest of your code (e.g. you use “rightMotor” instead of “rightMotor1”), and your for statement in the calibration part of the code is missing braces { and }. Could you try fixing those typos and seeing if that changes anything?

Brandon

Sorry Brandon

Just whipped some stuff to put in that section to indicate what I have previously tried. When I fix the typing errors the robot will just spin round on one wheel and never enter the main loop. Not sure what exactly is going on.

#include <QTRSensors.h>

#define Kp 0.5 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
#define Kd 8 // experiment to determine this, slowly increase the speeds and adjust this value. ( Note: Kp < Kd) 
#define RIGHT_MAX_SPEED 60 // max speed of the robot
#define LEFT_MAX_SPEED 60 // max speed of the robot
#define RIGHT_BASE_SPEED 50 // this is the speed at which the motors should spin when the robot is perfectly on the line
#define LEFT_BASE_SPEED 50  // 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 TIMEOUT       2500  // waits for 2500 us for sensor outputs to go low
#define EMITTER_PIN   QTR_NO_EMITTER_PIN     // emitter is controlled by digital pin 2

#define rightMotor1 12 
#define rightMotorPWM 10
#define leftMotor1 13
#define leftMotorPWM 11

QTRSensorsRC qtrrc((unsigned char[]) {2, 3, 4, 5, 6, 7, 8, 9} ,NUM_SENSORS, TIMEOUT, EMITTER_PIN); // sensor connected through analog pins A0 - A5 i.e. digital pins 14-19

unsigned int sensorValues[NUM_SENSORS];

void setup()
{
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotorPWM, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotorPWM, OUTPUT);
  
  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

  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
   { 
    digitalWrite(leftMotor1, LOW);
    digitalWrite(rightMotor1, HIGH);
    analogWrite(leftMotorPWM, 80);
    analogWrite(rightMotorPWM, 80);   
   }
     else
   {  
    digitalWrite(leftMotor1, HIGH);
    digitalWrite(rightMotor1, LOW);
    analogWrite(leftMotorPWM, 80);
    analogWrite(rightMotorPWM, 80);  
   }


   qtrrc.calibrate();   
   delay(20);
 
 delay(2000); // wait for 2s to position the bot before entering the main loop 
    
    /* comment out for serial printing
    
    Serial.begin(9600);
    for (int i = 0; i < NUM_SENSORS; i++)
    {
      Serial.print(qtrrc.calibratedMinimumOn[i]);
      Serial.print(' ');
    }
    Serial.println();

    for (int i = 0; i < NUM_SENSORS; i++)
    {
      Serial.print(qtrrc.calibratedMaximumOn[i]);
      Serial.print(' ');
    }
    Serial.println();
    Serial.println();
    */
} 

int lastError = 0;

void loop()
{
  unsigned int sensors[8];
  int 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.
  int error = position - 3500;

  int motorSpeed = Kp * error + Kd * (error - lastError);
  lastError = error;

  int rightMotorSpeed = RIGHT_BASE_SPEED - motorSpeed;
  int leftMotorSpeed = LEFT_BASE_SPEED + motorSpeed;
  
    if (rightMotorSpeed > RIGHT_MAX_SPEED ) rightMotorSpeed = RIGHT_MAX_SPEED; // prevent the motor from going beyond max speed
  if (leftMotorSpeed > LEFT_MAX_SPEED ) leftMotorSpeed = LEFT_MAX_SPEED; // prevent the motor from going beyond max speed
  if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep the motor speed positive
  if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep the motor speed positive
  
   {
  digitalWrite(rightMotor1, HIGH);
  analogWrite(rightMotorPWM, rightMotorSpeed);
  digitalWrite(leftMotor1, HIGH);
  analogWrite(leftMotorPWM
  , leftMotorSpeed);
}
}

It looks like you still do not have any braces enclosing the code in your for loop. This means that your code right now will run the qtrrc.calibrate(); and delay(20); only once after your for loop, instead of each time through like it should. This can be fixed by adding an open brace at the beginning of your for loop and a close brace after the delay, as shown below:

for (int i = 0; i < 100; i++) // calibrate for sometime by sliding the sensors across the line, or you may use auto-calibration instead
{ 	//Added open brace here

  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
   { 
    digitalWrite(leftMotor1, LOW);
    digitalWrite(rightMotor1, HIGH);
    analogWrite(leftMotorPWM, 80);
    analogWrite(rightMotorPWM, 80);   
   }
     else
   {  
    digitalWrite(leftMotor1, HIGH);
    digitalWrite(rightMotor1, LOW);
    analogWrite(leftMotorPWM, 80);
    analogWrite(rightMotorPWM, 80);  
   }


   qtrrc.calibrate();   
   delay(20);

}  	//Added close brace here

Can you try making that change and describing what happens when you run the robot with the updated code?

Brandon

That fixed it, thanks Brandon,

Im finding that the current setup “if ( i <= 25 || i >= 75 )” is to long, how can i shorten the amount of time the robot rotates in each direction without shortening the calibration time?

There are probably a few ways you could go about shortening the rotation. One option might be to simply reduce the motor speed during this step. Another option might be to reduce the delay(20) to something shorter like delay(10); doing this should give the motors less time to rotate, but still take the same number of calibration samples (one for each iteration). You could also change the way the if loop is broken up to shorten the initial and final turns (i <= 25 || i >= 75) and lengthen the middle turn by lowering 25 and raising 75. You might try doing this in small steps; for example, changing them to 20 and 80.

Whichever way you try, you should make sure that every sensor still passes over the line during the calibration, preferably multiple times.

Brandon