# Implementing a deadband on a PID controller for a dc motor

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;

{
setPWM(0);
}
else
{
if ( output >= 0 )
{
direcao(1);
setPWM(fabsf(output));
}
if ( output < 0 )
{
direcao(0);
setPWM(fabsf(output));
}
}


or

...
erro_ant = erro;

{
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.

• What exactly the problem is? I can't see any from the diagram. You should also record the setpoint value: setpoint, actual, controller output. I don't see the similarities from the described article. – Marko Buršič Sep 12 '17 at 13:17
• The problem is that the motor never stops in the setpoint it's always oscillating around it just like the image shows. When I got this problem I asked on some forums all of them suggested that the problem was friction and told me to read this article and to me it looks like they are right. Have you read section 2.4 PID Controller of the article? What do you mean with record the setpoint value? The setpoint will never change, it's always zero. – M_Luis Sep 12 '17 at 13:42
• This is much better description that just making a hypothesis that you have a problem with friction, maybe it is just an ordinary behavior of the closed loop control. Anyway, are you sure it is PI control response on the depiction or it is a PID control? The algorithm is basic one, I'll try later to respond. – Marko Buršič Sep 12 '17 at 13:51
• The figure in the article is a PID controller and the image I posted is a PID controller with the derivative gain set to zero wich is a PI controller. I've tried a PID and PI controller and the response is the same. The algorithm is meant to be as basic as possible so that when it's working I can add anti-windup, derivative filter etc... and see the changes to report in a essay. My main question is when implementing the deadband should I simply set the motor PWM to zero? or the PID controller output variable (named output in the code) to zero? or the integral term? – M_Luis Sep 12 '17 at 14:41

It's a common fact that a drive system has a resonance frequency due to moment of inertia and the elasticity of the transmission. If you have a high closed loop gain, then the system is always "nervous" waiting for dynamic action. To overcome this small oscillations problem in a professional equipment you set the notch filters to eliminate this resonance frequency. This is done by injecting signals and draw Bode plot. You can add a lowpass filter, but you will loose the dynamics, or you might decrease the gain.

Introducing the dead band means introducing the nonlinearity in the system. Perhaps there are better solutions rather a dead band for the drive control.

The professional drive controllers I have used, have an adaptation of Kp and Ti with regard the input value. At low error, the Kp is low and Ti is slightly higher. This could be also a way to go.

For example, you do the abs() on input then you make a linear function with minimal Kp at low input error and nominal Kp at high input error.

If you want a deadband anyway, you have a formula already in the article (29) and (30) give the new transformed input as depicted in figure 16.

To be continued...

• I saw those formulas but my difficulty is to understand what I should do when the error is within the deadband. Should I simply set the motor PWM to zero? or the PID controller output variable (named output in the code) to zero? or the integral term? What is u_o and u_i in the formulas? the error? the output variable of the PID controller? – M_Luis Sep 12 '17 at 14:44
• u_i is your erro and u_o is your new translated erro. – Marko Buršič Sep 12 '17 at 15:47
• but in section 3.2 Deadband, 2nd paragraph says: "Deadband sets the drive to the motor to zero when the input error is within some defined limit, so the motor...". And doing what you said will make the motor stop but won't set the drive to motor to zero, because the integral term will still hold some value, should I set the integral term to zero when the error is within the deadband? – M_Luis Sep 12 '17 at 16:53
• Frankly I don't find the article very useful, the explanation is "wrapped in the cloud". IMO, the method is not a general solution. – Marko Buršič Sep 13 '17 at 12:18
• I am not a controls guy. Maybe, if the position error is less than the deadband, then force the position error to zero before feeding the error into the loop control. Absent some external force, the motor will then stop within the deadband. Hopefully. – mkeith Dec 9 '17 at 21:46

going by that article and your code it looks like Marko's answer is the correct direction, and you're close with your code.

If you look at the block diagram in the article and apply that to your formula in your code it's relatively straight forward.

you can see the I and the D values are always applied, the only portion that is adjusted is when the P value is applied.

So your deadband is just a range where erro will be held zero.

deadband = <deadband value>; //choose your deadband size