# PID Control programming Questions

• posted

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

• posted

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 ```
• posted

ent

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

PID stands for Proportional, Integral, and Differential. Start with Propor 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 ystem you start with just the proportional signal, Then add in some differe 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

• posted

(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.

To answer your question (illustration, only): 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)

No.

Yes. "Gains"

'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!]
• posted

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 ```
• posted

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 worth fretting about.

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

• posted

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.

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.

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.

The interactive form with a derivative block is more different.

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 ```
• posted

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.

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.

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 ```
• posted

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 ```
• posted

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.

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 ```
• posted

Sure, to expand on Tim's example, consider a temperature control loop. Normally the output will be at its limit for a considerable time during start-up. A badly implemented controller can overshoot like crazy, but the solution isn't to put a megawatt heater in there for something that requires a kW steady-state, it's to fix the controller-- meaning it's no longer a textbook PID, but has some barnacles such as Tim mentions below.

Best regards, Spehro Pefhany

```--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com ```
• posted

Yes, that is indeed a good article. One point in it noted, and Tim is quite correct, if you do use derivative it's good to derive it from the measurement input rather than the error signal, so that you don't get large output spikes when the setpoint is changed (often in steps). In fact, it's sometimes good to have the *proportional* treated in this way as well, so that when a target change is made, the controller ramps to the new state at the integral time rate. Very applicable in process plants to keep operators happy, not so good if you're working with missile control.

Expanding a bit on derivative, industrial system algos generally used what's referred to as 'filtered derivative'. It's derived by applying a filter to the input (measurement or error as above), then subtracting the filter output from the filter input. The result is then multiplied by an arbitrary constant (typ 4 - 6) and this is the derivative term. It has the advantage over classical forms that if there's an 'infinitely fast' change in the input, the change in the output isn't 'infinitely' great.

• posted

Yes, I would have mentioned having the proportional run off of just the process output -- but I had a 5000 word limit, which I ran over and had to edit down to. I think that article had over 4900 words in it.

Also known as bandlimited derivative. I don't know if I mention it in the article -- I do in a related talk, but the talk has changed so many times over the years I couldn't say what's been said when.

Using a "naked" derivative term in a controller that's being sampled significantly slower than the desired bandwidth can also cause high frequency oscillations. This is highly dependent on the plant, of course, but bandlimiting the derivative can allow you to use higher derivative gains and keep the system stable.

Using a "naked" derivative term also causes problems if you have measurement noise -- noise is, by nature, broad-band, and derivative action, by nature, amplifies the high frequency. Put measurement noise and derivative together and you can get a control output that has so much noise that the desired control output is lost.

All in all, derivative control is something best approached with caution, and the right tools.

```--
Tim Wescott
Control system and signal processing consulting ```

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.