# PID Controller for PWM of a linear drive motor?

Thread Starter

#### ponas.jonas

Joined Feb 28, 2023
40
I have linear drive motor that I drive with a PWM signal of frequency 1kHz. The minimum duty cycle for the linear motor to start moving without any load is 30 %. Now I am trying to design and tune a PID controller to control the position (ranges from 0 - 10000 counts).

My difficulty in understanding is: do I change the duty cycle of the motor, or do I set it to a constant value? My thought process is the further away it is, the faster it should move and the closer it is to the setpoint, the more it should slow down. The minimum duty cycle is 30% and maximum is 100%. If so, how do I go about doing so?

I have written some code that works, but only because I have set the duty cycle to 60%. I currently do not have any requirements for settling time and overshoot %, I am just trying to get something to work.
C:
// PID
#define KP 0.05
#define KI 0
#define KD 0

//Variables
double setpoint = -3000;
double input = 0.0;
double output = 0.0;
double error = 0.0;
double integral = 0.0;
double derivative = 0.0;
double last_error = 0.0;
C:
void PID_Controller()
{
// Calculate error and integral
error = setpoint - distance_um; // distance_um is read from encoder
integral += error;

// Calculate derivative and output
derivative = error - last_error;
output = (KP * error) + (KI * integral) + (KD * derivative);

// Update last error
last_error = error;

// Set PWM signal and direction based on output
if(output > 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); // Motor direction: Low goes "out"
htim3.Instance->CCR1 = 100;

}
else if(output < 0)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); // Motor direction: High goes in
htim3.Instance->CCR1 = 100;

}
else
{
htim3.Instance->CCR1 = 0;
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET); // Stop the motor
}
}

#### crutschow

Joined Mar 14, 2008
34,692
do I change the duty cycle of the motor, or do I set it to a constant value? My thought process is the further away it is, the faster it should move and the closer it is to the setpoint, the more it should slow down.
Correct.
You have a high duty-cycle when it is far away from the set point, and reduce the duty-cycle to slow down the motor as it gets close to the set point.

Perhaps an easier way to do that is to use Fuzzy Logic to control the motor which is generally more intuitive to understand, and can handle non-linear system characteristics, such as backlash, as compared to PID, which is designed for controlling a smoothly linear system.
It basically consists of a series of If-Then-Else statements to control the motor, e.g.

If the position is far from the set point Then set the PWM to 100% Else
If the position is close to the set point Then set the PWM to 60% Else
If the position is very close to the set point Then set the PWM to 30% Else
If the position is at the set point Then set the PWM to 0% Else.........
(add as many statements as needed to get finer movement control for the response you want)

Of course "close" and the other distances are defined by you (likely experimentally) as numerical values for the distance between the set position and the measured position.
Basically it's fairly easy to fine tune the logic to get the desired motor operation.
Adjusting the proportional, integrator, and differential values of a PID system to get good system response is generally less obvious, and thus more difficult.

Here's a short article I wrote about Fuzzy Logic.

Last edited:
Thread Starter

#### ponas.jonas

Joined Feb 28, 2023
40
Is there another way to do it in a more "smooth" way than if/else statements?

#### StefanZe

Joined Nov 6, 2019
191
Is there another way to do it in a more "smooth" way than if/else statements?
If you want it "smooth" you get the P part of a PID controller

Thread Starter

#### ponas.jonas

Joined Feb 28, 2023
40
How would I do that with a PID controller if I want to control the position of the linear motor. Would I use a constant motor speed or would I have to implement something else?

#### Sensacell

Joined Jun 19, 2012
3,475
The "P" loop is simple:

Determine your position error (final position - current position = error) then multiply the error by some fixed gain coefficient and apply the result to the PWM.
The direction of the drive output must change as the error sign changes, so things move in the correct direction.

You can see that the error signal goes to zero as the current position approaches the destination position, so the drive level decreases as you get closer.

Repeat this calculation constantly, faster that the mechanics can respond, then it will approximate a continuous linear system.

If your gain is too high, it will oscillate and never converge.
If it's too low, it will be sluggish and have a large position error.

Last edited:
Thread Starter

#### ponas.jonas

Joined Feb 28, 2023
40
The "P" loop is simple:

Determine your position error (final position - current position = error) multiply the error by some fixed gain coefficient and apply the result to the PWM.
The direction of the drive output must change as the error sign changes, so things move in the correct direction.

You can see that the error signal goes to zero as the current position approaches the destination position, so the drive level decreases as you get closer.
so if I have determined that the PWM duty cycle runs between 30 (slowest) and 1000 (fastest), how would my pseudocode look like? I understand this is a simple problem, but something in my brain is not clicking and I keep going in loops...

#### Sensacell

Joined Jun 19, 2012
3,475
so if I have determined that the PWM duty cycle runs between 30 (slowest) and 1000 (fastest), how would my pseudocode look like? I understand this is a simple problem, but something in my brain is not clicking and I keep going in loops...
Your PWM should be able to output "0" when the system error = 0. Capping the max PWM is not necessary, this just limits your drive level.

#### StefanZe

Joined Nov 6, 2019
191
error = final_position - current postion

if(error < 0 )
change direction

dutycycle = error*kp

If kp is too low the system will be slow, if it is too high it will oscilate.

Thread Starter

#### ponas.jonas

Joined Feb 28, 2023
40
Thank you for the reply, I have tried this but for some reason thought it was incorrect. Just a question regarding the values - the distance is calculated in micro meters, giving a range of 0-10 000. That would make me choose a very small Kp, as the motor can only perform within the PWM range of 30-1000, correct? would it be better to convert them to millimeters?

#### crutschow

