Pid
- Namespace
- ZCore
FUNCTION_BLOCK Pid
Simple PID implementation (as seen on: https://en.wikipedia.org/wiki/PID_controller#Pseudocode) but with integrated Anti-Windup.
A proportional–integral–derivative controller (PID controller or three-term controller) is a control loop mechanism employing feedback that is widely used in industrial control systems and a variety of other applications requiring continuously modulated control. A PID controller continuously calculates an error value e(t) as the difference between a desired setpoint (SP) (set with SetSetPoint and a measured process variable (PV) (set with SetInput and applies a correction based on proportional, integral and derivative terms (denoted P, I, and D respectively) and also respecting the anti windup methodology.
PIDs come in different configurations. This implementation offers
- a complete parallel configuration (P, I and D parts are all in parallel, use SetControllerParametersParallel
- a semi-parallel configuration (P is in series with I AND D), use SetControllerParameters
What follows is a short example how the Pid can be used in practice. In the example we
control the AnalogOutput _io.FanPower in a way to keep a temperature, which is
measured by an AnalogInput _io.Temperature, at _setpoint.
Initialization of said I/Os is not covered in the example, for this, please refer to the I/O documentation.
The control parameters _kp,_ki,_kd are yet to be found, but in the comments we describe a way how to do this experimentally.
We also enable anti-windup by setting limits, which the PID's output is clamped in.
// Construction (in a VAR block)
_pid : ZCore.Pid(0); // the parameter for the cycle time is set to 0 for now
_rt : ZAux.RealTime(); // used to retrieve the cycle time of the current task in initalization
_kp : LREAL := 1E-6; // start with a small value gain, then increase manually until the system oscillates
_ki : LREAL := 0; // start without integration part, when the oscillation gain has been found, set to 0.6 * kp and optimize further
_kd : LREAL; := 0; // start without derivative part, when the oscillation gain has been found, set to 0.125 * kp and optimize further
_setpoint : LREAL := ?;
_minOutput : LREAL := ?;
_maxOutput : LREAL := ?;
----------------------------------
// Initialization (i.e. in a _step.OnEntry() condition)
_pid.SetCycleTime(_rt.CycleTimeInSeconds());
_pid.SetSetPoint(_setpoint);
_pid.SetControllerParameters(_kp, _ki, _kd);
_pid.EnableAntiWindup(TRUE, _minOutput, _maxOutput);
_pid.Reset(); // Optional to reset the integral and derivative parts
----------------------------------
// To be called cyclically (i.e. in a step outside of the OnEntry condition)
_pid.SetInput(_io.Temperature.Value);
_pid.Cyclic();
_io.FanPower.Value := _pid.Output;
Constructor
FB_init
METHOD FB_init (
[input] bInitRetains : BOOL,
[input] bInCopyCode : BOOL,
[input] cycleTime : LREAL) : BOOL
Inputs
bInitRetainsBOOLif TRUE, the retain variables are initialized (warm start / cold start)
bInCopyCodeBOOLif TRUE, the instance afterwards gets moved into the copy code (online change)
cycleTimeLREALCycle time in seconds of the PID controller loop in milliseconds (Attention: if not called every plc cycle, enter the actual cycle time of the Cyclic-method here)
Returns
- BOOL
Properties
ActualIntegral
PROPERTY ActualIntegral : LREAL
Returns the actual integral value of the integral part of the PID controller if parametrized accordingly. This can sometimes be useful to enable proper anti windup parameters by EnaleAntiWindup
Property Value
- LREAL
AntiWindupEnabled
PROPERTY AntiWindupEnabled : BOOL
Returns TRUE if the AntiWindup function was enabled before by passing on:=TRUE with EnableAntiWindup.
Property Value
- BOOL
AntiWindupType
PROPERTY AntiWindupType : PidAntiWindupType
Controls the method that is used if AntiWindup is enabled.
Note
For backwards compability the default anti-windup method is IntegralLimitation. However, in practice this method has a worse timing behavior when recovering from saturation and should no longer be used for new applications.
Property Value
MaxOutput
PROPERTY MaxOutput : LREAL
Returns the last set MaxOutput Value set with EnableAntiWindup method. To check if AntiWindup is enabled test AntiWindupEnabled property.
Property Value
- LREAL
MinOutput
PROPERTY MinOutput : LREAL
Returns the last set MinOutput Value set with EnableAntiWindup method. To check if AntiWindup is enabled test AntiWindupEnabled property.
Property Value
- LREAL
Methods
Cyclic
METHOD Cyclic ()
This method has to be cyclically called by the PLC program in order to let this Pid work properly For very slow plants (processes and actuators) it is no necessary to call this method every PLC cycle, but always make sure to parameterize the right cycle time However, it is not recomended to call this method randomly
EnableAntiWindup
METHOD EnableAntiWindup (
[input] on : BOOL,
[input] minOutput : LREAL,
[input] maxOutput : LREAL)
This method should be used to limit the PIDs output to physical relevant values. For instance, of a temperature should be controlled within some giving window, the user should supply the PID with this values. For instance, a heating device can not cool. Here a negative output should be cut off by setting minOutput to zero.
If anti windup is enabled, the integral part as well as the controllers output is limited to the windup parameters. The integral part is limited in the cyclic method and the controllers output is limited in the output method, respectively.
Inputs
onBOOLTRUE if anti windup should be generally enabled and FALSE if not
minOutputLREALmaximum value for the integral term to get summed up by the algorithm (in most cases its a negative value)
maxOutputLREALminimum value for the integral term to get summed up by the algorithm (in most cases its a positive value)
IsAntiWindupEnabled
METHOD IsAntiWindupEnabled () : BOOL
Returns TRUE if the AntiWindup function was enabled before by passing on:=TRUE with EnableAntiWindup.
Returns
- BOOL
Output
METHOD Output () : LREAL
Returns the calculated control output based on the parameters given to the proportional, integral and derivative terms of the PID controller. If antiwindup is enabled, the windup constants set with EnableAntiWindup are used to limit the controllers output;
Returns
- LREAL
Reset
METHOD FINAL Reset ()
This method resets the integral and derivative part of the PID, the method should in most cases be called after the controller parameters changed by calling SetControllerParametersParallel or SetControllerParameters.
SetAntiWindupType
METHOD SetAntiWindupType (
[input] antiWindupType : PidAntiWindupType)
Controls the method that is used if AntiWindup is enabled.
Note
For backwards compability the default anti-windup method is IntegralLimitation. However, in practice this method has a worse timing behavior when recovering from saturation and should no longer be used for new applications.
Inputs
antiWindupTypePidAntiWindupType
SetControllerParameters
METHOD PUBLIC SetControllerParameters (
[input] kp : LREAL,
[input] tn : LREAL,
[input] tv : LREAL)
This method is used to set the control parameters for the PID. The parameters that are passed with this method consider a PID in semi-parallel configuration, where P is in series with the I and D part, which are in turn parallel to each other.
This method can be called while the controller is active, but may cause unwanted side-effects. Usually a seperate call to Reset should be performed to reset the (old) integral and derivative parts.
Inputs
SetControllerParametersParallel
METHOD PUBLIC SetControllerParametersParallel (
[input] kp : LREAL,
[input] ki : LREAL,
[input] kd : LREAL)
This method is used to set the control parameters for the PID. The parameters that are passed with this method consider a PID in parallel configuration, where P, I and D are all in parallel to each other. The advantage when parametrizing this kind of PID is that all parameters are independent from each other.
- The proportional part (
kp) determines how aggressively the controller reacts to the current amount of error. - The integral part (
ki) determines how aggressively the controller reacts to the error over time. - The derivative part (
kd) determines how aggressively the controller reacts to the change in error. This parameter helps to 'slow' down if the input is approaching the set-point too fast.
A common way (trail-and-error method) to tune a PID is
- Set
ki=kd=0and increasekpuntil the system starts to oscillate - Set
ki=0.6 kpandkd=0.125 kp
This can be called while the controller is active, but may cause unwanted side-effects. Usually a seperate call to Reset should be performed to reset the (old) integral and derivative parts.
Inputs
SetCycleTime
METHOD SetCycleTime (
[input] cycleTime : LREAL)
This method overwrite the default cycle time of the PID that is the cycle time of the task. Use this method if you are not calling setInput on every cycle of the task, but only every x. cycle. cycleTime should be the elapsed time (in seconds) between calls to SetInput and Cyclic, respectively.
Inputs
SetInput
METHOD SetInput (
[input] value : LREAL)
This method should be called once every cycle to update the input value for the PID. This input parameter combined with the control parameters of the PID yield the output that should be set for this cycle.
Inputs
SetSetPoint
METHOD SetSetPoint (
[input] value : LREAL)
This method should be called to specify the set point of this PID.