# PID Control programming Questions

Started by September 27, 2013
```I have a program being ran every 20 milliseconds and I'm trying to implement
PID control.  So P = SetPoint - Actual, I = I + P ? , and D = P - Old_P????
On D, should  "Old_P" be from the previous round or should it be a value
from a certain length of time ago?  Also, is "I" just summed up or is it the
sum of I over a certain length of time?

I'm trying to find out if I need to set up arrays to accumulate 50 samples
per second of time for setting I and D values.  Also, are Kp, Ki, and Kd
just multipliers?  I can calculate a value for I and D each scan to scan but
it seems like it could be more stable if I use a time period that fights the
process's oscillation period.

RogerN

```
```On 9/27/2013 8:19 PM, RogerN wrote:
> I have a program being ran every 20 milliseconds and I'm trying to implement
> PID control.  So P = SetPoint - Actual, I = I + P ? , and D = P - Old_P????
> On D, should  "Old_P" be from the previous round or should it be a value
> from a certain length of time ago?  Also, is "I" just summed up or is it the
> sum of I over a certain length of time?
>
> I'm trying to find out if I need to set up arrays to accumulate 50 samples
> per second of time for setting I and D values.  Also, are Kp, Ki, and Kd
> just multipliers?  I can calculate a value for I and D each scan to scan but
> it seems like it could be more stable if I use a time period that fights the
> process's oscillation period.
>
> RogerN

If you want the control system to be approximately linear and time
invariant, you need to keep the sampling period consistent.

The real control system guys will chime in, hopefully, but one thing to
watch is that if the time step gets too coarse with respect to the
system bandwidth, your loop's performance will diverge more and more
from the continuous-time case.

Cheers

Phil Hobbs

--
Dr Philip C D Hobbs
Principal Consultant
ElectroOptical Innovations LLC
Optics, Electro-optics, Photonics, Analog Electronics

Briarcliff Manor NY 10510 USA
+1 845 480 2058

hobbs at electrooptical dot net
http://electrooptical.net
```
```On Friday, September 27, 2013 8:19:53 PM UTC-4, RogerN wrote:
> I have a program being ran every 20 milliseconds and I'm trying to implem=
ent=20
>=20
> PID control. =20
> RogerN

I am not a control person, but I am pretty sure you do not need 50 samples.

tional.  You have the value  desired and the actual value.  The difference =
between the two is the error signal.  So the proportional part is just the =
error signal times some amount.  Next is the differential.  This is just th=
e first derivative.  That is to say is the error signal decreasing or incre=
asing.  If the error signal is decreasing, you reduce the error signal a bi=
t depending on how fast the error signal is decreasing.  If the error signa=
l is increasing, you increase the error signal.  this helps the system to s=
ettle down and not overshoot.  Last is the Integral.  This is just a runnin=
g sum of the error signal.  So if the system is always a bit low, you add i=
n some signal to raise it up.It gets rid of constant errors.  In tuning a s=
ntial to improve system response and reduce overshooting.  And finally if t=
he system has some constant error, you add in some integral.

As I see it you only need one sample for the Proportional part.  Two sample=
s for the differential part , and one sample plus a running sum for the int=
egral part.

Mind you I have never implemented a digital PID system, so if anyone else c=
hims in, they are probably right and I am out in left field.

Dan

```
```Hi Roger,

On 9/27/2013 5:19 PM, RogerN wrote:
> I have a program being ran every 20 milliseconds and I'm trying to implement
> PID control.  So P = SetPoint - Actual, I = I + P ? , and D = P - Old_P????
> On D, should  "Old_P" be from the previous round or should it be a value
> from a certain length of time ago?  Also, is "I" just summed up or is it the
> sum of I over a certain length of time?

(sigh)  This is one of those things where (it appears) you really
should do a bit more homework.  There are lots of subtleties in
implementing control systems -- even using "classic" algorithms.

error = set_point - observed_value
proportional_term = Kp * error
integral_term = integral_term + Ki * error
derivative_term = Kd * (observed_value - old_value)
output = proportional_term + integral_term + derivative_term
old_value = observed_value
lather, rinse, repeat

There are *lots* of equivalent ways of rewriting this.  But, they
have subtle differences in the implementation.

For example, you could invert the sign of error.  Or, you could
implement the integrator as:
accumulator += error
integral_term = Ki * accumulator

Many controllers put limits on the various terms.  Or, introduce
a deadband (i.e., so small "error" values are treated as '0').

What you have to look at is how changes to your control parameters
affect the instantaneous output of the controller.

Note that changing the set point *looks* like a change in the error
term (as far as the math is concerned).

Similarly, changing a gain has an instantaneous effect on the
output.  Consider how changing Ki affects the two different forms
of integral_term implementations, above!

Once you add an integral term, you open the door for oscillations.

Not surprisingly, there are lots of mechanisms that try to control
this.  E.g., anti-windup prevents the "accumulator" from growing
*so* big that it dominates the control (and leads to oscillation).
Bumpless-transfer tries to "zero" the controller when first engaged
(setpoint changes, etc.)  Some algorithms will clear the "accumulator"
whenever the error changes sign.

At all times, you want to be sure you aren't asking your controller
to do more than is possible (i.e., if the output is "at its limits",
AT ANY INSTANT then the loop is probably in trouble).

You also want to be sure you are sampling the system at a much higher
rate than it's inherent bandwidth.  And, that there is little jitter
(variation) in your sample to sample time intervals.  Also, that you
are measuring the process with sufficient resolution that you can
actually discern the difference between values (if you have poor
resolution, the controller can oscillate between two "corrections"
that correspond to X and X+epsilon)

> I'm trying to find out if I need to set up arrays to accumulate 50 samples
> per second of time for setting I and D values.

No.

> Also, are Kp, Ki, and Kd just multipliers?

Yes.  "Gains"

> I can calculate a value for I and D each scan to scan but
> it seems like it could be more stable if I use a time period that fights the
> process's oscillation period.

'I' and 'D' vary as functions of the error (and accumulated error).

[(sigh) looking back over this, its just too many random notes,
poorly organized.  Find a good introductory reference and spend an
hour looking at what each term *tries* to do so you can see how they
can work in your favor -- as well as against you!]
```
```On Fri, 27 Sep 2013 19:19:53 -0500, the renowned "RogerN"
<regor@midwest.net> wrote:

>
>I have a program being ran every 20 milliseconds and I'm trying to implement
>PID control.  So P = SetPoint - Actual, I = I + P ? , and D = P - Old_P????
>On D, should  "Old_P" be from the previous round or should it be a value
>from a certain length of time ago?  Also, is "I" just summed up or is it the
>sum of I over a certain length of time?
>
>I'm trying to find out if I need to set up arrays to accumulate 50 samples
>per second of time for setting I and D values.  Also, are Kp, Ki, and Kd
>just multipliers?  I can calculate a value for I and D each scan to scan but
>it seems like it could be more stable if I use a time period that fights the
>process's oscillation period.
>
>RogerN

There are many ways to implement PID. Looks like you're trying to
implement the simplest version of the "position" type.

1)	You should scale the time constants by the sample time Ts so
that they can be specified in seconds
eg.  Ki = Ts/Ti, Kd = Td/Ts for Ti integral time, Td
derivative time.

2)	It's common to filter the D term by something like 1/10
the D time.. you can use a simple IIR filter. Otherwise it
tends to be useless or harmful because of noise. You can leave
it out and see if it's actually required.

3)	Whether you differentiate the error or the PV depends on the
requirements, I've had to do both, depending on whether
(and how!) the setpoint changes

A simple discrete-time PID controller is something like..

SP = setpoint
PV = process variable

error = SP - PV

Output = Kp * (error + Ki * sum_errors - Kd * (PV - last_PV)) + bias
^^^^^^^^^^^^
(oversimplified)

The sum_errors is a sum forever- it should (if the controller is tuned
properly, the system is cooperative, disturbances are minimal, and
sufficient control authority is available) eventually settle down to a
number such that it drives the controller output to the required
steady-state value without error or derivative input contributions.

When output hits the limits, at least stop summing the errors (digging
the hole) because otherwise you'll have horrible "reset windup"
over/undershoot and even oscillation.

To try to answer your questions.. the integral is the sum of errors
over time. There's no reason to filter it. Derivative is the problem
child and you may wish to implement a filter. If your sample time is
maybe 10x the process time constant, then you may not need to filter
it, but usually it's much faster, and you'll want to add a filter (or
not use the derivative term).

A simple IIR low pass filter (first order lag) with time constant Tc
seconds is

m += Kf * (x - last_m)

where Kf = Ts/(Ts + Tc)

For example, if Ts = 0.02 and you want a 30 second time constant,
Kf = 0.02/30.02

Obviously you'll need to initialize the sums in the filter and the
integrator to something reasonable (like maybe zero) to begin with.
An IIR filter intitialized to a random floating-point number might
never get to anything sensible, and same with the integral term.

BTW, in all cases we require that Ts is constant. It could actually be
changed dynamically, as could the tuning, but that requires special
considerations to deal with what happened in the past.

Often you need to do more sophisticated things with the integral term,
but that's beyond the scope of this discussion.

Best regards,
Spehro Pefhany
--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
```
```"RogerN" <regor@midwest.net> wrote in message
>
> I have a program being ran every 20 milliseconds and I'm trying to
> implement PID control.  So P = SetPoint - Actual, I = I + P ? , and D =
> P - Old_P???? On D, should  "Old_P" be from the previous round or should
> it be a value from a certain length of time ago?  Also, is "I" just summed
> up or is it the sum of I over a certain length of time?
>
> I'm trying to find out if I need to set up arrays to accumulate 50 samples
> per second of time for setting I and D values.  Also, are Kp, Ki, and Kd
> just multipliers?  I can calculate a value for I and D each scan to scan
> but it seems like it could be more stable if I use a time period that
> fights the process's oscillation period.
>
> RogerN
>

Implementing PID in an incremental form is useful, it makes switching on and
off without bumps easier. The basic idea is this:

Error = target value - measured value

Delta_output = (Pterm + Iterm + Dterm) * Gain

Pterm = Error - PreviousError

Iterm =  Error * SamplePeriod / Tintegral

Dterm = post again if you want more info. Derivative has many variants.
Depending on what you want to control, you may not need it, it's generally a
pain and best avoided.

This form is called 'interactive' because the gain applies to the composite
control action, rather than just eg. the proportional. IMHO, this isn't

It's easiest if you normalise your input and output to standard ranges,
maybe 0 - 100% or a 32 bit range.

Digital implementations need to watch numeric precision. If the sampling
rate is high, quantisation in the calcs can cause dead zones in the integral
response, because if the error is below the calculation MSB, integral action
ceases. HTH

```
```On Sat, 28 Sep 2013 21:33:25 +0800, the renowned "Bruce Varley"
<bv@NoSpam.com> wrote:

>
>"RogerN" <regor@midwest.net> wrote in message
>>
>> I have a program being ran every 20 milliseconds and I'm trying to
>> implement PID control.  So P = SetPoint - Actual, I = I + P ? , and D =
>> P - Old_P???? On D, should  "Old_P" be from the previous round or should
>> it be a value from a certain length of time ago?  Also, is "I" just summed
>> up or is it the sum of I over a certain length of time?
>>
>> I'm trying to find out if I need to set up arrays to accumulate 50 samples
>> per second of time for setting I and D values.  Also, are Kp, Ki, and Kd
>> just multipliers?  I can calculate a value for I and D each scan to scan
>> but it seems like it could be more stable if I use a time period that
>> fights the process's oscillation period.
>>
>> RogerN
>>
>
>Implementing PID in an incremental form is useful, it makes switching on and
>off without bumps easier. The basic idea is this:

Note that this method effectively integrates at the output. It's also
called the "velocity" algorithm (you could think of an output being
the angular velocity of a control valve shaft)- the motor and valve
acts as a mechanical integrator that stops when it hits a limit. As
Bruce implies, it's not quite as easy, but not impossible to do
bumpless auto-manual transfer etc. with the position algorithm, you
just have to preload the integrator with a back-calculated value to
avoid a bump. Challenging back in the analog/pneumatic days.

>Error = target value - measured value
>
>Delta_output = (Pterm + Iterm + Dterm) * Gain
>
>Pterm = Error - PreviousError
>
>Iterm =  Error * SamplePeriod / Tintegral

If the integration of the output is done digitally, it has to be
limited at the physical limits of the output or windup will occur.

>Dterm = post again if you want more info. Derivative has many variants.
>Depending on what you want to control, you may not need it, it's generally a
>pain and best avoided.

For this type of PID algorithm you have to estimate the _second_
derivative of the error or PV wrt time for the derivative function. It
can be done- but noise is a practical problem.

>This form is called 'interactive' because the gain applies to the composite
>control action, rather than just eg. the proportional. IMHO, this isn't

The interactive form with a derivative block is more different.

>It's easiest if you normalise your input and output to standard ranges,
>maybe 0 - 100% or a 32 bit range.
>
>Digital implementations need to watch numeric precision. If the sampling
>rate is high, quantisation in the calcs can cause dead zones in the integral
>response, because if the error is below the calculation MSB, integral action
>ceases. HTH

ITYM "LSB". This is only a problem with badly scaled or poorly
designed fixed-point calculations (and as Bruce says, very high
sampling rate relative to the time constants of the system).
The longest possible integration time constant divided into the sample
time, multiplied by the a number less than the resolution/noise of the
PV should not come out to zero in the calculation preceding
integration (nor can it not change the integral number when added to
it). If you're sampling 1000 times a second and using a 3600 second
time constant, that's 2.78E-7. Not a problem with floating point and
enough mantissa bits, but with fixed point it can't be allowed to fall
off the end or you can get persistent errors proportional to the
integration time setting (for a fixed sample time). This is one reason
I write my own fixed point math library routines for fractional math
with sensible radix point positions (and enough bits).

Best regards,
Spehro Pefhany
--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
```
```On Sat, 28 Sep 2013 16:24:06 -0400, Spehro Pefhany wrote:

> On Sat, 28 Sep 2013 21:33:25 +0800, the renowned "Bruce Varley"
> <bv@NoSpam.com> wrote:
>
>
>>"RogerN" <regor@midwest.net> wrote in message
>>>
>>> I have a program being ran every 20 milliseconds and I'm trying to
>>> implement PID control.  So P = SetPoint - Actual, I = I + P ? , and D
>>> =
>>> P - Old_P???? On D, should  "Old_P" be from the previous round or
>>> should it be a value from a certain length of time ago?  Also, is "I"
>>> just summed up or is it the sum of I over a certain length of time?
>>>
>>> I'm trying to find out if I need to set up arrays to accumulate 50
>>> samples per second of time for setting I and D values.  Also, are Kp,
>>> Ki, and Kd just multipliers?  I can calculate a value for I and D each
>>> scan to scan but it seems like it could be more stable if I use a time
>>> period that fights the process's oscillation period.
>>>
>>> RogerN
>>>
>>>
>>Implementing PID in an incremental form is useful, it makes switching on
>>and off without bumps easier. The basic idea is this:
>
> Note that this method effectively integrates at the output. It's also
> called the "velocity" algorithm (you could think of an output being the
> angular velocity of a control valve shaft)- the motor and valve acts as
> a mechanical integrator that stops when it hits a limit. As Bruce
> implies, it's not quite as easy, but not impossible to do bumpless
> auto-manual transfer etc. with the position algorithm, you just have to
> preload the integrator with a back-calculated value to avoid a bump.
> Challenging back in the analog/pneumatic days.
>
>>Error = target value - measured value
>>
>>Delta_output = (Pterm + Iterm + Dterm) * Gain
>>
>>Pterm = Error - PreviousError
>>
>>Iterm =  Error * SamplePeriod / Tintegral
>
> If the integration of the output is done digitally, it has to be limited
> at the physical limits of the output or windup will occur.
>
>>Dterm = post again if you want more info. Derivative has many variants.
>>Depending on what you want to control, you may not need it, it's
>>generally a pain and best avoided.
>
> For this type of PID algorithm you have to estimate the _second_
> derivative of the error or PV wrt time for the derivative function. It
> can be done- but noise is a practical problem.
>
>>This form is called 'interactive' because the gain applies to the
>>composite control action, rather than just eg. the proportional. IMHO,
>
> The interactive form with a derivative block is more different.
>
>>It's easiest if you normalise your input and output to standard ranges,
>>maybe 0 - 100% or a 32 bit range.
>>
>>Digital implementations need to watch numeric precision. If the sampling
>>rate is high, quantisation in the calcs can cause dead zones in the
>>integral response, because if the error is below the calculation MSB,
>>integral action ceases. HTH
>
> ITYM "LSB". This is only a problem with badly scaled or poorly designed
> fixed-point calculations (and as Bruce says, very high sampling rate
> relative to the time constants of the system).

This can also happen with poorly designed floating point implementations,
particularly when the sampling rate is high with respect to the loop
closure bandwidth, and you are using single-precision floating point.

> The longest possible integration time constant divided into the sample
> time, multiplied by the a number less than the resolution/noise of the
> PV should not come out to zero in the calculation preceding integration
> (nor can it not change the integral number when added to it).

That's a very effective way of putting things, and it applies to floating
point as well as fixed point math.  The big difference between fixed and
floating point is that with fixed point if it works at one integrator
value it works at all, while with floating point the input required to
affect the integrator grows as the integrator absolute value grows.

> If you're
> sampling 1000 times a second and using a 3600 second time constant,
> that's 2.78E-7. Not a problem with floating point and enough mantissa
> bits, but with fixed point it can't be allowed to fall off the end or
> you can get persistent errors proportional to the integration time
> setting (for a fixed sample time). This is one reason I write my own
> fixed point math library routines for fractional math with sensible
> radix point positions (and enough bits).

Again, it can be a problem with floating point (as Spehro alludes to in
his comment about mantissa bits).  For most real systems it's never going
to be a problem if you use double-precision floating point, but with
single-precision floating point it crops up often as an issue.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
```
```On Fri, 27 Sep 2013 19:40:07 -0700, Don Y wrote:

> Hi Roger,
>
> On 9/27/2013 5:19 PM, RogerN wrote:
>> I have a program being ran every 20 milliseconds and I'm trying to
>> implement PID control.  So P = SetPoint - Actual, I = I + P ? , and D =
>> P - Old_P???? On D, should  "Old_P" be from the previous round or
>> should it be a value from a certain length of time ago?  Also, is "I"
>> just summed up or is it the sum of I over a certain length of time?
>
> (sigh)  This is one of those things where (it appears) you really should
> do a bit more homework.  There are lots of subtleties in implementing
> control systems -- even using "classic" algorithms.
>
>     error = set_point - observed_value proportional_term = Kp * error
>     integral_term = integral_term + Ki * error derivative_term = Kd *
>     (observed_value - old_value)
>     output = proportional_term + integral_term + derivative_term
>     old_value = observed_value
> lather, rinse, repeat
>
> There are *lots* of equivalent ways of rewriting this.  But, they have
> subtle differences in the implementation.
>
> For example, you could invert the sign of error.  Or, you could
> implement the integrator as:
>     accumulator += error integral_term = Ki * accumulator
>
> Many controllers put limits on the various terms.  Or, introduce a
> deadband (i.e., so small "error" values are treated as '0').
>
> What you have to look at is how changes to your control parameters
> affect the instantaneous output of the controller.
>
> Note that changing the set point *looks* like a change in the error term
> (as far as the math is concerned).
>
> Similarly, changing a gain has an instantaneous effect on the output.
> Consider how changing Ki affects the two different forms of
> integral_term implementations, above!
>
> Once you add an integral term, you open the door for oscillations.
>
> Not surprisingly, there are lots of mechanisms that try to control this.
>  E.g., anti-windup prevents the "accumulator" from growing *so* big that
> it dominates the control (and leads to oscillation). Bumpless-transfer
> tries to "zero" the controller when first engaged (setpoint changes,
> etc.)  Some algorithms will clear the "accumulator"
> whenever the error changes sign.
>
> At all times, you want to be sure you aren't asking your controller to
> do more than is possible (i.e., if the output is "at its limits", AT ANY
> INSTANT then the loop is probably in trouble).

I have not found this to be the case in practice.  Particularly with
motion control loops going from point A to point B, if you design your
anti-windup logic correctly you can be at the rails at various spots in
the trajectory and be fine.

Even with fairly primitive anti-windup, you can often have the output at
the rail for a small part of the trajectory without undue problems.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
```
```On Fri, 27 Sep 2013 19:19:53 -0500, RogerN wrote:

> I have a program being ran every 20 milliseconds and I'm trying to
> implement PID control.  So P = SetPoint - Actual, I = I + P ? , and D =
> P - Old_P???? On D, should  "Old_P" be from the previous round or should
> it be a value from a certain length of time ago?  Also, is "I" just
> summed up or is it the sum of I over a certain length of time?
>
> I'm trying to find out if I need to set up arrays to accumulate 50
> samples per second of time for setting I and D values.  Also, are Kp,
> Ki, and Kd just multipliers?  I can calculate a value for I and D each
> scan to scan but it seems like it could be more stable if I use a time
> period that fights the process's oscillation period.
>
> RogerN

You've gotten lots of good answers.  Doing PID control "right" takes a
lot of knowledge, but doing it "kinda right" is often more than enough
and doesn't take a lot at all.

Unfortunately, if you don't have much control smarts you don't always
have the tools to know if "kinda right" is going to be good enough
without giving it a whirl.

http://www.embedded.com/design/prototyping-and-development/4211211/PID-
without-a-PhD

I'm going to have to put this up on my website: it seems like they're
changing the link on a monthly basis these days.

It kinda-sorta contradicts things that Bruce and Spehro said.  That's
because I'm 100% right and they're a couple of -- uh wait.  That's
because there's a lot of different ways to skin this particular cat.  I
hope my article helps.

--
Tim Wescott
Control system and signal processing consulting
www.wescottdesign.com
```