Appearance
Feedforward Controller
Disturbance-based feedforward with lead-lag compensation
Overview
The Feedforward Controller anticipates process disturbances and adjusts the manipulated variable proactively. Combined with optional feedback PID, it provides excellent disturbance rejection by acting before the disturbance affects the controlled variable.
When to Use
- Measurable disturbances: Flow, load, composition changes
- Fast disturbance rejection: When feedback alone is too slow
- Known process relationships: Static gain can be determined
- Predictable upsets: Diurnal patterns, batch operations
Common Applications
| Disturbance | Compensated Variable | Application |
|---|---|---|
| Influent flow | Chemical dose | Flow-paced dosing |
| Load change | Aeration rate | DO control |
| Temperature | Reaction rate | Digester heating |
| pH upset | Lime dose | pH control |
Control Theory
Concept
mermaid
graph TB
D[Disturbance] --> FF[Feedforward]
D --> Process[Process]
FF --> Sum((+))
FB[Feedback PID] --> Sum
Sum --> MV[Manipulated Variable]
MV --> Process
Process --> PV[Process Variable]
PV --> FB
SP[Setpoint] --> FBMathematical Model
Feedforward output: $$FF = K_{FF} \cdot G_{LL}(s) \cdot d$$
Lead-lag compensator: $$G_{LL}(s) = K_{LL} \cdot \frac{1 + \tau_{lead} \cdot s}{1 + \tau_{lag} \cdot s}$$
Combined output: $$output = FF + FB + bias$$
Where:
- $d$ = Disturbance variable
- $K_{FF}$ = Static feedforward gain
- $\tau_{lead}$ = Lead time constant
- $\tau_{lag}$ = Lag time constant
- $FB$ = Feedback PID output
Lead-Lag Compensation
Without Lead-Lag:
Disturbance ────┐
│ Output change instant
Output ─────┴──────────
With Lead-Lag:
Disturbance ────┐
│ Output leads then lags
Output ───╮ ╭─────────
╰─╯
↑
Lead spikeParameters
Feedforward Parameters
| Parameter | Unit | Range | Default | Description |
|---|---|---|---|---|
| Static Gain | - | 0.1-10 | 1.0 | Process gain (output/disturbance) |
| Lead Time | days | 0-0.1 | 0.01 | Lead time constant |
| Lag Time | days | 0-0.1 | 0.02 | Lag time constant |
| Bias | % | 0-100 | 50 | Base output level |
| Output Min | % | 0-100 | 0 | Minimum output |
| Output Max | % | 0-100 | 100 | Maximum output |
Optional Feedback PID
| Parameter | Unit | Range | Default | Description |
|---|---|---|---|---|
| FB Enabled | - | true/false | false | Enable feedback trim |
| FB Kp | - | 0.1-10 | 1.0 | Feedback proportional |
| FB Ki | - | 0.01-2 | 0.1 | Feedback integral |
| FB Kd | - | 0-1 | 0 | Feedback derivative |
| FB Setpoint | varies | - | - | Feedback target |
Tuning Guidelines
Static Gain Calculation
$$K_{FF} = -\frac{K_{process,d}}{K_{process,m}}$$
Where:
- $K_{process,d}$ = Process gain from disturbance to PV
- $K_{process,m}$ = Process gain from MV to PV
Example: Flow-paced chemical dosing
- If flow increases 10%, pH drops 0.2
- If chemical increases 10%, pH rises 0.2
- K_FF = 0.2/0.2 = 1.0 (1:1 flow pacing)
Lead-Lag Tuning
- Lead time: Match process dead time
- Lag time: Match process time constant
- Lead/Lag ratio: Lead ≤ Lag typically
Recommended Settings
| Application | Static Gain | Lead Time | Lag Time |
|---|---|---|---|
| Flow pacing | 1.0 | 0.005 | 0.01 |
| Load compensation | 0.5-2.0 | 0.01 | 0.02 |
| Temperature FF | 0.8 | 0.02 | 0.05 |
Configuration
Example: Flow-Paced Chemical Dosing
json
{
"id": "flow-paced-dosing-1",
"type": "Feedforward",
"enabled": true,
"targetNodeId": "dosing-pump-1",
"disturbanceNodeId": "influent-1",
"disturbanceVariable": "flow",
"manipulatedVariable": "doseRate",
"staticGain": 0.005,
"leadLag": {
"leadTime": 0.005,
"lagTime": 0.01,
"gain": 1.0
},
"outputMin": 0,
"outputMax": 100,
"bias": 0,
"feedbackPID": {
"enabled": true,
"pvNodeId": "reactor-1",
"pvVariable": "pH",
"setpoint": 7.0,
"kp": 2.0,
"ki": 0.5,
"kd": 0
},
"mode": "auto"
}Example: Load-Based Aeration
json
{
"id": "load-aeration-1",
"type": "Feedforward",
"enabled": true,
"targetNodeId": "blower-1",
"disturbanceNodeId": "influent-1",
"disturbanceVariable": "flow",
"manipulatedVariable": "airflow",
"staticGain": 50,
"leadLag": {
"leadTime": 0.01,
"lagTime": 0.02,
"gain": 1.0
},
"outputMin": 100,
"outputMax": 1000,
"bias": 200,
"feedbackPID": {
"enabled": true,
"pvNodeId": "aerobic-reactor-1",
"pvVariable": "DO",
"setpoint": 2.0,
"kp": 50,
"ki": 10,
"kd": 5
},
"mode": "auto"
}Integration Example
Chemical Dosing with Flow Compensation
Scenario: Maintain pH 7.0 with flow-paced lime dosing
Flow Increase: 10,000 → 12,000 m³/d (+20%)
Without Feedforward:
- pH drops from 7.0 to 6.8
- Feedback slowly increases dose
- Recovery takes 30+ minutes
With Feedforward:
- Flow increase detected immediately
- Dose increased by 20% proactively
- pH dip limited to 6.95
- Feedback provides fine trimResponse Comparison
Flow (m³/d)
12000 ───────────────────────────
┌─────────────────────
10000 ─────┘
pH
7.0 ─────┐ ╭───────────────── With FF+FB
╲╱ (small dip)
6.8 ───────╲──────────╭───────── FB only
╲────────╯ (large dip)
Dose
120% ────────────────────────────── FF+FB
┌─────────╭───────────
100% ─────────────────╯ FB only
┌─────────────────────Best Practices
Accurate disturbance measurement
- Good flow meters essential
- Filter noisy signals
Correct static gain
- Determine from process tests
- Adjust based on performance
Lead-lag tuning
- Start with lead = lag
- Adjust for response timing
Combine with feedback
- Feedforward handles load
- Feedback handles errors
Monitor both components
- Track FF and FB contributions
- Verify FF is helping
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Overcorrection | Gain too high | Reduce static gain |
| Undercorrection | Gain too low | Increase static gain |
| Phase mismatch | Lead/lag wrong | Adjust time constants |
| Oscillation | Lead too high | Reduce lead time |
| Drift | No feedback | Enable feedback PID |
Advanced Topics
Dynamic Compensation
The lead-lag compensator handles timing mismatch:
- Lead: Anticipates slow process response
- Lag: Smooths rapid changes
- Ratio: Lead/Lag < 1 for most cases
Discrete Implementation
typescript
// Lead term
const disturbanceRate = (disturbance - previousDisturbance) / dt;
const leadOutput = disturbance + leadTime * disturbanceRate;
// Lag term (first-order filter)
const lagAlpha = dt / (lagTime + dt);
lagState = lagAlpha * leadOutput + (1 - lagAlpha) * lagState;
// Final FF output
ffOutput = staticGain * lagGain * lagState;Related Controllers
- Ratio-Controller - For ratio-based feedforward
- Cascade-Controller - Alternative disturbance rejection
- PID-Controller - Feedback component
References
- Shinskey, F.G. "Feedforward Control Applied" (ISA, 1977)
- Seborg, D.E. "Process Dynamics and Control" (4th Edition)
- Smith, C.L. "Practical Process Control" (2009)