# DC motor doesn't rotate with low duty cycle PWM using L293D

#### MLuis

Joined Jul 20, 2017
17
If the motor speed is too slow the PID loop should set the duty-cycle to the maximum value, not the minimum.
I don't understand why it's setting it to the minimum?
Sounds like you have the PID signal phase reversed from what it should be.
I don't think you are understanding. Here is a very summarized pseudo-code of what I do:

...
output = kp*erro + ki*i_term + kd*d_term;
duty = abs(output);
if (duty > 0 && duty < 30000) duty = 30000; //this is the line of code i'm talking about
//30000 is the minimum OCR value to make the motor rotate (30000/65535)*100% = 45%
if (duty > 65535) duty = 65535;
OCR1A = duty;

Like I said this is a very summarized version of the code and I skip many steps but neither the output or duty variables are used in those steps I skiped.
The problem is not the PID code because I've asked an automation engineer to look at it and he said that is correct except the part where I set the duty cycle as 30000 when the PID output is lower than duty cycle (the line of code we are talking about) and that it should be exactly the output of the PID controller, but if the motor doesn't move I can do what I'm doing (wich is a poor solution) but the minimum value can't be 30000, is too high. From the research I made the minimum value should 10% duty cycle or lower for a proper control but I can't make the motor move for values that low. The engineer didn't know aswell why the motor needs such a high duty cycle.
My guess would be that it can't overcome the friction from the gearbox but I don't know how to solve it.

#### crutschow

Joined Mar 14, 2008
29,494
You still haven't explained why, if the motor speed is too slow, the duty-cycle is not increased to speed up the motor?

#### ebeowulf17

Joined Aug 12, 2014
3,275
I'm with crutschow. If the PID controls were working right, they would keep increasing duty cycle until the motor reached its target speed. There should be no need for a hard coded limit. Fix the code and/or PID settings.

#### Kjeldgaard

Joined Apr 7, 2016
461
...
output = kp*erro + ki*i_term + kd*d_term;
duty = abs(output);
...
I do not understand that abs instruction?

#### MLuis

Joined Jul 20, 2017
17
You still haven't explained why, if the motor speed is too slow, the duty-cycle is not increased to speed up the motor?
I'm with crutschow. If the PID controls were working right, they would keep increasing duty cycle until the motor reached its target speed. There should be no need for a hard coded limit. Fix the code and/or PID settings.
But I'm not controlling the motor's speed I'm controlling motor's position, and for example if I let the PID increase until it reaches the minimum value by itself won't it overshoot?
And my main question is why does the motor only moves with 45% duty cycle? I want to reduce that value.

#### MLuis

Joined Jul 20, 2017
17
I do not understand that abs instruction?
You can't set a negative duty cycle, can't you?. The lines where I determine, and set, the direction it's ommited.

#### ebeowulf17

Joined Aug 12, 2014
3,275
What you see is expected. Because the motor load is inductive, it takes time for the current to build. With PWM, it will never reach the same current you get with a constant voltage. And the higher the frequency, the worse it gets.

Bob
It's beyond my expertise to understand how big this effect would be, but this sounds right to me.
The power supply I used shows the current aswell and the motor needs around 0.4A (measured when the motor is directly connected to the power supply) to start rotating but when driving the motor through the h-bridge and giving it a PWM with a duty cycle below 45% the motor doesn't move and the power supply shows around 0.13A.
Note that at 45% duty cycle, you're not supplying anywhere near enough current, so you obviously need more duty cycle.

I think maybe the heart of this problem is that your PID control is based on position, not speed, so it's output represents the speed you need the motor to run at in order to achieve the desired position both quickly and smoothly. This might work if motor speed and duty cycle were directly proportional to each other, but obviously they're not, especially not at lower duty cycles.

