Migrate to new Gitea instance (gitea.wbd-rd.nl)
- Update all submodule URLs from gitea.centraal.wbd-rd.nl to gitea.wbd-rd.nl - Add settler as proper submodule in .gitmodules - Add agent skills, function anchors, decisions, and improvements - Add Docker configuration and scripts - Add manuals and third_party docs - Update .gitignore with secrets and build artifacts - Remove stale .tgz build artifact Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
168
third_party/docs/pid-control-theory.md
vendored
Normal file
168
third_party/docs/pid-control-theory.md
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
# PID Control for Process Applications
|
||||
|
||||
> **Used by**: `mechanical-process-engineer` agent, `node-red-runtime` agent, `generalFunctions/src/pid/`
|
||||
> **Validation**: Verified against Astrom & Hagglund (ISA, 2006) and MATLAB/Simulink documentation
|
||||
|
||||
## Continuous PID Controller
|
||||
|
||||
### Standard (ISA/Ideal) Form
|
||||
|
||||
```
|
||||
u(t) = K_p · [e(t) + (1/T_i) · ∫e(τ)dτ + T_d · de(t)/dt]
|
||||
```
|
||||
|
||||
Where:
|
||||
- u(t) = controller output
|
||||
- e(t) = error = setpoint - process variable (SP - PV)
|
||||
- K_p = proportional gain
|
||||
- T_i = integral time (seconds)
|
||||
- T_d = derivative time (seconds)
|
||||
|
||||
### Parallel Form
|
||||
|
||||
```
|
||||
u(t) = K_p · e(t) + K_i · ∫e(τ)dτ + K_d · de(t)/dt
|
||||
```
|
||||
|
||||
Where K_i = K_p/T_i and K_d = K_p · T_d
|
||||
|
||||
## Discrete PID Implementation
|
||||
|
||||
### Positional Form (absolute output)
|
||||
|
||||
```
|
||||
u[k] = K_p · e[k] + K_i · Δt · Σe[j] + K_d · (e[k] - e[k-1]) / Δt
|
||||
```
|
||||
|
||||
- Computes the absolute output value each cycle
|
||||
- Requires tracking of the integral sum
|
||||
- Subject to integral windup
|
||||
- Used when the controller output directly sets an actuator position
|
||||
|
||||
### Velocity Form (incremental output)
|
||||
|
||||
```
|
||||
Δu[k] = K_p · (e[k] - e[k-1]) + K_i · Δt · e[k] + K_d · (e[k] - 2·e[k-1] + e[k-2]) / Δt
|
||||
u[k] = u[k-1] + Δu[k]
|
||||
```
|
||||
|
||||
- Computes the **change** in output each cycle
|
||||
- Inherently bumpless on mode transfers (auto→manual→auto)
|
||||
- Less prone to windup (but still needs anti-windup for output limits)
|
||||
- Preferred for incremental actuators (VFDs, variable valves)
|
||||
|
||||
## Anti-Windup Strategies
|
||||
|
||||
Integral windup occurs when the controller output saturates (hits actuator limits) but the integral term continues to accumulate, causing large overshoot when the error changes sign.
|
||||
|
||||
### 1. Clamping (Conditional Integration)
|
||||
|
||||
Stop integrating when the output is saturated **and** the error has the same sign as the integral term:
|
||||
|
||||
```
|
||||
if (u_raw > u_max || u_raw < u_min) && sign(e) == sign(integral):
|
||||
freeze integral (do not accumulate)
|
||||
else:
|
||||
integral += e * Δt
|
||||
```
|
||||
|
||||
- Simple to implement
|
||||
- Effective for most process control applications
|
||||
- The approach used in the EVOLV generalFunctions PID implementation
|
||||
|
||||
### 2. Back-Calculation
|
||||
|
||||
When the output saturates, feed back the difference between the saturated and unsaturated output to "unwind" the integrator:
|
||||
|
||||
```
|
||||
integral += (K_i · e + K_b · (u_saturated - u_raw)) · Δt
|
||||
```
|
||||
|
||||
Where K_b = 1/T_t (tracking time constant, typically T_t = √(T_i · T_d) or T_t = T_d).
|
||||
|
||||
- More sophisticated than clamping
|
||||
- Better performance for systems with large disturbances
|
||||
- Recommended by Astrom & Hagglund for demanding applications
|
||||
|
||||
### 3. Integrator Reset
|
||||
|
||||
Reset the integrator to a value that would produce the saturated output:
|
||||
|
||||
```
|
||||
if u_raw > u_max:
|
||||
integral = (u_max - K_p · e) / K_i
|
||||
```
|
||||
|
||||
- Simple but can be aggressive
|
||||
- May cause discontinuities
|
||||
|
||||
## Derivative Filtering
|
||||
|
||||
The derivative term amplifies high-frequency noise. Always filter it:
|
||||
|
||||
### First-Order Low-Pass Filter on D-Term
|
||||
|
||||
```
|
||||
D_filtered[k] = α · D_filtered[k-1] + (1-α) · D_raw[k]
|
||||
```
|
||||
|
||||
Where α = T_f / (T_f + Δt) and T_f = T_d / N (N typically 5-20, default 10).
|
||||
|
||||
### Derivative on PV (not Error)
|
||||
|
||||
To avoid derivative kick on setpoint changes:
|
||||
```
|
||||
D = -K_d · (PV[k] - PV[k-1]) / Δt (instead of using error)
|
||||
```
|
||||
|
||||
This is the standard approach for process control.
|
||||
|
||||
## Cascade PID
|
||||
|
||||
Two nested loops where the outer (master) loop's output is the setpoint for the inner (slave) loop.
|
||||
|
||||
```
|
||||
[SP_outer] → [PID_outer] → [SP_inner] → [PID_inner] → [Actuator] → [Process]
|
||||
↑ ↑
|
||||
[PV_outer] ←──── [Process] ←── [PV_inner]
|
||||
```
|
||||
|
||||
### Design Rules
|
||||
- Inner loop must be **5-10x faster** than outer loop
|
||||
- Tune inner loop first (with outer loop in manual)
|
||||
- Then tune outer loop
|
||||
- Anti-windup on outer loop essential (its output is bounded by inner loop's SP limits)
|
||||
|
||||
### EVOLV Application
|
||||
- Outer: Level controller → outputs flow setpoint
|
||||
- Inner: Flow controller → outputs pump speed
|
||||
- pumpingStation node coordinates this cascade
|
||||
|
||||
## Tuning Methods
|
||||
|
||||
### Ziegler-Nichols (Ultimate Gain Method)
|
||||
1. Set I and D to zero, increase K_p until sustained oscillation
|
||||
2. Record ultimate gain K_u and ultimate period T_u
|
||||
3. Apply: K_p = 0.6·K_u, T_i = T_u/2, T_d = T_u/8
|
||||
|
||||
### Cohen-Coon (Process Reaction Curve)
|
||||
1. Apply step change, record process reaction curve
|
||||
2. Identify: gain K, dead time L, time constant τ
|
||||
3. Apply formulas based on K, L, τ
|
||||
|
||||
### Lambda Tuning (IMC-based)
|
||||
1. Identify process as FOPDT: K, L, τ
|
||||
2. Choose closed-loop time constant λ (typically λ = max(3·L, τ))
|
||||
3. K_p = τ/(K·λ), T_i = τ
|
||||
|
||||
- **Preferred for process control** — gives non-oscillatory response
|
||||
- Directly specifies desired closed-loop speed
|
||||
- Robust to model uncertainty when λ is chosen conservatively
|
||||
|
||||
## Authoritative References
|
||||
|
||||
1. Astrom, K.J. & Hagglund, T. (2006). "Advanced PID Control." ISA — The Instrumentation, Systems, and Automation Society.
|
||||
2. Astrom, K.J. & Hagglund, T. (1995). "PID Controllers: Theory, Design, and Tuning." 2nd ed., ISA.
|
||||
3. Seborg, D.E. et al. (2011). "Process Dynamics and Control." 3rd ed., Wiley. (Chapter on PID control)
|
||||
4. MATLAB/Simulink documentation — "Anti-Windup Control Using PID Controller Block"
|
||||
5. Smith, C.A. & Corripio, A.B. (2005). "Principles and Practices of Automatic Process Control." 3rd ed., Wiley.
|
||||
Reference in New Issue
Block a user