PID Line Follower issue

Hello everyone , my name is Rares and I start this topic cuz i need help from you guys . I am building a new Line Follower robot. I am using Reduino Core , Motor driver TB6612FNG (DUAL) , QTR8 Analog Sensors (8 active sensors) and 2x 10:1 motors (3000rpm). Its not my first line follower robot. I had another one with 10:1 motors but now .. its a little bit old. It was at the level of 2013-2014 difficulty and now .. its just for showcase or Dragster... nvm

Is the first time when i am using PID (its just PD) so.. i have a lot of problems. First problem is with the weight of the robot. The "Inertia" give me a lot of problems. Ok.. robot works in straight line but with oscilation.. and if it turns left or right and the radius of turn is big, the robot start oscilating so hard and after another turn , it loses the line. I tryed a lot of Kp and Kd values. I seen a topic on polulu forum about a formule to calculate the Kp and its sounds someting like:
255(max motor speed) / 3500(position) = ~0.07 (i tryed from 0.01 to 0.10 and noting good) after i got the Kd witch was 10times bigger than Kp = 0.7 and again.. it doesn't work verry good. I tryed 20times bigger.. 1.4 again .. noting good. Another problem is : The lowest speed of motor (that's mean brake) its 0. It worked on 30:1 motors cuz they have more traction power.. but at 10:1 , the motor keep going.

What can I do? I know I have a lot of variants but I am blocked.. I don't have any Ideea.

My robot dimensions: FROM MOTOR1 TO MOTOR2 (ax) 140mm . From MOTOR1 / MOTOR2 to the middle of the sensors 140mm. So my robot its a equilateral triangle.
The weight of the robot is about ~110grams (+/- 10grams).
-The LiPo batteries which I am using ATM has 50grams (7.4V @1200mAh) but i wanna change them with 2 Drone LiPo batteries (7.2V @ 380mAh) which has 28grams.
-Motor and Wheels : ~15-20grams / motor
-The PCB plate(chassis) has 5-10grams
-And an extended "motherboard" with Reduino , Driver motor and voltage controll part (60mmx50mm) about 15-20grams.

My target is to make the robot very light(not heavy) so i can control the inertia.

  • Another question: Can I use a function to brake the motor for 100milliseconds or someting to brake it? If yes , tell me how.

To move motors I am using the classic analogWrite (pwm) and a function which works someting like:

move(motor,speed,direction)
motor: 1 or 2
speed: 0-255
direction: 0 (backward) - 1 (forward)

I don't have the code right in this moment (its on my friend's laptop) but PD formula is:

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 = rightBaseSpeed + motorSpeed;
 int leftMotorSpeed = leftBaseSpeed - motorSpeed;
 
   if (rightMotorSpeed > rightMaxSpeed ) rightMotorSpeed = rightMaxSpeed; // prevent the motor from going beyond max speed
 if (leftMotorSpeed > leftMaxSpeed ) leftMotorSpeed = leftMaxSpeed; // 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(motorPower, HIGH); // move forward with appropriate speeds
 digitalWrite(rightMotor1, HIGH);
 digitalWrite(rightMotor2, LOW);
 analogWrite(rightMotorPWM, rightMotorSpeed);
 digitalWrite(motorPower, HIGH);
 digitalWrite(leftMotor1, HIGH);
 digitalWrite(leftMotor2, LOW);
 analogWrite(leftMotorPWM, leftMotorSpeed);
}
}

Hi,

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom...... :slight_smile:

There is the code. Don't care about //comments . They are written in ro.

#include <QTRSensors.h>

#define Kp 0.09 // valori la panarama -------------------------------
#define Kd 1.4 // valori si mai panarama(Kp < Kd) 
#define rightMaxSpeed 100 // max speed 
#define leftMaxSpeed 100 // max speed 
#define rightBaseSpeed 255 // viteza dreapta
#define leftBaseSpeed 255  // viteza stanga
#define TIMEOUT       3000  // timeout
#define EMITTER_PIN   2     // nvm

#define rightMotor1 9
#define rightMotor2 10
#define rightMotorPWM 11
#define leftMotor1 7
#define leftMotor2 6
#define leftMotorPWM 5
#define motorPower 8


