Loading

7842 Navigators

PID Tutorial​

Movement without PID

To explain PID we will use the example of moving forward a distance. Let’s first try to make one without any PID.

Our goal is to drive 360deg forward from the current position. A simple code that might work is:

Loop Forever: { 
If Distance is > than Wanted distance: Move forwards at 50% Power
If Distance is < than Wanted distance: Move backwards at 50% Power
If Distance is = to Wanted: Stop Moving
}

That is very simple. If the wanted distance is greater than current distance, run the motors forward, otherwise run them backward.

However, this code will not work as expected. Since the robot can only move at 50% power, it will move at that speed toward the goal regardless of how close the goal is. It will then overshoot the goal at 50% power. If we make the robot exit out of the loop when the goal is achieved (which we don’t in this case), it will do so. This is because the distance received from the sensors was correct for a fraction of a second.

To fix the potential issue of the robot exiting the loop early we could put a 100ms wait at the end of the loop. That will let the robot overshoot past the goal without stopping the loop, and then correct itself and apply reverse power.

However, the code will still not work. Even without the wait, the robot will still oscillate at full power and never stop because the robot will always overshoot its goal. This is because the robot will never be at 0 power at the correct spot. It will always apply 50% power when the robot only has a tiny amount of distance left to achieve, even one as small as 1cm.

What most people do to resolve this issue is to have a code that applies 50% power to the robot until it has completed 80% of its goal. Then the robot will slowly move to the final goal at 20% power. That works, but is not ideal in many conditions, and is time-consuming. It might suffice for moving a certain distance from a wall, but it would never work for something more dynamic.

Elements of PID

The best solution to fix the issue of oscillating is to have the motor power be dynamically calculated. That means that the motor power can be anything from 100 to 0, and is calculated proportionally depending on distance remaining from the goal. That is what a PID loop does, with some additions.

A PID system calculates the power sent to the motors based on three equations. It adds the result of all three of those equations together to result in the final motor power.

  • P for Proportional – The difference between the wanted distance and the current distance Error) This times a proportional constant (Lets call it Kp) equals its share of the power sent to the motor.
  • I for Integral – The accumulated Error. Every loop add the Error to a counter. That times a proportional constant Ki equals its share of the power sent to the motor.
  • D for Derivative (rate of change) – The current Error minus the previous Error. That calculates the amount the Error has changed since the last loop. That times a proportional constant Kd equals its share of the power sent to the motor.

Each of these three sections each output a number, which is weighed by the constants, to equal the final motor power. The hardest part of making a PID is that you have to tune each constant and figure out what is the likely range for each of these outputs and what do we want them to proportionally output to the motor.

The P OF PID: Proportional

Let’s start with the first part of PID: the P.

If we make the motor power simply be proportional to the Error, it could work. Here is a code that simply does this:

Loop Forever:
{
Error = Current Distance - Wanted Distance
Kp = 20
Motor Power = Error * Kp
}

Lets imagine a couple scenarios:

The program has just started. The robot is 15cm away from the goal. That means that the Error is 15cm. Kp is 20. 15 * 20 = 300. That means the motor power will be 300. Since the maximum power of the motor is only 100, the motors will be turning at 100% power.

The program has been running for a bit. The robot is now 4cm away from the goal. That means that the Error is 4cm. Kp is 20. 4 * 20 = 80. That means the motor power will be 80. Since the maximum power of the motor is 100, the motors will be turning at 80% power.

The robot is almost at its goal. The robot is 1cm away from the goal. That means that the Error is 1cm. Kp is 20. 1 * 20 = 20. That means the motor power will be 20. Since the maximum power of the motor is 100, the motors will be turning at 20% power.

For some reason the robot has overshot its goal. The robot is now -1cm away from the goal. That means that the Error is -2cm. Kp is 20. -2 * 20 = -40. That means the motor power will be -40. Since the maximum reverse power of the motor is -100, the motors will be turning at -40% power.

As you can see, the robot will go at full power towards the goal until it gets in the +- 15cm range. Then the robot will slow down proportionally until the robot comes to a stop exactly at the goal. This program will work perfectly whether the robot is above or below the goal.

You might be wondering “where did you get the Kp value of 20?”. The answer is that we just did much trial-and-error to find that number. We started with an educated guess of how much an error in cm merits how much motor power. We increased the Kp until the robot would aggressively stick to the proper distance without oscillating. Oscillating is possible because if the Kp is too high any small error would result in a massive reaction from the robot, which would then overshoot the goal and cause a even bigger error, which would cause the robot to compensate in greater and greater increments.

A P loop is useful for many applications, you just have to change the inputs, outputs, and Kp. You can do almost everything with P, so if this is getting too complicated, you can stop reading here and still make a successful drive forward code.

This tutorial is not complete past this point

Comment

Leave us a comment or question!

Shopping Basket