Correct implementation of the difference scheme of the PID controller

  • Tutorial
The PID controller is the simplest controller having effective hardware analog implementations, and therefore it is used most widely. For its work, it requires setting 3 coefficients for a specific object, allowing you to choose the regulatory process according to the requirements. With a simple physical meaning and simple mathematical notation, it is widely and often used in temperature controllers, gas flow controllers, and other systems where it is required to maintain a certain parameter at a given level, with possible transitions between different given levels. Of course, there are more complex regulators that allow more accurately and quickly and with less overshoots to reach the specified parameters, as well as taking into account the non-linearity or hysteresis of the adjustable object,

Despite the simplicity of both the physical meaning and the mathematical notation:

in the software implementation of the PID controller very often mistakes are made that are found even in trusted automation devices.

Moreover, it is extremely easy to check the quality of PID controller implementation.

Consider the simplest example: a thermostat. To test its quality, a fast, low-inertial, low-power object is best suited. Classics of the genre: an ordinary 100W bulb with a thin thermocouple (HA) bolted to it. And the first thing to check the PID controller is the degradation of the PID to just a P-controller. That is, we set the integral and differential coefficients to zero, and put the proportional to the maximum.

We turn on the regulator, check: the current temperature is 22 degrees, the setting is 16 degrees. The light is off. We start to increase the setpoint: 16.1, 16.3, 16.7, 18 ... 19 ... the light comes on. How?! Where from ?! We stop - it turned off. So, we met with the first classic error in the implementation of the PID controller.

A small mathematical digression: remember once again the integral notation indicated above. We implement it programmatically, which means it is discrete. That is, with enviable regularity, we measure the input quantity, compare it with the setpoint, calculate the effect, issue, repeat. So, it is necessary to switch from the integral form to the finite-difference scheme. During the transition, the “forehead” transition is usually used:

whereE(n) = X(n) - X0(n)- that is, the value of the mismatch between the current and the set value of the adjustable parameter.

Using a direct formula requires firstly to read and store the mismatch integral over a large period, secondly it requires working with a floating point of high accuracy (since the integral coefficient Ki is always <1), or the division operation (representing a coefficient in the form 1 / Ki) is large bit depth. All this requires computational resources, which are usually very limited in embedded ... Therefore, instead of implementing a direct scheme, they implement a recurrence formula:

using a recurrence formula reduces the amount of computation and the bit depth of intermediate values.

So, back to our regulator. So, there is an adjustable object: a light bulb. To control the power supplied to it, they use a simple approach: the power supply network (220V 50Hz) is fed through the triac to the load. At the moment the half-wave passes through zero, the triac turns off, and remains off until a signal is sent to the control electrode. Thus, the sooner after the start of the half-wave we give a control signal, the more energy from this half-wave will reach the controlled object. Correctly calculating the time for the linearity of the area of ​​the half-wave part from the time X to the end of the half-wave, we get the opportunity to output power from 0 to 100% with the accuracy with which the linearization table was calculated.

So, we can give out power from 0 to 100%. In real objects, it is often impossible to give out 100% of the power - for example, this is fraught with burnout of the heating element. Therefore, all devices have a minimum and maximum output power setting for the object.

So, after calculating U(n)by the higher formula, the result limitation is added:
if Un < Umin then Un := Umin; if Un>Umax then Un := Umax;
After which, the calculated Un is the required output power at the current moment. Ta Dam! It is this implementation that creates the error described above.

The reason is banal: at the time of transition from the discrete to the finite-difference scheme, we “bracket” the operation of calculating the integral, and at each step we add the derivative to the accumulated sumU(n-1). Having imposed a restriction on it, we practically nullify the entire calculated integral. (Well, not how much we reset, how much we bring to the range 0-100, which in this case is insignificant). Thus, we differentiate the PID controller, and the differential accelerator remains. What in reality looks like just a differential controller - the power is supplied in proportion to a change in the set point or adjustable value, and not in proportion to the difference between the set point and the controlled value.

Conclusion No. 1 : the calculation of U (n) cannot be limited. To limit the power supplied to the output device, a separate variable should be set up.

Now that we have started Urn, for limited power, reload, continue testing.
We turn on the regulator, check: the current temperature is 22 degrees, the setting is 16 degrees. The light is off.
We begin to add the setting: 16.1, 16.4, 17, 18, 20, 22, 24 (oops! Lit up! Cheers!), 28, 30, 40, 60 ... Beauty! Works!
We observe the process - it turned out about 60, hangs a little back and forth, but holds it. Everything seems to be beautiful. Exhale, check the control from the PC: set 600 degrees. And ... The light goes off. How so? Setpoint 600, current 60, but the light is off?

While we wait and slowly realize that we have clearly run into some kind of “Classic Jamb No. 2” ™ the lamp slowly flares up, reaches 100% power, and it remains the same - it can’t give out at least 600 degrees.

