Skip to content

Important Notes

Alex edited this page Aug 18, 2026 · 1 revision

Why Derivative-on-Measurement Is Used

A conventional derivative-on-error implementation uses:

$D = K_d \frac{d(error)}{dt}$

Because:

$error = setpoint - actual$

a sudden setpoint change also produces a sudden derivative response.

This is known as derivative kick.

This implementation instead uses:

$D = -K_d \frac{d(actual)}{dt}$

for a direct-acting controller.

Advantages:

  • avoids derivative kick caused by setpoint changes
  • reacts directly to process motion
  • reduces output while the process value approaches the setpoint quickly
  • is well suited for overshoot-prone systems

Time Scaling

The controller uses seconds for all time-dependent calculations.

Integral:

mIntegral += error * dt;

Derivative:

(actual - mPrevActual) / dt;

This is important because the controller gains then remain meaningful if the sample time changes.

For example, changing:

100 ms

to:

200 ms

does not fundamentally change the mathematical meaning of Ki and Kd.


Important Notes

Existing PID Values Must Be Retuned

PID values from a previous implementation should not automatically be reused.

If an older controller used:

mIntegral += error;

without multiplying by elapsed time, its Ki value had a different scale.

Likewise, if the derivative previously divided by milliseconds instead of seconds, its Kd value also had a different scale.

After changing to proper time scaling, Ki and Kd must usually be tuned again.


Sample Time

For many slow physical processes, values such as:

100 ms
200 ms
500 ms
1000 ms

may be reasonable.

The correct value depends on the process dynamics and sensor update rate.

The PID should generally not be updated significantly faster than the measured process can provide meaningful new information.


Output Range

Make sure the configured output limits match the actuator interface.

For example, standard Arduino analogWrite() on many AVR boards uses:

0 ... 255

If the PID internally uses:

0 ... 1023

the output must be scaled before passing it to an 8-bit PWM interface.


Multiple PID Instances

Timing variables are stored as member variables:

uint32_t mLastComputeMs;

and not as function-local static variables.

Therefore multiple PID objects can operate independently:

PID temperaturePID;
PID pressurePID;
PID flowPID;

Each controller has its own timing, integral state, derivative state, and output state.


Summary

The controller combines several mechanisms to improve stability and reduce overshoot:

Mechanism Purpose
Proportional term Reacts to current control error
Integral term Removes steady-state error
Integral activation range Prevents early integral accumulation
Integral tolerance Stops unnecessary integration near setpoint
Conditional integration Prevents integral windup
Derivative-on-measurement Brakes fast approach to setpoint
Derivative filter Reduces noise sensitivity
Output limits Protects actuator range
Slew-rate limiter Prevents abrupt output changes
Time-based calculation Makes Ki and Kd mathematically consistent
Instance-local timing Allows multiple independent PID controllers

For overshoot-prone systems, the most important features are typically:

  1. Derivative-on-measurement
  2. Restricted integral action
  3. Anti-windup
  4. Proper time scaling
  5. Optional output slew-rate limiting

Clone this wiki locally