I have come across a handful of examples of PID controllers where the process input is the accumulated PID output, i.e. the controller loop is u += pid(...)
rather than u = pid(...)
where u
is the process input.
For the sake of example, say we are using PID to control the speed of a motor via PWM,
class PID:
def __init__(self, kp, ki, kd):
self.kp = kp
self.ki = ki
self.kd = kd
...
def pid(self, set_point, process_variable):
now = time()
dt = now - self.last_time
error = set_point - process_variable
p = self.kp * error
i = self.ki * error * dt + self.i_sum
d = self.kd * (error - self.last_error) / dt
output = p + i + d
self.i_sum = i
self.last_error = error
self.last_time = now
return output
My understanding of PID is that we should use the controller as
pid = PID(kp, ki, kd)
...
motor_pwm = pid.pid(target_speed, measured_speed)
But I often see it implemented as
pid = PID(kp, ki, kd)
...
motor_pwm += pid.pid(target_speed, measured_speed)
Now, for ki = kd = 0
, the latter makes some intuitive sense to me; in fact, I think it actually gives you a kind of PI controller with ki = kp
, and dt = 1
enforced. Once you introduce ki != 0
or kd != 0
, however, I can't square this with any of the textbook explanations of PID I have read.
Is this 'accumulated' u += pid(...)
controller simply an incorrect implementation of PID?
u
denotes. \$\endgroup\$u
is the process input. The code examples I am referring to are linked in the question. \$\endgroup\$