Joined Mar 14, 2008
34,692
Is there another way to do it in a more "smooth" way than if/else statements?
Increase the number of statements.
You likely can use a 100% duty-cycle until you get close to the set point, and then use a series of statements to slow it down until it stops at the set point.
A series of If-Then-Else statements is much faster than doing mathematical calculations in the loop.

Last edited:

#### StefanZe

Joined Nov 6, 2019
191
Thank you for the reply, I have tried this but for some reason thought it was incorrect. Just a question regarding the values - the distance is calculated in micro meters, giving a range of 0-10 000. That would make me choose a very small Kp, as the motor can only perform within the PWM range of 30-1000, correct? would it be better to convert them to millimeters?
It does not matter.
If the duty cycle is calculated to be higher then 100% (1000 in your example) just cap it to 100%.

#### StefanZe

Joined Nov 6, 2019
191
Increase the number of statements.
You likely can use a 100% duty-cycle until you get close to the set point, and then use a series of statements to slow it down until it stops at the set point.
A series of If-Then-Else statements is much faster than doing mathematical calculations in the loop.
One multiplication will be faster than the tree of if else statements.

And the PID solution will give you a faster response time and a smaller error.

I don't see a reason to use the fuzzy logic solution.

#### crutschow

Joined Mar 14, 2008
34,692
One multiplication will be faster than the tree of if else statements.
Don't see that is true for a standard microprocessor unless you have a dedicated multiplier circuit.
And the PID solution will give you a faster response time and a smaller error.
What's your basis for that statement?
The calculations to rapidly perform all the math for analog PID equations takes significant processing power and time.
I don't see a reason to use the fuzzy logic solution.
And I see no reason to use PID which was an analog technique developed a century ago that is difficult to optimize and requires band-aids for proper control if the system is not linear.

#### StefanZe

Joined Nov 6, 2019
191
Don't see that is true for a standard microprocessor unless you have a dedicated multiplier circuit.
I think he is using a STM32 microcontroller, they have a multiplier circuit. And in this example you don't ned to use floating point numbers

What's your basis for that statement?
The calculations to rapidly perform all the math for analog PID equations takes significant processing power and time.
The PWM runs with 1kHz so you have more than enough time to calculate the output. So it does not matter how fast you calculate if you only update every 1ms.

And I see no reason to use PID which was an analog technique developed a century ago that is difficult to optimize and requires band-aids for proper control if the system is not linear.
Thats why nobody is using PID anymore and everything is controlled by fuzzy logic nowadays?

#### crutschow

Joined Mar 14, 2008
34,692
Thats why nobody is using PID anymore and everything is controlled by fuzzy logic nowadays?
Nice sarcasm.
No, just some who aren't stuck in the analog past and trying to control a non-linear system.

Below is from an old thread where I suggested a poster try Fuzzy Logic for his control problem:

I'm just embarking on an R&D project that involves closed loop pressure/flow control in a very dynamic environment. I had assumed I'd use PID, but was already considering adding some If-Then-Else logic to speed response in extreme cases that are hard to tune for. I might take an alternate stab at it with fuzzy logic and see how it compares!

Later post:
I've successfully coded my first fuzzy logic control system! Just like the tutorial said, my very first pass at it worked better than the PID algorithms had been doing, despite a few bugs I later discovered. I think all the bugs are out, and it's working quite nicely now, although I still intend to refine things further to smooth out the response even more, if I can do so without sacrificing responsiveness too much. Although it was a fair bit of coding for a novice like myself, in reality was not that much work for how well the system works now. Wish I had known more about fuzzy logic sooner!

#### MaxHeadRoom

Joined Jul 18, 2013
28,770
I have linear drive motor that I drive with a PWM signal of frequency 1kHz. The minimum duty cycle for the linear motor to start moving without any load is 30 %. Now I am trying to design and tune a PID controller to control the position (ranges from 0 - 10000 counts).
PIcmicro have AN600 on Fuzzy-Logic.

#### nsaspook

Joined Aug 27, 2009
13,433
I use both fuzzy logic and PID. PID for time critical phase/frequency/amplitude error offset calculations in interrupts (on 32-bit hardware with floating point hardware) and fuzzy logic for time continuous error feedback adjustments for dynamic tracking.

Last edited:

#### Danko

Joined Nov 22, 2017
1,843

#### Attachments

• 204.7 KB Views: 4

#### StefanZe

Joined Nov 6, 2019
191
Nice sarcasm.
No, just some who aren't stuck in the analog past and trying to control a non-linear system.

Below is from an old thread where I suggested a poster try Fuzzy Logic for his control problem:

I'm just embarking on an R&D project that involves closed loop pressure/flow control in a very dynamic environment. I had assumed I'd use PID, but was already considering adding some If-Then-Else logic to speed response in extreme cases that are hard to tune for. I might take an alternate stab at it with fuzzy logic and see how it compares!

Later post:
I've successfully coded my first fuzzy logic control system! Just like the tutorial said, my very first pass at it worked better than the PID algorithms had been doing, despite a few bugs I later discovered. I think all the bugs are out, and it's working quite nicely now, although I still intend to refine things further to smooth out the response even more, if I can do so without sacrificing responsiveness too much. Although it was a fair bit of coding for a novice like myself, in reality was not that much work for how well the system works now. Wish I had known more about fuzzy logic sooner!
Hi,
Thanks for noticing the sarcasm.

Maybe the fuzzy logic is the way to go with this problem. I don't think so, but only the TS can find out for us.

The fuzzy logic is "easier" to code and will perform better without optimizing because it has broader range of stable parameters.
I'm not so sure how good the performance is with disturbance and correcting the error because of it.