QTRSensorsRC qtrrc((unsigned char[]) {14, 15, 16, 17, 18, 19, 20, 21} ,8, TIMEOUT, EMITTER_PIN); // sensor connected through analog pins A0 - A5 i.e. digital pins 14-19

unsigned int sensorValues[8];
//-------------------------------SETUP-----------------------
void setup()
{
  Serial.begin(9600);
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotor2, OUTPUT);
  pinMode(rightMotorPWM, OUTPUT);
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);
  pinMode(leftMotorPWM, OUTPUT);
  pinMode(motorPower, 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
   qtrrc.calibrate();
   delay(20);
    wait();  
    delay(2000); // wait for 2s to position the bot before entering the main loop 
  } 
//------------------------------------PID LINE FOLLOW-------------------------------------------
  void lineFollowPID(){
  int lastError = 0;
  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 = rightBaseSpeed + motorSpeed;
  int leftMotorSpeed = leftBaseSpeed - motorSpeed;
  
  if (rightMotorSpeed > rightMaxSpeed ) rightMotorSpeed = rightMaxSpeed; // prevent the motor from going beyond max speed
  if (leftMotorSpeed > leftMaxSpeed ) leftMotorSpeed = leftMaxSpeed; // 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(motorPower, HIGH); // move forward with appropriate speeds
  digitalWrite(rightMotor1, HIGH);
  digitalWrite(rightMotor2, LOW);
  analogWrite(rightMotorPWM, rightMotorSpeed);
  digitalWrite(motorPower, HIGH);
  digitalWrite(leftMotor1, HIGH);
  digitalWrite(leftMotor2, LOW);
  analogWrite(leftMotorPWM, leftMotorSpeed);
}
}
//---------------------------------LOOP---------------------------------
void loop()
{
  lineFollowPID();
}
//-------------------------------INFRAROSU SENZOR START /STOP----------------------------
  
//----------------------------------MOVE--------------------------------
void move(int motor, int speed, int direction)
{
//Move specific motor at speed and direction
//motor: 0 for B 1 for A
//speed: 0 is off, and 255 is full speed
//direction: 0 clockwise, 1 counter-clockwise

  digitalWrite(motorPower, HIGH); //disable standby

  boolean inPin1 = LOW;
  boolean inPin2 = HIGH;

  if(direction == 1)
  {
    inPin1 = HIGH;
    inPin2 = LOW;
  }

  if(motor == 1)
  {
    digitalWrite(rightMotor1, inPin1);
    digitalWrite(rightMotor2, inPin2);
    analogWrite(rightMotorPWM, speed);
  }
  else
  {
    digitalWrite(leftMotor1, inPin1);
    digitalWrite(leftMotor2, inPin2);
    analogWrite(leftMotorPWM, speed);
  }
}  
void wait(){
    digitalWrite(motorPower, LOW);
}

Hi,
You are using pins 11 and 5 as your PWM for the motors

pins 5 and 6 PWM Frequency = 62500Hz
pins 3, 9, 10, 11 PWM Frequency = 31250Hz

From this info your PWM frequencies are different for each motor.
If the loads were LEDs or lamps you would not have a big difference in performance.
However because you are using motors, and they have inductance, they respond differently to different PWM frequencies.
I would say that this could be part of your problem. The motors are responding differently to the same signal.
So I would suggest you try putting the motor PWM on 5and6 or 9and10 or 11and13.

Tom.... :)

I think you saved 2 of my projects with this information :D. I will make a small on-board edit with 2 wires and a cutter and i will use 5 and 6 as PWMsignals for motors. But.. about the inertia problem.. it should still a big problem.. ok I will probably solve the PID control but at close ungles like 60*+ it should lose the line.. one of my ideeas should be: for a fast brake i should change the direction of motor for 100milliseconds so it will brake . But.. i really don't know how can i actualy do this.. i am out of ideeas :confused:

Thank you again.

any ideeas? Someone?

Hi,
Did changing the PWM pins fix the travelling straight problem?

Tom.... :slight_smile:

it helped . Now the motors run at the same speed. But.. the PID still bad. I told you its first time when I am using it... I tried a lot of values.. after a turn , the robot starts oscilating and the oscilation increase and after 3-5 seconds is losing the line....If you want , I can post a video with the robot.

I am trying at low speed (100) .

Hi,
Have you researched PID?
If your response is over shooting and getting worse, you need to use P and I and D parameters.
The I parameter will help to remove the overshoot.
Have you tried the PID library that works on the arduino?

http://playground.arduino.cc/Code/PIDLibrary

Tom..... :slight_smile:

I researched the PID algorithm. I ask a lot of people about how does it work and how can I get the Kp and Kd values. Someone told me to start by Kd and Kp 0 and increase the Kp value . When the robot starts oscilating very bad , i split the value and I got 6. After i start giving values to Kd and now i keep trying but nothing good.

About the PIDLibrary (the link which you gave me) , I don't really know if i can do something with... I told you its the first time when I am using PID on a Line Follower robot. I am trying to understand how this library works but... I maybe wanna stay on my code .. Now , about de Ki.. i have 2 or 3 questions about this: How is it gonna help me? How can I implement this in my code? How can I get the values? (It is just randomly?)

Thank you for feedback and I wish I will finish my robot without problems

-Rares

Hi,

http://letsmakerobots.com/blog/enigmerald/pid-tutorials-line-following

https://syclops.wordpress.com/2011/08/06/line-following-robot-code-guideline-using-pid/

Tom..... :slight_smile:

Hi Tom , I am using already this tutorials... The second one wasn't that helpful for me but the first one. If you look again to my code , its 60% based by the first tutorial. I was trying anyting. I tryed with KD 10x bigger than KP or 20x bigger and nothing good. Right in this moment I started everyting from 0. KP 0 and I am giving values to KD. My sensors are reading good.I don't know why it doesn't work. I did everyting what was needed. If you want I can post a video so maybe you will can study this problem better and give me a response.. Meanwhile I will try every value possible from 0.00000001 to 999.9999999 :))

UPDATE: I really don't know how but with KD=5 and Kp = 0.05 or 0.1 it starts following the line (with small oscilation at turns and if its an ~90* turn it starts to oscilate more. I will try different speed and values. I think I will finish this :smiley:

TomGeorge:
The I parameter will help to remove the overshoot.

Tom..... :slight_smile:

No, it will make it much worse....

D reduces overshoot and oscillation, I reduces steady-state error at the expense of stability.

@MarkT

I waste yesterday some hours to learn about the Ki (INTEGRAL). Now I can say the time wasn't wasted. I am running the robot at low speed (100) and it seems to work... with small problems etc. But still doing his work.. but now.. I wanna make a competition robot. I had 2 robots before this and they destroyed eveything. Now they are "old" and I wanna do one better. I am prepairing this Line Follower for the biggest contest in my country "robochallenge" . In 2014 I got 6th place from about 40robots. My robot finished in about 11seconds the "route" (i really don't know how can I call this) and the difference between me and 3rd place and 2nd was about 1.5 or 2.5 seconds. But the 1st place got about 5seconds..It was verry fast. And the map its not easy because you have a gliding ramp like:
.............................................../
/| and after the ramp is |______

and an wall to avoid. (25Lx5lx10H)

Now.. the robot has about 110-120grams and I am looking for a higher speed. I will try everything . I really wanna see "him" "alive".

BTW Any ideea for a MAZE robot? (with walls not lines). Maybe a short pseudocode example.. I wanna try the right hand algorithm.

can i use pid for digital output from sensor array please sen d the code

Quick way to experiment with PID:

set I = D = 0.

Try a value of P. If it oscillates halve it, if not double it. Repeat until you home in
on the max P-only setting that works with slight overshoot. Now increase P until is oscillates
a couple of times on each step-change and increase D until this is nicely damped. You can
try to increase P some more and repeat with D - this will speed up the response, but the
noise/jitter will increase...

Only if accuracy is inadequate do you need to add the I term, which you can add in small steps
until the system converges to correct value better. If it oscillates a little, increase D a little,
if it oscillates a lot, decrease I again. Integral wind-up may bite you with a naive PID
algorithm (characterised by overshoot and slow recovery, rather than overshoot with oscillations).