PID control of a DC motor with PWM from Raspberry Pi - how to cross dead area?

I'm driving a DC motor (actually a linear actuator) with a Polulu motor controller from a Raspberry Pi. The motor drives if you ask for anything between 20 and 100% duty cycle, so there is a dead zone between -20% and 20% duty cycle.

I'm using a laser distance sensor to measure position of the actuator, and I'd like to make the actuator track a desired position using a PID controller.

The problem I'm facing is that as the position crosses over from being too low to too high, the PID controller takes a load of time to cross through this deadband, after which the position is completely wrong!

I've tried creating a lookup table for the motor speed based on the requested speed, but this doesn't help a huge amount. I was thinking of creating two lookup tables, one for when the position is above setpoint and one for when it is below which cross over instantly from -20 to 20 and vice-versa.

Any thoughts on this problem (or just what it is called so I can Google it!) would be much appreciated.

• Is it likely that the dead band is caused by static friction of your system? Could you reduce this friction? – fibonatic Mar 14 '19 at 11:54
• How is your PID loop implemented? Have you tried adjusting the tuning? If so how? – Ohio ChemE Mar 14 '19 at 17:00

Cascaded control may be a good solution, but there's something simpler that you could try first. Simply add a bit of logic after the PID loop to skip from -20 to 20%.

if(pid_output > 0%)      pid_output = (pid_output+20%)/1.2;
else if(pid_output < 0%) pid_output = (pid_output-20%)/1.2;


What your essentially doing is remapping the -100% to 100% output range of the PID controller onto the usable input range of the linear actuator.

I'd throw a bit of deadzone in there as well to keep the system from oscillating. Like maybe if the pid output < +-5% just set it to zero.

You just need a two loops control strategy.

An inner speed loop will simply set PWM needed to achieve requested rotational speed . This unfortunately needs a speed transducer on the motor spindle but it's definitely worth. The input of this sub-system is requested speed coming from outer position loop

The outer position loop processes requested position set point and position feedback and feeds inner loop. This is basically what you've already implemented .

This approach to position control roots back to the very beginning of control theory, it shouldn't be hard to Google much more details

Google "Controlling motors in the presence of friction and backlash".

It's a big subject, but the two essentials are:

1. Use an inner velocity loop on the motor, if you can (i.e., don't put a PID on the position of the whole thing -- put a velocity PI on just the motor -- especially if the motor is geared).
2. If there's friction, pulse the power to the motor slowly, with a drive greater than that magic 20% where you get no response. Each time you pulse the motor it'll move a bit, and thus crawl in the direction you want. It's not ideal, but it can be much better than sitting still forever, and then jumping (and overshooting) as happens with such an assembly under pure PID control.