PID control

Planning
Step 1
PID controllers

A PID controller is a feedback loop system.

The basic idea is to steer the robot towards the line, and the farther off it is, the more it corrects itself.

The process is a feedback loop as shown in the picture:

1. Compare the desired position to the current position
2. The result is stored as the "Error"
3. The PID system decides how much to steer
4. The motors steer the robot and the sensors check the position again
5. Repeat
Information
Step 2
Let's define position concretely so we can work with it in our code

We'll do this by giving a numeric value to the position of our cart based on where it is in relation to the line

Perfectly on the line corresponds to a position of 1000.

The further to the left our cart is, the closer position is to 0
The further to the right our cart is, the closer position is to 2000.

Position is never greater than 2000 or less than 0!

Step 3
Create an integer to say our target position is 1000
Planning
Step 4
We've just defined our desired position

The first step of creating our PID feedback loop is to define our desired position, which we've decide it going to be 1000

Next we need a way to figure out what the current position of the robot is

Planning
Step 5
Using the sensor to find the line

We can have each sensor report how much light is reflected and get a picture of which side the line is on.

If we then take a weighted average of the sensor values, we get a single number representing our position.

In this case we know we know the sensor is to the left of the center position, 1000.

So we can expect the values to average out to a bit lower, around 750.

Information
Step 6
Taking a weighted average

To take an average of a bunch of values, we use this formula

We're going to take a weighted average, which is similar, only each value is multiplied by a "weight"

Here's an example:

Step 7
Create a function called findLine()

This function needs to take a weighted average of your calibrated sensor values.

int findLine() {
//call readCalibrated()
//return a weighted average of the sensor values
}
Check Your Work
Step 8
Check your findLine() function

Turn on your robot, calibrate it, and move it back and forth across the line.
Use the Serial Monitor commands to output the position of the robot.

You'll notice that you get some weird results if you move completely off of the line.

Step 9
We'll fix the weird numbers using the following pseudocode

The sensor gives strange values if all of the sensors move off the line. In this case we want to set the sensor to either 2000 or 0 depending on which side of the line it slid off.

IF [sensor1 sees the line OR 
    sensor2 sees the line OR 
    sensor3 sees the line]
THEN
  IF position > 1000
    THEN lastDir = 1
  ELSE
    lastDir = -1
ELSE
  IF lastDir == 1
    position = 2000
  ELSE
    position = 0

If the car slid off to the left, position should be set to 0.
If the car slid off to the right, position should be set to 2000.

Step 10
Create an integer named "position" which gets set equal to findLine()

You'll want this to get set every clocktick (every iteration of the loop function).

Planning
Step 11
What's next?

Our program now does 2 steps of the PID feedback loop.

We can now check the current position of your robot with findLine().
And we already know that our desired position we defined as 1000.

We now must compare the desired position to our current position to calculate the error

Information
Step 12
We need to define the concept of Error

Error is a measure of how far the cart is from the track. The further the cart is from the track, the larger the error.

More specifically we can say that error is the difference between the current position and the target position.

If the cart is to the left of the track, the error is negative. If it's to the right of the track, the error is positive.

Step 13
Create a variable named "error" and calculate its value at the start of every loop iteration
int error = position - target;
Planning
Step 14
Now we need to use a PID algorithm to determine how much the line follower needs to steer

We come to the PID controller step with an error which is a value from -1000 to 1000 which represents how far our robot is from the line.

After this step we want to modify the speed of our motors so that the robot will steer back towards the track.

The PID controller is a formula which will take in the error, and output an amount by which the motor speeds change

Information
Step 15
The proportional constant

The first term in a PID equation is the Proportional constant Kp.
Suppose we take some constant value Kp = 0.02;

If we take the error and multiply it by Kp, we can change the motor speeds by that value and get something like this

Information
Step 16
Using just Kp

This is a good start but here is the problem. If we only have Kp we'll have something like this.

Notice how the square reacts to changing Kp

Information
Step 17
Adding a dampener

We want to add some dampening to the result above. To do this we will add a second term, the Derivative constant, Kd.

This term looks at the last change to the system and tries to slow it down to prevent overshooting

Information
Step 18
PID controller in action

Instead of multiplying the error by Kd, we multiply the change in error since the last error calculation, (error - lastError)

The result off adding these two terms together gets us this:

Play around and see how quickly you can get the green rectangle to settle on the line. What happens if your Kd is too high/too low?

Step 19
We wont be using the "I" term in PID

That means our formula- which you will need to construct in the next step is:

correction = error * Kp + (error - lastError) * Kd
Step 20
create a function called getPID()

This function will take Kp, Kd, and the error, and return a value which will be used to change the speed of our motors.

int getPID() {
   //Define Kp, start with around 0.1
   //Define Kd, it should be at least 20 times as large as Kp

  //Calculate the error from position 1000;
  //Calculate the correction using Kp, and Kd;

  return correction;
}
Step 21
Output

The last step of the feedback system is to actually set the output of the motors.

The motors speed will always be a set amount, say 100, plus the correction calculated by the PID controller.

Example:

int PIDcorrection = getPID();

int leftMotorSpeed = 100 + PIDcorrection;
int rightMotorSpeed = 100 - PIDcorrection;
Information
Step 22
PID feedback control video

Here is a slideshow which steps through the feedback control loop from beginning to end.

Your program should seek to emulate this controller

PID control Info

Account

MVCode

Created By

jamie

Course:

Feedback Control Systems: Line follower

Access Level

public

For Teachers and Schools

Teach coding to your students with MVCode Teach

MVCode offers an integrated product designed to teach coding to students.

Learn more about MVCode Teach