PID Controller Algorithm
This guide explains the features of the Aqueduct PID Controller API. It covers the PID Update Process and shows how each userconfigurable parameter affects the controller output.
Glossary
Symbol  Meaning  Detail 

\(SP\)  Setpoint, the target Process Value  in units of \(PV\) 
\(PV\)  Process Value  
\(Error\)  Deviation between Setpoint and Input  \(Error := SP  PV \) 
\(CO\)  Control Output  
\(Δt\)  Time Difference between updates  user configurable update interval, minimum 100 ms 
\(P\)  Proportional Term  
\(I\)  Accumulated Sum of Error * Ki  
\(D\)  Derivative Term  
\(CO_{\text{min}}\)  Minimum Limit for Control Output  in units of \(CO\) 
\(CO_{\text{max}}\)  Maximum Limit for Control Output  in units of \(CO\) 
Schedule Constraints  Meaning  Detail 

\([Error_{\text{min}}, Error_{\text{max}}]\)  Error Range  restrict the schedule to apply when the error falls in the provided range 
\([PV_{\text{min}}, PV_{\text{max}}]\)  Process Range  restrict the schedule to apply when the process value falls in the provided range 
\([CO_{\text{min}}, CO_{\text{max}}]\)  Control Range  restrict the schedule to apply when the control output falls in the provided range 
Schedule Parameters  Meaning  Detail 

\(Bias\)  Bias Offset  
\(K_{p}\)  Proportional Gain  positive value direct acting, negative value reverse acting 
\(K_{i}\)  Integral Gain  positive value direct acting, negative value reverse acting 
\(K_{d}\)  Derivative Gain  positive value direct acting, negative value reverse acting 
\(P\)  Proportional Term  
\(P_{\text{limit}}\)  Limit for Proportional Term  
\(I_{\text{limit}}\)  Limit for Integral Term  
\(D_{\text{limit}}\)  Limit for Derivative Term  
\(β\)  Setpoint Weighting Factor  
\(L\)  Linearity Factor  
\(SP_{\text{range}}\)  Setpoint Range  
\(DZ\)  Dead Zone  in units of \(PV\) 
\(I_{\text{valid}}\)  Integral Valid Bounds  in units of \(PV\) 
\(\Delta CO_{\text{limit}}\)  Maximum Control Output Change  in units of \(CO\) 
PriorityBased Parameter Scheduling
The PID Control Algorithm incorporates the concept of "schedules" into the traditional PID control framework. Each PID controller features a list of schedules, where each schedule is defined by a set of constraints and parameters such as \(K_p\), \(K_i\), \(K_d\), dead zones, and limits.
At each time step, the algorithm evaluates the list of schedules starting from the highestpriority index (index 0). It selects the first schedule whose constraints are met based on realtime data and userdefined conditions. Once a schedule is selected, the PID controller then calculates and updates the Control Output (CO) using the parameters defined in that schedule. This hierarchical and dynamic approach enables the algorithm to adapt to a variety of operating conditions, making it both robust and versatile.
Understanding Controller Schedules

Priority Order: The schedules in the list are arranged based on priority, with the highestpriority schedule at the beginning of the list. The schedules cannot be reordered after the controller is created.

Schedule Constraints: Each schedule is associated with constraints for the process value, error, and control output. These constraints define the range of conditions under which the controller schedule is applicable. If a constraint is left empty, it is considered always applicable.

Controller Selection: When the control system receives new process, error, and control values, it starts by checking the controller schedule with the highest priority. It verifies if the current values fall within the defined bounds for that schedule using the
is_applicable
method. 
Applicability Check: If the current values satisfy the bounds of the constraints, the control system selects that schedule for execution.

Fallback and Next Priority: If the highestpriority schedule is not applicable, the control system moves to the next schedule in the list and repeats the applicability check. This process continues until an applicable schedule is found or all schedules have been checked.
Benefits of Controller Scheduling

Adaptability: Controller scheduling allows the control system to adapt to varying conditions without manual intervention. Different schedules can be tailored to different operating scenarios.

