# Controlling motor speed with PID how to scale PWM to RPM and back

I want to control the speed of a motor using PID controller. My problem is, the valid PWM range I can set in my microcontroller is from 0 to 199 but I measure the speed of the motor (using an encoder) in range of ~50 to 6000 RPM.

How can I meaningfully interchange these values?

Example:

I set the target speed to 6000 when motor is at 0RPM. Then the PID starts and at that moment the error is 6000...so the PID gives maximum output which will be 32767. But I only can set the timer PWM from 0~200.

I am using the code in AVR221 application note and there every variable is signed integer (no floating points). My own micro controller is stm32 that can handle floating points efficiently I beleive.

No need to scale. You need to limit your PID controller output wit 0% and 99%, and find out what factors work best. There is I*R, all kinds of interference, acceleration, so voltage is not strictly related to speed. Actually sometimes it may seem like there is no relation at all. So you do PI or PID, and tune it. Best practice is to also use SI units everywhere, but not mandatory.

By the way, and this is very important. You must build motion profile. Which in case of velocity control means you have to gradually raise the velocity according to acceleration. Otherwise you will get overshoots and very unstable behavior, or poor control if you will lower your gain to calm system down.

• Instead of "you need to limit your PID controller output wit 0% and 99%", I would formulate as "use the output of the PID controller, clamped between 0 and 199". I think it makes it more clear, and more specific to OP's case.
– dim
Commented Jun 28, 2018 at 9:53
• Maybe. Hope he is independent enough to research the topic further by himself
– user76844
Commented Jun 28, 2018 at 9:59
• @GregoryKornblum "By the way, and this is very important. You must build motion profile. Which in case of velocity control means you have to gradually raise the velocity according to acceleration. Otherwise you will get overshoots and very unstable behavior, or poor control if you will lower your gain to calm system down." Commented Apr 26, 2021 at 13:47
• @GregoryKornblum Hi, I know this an old question but would like to ask you something. I am working on a PID to PWM and having some trouble, and when I read what you wrote in the above comment, I have a question. Are you suggesting that every scan cycle of the PID loop, that the rate of change of the PWM duty cycle is capped to a max rate of change? I have trouble with excessive overshoot no matter what I do, and I think my PID loop time is maybe too slow, but what you have mentioned could be one way to fix this issue? Commented Apr 26, 2021 at 13:50
• @David777 no, this is not what i say. But to answer your question I need to better understand what you are doing.
– user76844
Commented Apr 26, 2021 at 19:07

Usually the output of a PID function is a number between 0.0 and 1.0 (0-100%), you can multiply this by your timer period to get the duty cycle value.

But if you use integer mathematics, the output of your PID function is -32768 to 32767, then you have -1.0 to 1.0 with 1/32767 resolution.

In your case, divide the signed 16 bit output by 163.

The PID output is basically the required increase in POWER to plot a path to the required set point - think of a cruise control on a car, as speed drops below setpoint, more accelerator is fed in. The torque curve on most DC motors follows a parabolic shape, so at high and low RPM's your "accelerator" input needs to be scaled up accordingly. Torque curves change with input voltage of course, so a good idea to help stabilise the system would be to use a voltage regulator, that will help eliminate at least one moving target from the system.

PWM does not change speed of a motor directly, it changes the voltage across the motor, while maintaining the torque. The only way to translate PWM duty cycle to speed of a motor reliably and accurately, is to do a graph yourself. I'd say do at least 5 points, and plot speed against duty cycle in a graph.

• I don't get it. At the end I have to change the PWM value to change the speed, so how that graph would help? Commented Jun 28, 2018 at 8:42
• You set PWM to 20%, 40%, 60%, 80%, 100% in turn, and measure the speed of the motor. That will then let you plot a graph to show the relationship of PWM to motor speed. Commented Jun 28, 2018 at 8:52
• That would not be the solution...because of the variation in the BUS voltage to the motor that graph would be meaningless. e.g. one day its 12V and another day its 11V ... worse if on batteries Commented Jun 28, 2018 at 9:00
• Oh right, so the input to the motor varies all over the place! That does make it more complicated: you therefore need to have a simple control loop in the software controlling it. You will need to feed in the desired speed, and either the current speed or the feed in voltage. Then put it through a control algorithm, you can probably just use proportional control unless your set up is charging very quickly. Commented Jun 28, 2018 at 9:34