# PID without the D

so I looked around a bit for this and I can’t seem to find a way to do this on the multiple white papers that are posted. So my question is, how do I use the proportional and Integral parts of the theory with out the derivative part of it.

I know how to do them individually but have no idea on how to combine ay of these aspects to do anything meaningful.

Thanks in advance for any help that can be provided

Well if you have a full PID loop up and running, then just set the D gain to zero and you’ll be running PI, you’ll need to retune the loop though.

Otherwise, if you have them running individually but not together, just take the output of P and I and add them together for a simple PI loop, once again you’ll have to retune it.

If you know how to calculate the P, I, and D errors, combining them is easy. Just use a different gain constant for each and add the outputs together.

For example output = Kgain * Kerror + Igain * Ierror + Dgain * Derror.

Once you have code that does all three, an easy way to disable any of them is to set the gain to 0 for that one.

on that note, the PID

loop, how fast do I really need it. Is the normal 26ms loop fast enough? or does this need to be faster?

When implementing the integral part, you can start by just adding or subtracting a constant value (start with one) and adding the integral part to the Proportional part. So, suppose you have a 5V analog potentiometer that is connected to an arm. The target or set point you want is 4V which corresponds to about 818 counts or units on the 10 bit A/D. If you are presently at 3V or about 614 counts or units, you want to move towards 818 counts. So, Error is 818 minus 614 = 204 counts. Multiply 204 by let’s say 10 percent . To speed up calculation , use multiply by 26 and divide by 256 (26/256 is about 10 %).
So, (204 times 26)/256 is 20.7. With roundoff you will get 20 counts. Next, since PWM units are scaled 0 to 255, which is 1/4 range of 0-1023 a-d units, you will need to rescale (divide by 4) the 20 counts output by 4 to get 5 counts. This will be what you add to the present value you are already outputting to the PWM (which is scaled zero to 127 for one direction and 127 to 254 for the other direction). So if your present PWM output is 150 counts, you will add 5 counts for the proportional part of the 26.2 msec loop you are in. Next, since you are below your target, add 1 PWM output unit to the 150 counts for the integral portion of the PI gain. Remember this is all happening 38 times per second, so the numbers you add for the Proportional and Integral part can be small. Hope this sheds some insight into one way of making your PID work for you.

a) We’ve always done the PID

loop in the 26ms loop, and it’s worked for us.
b) Since you can’t update the PWM
outputs any faster[li] than every 26ms, I don’t see how running your PID
calculations any faster would be of help to you.
[/li]
Why do you want to do just a PI loop? I’ve heard of people using just P, or PD, but never PI.

[*] Actually, you can update your PWM

outputs faster, if you use PWMs 13-16 and your own pwm generation functions (or one from a non-IFI
library)

I would think that doing a PI would be really unstable. The D part has the effect usually of dampening the I since the I will always overshoot the goal. Of course the instability will dampen itself over time because of friction in the system but I would agree that I have never seen a PI loop. Plenty of P+D and P-D and just P loops but never a PI loop.

What exactly is your reason for not using the derivative part of the loop?

Not meaning to side track here, but that is what I’m going to do.

P+D and P-D, which is correct? Or should I ask, how do I determine which to use?

Actually PI control loops are fairly common. If you have a situation where proportional control alone works well, it’s common to add an integral term with a low gain to remove the fixed error inherent with proportional control. Here is example integer PI code from the camera tracking code:

``````
*//*
*// *
*// x-axis/pan tracking code*
*//*
*//*

*// save the current pan servo PWM value into a local*
*// integer variable so that we can detect and correct *
*// underflow and overflow conditions before we update *
*// the pan servo PWM value with a new value*
temp_pan_servo **=** (**int**)pan_servo_position;

*// calculate how many image pixels we're away from the*
*// vertical center line.*
pan_error **=** (**int**)T_Packet_Data**.**mx **-** (**int**)Tracking_Config_Data**.**Pan_Target_Pixel;

*// Are we too far to the left or right of the vertical *
*// center line? If so, calculate how far we should step*
*// the pan servo to reduce the error.*
**if**(pan_error **>** (**int**)Tracking_Config_Data**.**Pan_Allowable_Error)
{
*// calculate how far we need to step the pan servo*
servo_step **=** pan_error **/** (**int**)Tracking_Config_Data**.**Pan_Gain;

*// Due to rounding error in the division calculation above,*
*// the step may be calculated as zero, which will make it*
*// impossible to converge on the target when pan_error is*
*// smaller than Pan_Gain. To get around this problem, we just *
*// test for the zero case and set the step size to one. *
** if**(servo_step **== **0)
{
servo_step **= **1;
}
}
**else****if**(pan_error **<**-1***** (**int**)Tracking_Config_Data**.**Pan_Allowable_Error)
{
*// calculate how far we need to step the pan servo*
servo_step **=** pan_error **/** (**int**)Tracking_Config_Data**.**Pan_Gain;

*// Due to rounding error in the division calculation above,*
*// the step may be calculated as zero, which will make it*
*// impossible to converge on the target when pan_error is*
*// smaller than Pan_Gain. To get around this problem, we just *
*// test for the zero case and set the step size to one. *
** if**(servo_step **== **0)
{
servo_step **= **-1;
}
}
**else**
{
*// if we've fallen through to here, it means that we're*
*// neither too far to the left or too far to the right*
*// of the vertical center line of the image and don't *
*// need to move the servo*
servo_step **=**0;

*// signal that the pan servo is on target*
Tracking_State **+=** STATE_PAN_ON_TARGET;
}

*// add the step to the current servo position, taking into*
*// account the direction set by the user in tracking.h*
temp_pan_servo **+=** ((**int**)Tracking_Config_Data**.**Pan_Rotation_Sign ***** servo_step);

*// check the pan servo PWM value for under/overflow*
**if**(temp_pan_servo **<** (**int**)Tracking_Config_Data**.**Pan_Min_PWM)
{
temp_pan_servo **=** (**int**)Tracking_Config_Data**.**Pan_Min_PWM;
}
**else****if**(temp_pan_servo **>** (**int**)Tracking_Config_Data**.**Pan_Max_PWM)
{
temp_pan_servo **=** (**int**)Tracking_Config_Data**.**Pan_Max_PWM;
}

pan_servo_position **=** (**unsigned ****char**)temp_pan_servo;

*// update pan servo PWM value*
**Set_Pan_Servo_Position**(pan_servo_position);

``````

-Kevin