PID Tutorial

Updated: Apr 11, 2019


Setpoint (SP): the position you want to get to

Process Variable (PV): where we currently are. In this context, PV is our current position.

Error: how far away from the setpoint we are, given by SP-PV

Position: for our purposes, this will normally refer to the angular position / rotation of the shaft--given in raw encoder values. We can convert these values to a 1-100 scale fairly easily in code. We'll set some physical point as encoder raw value=0 by calling



// range of encoder raw values -> 0 to ENCODER_IN are the limits private final double ENCODER_IN = 176000;

// preferred range of encoder values (for degrees, percent, etc) -> 0 to ENCODER_OUT private final double ENCODER_OUT = 100;


private double fromEncoder (double in) { // become bigger return in * ENCODER_OUT / ENCODER_IN; }

private double toEncoder (double in) { // become smaller return in * ENCODER_IN / ENCODER_OUT; }

PID Overview:

Let’s say you want to control physical values like position, velocity, and temperature. You want to go from the current value to the desired value and stay at that desired value. For that you would need PID.

A proportional–integral–derivative (PID) controller is a control loop feedback mechanism used to get your robot to do what you want without it going out of control.

Proportional (P) - The error (SP-PV).

Integral (I) - Accumulative error over a period of time. If there’s still an error after proportional control, the integral term tries to eliminate that error by adding a control effect due to the historic cumulative value of the error.

Derivative (D) - An estimate of the future trend of the error, based on its current rate of change. This is an “anticipatory control”, as it seeks to reduce error by exerting a control influence generated by the rate of error change.

Tweak Constant - Tweak each term (P, I, D) in the code. After building the robot, test different values for the constants until the settling time is minimal, but there is also no overshoot.

Output = Kp*P + Ki*I + Kd*D

PID is used when:


To move our motors, we typically do one of 2 things:

motor.set(ControlMode.PercentOutput, speed);


motor.set(ControlMode.Position, position);

The former will change the speed of the motor, and the latter will move the motor to a position. In order to properly move to certain positions, we need to configure PID.

In layman’s terms, play with the values of Kp until the error is relatively small, then tune Ki, then tune Kd, until there’s a minimum amount of error. Basically just look at the error by printing out the motor.getSetPoint() (the position the motor wants to go) and compare it to motor.getPosition() (where the motor is). Try to minimize it as much as possible with Kp before tuning Ki and Kd.

For reference, in our class, our PID values were (this is also how to set PID values for a motor):

motor.config_kP(0, 0.005);

motor.config_kI(0, 0);

motor.config_kD(0, 0);

We have to reach these values empirically, meaning that there isn’t any way to know what these values will be on any given robot without testing that robot individually.

In certain cases, we’ll use PID to keep something in a certain position against gravity. Feedforward is a type of PID control where a known value is supplied to the output as a guesstimate so that PID only has to make minor corrections. Because gravity is constant, feedforward is particularly applicable to keeping something at the same position vertically.

We do so with a similar function call:

motor.set(ControlMode.Position, position, DemandType.ArbitraryFeedForward, kAF);

The new parameters are DemandType.ArbitraryFeedForward and kAF. kAF is the arbitrary feed forward constant we find, and DemandType is, well the Demand Type--specifying what we’re doing.

Guide compiled by Ryan Wei and Andrew Liu

Information drawn from:

37 views0 comments

Recent Posts

See All