# Implement a software PID for the first time in real time software, I can find P what about I and D?

Here we have the basic formula of a Proportional Integral Derivative controller. This is the formula from the Wikipedia page on the subject

I want to implement this type of controller in my system. Currently the system (function in the software) is fed a psi value and told to set an analog output to a value so that this pressure is achieved. The function, lets call it SetPressure(int psi), has access to a table of psi vs analog signal output, it does quick binary search and finds the closest match and sets the analog output to that match.

This is not good enough for when the machinery/valves "wears in".

So now I have access to a pressure transducer to tell me the actual pressure in the line I am trying to control. It gives me an analog input to my function. I would like to figure out, given these values of commanded and actual values, how to create a software PID.

So, the first value is easy; P. This is found by determining the error in the value error = DesiredValue - ActualValue and multiplying it by some proportional gain Kp. So P = Kp*error this is easy enough to understand. After some tuning I should find a suitable value of Kp such that I can control the pressure a little better.

But what about if I would like to find the I and D?

The software this PID runs in is real time. It gets called every few milliseconds and reads the inputs and determines the outputs based on its state.

I guess for a start, where do I go from here to get I and D. I understand that there are gains for each of these terms but I am not sure about how I calculate the entire term.

For instance, Do I need to save each calculated error for each time t so that I might find the integral? This seems it would be a waste of memory, saving each error for each moment in time would accumulate to a huge list in a matter of seconds.

Any help is appreciated. Please ask for clarification if needed, and note this is my first time working with something like this.

.

Code Sample so far:

(anaOutput[PRESS_OUT_DAC] is already determined above in the code from the analog vs psi table)

float KpPressure = 1; // These gains are to be determined
float KiPressure = 1;
float KdPressure = 1;
float MVout = anaOutput[PRESS_OUT_DAC]; // Init to output

if(anaInput[PRESS_IN_DAC] != anaOutput[PRESS_OUT_DAC])
{
// error = SetPoint - ProcessValue
float error = (float)anaOutput[PRESS_OUT_DAC] - (float)anaInput[PRESS_IN_DAC];

// Pout = Kp * error
float Pout = KpPRessure * error;
// Iout = Ki * Int(0,t)[error(t)]
float Iout = KiPressure * 1;              //// What should 1 be?
// Dout = Kd * (d/dt)[error(t)]
float Dout = KdPressure * 1;              //// What should 1 be?

// Manipulated Output = Combination of PID
MVout = P + I + D;
}
if(MVout > MAX_SIGNAL)
MVout = MAX_SIGNAL;

anaOutput[PRESS_OUT_DAC] = (UWORD)MVout + ANALOG_ZERO;


It sounds like you're on the right track for the proportional part of the controller; you seem to understand what's going on pretty well. The other two portions are easier than you think. The main difference between what you might read in basic control theory and how you're implementing it is that your computer is a discrete-time system. Since you don't have infinitesimal time steps, you'll need to approximate the other two branches in the controller.

• Integral: You can approximate integration via discrete summation: $$I_{out} = K_i\int_{0}^{t}e(\tau)d\tau \approx K_i \sum_{n=0}^{N} e[n]\Delta t$$ where $\Delta t$ is the time step between updates of the controller output, and $e[n]$ is the calculated error at the $n$-th time step. This does not require a lot of memory; instead of storing each error sample, you can store their cumulative sum. This is analogous to how an analog integrator would operate.

• Derivative: You can approximate differentiation in multiple ways. The simplest is a first-order difference: $$I_{out} = K_d\frac{d}{dt}e(t) \approx K_d \frac{e[n] - e[n-1]}{\Delta t}$$ If your time step is large, then this may not be a great approximation of the derivative. In fact, it is difficult in any case to implement a good, robust differentiator in practice. You could improve the approximation by decreasing your time step (effectively increasing the sample rate of your discrete-time controller) or by using a more sophisticated digital differentiator design.

• AHHH, I see now. Sorry, couldn't wrap my head around that for some reason. I think I know just what to do now. And for clarification, what is the terminology for realtime software (same code called every ~3ms) versus I guess normal software (can go fast as the CPU lets it, or stops, has threads, can just to different code segments, etc) – KDecker May 15 '13 at 17:16
• @BumSkeeter, It's actually called 'real-time' software. To get this, you need hardware capable of real-time scheduling (PCs can do this), but you also need a scheduler that supports it (Windows won't do this out of the box, but there are real-time extensions that do; there are also real-time Linux kernels.) Another common approach is to use a PLC, microcontroller or other proprietary controller that supports real-time task scheduling. – Dan Bryant May 15 '13 at 18:02
• Ok yeah, that's what I figured. So it might also be called a "discrete time" controller? How is this different from a PC that also calculates in discrete intervals (ex 4.0Ghz). Is that realtime software has to do something in this interval and a PC can do something in this interval? – KDecker May 16 '13 at 11:46
• @BumSkeeter: As a general rule, if you have a control system that isn't implemented with analog hardware (e.g. resistors, capacitors, inductors, etc.), then you probably have a discrete-time system. Whether the control is implemented on a PC, a microcontroller, or something else doesn't really make a difference. If the inputs and outputs are sampled at discrete intervals, that's enough to qualify as a discrete-time system. – Jason R May 16 '13 at 12:20

Once you get the basics covered (Jason has covered this pretty well), you will also want to research Integral Windup and filtering of the error signal and its estimated derivative. The former is very important if your control point changes discontinuously (i.e. you don't have a separate controller 'ramping' the control signal for your PID.) The latter is important in the presence of real-world sensor noise, in order to avoid instability. Many sensors can introduce large noise 'spikes' that can greatly perturb a control system without filtering.

Many physical systems also exhibit resonance effects that can lead to run-away oscillations (the Tacoma Narrows Bridge is the classic example of how bad this can get.) A feedback system can exacerbate these effects, so an important part of 'tuning' your PID is characterizing its stability at the various feedback and control signal frequencies you will encounter. This is another area where filtering of the feedback signal is helpful; in particular, notch filters at 60Hz are common for systems using AC power in the US. In practice, the resonances are application-specific, so most controller manufacturers supply a general toolkit of filters that can used and then leave it up to the process engineers to configure them appropriately for their application.

Next steps after you've covered stability:

1. 'Ramping' the control signal by applying constraints on its rate of change. For motion systems, this typically involves limiting velocity and acceleration. This makes the job of the PID easier, as the control signal is moving more 'smoothly'. It also generally results in a smoother output signal for your actuator, which can be important, since most actuators have practical limits on their ability to respond to rapid changes in their control signal.

2. Adjusting the feedback/control signals outside the PID to get the best response from your particular system. For instance, there may be known hysteresis effects in the actuator or sensor that you want to correct for.

All that said, there's a reason why most integrators buy off-the-shelf controllers for the devices they're integrating. Control systems are complicated and there are a lot of proprietary tricks that vendors have developed over the years to get the best performance out of their particular components. It's still valuable to understand these systems to get the best results from them, but there is more going on here than you may realize.