Improving dcservo accuracy

Not being an expert in motor control, I created dcservo project to make a basic platform to create cheap servomotors that could replace stepper motors on certain systems, like 3D printers. I chose to implement a full PID controller but that might have been a bit overkill.

I was talking today to a more knowledgeable colleague who asked me why I needed a PID. My answer was that without the integral action I was getting a significant position error in the steady state, and the derivative action, though a really small value, was needed to keep the system from overshooting. However, he suggested me to focus only on a simpler, proportional controller with a twist: most of my position error is coming from the fact that there is a dead zone where motor does not respond to control action.

It is true, though the motor will move faster the higher the PWM value it is applied to the motor drive, it is also true that low values (between 1 and 50 in my test system) do not cause the motor to move.

I was willing to know how much a difference that could make. The change is actually just a line of code:

if( m>0 ) m = map(m,1,255,50,255);

In the motor PWM output code. 'm' is the absolute value of the output from PID controller and what I am doing now is to scale the values from 1...255 to a new range from 50...255, so any output different than 0 is actually causing the motor to move, thus removing effectively the dead-zone.


The purple line represents the position error of a collection of consecutive movements to different random locations using just a proportional controller with a gain close to the critical gain. While the green line represents the same error when using the same proportional controller with dead-zone elimination code (proportional gain was reduced ten-fold to keep the system from oscillating). 

Having only a proportional controller makes tuning much simpler and faster now, so I think it is a big improvement over the existing code.

Comments

Shafik said…
Good Fix, this is actually normal behavior for a DC Motor, last time I checked when I worked in Arduino projects with DC motors. This happens because the torque is proportional to the average current through the motor, the current drops as the duty cycle of the motor decreases, thus reaching a point where the torque is not even sufficient to overcome the friction at a certain range. I think I read about this issue once in a forum. Good catch, simple, elegant.
Anonymous said…
Another win for accuracy through simplicity!! Fantastic improvement!

Question:

Can DCServo be used in combination with Klipper, now that as of December Klipper has added experimental support for closed loop steppers (Mechaduino, uStepper, etc) and has a development branch dedicated to closed loops (see discussion #1038).

Would the DCServo code need to be integrated into the Klipper firmware, or can a second Arduino sit in front of the DCServo Arduino in a sort of Daisy Chain with Klipper as the master controller?

Popular posts from this blog

VFD control with Arduino using RS485 link

How to get sinusoidal s-curve for a stepper motor

Importing OpenSCAD designs into Onshape