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

Pololu Forum

How to take acute angles using qtr 8A rc for a line follower

Actually I want to develop an fast line follower that can take 90° and 45° more accurately,their are lot of line follower competition is going on here if only I could win these if my bot is more accurate in taking angles …also I want a sample program to run the bot on white line on black surface, currently now I m using a Audrino Uno and motor sheild,Bo motor qtr 8a rc . If any one could answer this and give a sample code

Hello.

Since the line following algorithm would depend on many factors of your robot (e.g. motor driver, motors, diameter and distance apart of the wheels, battery voltage) as well as your line following course, an example program would not be practical. You might be able to use the sample code in the “Advanced Line Following with 3pi: PID Control” section of our 3pi Robot’s users guide to get an idea of how to structure your code for PID control. The LineFollower example program from our Zumo Robot’s Arduino library might also be a useful reference. However, please note that the QTR sensor functions are slightly different in our QTR sensor Arduino library.

In general, there are a lot of factors that can change how well your robot can follow a tight turn. If you are talking about sharp 90° turns (e.g. not smooth and with no radius), that is something that is commonly handled by breaking out of your main line-following algorithm. For example, when a right-angle turn is detected, the robot can be programmed to perform a pre-programmed 90° turn before going back into its line following algorithm.

By the way, “qtr 8a rc” does not match the name of any of our QTR sensors. It sounds like you are trying to refer to either the QTR-8A or QTR-8RC.

Brandon

Actually some adjustments in my motor and sensors results very good progress,now my line follower following back line on white surface very smoothly …Thank yu so much …But if yu can I also want a SAMPLE CODE FOR BLACK LINE ON WHITE SURFACE …can yu plz help me for it

A complete example program for line following would not be very helpful since there are many factors that are heavily dependent on your hardware (such as your motors and motor driver, as well as the size of your wheels and axle track).

Also, please note that the only difference in using our QTRSensors library with a black line on a white surface and using them with a white line on a black surface is just which version of the read line command you use. If you are using a black line on a white surface, you would use the readLineBlack() command. If you are using a white line on a black surface, you would use the readLineWhite() command.

However, as I mentioned in my previous post, the examples for our 3pi and Zumo robots that I linked to might be useful for getting an idea of how to structure your code for PID control, even with the QTR functions differing slightly.

Brandon

#include <QTRSensors.h>

#define KP 0.5
#define KD 0
#define M1_MAX_SPEED 70
#define M2_MAX_SPEED 70
#define M1_DEFAULT_SPEED 50
#define M2_DEFAULT_SPEED 50
#define MIDDLE_SENSOR 4, 5
#define NUM_SENSORS  6     // number of sensors used
#define TIMEOUT       2500  // waits for 2500 us for sensor outputs to go low
#define EMITTER_PIN   2     // emitter is controlled by digital pin 2
#define DEBUG 1 // set to 1 if serial debug output needed

#define rightMotor1 3
#define rightMotor2 4
#define rightMotorPWM 5
#define leftMotor1 12
#define leftMotor2 13
#define leftMotorPWM 11
#define motorPower 8

QTRSensorsRC qtrrc((unsigned char[]) {  14, 15, 16, 17, 18, 19} ,NUM_SENSORS, TIMEOUT, 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);
  
  
  manual_calibration(); 
}

int lastError = 0;
int  last_proportional = 0;
int integral = 0;


