Looking at the code, the contribution calculations do not seem correct.
The code has
i_contrib = pid._integral * ki
but pid._integral has already been multiplied by ki within simple-pid.
For D the code has
d_contrib = pid._last_output - output if pid._last_output is not None else 0.0
but as far as I can see it should be (error - last_error) / sample period.
The simple-pid module has support for getting the contributions, so AFAICS we could just use that instead:
p_contrib, i_contrib, d_contrib = pid.components
Looking at the code, the contribution calculations do not seem correct.
The code has
but pid._integral has already been multiplied by ki within simple-pid.
For D the code has
but as far as I can see it should be (error - last_error) / sample period.
The simple-pid module has support for getting the contributions, so AFAICS we could just use that instead: