I've been building a system to control motor position using a microcontroller.
But I faced some problems during the implementation of the PID controller and I found out, thanks to this article: http://www.wescottdesign.com/articles/Friction/friction.pdf
that the problem is friction. The following image shows the response of my system using a PI controller:
Where the orange line is the PID output variable and the blue line is the angle of the motor axis(what I want to control). If you compare this image to figure 12 on page 12 of the article posted above we can conclude that friction is the problem. Also in the same article one of the given solutions is to apply a deadband to the controller but I'm having some difficulties understanding how to implementing it. If my PID controller code is:
angulo = (encoder*360)/(4*102.0);
erro = setpoint - angulo;
d_term = kd*((erro - erro_ant)/0.00125);
i_term = i_term + ki*(0.00125*erro);
output = kp*erro + d_term + i_term;
erro_ant = erro;
if ( output >= 0 )
{
direcao(1);
setPWM(fabsf(output));
}
if ( output < 0 )
{
direcao(0);
setPWM(fabsf(output));
}
The direcao() function will change the h-bridge pins to make the motor rotate in the correct direction. And what I fought to do was:
...
erro_ant = erro;
if (error is within deadband)
{
setPWM(0);
}
else
{
if ( output >= 0 )
{
direcao(1);
setPWM(fabsf(output));
}
if ( output < 0 )
{
direcao(0);
setPWM(fabsf(output));
}
}
or
...
erro_ant = erro;
if (error is within deadband)
{
output = 0;
}
if ( output >= 0 )
{
direcao(1);
setPWM(fabsf(output));
}
if ( output < 0 )
{
direcao(0);
setPWM(fabsf(output));
}
I also fought about setting the integral term to zero, when it is within the deadband, but that will act as a anti-windup technique when the system overshoots.
Thanks in advance to anyone who answers.