A proportional controller forgets: once the error is zero it delivers nothing. Integral action gives the controller a memory. It keeps a running total of the error, each sample weighted by how long it lasted:
I = I + error * dt
I is the integral of the error (in °C·seconds when the error is in °C and dt in seconds): it grows for as long as the controller is short of the setpoint, and shrinks while it is past it. A PI controller adds the two terms:
u = Kp * error + Ki * I
A coffee roaster's controller logged its temperature error (setpoint minus drum temperature, °C) every dt seconds. Recompute what it commanded. The integral starts at I = 0; for each error in order, first add it to the integral, then compute the command.
Write pi_commands(errors, dt, Kp, Ki) that returns the list of commands, one per error.
Examples
Input: errors = [4, 2, 1, 0, -1], dt = 0.5, Kp = 2, Ki = 0.5
Output: [9.0, 5.5, 3.75, 1.75, -0.5]
Explanation: the integral goes 2, 3, 3.5, 3.5, 3. At the fourth sample the error is 0,
but the controller still commands 0.5 * 3.5 = 1.75: it remembers the shortfall.
Input: errors = [], dt = 1, Kp = 1, Ki = 1
Output: []
Constraints
- answers are compared with a tolerance of
1e-6; do not round
Goals
- Keep a running sum of the error, weighted by the time step
- Combine a proportional and an integral term into one command
- See that the integral term keeps pushing after the error has gone