You need something to translate your required speed (the output of your current PID algorithm if it's working right) into an appropriate duty cycle to achieve that speed.

It almost seems like you need a PID for your PID! You feed current position and target position into the first PID and it outputs target speed. Then you feed current speed and target speed into the second PID and it outputs duty cycle.

More simply though, you might get away with a mapping function that scales your zero-to-whatever speed requirement to 45-100% duty cycle.

#### MLuis

Joined Jul 20, 2017
17
It's beyond my expertise to understand how big this effect would be, but this sounds right to me.

Note that at 45% duty cycle, you're not supplying anywhere near enough current, so you obviously need more duty cycle.

I think maybe the heart of this problem is that your PID control is based on position, not speed, so it's output represents the speed you need the motor to run at in order to achieve the desired position both quickly and smoothly. This might work if motor speed and duty cycle were directly proportional to each other, but obviously they're not, especially not at lower duty cycles.

You need something to translate your required speed (the output of your current PID algorithm if it's working right) into an appropriate duty cycle to achieve that speed.

It almost seems like you need a PID for your PID! You feed current position and target position into the first PID and it outputs target speed. Then you feed current speed and target speed into the second PID and it outputs duty cycle.

More simply though, you might get away with a mapping function that scales your zero-to-whatever speed requirement to 45-100% duty cycle.
I understand that running the motor with a PWM or with a power supply is not the same thing, but from my research I found out that usually motors work fine with 10% of duty cycle.

Can you explain better the mapping function part, I don't understand. How can I scale the PID output into 45%-100%?

#### ebeowulf17

Joined Aug 12, 2014
3,275
In the Arduino world it's called a map function, but there might be a better name/description for it in general use. A good description can be found here:

https://www.arduino.cc/en/Reference/Map

If you don't feel like clicking through, here's the basic formula:
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

I don't know what to tell you about 10 vs 45% duty cycle requirements. If you have an oscilloscope, you could examine the output of your motor driver compared to its input signal and look for performance issues. As it is, I personally don't see the problem. Give the motor whatever duty cycle you have to in order to move it where you want. Who cares what the numbers are as long as the motor moves?

#### MLuis

Joined Jul 20, 2017
17
In the Arduino world it's called a map function, but there might be a better name/description for it in general use. A good description can be found here:

https://www.arduino.cc/en/Reference/Map

If you don't feel like clicking through, here's the basic formula:
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

I don't know what to tell you about 10 vs 45% duty cycle requirements. If you have an oscilloscope, you could examine the output of your motor driver compared to its input signal and look for performance issues. As it is, I personally don't see the problem. Give the motor whatever duty cycle you have to in order to move it where you want. Who cares what the numbers are as long as the motor moves?
Thanks for the answer, I'll look to the arduino function.
The problem now is that when I have to do small corretions the motor overshoots and oscillates a lot because I can't do small corretions, because the minimum duty cycle is too high.

#### crutschow

Joined Mar 14, 2008
29,494
Thanks for the answer, I'll look to the arduino function.
The problem now is that when I have to do small corretions the motor overshoots and oscillates a lot because I can't do small corretions, because the minimum duty cycle is too high.
That's more likely due to the PID loop not having the proper compensation values.
A motor has a lot of inertia and will require significant loop compensation for that.
How have you determined the values for the P, the I, and the D corrections in the loop?
Do you understand how PID works?

#### MLuis

Joined Jul 20, 2017
17
That's more likely due to the PID loop not having the proper compensation values.
A motor has a lot of inertia and will require significant loop compensation for that.
How have you determined the values for the P, the I, and the D corrections in the loop?
Do you understand how PID works?
I do understand, and I don't think that the problem is the parameters, I haven't tuned it yet even but I've done experiments with P only and the motor reacts the same way to every number between Kp=1 and Kp=200 (I haven't tried with higher numbers but I think it will respond in the same way until Kp is big enough for the PID output to be higher than 45% duty cycle) and I don't think that's suppose to happen.

#### crutschow

Joined Mar 14, 2008
29,494
I do understand, and I don't think that the problem is the parameters, I haven't tuned it yet
If you haven't tuned it yet than how do you expect it to be stable?

#### ebeowulf17

Joined Aug 12, 2014
3,275
Another possible issue here is the difference between static vs kinetic friction and start vs run motor current requirements. In other words, you may need "a lot" of power up front to make the motor move initially, but much less to keep it moving at a slow speed. I'm not sure how easy that would be with PID. This is starting to feel like a good candidate for one of my favorite things, fuzzy logic!

https://en.m.wikipedia.org/wiki/Fuzzy_logic

Last edited:

Joined Feb 20, 2016
4,110
Just a thought, Are you using the L293D as your data sheet says, or the L293 (no "D")?
If your circuit does not have fly back diodes for the motor current to continue when the driver switches off, the motor will be very sluggish at the low end. This may be worth a look. Even to adding a diode bridge rectifier to the circuit, + to the supply, - to the 0V and the AC ~ to each side of the motor. Schottky (high frequency) diodes will be best, and they need to be rated at the stall current of the motor at least.
But that said, it still just may be your code.

#### MLuis

Joined Jul 20, 2017
17
Just a thought, Are you using the L293D as your data sheet says, or the L293 (no "D")?
If your circuit does not have fly back diodes for the motor current to continue when the driver switches off, the motor will be very sluggish at the low end. This may be worth a look. Even to adding a diode bridge rectifier to the circuit, + to the supply, - to the 0V and the AC ~ to each side of the motor. Schottky (high frequency) diodes will be best, and they need to be rated at the stall current of the motor at least.
But that said, it still just may be your code.
I was using the L293D, meanwhile I changed it for a L298N that doesn't has diodes so I added Schottky diodes but they're not rated at the stall current of the motor, it's lower...

Joined Feb 20, 2016
4,110
Under load you will run a good chance of popping the diodes. They need to be rated high enough to carry the current generated by the back EMF. It can be substantial. Just imagine what will happen if you suddenly reverse the motor while it is moving. Big current. So always try to slow the motor to a stop before reversing it. A good idea is to over engineer motor drives to make them more rugged.