Recently I've successfully implemented PID controller for my robot's moving motors. Now the system can automatically adjust it's speed depending on different situations: increase it if something blocks robot's movement, decrease it if robot moves to fast and so on and so on. But with it system gained specific feature: after stop of the movement (sending zero speed from the joystick) integral error doesn't go to zero, it stays active resulting some signal on the output of pid controller. Check the diagrams: diagrams

On the upper diagram you can see 4 variables changing with time:

'LeftWheel.target_ticks_speed' - speed which is sent from joystick

'actual_speed' - measured on the run

'speed_error' - difference between joystick speed and actual

'calc_pwm_value.summary' - output of pid controller which goes directly on motor

On the below diagram there are 3 components of the pid controller: proportional, integral and derivative.

As you can see at the time stamp 48.600 'speed_error' goes to zero but integral error and summary of pid controller save some value.

Does anybody encountered issues like that in their pid controller implementations? I'm just not sure is math model should be improved somehow? Or speed setting mechanism should be reworked? Any comments or thougths would be appreciated.

Posting here C code of pid controller math model:

#include "pid.h"

#define K_P 1.0f
#define K_I 0.2f
#define K_D 0.5f

/* Used for testing in STM studio*/
/*float sum_prop = 0;
float sum_int = 0;
float sum_diff = 0;*/

static inline float prop_compute(float error)
    return error * K_P;

static inline float int_compute(float error, float* int_error)
    float sum = 0;
    sum = *int_error + (K_I * error);
    *int_error = sum;
    return sum;

static inline float diff_compute(float error, float* der_error)
    float sum = 0;
    sum = K_D * (error - *der_error);
    *der_error = error;
    return sum;

void pid_calculate(int16_t error, pid_entity* process)
    /* Used for testing in STM studio*/
    /*sum_prop = prop_compute(error);
    sum_int = int_compute(error);
    sum_diff = diff_compute(error);
    result = sum_prop + sum_int + sum_diff;*/

    process->prop_calc = prop_compute(error);
    process->integral_calc = int_compute(error, &(process->integral_error));
    process->derivative_calc = diff_compute(error, &(process->derivative_error));

    process->summary = process->prop_calc + process->integral_calc + process->derivative_calc;

1 Answer 1


You should only enable the integral term when the system is “close” to the desired state. This is because all physical systems will lag the control input, and the integral term will continue to build due to this lag. This leads to overshoot before finally settling at the final state.

Controllers I’ve developed turn on the $I$ gain when within $x$ counts of the final state, or after they are 90% to that state. This decreases overshoot but still allows the $I$ term to eliminate steady-state offsets. Some motor controllers will have a “settling” signal that you can use to turn on the $I$ gain.

  • $\begingroup$ I've noticed that integral term participates in a lot of situations. For example constant speed is based only on integral term (it is reflected on diagram). Your solution is quite complex. Do you know open source examples or something? In my opinion if math model can't be improved then I should add a flag to joystick message which will switch on/off pid controller $\endgroup$
    – r_spb
    Apr 29, 2020 at 13:35
  • $\begingroup$ SteveO, don't forget that often times the I term is strictly required to compensate for external disturbances. A system undergoing external disturbances won't be even able to approach the setpoint without the integral action. That said, the term I should be always on, as it is in many standard PID controllers. Counteracting the lag introduced by the integral term can be achieved in many different ways. $\endgroup$ Apr 29, 2020 at 15:30
  • 1
    $\begingroup$ Fair comment, @UgoPattacini. For the robotics systems I’ve built I have always been able to use PD control during motion, and added the I term for steady-state offset or drift. I will edit my answer. $\endgroup$
    – SteveO
    Apr 29, 2020 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.