Optimization: By choosing the appropriate schedule, the control system can optimize its performance for specific conditions, leading to improved stability and efficiency.

Structured Approach: The prioritybased organization of schedules provides a structured way to handle different scenarios, ensuring that the most suitable schedule is chosen.
Controller Selection
At each update tick, the following algorithm is used to determine the applicable schdule:
flowchart TD A((Start)) > B[Set i = 0] B > C{Is i less\nthan the number\nof schedules?} C >Yes D{Check\nError\nConstraint} D >Error constraint provided\nand out of bounds bounds H{Continue} D >Otherwise F{Check\nProcess\nConstraint} G > C F >Process constraint provided\nand out of bounds H{Continue} F >OtherwiseI{Check\nControl\nConstraint} H > G[Increase i by 1] I > K((Select\nSchedule i)) I >Control constraint provided\nand out of bounds H{Continue} C >No J((No Applicable\nSchedule)) click D "#checkerrorconstraint" _blank click F "#checkprocessconstraint" _blank click I "#checkcontrolconstraint" _blank
Check Error Constraint
If an error constraint is defined for the schedule and the error value falls within the specified range, the schedule is considered applicable with respect to the error constraint. If no error constraint is defined for the current schedule, it is automatically considered applicable for this constraint.
\[ \text{error_is_applicable} = \begin{cases} \text{false} & \text{if } E_{\text{constraint}} \text{ is provided and error not in bounds} \\ \text{true} & \text{otherwise} \end{cases} \]
Check Process Constraint
If a process constraint is defined within the schedule, the algorithm checks to see whether the current process variable (\(PV\)) falls within the specified bounds. If it does, the schedule is considered applicable concerning the process constraint. If no process constraint is defined for the current schedule, then it is automatically considered applicable for this constraint.
\[ \text{process_is_applicable} = \begin{cases} \text{false} & \text{if } PV_{\text{constraint}} \text{ is provided and } PV \text{ not in bounds} \\ \text{true} & \text{otherwise} \end{cases} \]
Check Control Constraint
Similarly, if a control constraint is specified within the schedule, the algorithm evaluates whether the current Control Output (\(CO\)) is within the defined limits. If it is, the schedule is deemed applicable with respect to the control constraint. If no control constraint is specified for the schedule, it is automatically considered applicable for this constraint.
\[ \text{control_is_applicable} = \begin{cases} \text{false} & \text{if } CO_{\text{constraint}} \text{ is provided and } CO \text{ not in bounds} \\ \text{true} & \text{otherwise} \end{cases} \]
Example
Consider the example schedule below:
Schedules  Error Range  Process Range  Control Range 

Schedule 0  [50, 50]  [100, 110]  
Schedule 1  [500, 600]  
Schedule 2 
Example 1:
Error  Process  Control 

30  550  105 
 Start at Schedule 0:
 Error (30) is within the range of 50 to 50, so the error constraint is in bounds.
 No Process constraint is provided for Schedule 0, so continue to Control constraint.
 Control (105) is within the range of 100 to 110, so the control constraint is in bounds.
 Schedule 0 is selected and the parameters for Schedule 0 are used to determine the control output.
Example 2:
Error  Process  Control 

75  590  105 
 Start at Schedule 0:
 Error (75) is not within the range of 50 to 50, so Schedule 0's error constraint is out of bounds.
 Move to Schedule 1:
 No Error constraint is provided for Schedule 1, so continue to Process constraint.
 Process (590) is within the range of 500 to 600, so the process constraint is in bounds.
 No Control constraint is provided for Schedule 1.
 Schedule 1 is selected and the parameters for Schedule 1 are used to determine the control output.
Example 3:
Error  Process  Control 

20  750  720 
 Start at Schedule 0:
 Error (20) is within the range of 50 to 50, so the error constraint is in bounds.
 No Process constraint is provided for Schedule 0, so continue to Control constraint.
 Control (720) is not within the range of 100 to 110, so the control constraint is out of bounds.
 Move to Schedule 1:
 No Error constraint is provided for Schedule 1, so continue to Process constraint.
 Process (750) is not within the range of 500 to 600, so Schedule 1's process constraint is out of bounds.
 Move to Schedule 2:
 No bounds are defined for Error, Process, or Control for Schedule 2, so this schedule is applicable by default.
 The parameters for Schedule 2 are used to determine the control output.
Update Process
After a schedule has been selected, the following algorithm is used to determine the control output at time \(t\) based on the schedule's parameters.
flowchart TD A((Time t)) >PV_t, SP_t, L, β, K_p, K_i, K_d, Δt_s, Bias B(Error_t = SP_t  PV_t) B >Dead Zone Check C{Error_t < DZ} C >No F[Calculate Proportional Term] C >Yes E((No Control Output)) F > G[Calculate Integral Term] G > H[Calculate Derivative Term] H > I[Calculate Unbounded Control Output] I > J[Limit Control Output Change] J > K[Limit Control Output] K > L((Control Output at t)) click B "#errorcalculation" _blank click C "#deadzonecheck" _blank click F "#calculateproportionalterm" _blank click G "#calculateintegralterm" _blank click H "#calculatederivativeterm" _blank click I "#calculateunboundedcontroloutput" _blank click J "#limitthecontroloutputchange" _blank click K "#limitthecontroloutput" _blank
Error Calculation
The control output:
\(CO_{t} := \text{control output at time } t \)
based on the process value at time \(t\):
\(PV_{t} := \text{process value at time } t \)
and the userconfigurable controller parameters.
The error at time \(t\) is:
\(Error_{t} := \text{error at time } t = SP_{t}  PV_{t} \)
Dead Zone Check
The dead zone is a range around the desired setpoint where no control action is taken. If the absolute value of the error is smaller than the absolute value of the dead zone \(DZ\), no adjustment is made to the Control Output.
\[ Error_{t} < DZ \Rightarrow \text{no action} \]
Calculate the Proportional Term
Next, the proportional term is calculated using an error term that incorporates the nonlinear scalings:
\[ \text{NonLinear Error} = \left( \beta \times SP_{t}  PV_{t} \right) \times \left( \text{L} + \left( 1  \text{L} \right) \times \frac{\left \beta \times SP_{t}  PV_{t} \right}{SP_{range}} \right) \]
When \( L = 1 \), the nonlinear error is equivalent to the linear error.
The proportional term \( P \) is calculated by multiplying the nonlinear error by the proportional gain \(K_{p}\), resulting in an unbounded proportional value \( P_{\text{unbounded}} \):
\[ P_{\text{unbounded}} = \text{NonLinear Error} \times K_p \]
If a limit \( P_{\text{limit}} \) is provided and the unbounded proportional term \( P_{\text{unbounded}} \) is less than the negative value of the limit, then the proportional term \( P \) is set to the negative limit \( P_{\text{limit}} \). Similarly, if the limit is provided and the unbounded proportional term \( P_{\text{unbounded}} \) exceeds the limit, then the proportional term \( P \) is set to the limit \( P_{\text{limit}} \). Otherwise, if no limit conditions are met, the proportional term \( P \) remains the same as the unbounded value \( P_{\text{unbounded}} \):
\[ P = \begin{cases} P_{\text{limit}} & \text{if } P_{\text{limit}} \text{ is provided and } P_{\text{unbounded}} < P_{\text{limit}} \\ P_{\text{limit}} & \text{if } P_{\text{limit}} \text{ is provided and } P_{\text{unbounded}} > P_{\text{limit}} \\ P_{\text{unbounded}} & \text{otherwise} \end{cases} \]
Calculate the Integral Term
Next, the integral is checked for validity. If no \(I_{\text{valid}}\) value is provided, the \(\text{valid_integral}\) is considered true. If \(I_{\text{valid}}\) is provided and the absolute value of the error is less than the absolute value of \(I_{\text{valid}}\), then \(\text{valid_integral}\) is also considered true. Otherwise, it is set to false.
\[ \text{valid_integral} = \begin{cases} \text{true} & \text{if } I_{\text{valid}} \text{ is not provided} \\ \text{true} & \text{if } I_{\text{valid}} \text{ is provided and } \text{error} < I_{\text{valid}} \\ \text{false} & \text{otherwise} \end{cases} \]
The \(I_{\text{unbounded}}\) value is updated based on the \(\text{valid_integral}\) determination.
\[ I_{\text{unbounded}} = \begin{cases} I + \text{error} \times K_{i} \times \Delta t_s & \text{if } \text{valid_integral} \text{ is true} \\ I & \text{otherwise} \end{cases} \]
Finally, the new \(I\) term is calculated based on the provided (\( I_{\text{limit}} \)).
\[ I = \begin{cases} I_{\text{limit}} & \text{if } I_{\text{limit}} \text{ is provided and } I_{\text{unbounded}} < I_{\text{limit}} \\ I_{\text{limit}} & \text{if } I_{\text{limit}} \text{ is provided and } I_{\text{unbounded}} > I_{\text{limit}} \\ I_{\text{unbounded}} & \text{otherwise} \end{cases} \]
Calculate the Derivative Term
The unbounded derivative term is calculated using:
\[ D_{\text{unbounded}} = \frac{PV_{t}  PV_{t1}}{\Delta t_s} \times K_d \]
The new \(D\) term is calculated based on the provided (\( D_{\text{limit}} \)).
\[ D = \begin{cases} D_{\text{limit}} & \text{if } D_{\text{limit}} \text{ is provided and } D_{\text{unbounded}} < D_{\text{limit}} \\ D_{\text{limit}} & \text{if } D_{\text{limit}} \text{ is provided and } D_{\text{unbounded}} > D_{\text{limit}} \\ D_{\text{unbounded}} & \text{otherwise} \end{cases} \]
Calculate Unbounded Control Output
The unbounded control output is calculated:
\[ CO_{t} = P + I + D + Bias \]
Limit the Control Output Change
The controller allows for limiting sudden changes in the control output \( CO \). The change in the control output between two consecutive time points is calculated:
\[ \Delta CO_{\text{unbounded}} = CO_{t}  CO_{t1} \]
If \( \Delta CO_{\text{limit}} \) is set and the calculated change is smaller than \( \Delta CO_{\text{limit}} \), the change is capped at \( \Delta CO_{\text{limit}} \). If \( \Delta CO_{\text{limit}} \) is set and the change exceeds it, the change is limited to \( \Delta CO_{\text{limit}} \). Otherwise, if the calculated change is within limits, it remains unchanged.
\[ \Delta CO_{t} = \begin{cases} \Delta CO_{\text{limit}} & \text{if } \Delta CO_{\text{limit}} \text{ is provided and } \Delta CO_{\text{unbounded}} < \Delta CO_{\text{limit}} \\ \Delta CO_{\text{limit}} & \text{if } \Delta CO_{\text{limit}} \text{ is provided and } \Delta CO_{\text{unbounded}} > \Delta CO_{\text{limit}} \\ \Delta CO_{\text{unbounded}} & \text{otherwise} \end{cases} \]
The control output at time \( CO_{t} \) is updated by adding the calculated change \( \Delta CO_{t} \) to the previous output at \( CO_{t1} \).
\[ CO_{t} = CO_{t1} + \Delta CO_{\text{t}} \]
Limit the Control Output
Finally, the calculated output is adjusted to ensure that it adheres to any predefined output limits provided by the user:
\[ CO_{t} = \begin{cases} CO_{\text{min}} & \text{if } CO_{\text{min}} \text{ is provided and } CO_{t} < CO_{\text{min}} \\ CO_{\text{max}} & \text{if } CO_{\text{max}} \text{ is provided and } CO_{t} > CO_{\text{min}} \\ CO_{t} & \text{otherwise} \end{cases} \]