# Kp, Ki, Kd for software PID control

I am designing a software PID control. Logic is almost final but I wonder how do I decide the value of $k_p$, $k_i$ and $k_d$. Also, I need to determine the max and min value for the Pterm Item and Dterm. How do I do that?. Also, I am trying to implement the inverse control. Also, am I going in the right way in designing the software PID? Also, if integral time and $k_i$ both are same? The code I wrote so far is given below.

Calculate_Error();
P_Term = Percnt_Error;

P_Term = KP * P_Term;

if(P_Term >= PMAX)
{
P_Term = PMAX;
}
else if(P_Term <= PMIN)
{
P_Term = PMIN;
}

// Integral calculation

if(Integraltime==1)                 // Take integration at every 1s
{
Integraltime = 0;
Error_Accum = Error_Accum + Percnt_Error;   // Error Accumulation over time
if(Error_Accum >= MaxAccumError)
{
Error_Accum = MaxAccumError;
}

if(Error_Accum <= -MinAccumError)
{
Error_Accum = -MinAccumError;
}

I_Term = (Error_Accum)*KI;

if(I_Term >= IMAX)
{
I_Term = IMAX;
}
else if(I_Term <= IMIN)
{
I_Term = IMIN;
}
}

• Have you tried searching for "PID tuning"? I seem to recall there are some standard tuning methods that will get you close, however fine-tuning is as much art as science. Apr 13 '15 at 9:07
• There is the zeigler-nichols' ultimate method, first implement the Kp portion, set Kp to 0, increase Kp until output behavior becomes cyclic (easier said then done), the periodicity of this cyclic behavior as well as amplitude will serve as a heuristic to tune the PI, PD, or PID controller. Apr 17 '15 at 1:58

All credit for this is from the (now unfortunately dead) Balancing Robots for Dummies thread on the Arduino forum.

The PID controller is as follows:

int
updatePID(int setPoint, int currentPoint)
{
float error;
static float last_error;
static float integrated_error;

float pTerm, iTerm, dTerm;

/*  Calculate error and proportional value.*/
error = setPoint - currentPoint;
pTerm = Kp * error;

/*  Calculate error and intergral value.*/
integrated_error += error;
iTerm = Ki * constrain(integrated_error, LOWER_LIMIT, UPPER_LIMIT);

/*  Calculate deriviative value and reset error.*/
dTerm = Kd * (error - last_error);
last_error = error;

/*  Return the PID controlled value.*/
return constrain(i32K*(pTerm + iTerm + dTerm)), LOWER_LIMIT, UPPER_LIMIT);

}


This version of 'software PID control' implements the limit on the intergral value (similar to your code) using the constrain function from the Arduino library. Added benefit of this code is that it allows you to choose what from controller you want by changing the return value. E.g. a PD controller would remove the iTerm from the return value.

As far as tuning goes, it is similar to what Illegal Immigrant said.

Set Ki, Kp, and Kd to 0.
Tune Kp until oscillation occurs.
Reduce oscillation and overshoot by tuning Kd.
Tune Ki to increase the speed of the system.


This is my first time answering, hopefully I've done this correctly and helped you a little on the way!

• Welcome to EE:SE. I wish my first answer had been as good as this one! Apr 21 '15 at 18:34

What type of integrator are you hoping to implement? looking at your code you have a simple accumulator, it will function but there are better integrators out there that also facilitate mapping to the s-domain easier

fwdEuler? $y(n) = y(n-1) + K \times [t(n)-t(n-1)] \times x(n-1)$

revEuler? $y(n) = y(n-1) + K \times [t(n)-t(n-1)] \times x(n)$

Trap? $y(n) = y(n-1) + K\times[t(n)-t(n-1)]\times[x(n)+x(n-1)]/2$

It is good you are considering putting summation limits on the PID. May I recomend you place an individual limit on the $K_i$ term and an overall summation limit. This will mitigate windup concerns with the integrator.

$$\lim_{-x\to x} ( K_p + \lim_{-x\to x} K_i + K_d)$$

How do you determine the maximum value for the limits? It depends what the PID will feed into.

Say it is the controller for a speed loop. The output of which will be a current demand. If the maximum current you want to control to is say... 100amps, you wouldn't want the speed PID outputting a demand higher than that, equally you wouldn't want the $K_i$ accumulating higher (see the previous statement about anti-windup)

How to choose the numeric $K_p$, $K_i$, $K_d$? Welcome to control theory. There are a number of ways. A system model and stability criteria is usually required.

• I havent mentioned it in here but i have provided the min and max limit to my PID output as well. Like final PID = P+I-D. considering the max value of each and every component i got the PIDmax and PIDmin. About the kp, KI and kd, right now i am approaching on try and error method. But i am little bit unsure if it;s a good practice or not.
– sam
Apr 13 '15 at 12:12
• for simulation can i have a generic tool or something?
– sam
Apr 15 '15 at 9:58
• you can use python. I have a simple z-domain controller functioning in python. Apr 15 '15 at 12:13
• Any good excel simulator available? I am trying my self to build one for my application, a reference may be quite useful.
– sam
Apr 16 '15 at 3:27
• There are a number flying around (google "PID excel") I have one that I used because sometimes its easier giving someone an excel sheet (that they can open) rather than a matlab model or a py script Apr 16 '15 at 11:49

If you can tolerate overshoot try reading up on the Ziegler-Nichols method on wikipedia. This is aggressive often finds the best speed of response within the limits of your actuator's performance. If you need critical damping (e.g. machine tools) you will need some else. Much more at Loop Tuning methods