We return again to our difference scheme.U(n) = U(n-1) + Kp*(dE + ...). To the current calculated value of the impact, the residual difference times the proportionality coefficient is added. We had a set point of 60, a temperature of 60, that is, the residual is zero. The output power was also zero. And here at once, in a jump, the setpoint was increased to 600 degrees. the residual sharply became 540 degrees, multiplied also by the proportionality coefficient ... and flew beyond the storage capacity U (n). Do not laugh, use math with a fixed point, instead of a floating point. With a difference of 540 degrees and work through 1/16, with a proportionality coefficient of 20, we get ... 540 * 20 * 16 = 172800, and if we have 16-bit U (n), and even a significant one, then in fact, as a result of the calculation, we got A300h = −8960. Overshoes. Instead of a big plus - a tangible minus.

Conclusion number 2: Calculations should be done with correct overflow support. Overfilled? Limit the limit, do not wrap.

So, we increased the capacity of U (n), relayed it, sewn it up, and started it. The light bulb has not completely cooled down yet, there it is 80 degrees, the setting is still the same 600. The light comes on ... and goes out. It lights up and goes out. How so? The setting is 600, the bulb is 80 - and it supports quite its 80! How is that?! Obviously, bug No. 3 crawled out from us .

And again lyrical-mathematical digression. So, there is our difference scheme:U(n) = G(U(n-1), dE(n)). Once again: the new value of the impact is the sum of the past impact and a certain impact, depending on the difference of the residual at the current moment and the previous one. And what is the previous moment? And what is the previous moment of the previous one? Well, remember the school. Proof by induction. If it is possible to construct a proof for K + 1, assuming that the proof for K is true, and to prove separately what is true for K = 0, then the proof is true. So, what do we think of U (0)?

A frequently encountered solution: we reset everything, read the setpoint from the flash memory and setpoints, wait 1 polling cycle, and read X (0). Here, zero is ready, now we are working. And ... And not right. Why? Because the recursive formula is repelled by changes in the residual. And initializing with zero and loading the current values, we lost the starting conditions. Everything - instead of maintaining the absolute temperature value at a level equal to the absolute set point, the controller starts to keep the temperature equal to the start plus the difference in set point. That is, it was 80 degrees and the setpoint was 200, they turned on the device - it holds 80. Changed the setpoint to 240 - it started to hold 120.

Correct initialization of the difference scheme: zero all_. That is,
X(0) = 0, X0(0) = 0. U(0) = 0. E(0)=X(0)-X0(0)=0.
And on the very first cycle of calculations, the set point and the current value appear as if in a jump:
X(1) = 80. X0(1)=200. U(1) = U(0)+Kp*(E(1)-E(0)) = U(0)+Kp*(X(1)-X0(1)-E(0)) = 0 + 20*(200 - 80 - 0) = 2400
Now the circuit is working correctly.

Conclusion number 3 : correctly initialize the starting conditions.

Right? Well, well ... Once again ... We set the setting 20. We are waiting for cooling ... Turn off. Turn on. So, the beauty: the current 20, the setting is 20. We set the jump to 600. Went to bask. 100, 120 ... set the setting 20. Disconnected, it started to cool. We are waiting a bit (120 ... 110 ... 100 ... 90 ... 80 ...) and set the setting to 100. Went to warm up ... 105 degrees, turned off. Stop. And why does it hold 105? But now only the proportional component works for us. With the correct implementation of the physical meaning of the process, the oscillatory process cannot keep the setpoint higher than specified. Strictly below. And holds 5 degrees more than asked. This is observed Joke number 4 .

So, we recall what we had above: Conclusion No. 2: U (n) cannot be limited. And Conclusion No. 3: in case of overflow, you still have to limit it. Yes Yes. Otherwise, the "operating point" is shifted by a limited moment. What to do? Increase capacity? Well, if there is enough computing power. Is it necessary? Actually, what is bad that we have U (n) = 9999.99, and not 29999.99? In general, it’s only that we lost 20,000. But now, for work, we just need to roll in 100% of the power anyway, right? Right. This means that there is no problem with the restriction in the regiment, until we move away from the limit. Thus, in case of overflow, you must set the flag, and after reaching, for example, half the range (that is, as U (n) after 9999.9 drops below 5000.00), reinitialize the circuit. That is, discard the story, say that n = 0 and see Conclusion No. 3 above. An inquiring mind has already realized that in the case of the complete scheme, when all three components are not equal to zero, zeroing out the iterative process in the process, we also reset the accumulated integral of the integral component. However, due to the fact that we reset to zero much in advance, he will have time to accumulate during the completion of the remainder. And it’s not entirely correct to accumulate the integral on “large” stages, since the goal of the integral component is to “choose” a residual that the proportional component cannot work out separately.

Conclusion No. 4 : if for some reason U (n) was limited, the circuit should be reinitialized as soon as it seems that the circuit has returned to normal.

In the next issue : is it really necessary to implement a difference scheme? A detailed implementation of a direct discrete circuit with simple and understandable customizable coefficients, with a direct physical meaning, which without any problems calculates the control action with a frequency of 25 Hz on an ADuC847 processor (fast 8-bit controller, with an 8051 core), leaving still a lot of processor time for other processes .

(The pictures with the image of the formulas are taken from the PID-Regulator article on Wikipedia)

Also popular now: