Skip to content

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 ​

DisturbanceCompensated VariableApplication
Influent flowChemical doseFlow-paced dosing
Load changeAeration rateDO control
TemperatureReaction rateDigester heating
pH upsetLime dosepH 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] --> FB

Mathematical 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 spike

Parameters ​

Feedforward Parameters ​

ParameterUnitRangeDefaultDescription
Static Gain-0.1-101.0Process gain (output/disturbance)
Lead Timedays0-0.10.01Lead time constant
Lag Timedays0-0.10.02Lag time constant
Bias%0-10050Base output level
Output Min%0-1000Minimum output
Output Max%0-100100Maximum output

Optional Feedback PID ​

ParameterUnitRangeDefaultDescription
FB Enabled-true/falsefalseEnable feedback trim
FB Kp-0.1-101.0Feedback proportional
FB Ki-0.01-20.1Feedback integral
FB Kd-0-10Feedback derivative
FB Setpointvaries--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 ​

  1. Lead time: Match process dead time
  2. Lag time: Match process time constant
  3. Lead/Lag ratio: Lead ≤ Lag typically
ApplicationStatic GainLead TimeLag Time
Flow pacing1.00.0050.01
Load compensation0.5-2.00.010.02
Temperature FF0.80.020.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 trim

Response 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 ​

  1. Accurate disturbance measurement

    • Good flow meters essential
    • Filter noisy signals
  2. Correct static gain

    • Determine from process tests
    • Adjust based on performance
  3. Lead-lag tuning

    • Start with lead = lag
    • Adjust for response timing
  4. Combine with feedback

    • Feedforward handles load
    • Feedback handles errors
  5. Monitor both components

    • Track FF and FB contributions
    • Verify FF is helping

Troubleshooting ​

IssueCauseSolution
OvercorrectionGain too highReduce static gain
UndercorrectionGain too lowIncrease static gain
Phase mismatchLead/lag wrongAdjust time constants
OscillationLead too highReduce lead time
DriftNo feedbackEnable 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;

References ​

  1. Shinskey, F.G. "Feedforward Control Applied" (ISA, 1977)
  2. Seborg, D.E. "Process Dynamics and Control" (4th Edition)
  3. Smith, C.L. "Practical Process Control" (2009)