void loop()
{
  unsigned int sensors[6];
  int position = qtrrc.readLine(sensors);
  int error = position - 2500;

  int motorSpeed = KP * error + KD * (error - lastError);
  lastError = error;

  int rightMotorSpeed = M2_DEFAULT_SPEED - motorSpeed;
  int leftMotorSpeed = M1_DEFAULT_SPEED + motorSpeed;
  
    if (rightMotorSpeed > M1_MAX_SPEED ) rightMotorSpeed = M1_MAX_SPEED; // limit top speed
  if (leftMotorSpeed > M2_MAX_SPEED ) leftMotorSpeed = M2_MAX_SPEED; // limit top speed
  if (rightMotorSpeed < 0) rightMotorSpeed = 0; // keep motor above 0
  if (leftMotorSpeed < 0) leftMotorSpeed = 0; // keep motor speed above 0
  
   {
  digitalWrite(motorPower, HIGH);
  digitalWrite(rightMotor1, HIGH);
  digitalWrite(rightMotor2, LOW);
  analogWrite(rightMotorPWM, rightMotorSpeed);
  digitalWrite(motorPower, HIGH);
  digitalWrite(leftMotor1, HIGH);
  digitalWrite(leftMotor2, LOW);
  analogWrite(leftMotorPWM, leftMotorSpeed);
}
}

  
void manual_calibration() {

  int i;
  for (i = 0; i < 250; i++)  // the calibration will take a few seconds
  {
    qtrrc.calibrate(QTR_EMITTERS_ON);
    delay(20);
  }

  if (DEBUG) { // if true, generate sensor dats via serial output
    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();
  }
}

What should I change for following white line on black surface on this program…

It looks like you are using an older version of our QTRSensors library. For that version, the readLine() function accepts an optional third argument that specifies if the line is white or not. If not specified, the default is to assume it is running with a black line on a white surface (i.e. the third argument is 0). To specify a white line on a black surface, you need to make it 1. You can do this by changing your int position = qtrrc.readLine(sensors); to int position = qtrrc.readLine(sensors, QTR_EMITTERS_ON, 1);

Brandon

That’s helps me a lot … Thank you so much

Now the only problem I m facing is its speed … Iy ia Lil bit slower I think the main two problems is with the weight and motor … I m using a 200rpm gear motor and by bot weight is nearly 1kg …Can yu plz suggest a motor suitable for 1kg weigh also to provide sufficient torques

1kg is a relatively heavy robot for line following. If you can reduce that weight, it might help. At 1kg weight, you would probably want to use something on the scale of our 20D or 25D gearmotors. The amount of torque your motors will need depends on a couple of aspects about your robot aside from the weight, such as wheel diameter and number of drive motors. You might find the “Force and torque” blog post helpful for calculating the necessary torque.

The weight distribution of the robot can be very important as well. For example, it is common for a line following robot to use a differential drive setup with the wheels in the rear and the line sensor out in front, similar to the way I made my “Chariot” line follower. In that scenario, it is important to keep the center of gravity toward the rear of the robot; if the weight gets too far toward the front, it will be difficult for your robot to control.

Brandon

Hey,
I want to develop a line follower which follows black line on white surface also in white line on black in mixed backgrounds

Hello.

That sounds like a fun challenge. You should be able to do that by detecting which surface your robot is on a switching your read line statement based on that.

To determine what surface you are on, you might try doing something like checking some of the outermost sensors and seeing if they are both reading white or black. Then (if you are still using the older version of our QTRSensors library that you were using before) you can switch the third argument in the qtrrc.readLine() statement accordingly.

Brandon

Hey Barton ,
Unfortunately I am a mechanical engineering students I don’t know anything about programming , it would be so helpful if yu can edit ma program for switching surfaces , I don’t know any idea about C++ programs . Actually my competiton is tomorrow , through yur help I made some changes in my bot and now it could run on white line on black surface and black line on white surface , but I don’t have a program to cover both of these surfaces in one time .

It is generally beyond the scope of our direct technical support to modify your code to do what you want, but figuring out how to implement that kind of feature is part of the challenge of a competition like that. I would encourage you to try, and if you run into problems I can try to help you work them out.

Probably the simplest way to do it would be to have a variable (let’s call it isOnWhite) that you set to 1 if your robot is on a white surface and 0 if it is on a black surface. Then, you can use that variable as your third argument to the qtrrc.readLine() call. For example:

int position = qtrrc.readLine(sensors, QTR_EMITTERS_ON, isOnWhite);

You could probably do a simple check of the values stored in your sensors[] array to see which surface you are on. For example, if the values of the outermost sensors (sensors[0] and sensors[5]) are both below 300, the surface is most likely white, and you can set isOnWhite equal to 1; otherwise, isOnWhite should be set to 0. You might need to do a more thorough check depending on your course, but I think that could be a good start.

Brandon