### Author Topic: PID motor control  (Read 4600 times)

0 Members and 1 Guest are viewing this topic.

#### MikeK

• Full Member
• Posts: 97
##### PID motor control
« on: March 19, 2011, 08:09:42 PM »
Does a PID algorithm only work well for a steady motor demand, like when the robot is running on a flat surface?

I've been looking into working PID into the control of my robot's wheel speed.  But since it travels on downhills as well as flat ground I'm wondering if the PID constants, developed for flat ground, would be totally wrong for when it does downhill.

And then I thought: Is it even necessary to use PID for wheel speed control?  If I just use a simple feedback loop, wouldn't this be good enough?:

Code: [Select]
`while (1){    s = CalcSpeed();    if (s > targetSpeed)        pwm = pwm - 1;    else if (s < targetSpeed)        pwm = pwm + 1;    SetMotorSpeed(pwm);}`
Mike

#### waltr

• Supreme Robot
• Posts: 1,944
##### Re: PID motor control
« Reply #1 on: March 19, 2011, 08:27:29 PM »
When the motor 'load' is not constant it is more important to use PID in the control loop.
A properly tuned PID will ensure that the loop response is quick without oscillating even with a drastic change (load or command).

You may not need full PID, many times only 'P'roportional or PD is enough. You need to measure the control loop response to determine what you really need or can get away with.

Write some code that outputs the Control output (motor duty cycle) value, feed-back value (encoder) and set-point (input command speed) to the UART and a PC. Do this with the Bot on a flat, level surface, up hill, down hill and then over bumps or from flat to up etc. Plot the values (Excel works well) and see how fast the control loop adjusts and if it rings or oscillates when perturbed.

My small Bot just uses Proportional. There is some ringing when the load or speed command changes but not enough to cause problems.
« Last Edit: March 19, 2011, 08:39:42 PM by waltr »

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #2 on: March 19, 2011, 08:35:45 PM »
Okay, that brings me back to my original question then.  Wouldn't the PID constants for flat ground be totally inappropriate for hills?...Since the response in those two situations will clearly be different.

#### waltr

• Supreme Robot
• Posts: 1,944
##### Re: PID motor control
« Reply #3 on: March 19, 2011, 08:42:35 PM »
No, the PID constants are to optimize the control loop response which will compensate for any external disturbances.

#### Billy

• Robot Overlord
• Posts: 132
##### Re: PID motor control
« Reply #4 on: March 22, 2011, 01:47:40 PM »
If I just use a simple feedback loop, wouldn't this be good enough?:

Code: [Select]
`while (1){    s = CalcSpeed();    if (s > targetSpeed)        pwm = pwm - 1;    else if (s < targetSpeed)        pwm = pwm + 1;    SetMotorSpeed(pwm);}`
Mike

Yes, that would work if you're simply trying to get something to move using a velocity command. It would be slow to adapt to changes in command. Here's a very simple P loop.

Code: [Select]
`while (1){    error = setSpeed - CalcSpeed(); // if moving slower than wanted, positive error     pwm = pTerm*error;    SetMotorSpeed(pwm); // assumes SetMotorSpeed can handle negative numbers}`
This will react to changes in command or load quicker. Set pTerm to get quick response but without oscillation.
Adding I and D terms requires you control the timing of the updates carefully so complicates things, but you can run the P term at varying intervals without large impacts provided CalcSpeed() can provide accurate measurements of speed. Even for P, the updates should be much faster than mechanical reaction time of the motor/wheel combination. Otherwise you do need to control the timing carefully.

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #5 on: March 23, 2011, 10:08:44 AM »
Actually, for the D term, the exact timing is not important.  Consider this:

the output of the PD controller is T, so:

T = P*error + D*dError

Where dError = (error1 - error2)/deltaT

right?

but since deltaT is (approximately) constant, we can just absorb it into the gain, D, so we get

T = P*error + D'(error1-error2)

And that should work fine (it works great in just about any PD loop I've ever used :-P ).  Since no one ever tunes a PD controller using formulae (but yes, it IS possible, especially for a DC motor), and everyone just chooses gains and screws around with it until it works, this is a fine way of doing it.  Note that since this is for speed control, we'll have to make the same argument for P, since error is, in fact, an error on speed, but the same idea applies -- just tune P until it works, and the gains will take care of timing for you.

As for the "I" term: that should only ever be used if there is some reason you'd have steady-state error (that is, error that doesn't go away once the motion is done).  If we consider a motor control loop for motor speed, steady state error will only happen if the motor isn't powerful enough to overcome the disturbances acting on the system anyway.  That means that the integral term will do nothing but ramp up the control signal -- but it'll be completely saturated anyway, since the PWM is giving the most it can give.

What the I term is spectacular for, though, is overshooting where you want to be.  So ignore it unless you have weird friction effects and are doing position control (and even then...)

In reality, the OP's "simple feedback loop" would behave very strangely.  It would do what's known as "chattering": consider what happens with s = targetSpeed + 1.  Well, then pwm goes down.  But now (say) s = targetSpeed - 1, so pwm goes up, and s = targetSpeed +1.  Since the calcSpeed() function will probably be noisy, PWM will chatter around where it should be, and the robot will lurch.  *that* is why we use feedback control.
Current project: tactile sensing systems for multifingered robot hands

#### Billy

• Robot Overlord
• Posts: 132
##### Re: PID motor control
« Reply #6 on: March 23, 2011, 11:33:22 AM »
Actually, for the D term, the exact timing is not important.  Consider this:
...we can just absorb it into the gain, D, so we get
T = P*error + D'(error1-error2)

Absorbing the time into the dTerm gain is exactly why timing is important. If you explicitly have the time term calculated, then timing isn't important as the math takes care of variability. With the time "assumed" in the dTerm, you'd better get the timing right or you'll have huge errors as the dTerm is usually a large multiplier.

I've seen an industrial motor controller have glitches of full scale output positive then immediately full negative caused by a few uS delay of getting encoder values. An ADC interrupt would occasionally prevent the DSP PID loop from starting on time and they had also absorbed the time part of D into the gain. It's ok to do it provided the PID loop gets input data in top priority interrupt.

For the OP, an I term may help him on the slope he wants his robot to climb...less likely to jump forward when it gets to the top and the load changes quickly.

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #7 on: April 01, 2011, 11:49:35 AM »
You've provoked a question I've had about PID for a while now...

Aren't the PID constants much more than correcting error response?

That is, your sensor measures speed  - or probably in most cases it measures the time of two segments (B&W) of a decoder wheel to pass in front of the sensor.  Changing the speed requires changing the PWM duty cycle.  You measure time and then apply that value to setting duty cycle.  They're different units that don't directly convert from one to the other.

Isn't it likely that the PID constants will do a poor job of correcting error because they're also scaling time to duty cycle?

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #8 on: April 01, 2011, 11:56:43 AM »
I'm not sure I fully understand your question, but I interpret it like this:

Since the PID controller outputs a *continuous* function,and the PWM effectively takes that continuous function and converts it into a discrete approximation, is it likely that PID will do a poor job because the output of the PID and the input to the motor are in different domains? (was that right?)

If so, it's not the PID that's the problem, it's the PWM.  PWM is a discrete approximation to a continuous input, but if your time step is too large, that approximation fails to be valid.  In the ideal case, PWM would have infinitessimal (that is...almost but not quite zero*), but in reality PWM works fine even if the period is quite large for a vast array of systems.  One lab I used to work in used a PWM period of 2 minutes.  The system, a satellite in this case, responded so slowly to the input anyway that such a large period was acceptable.  But that period wouldn't have been suitable to, say, dimming an LED.

So it's a bit of an art to choose the right PWM period that sufficiently approximates the input for the system you're using, and sometimes if the control starts to fail, it might not be that the PID gains are tuned badly, but that the PWM settings are off.

Of course, if that wasn't your question.. :-P Now you know about PWM anyway haha (assuming you didn't already :-P)

*Although if this were the 1700s, that definition would have created a terrible debate amongst mathematicians.
Current project: tactile sensing systems for multifingered robot hands

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #9 on: April 01, 2011, 12:20:07 PM »
What I was getting at is that you measure speed, but you don't output speed.  You don't tell the PWM to go 50MPH.  And because of this there is a [at least rough] scaling that needs to be performed.  That is...A scaling to answer the question: What is the relationship between PWM value and speed?

To take a simple example...The sensor measurement is a value of 5000 (clock ticks), but the PWM is to be set in the range of 0 - 255.  Right off the bat you see that the "P" constant needs to be a fraction that is less than 1.  Which isn't necessarily a problem, but you'd have to know that you're dealing with such a small number (and the processing necessary to make the calculation), instead of just trying out various integer constants.

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #10 on: April 01, 2011, 12:39:50 PM »
I don't see why the P gain would have to be a value less than 1.  PWM works by having some maximum output (let's call it 100).  If we then compute from the PID that we need an output of 50, then the PWM duty cycle is set to:

(nearest integer)255*(50/100) (which in our case is 127 or so).

If the PID outputs some gigantic value, like 5000, then we'd have to set PWM duty cycle to 255, since it can't be larger than 100%.  This means that an output of 255 isn't an output of torque, but an output of time that the motor should be on in the next PWM cycle.

In this case, yes, there is a scaling-type issue, but it comes from what we decided our maximum output should be, which depends on the motors (or whatevers) we're controlling.  So let's say my motors give me a maximum torque of 100Nm, but my PID requires a torque of 500Nm.  Nothing my robot can do will ever get me what the PID asked for.  My controller will then *saturate*, which is a nonlinear phenomenon that can sometimes cause controllers to perform terribly.

Doing a real analysis on your motors and robot might be fun, but often times we just choose numbers that "feel right" and tune them experimentally until the robot does more or less what we expect it to.

Does that answer the question?  You're correct to say that PID will come up against these problems.  PID is a linear controller and in theory could demand any possible value.  Motors are nonlinear because they can't provide more torque that a certain amount (depending on the motor itself, the power supply etc) , so eventually you'll get to a point where your robot can't do what the PID wants it to, and those are fun times indeed.  There are controllers that deal with this, but people use PID because:

a) It's very simple
b) When it works, it works REALLY well.  And most of the time it works.

MIKE
Current project: tactile sensing systems for multifingered robot hands

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #11 on: April 01, 2011, 12:52:57 PM »
I think what's throwing me off is that in my test setup there is an inverse relationship between PWM value and sensor value.  A large sensor value means a slow speed, because the sensor measures interrupt time at the decoder wheel.

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #12 on: April 01, 2011, 02:13:16 PM »
I'm going to take another stab at explaining my confusion.  I do appreciate your help, Mike.

I have a small DC motor I'm controlling with a PIC.  I have the PWM setup such that it has a setting range of 0 - 255.  My encoder wheel sensor measures the pulse period, which is a two-byte value (0 - 65535).  I picked an arbitrary setpoint and calculated the period to be about 3750 (equates to about 1000 RPM).

So if I measure the period and get a value of 5000, the error is 1250.  This doesn't translate to the PWM range, hence my confusion about scaling.  And I know from experimenting that a PWM value of 70 gets me about the value that I want (period of 3750).

(I have the additional problem of a large PID error requiring a reduction in PWM - since they're inversely related - but this seems to be just a matter of flipping the sign of the error.)

Mike
« Last Edit: April 01, 2011, 02:25:28 PM by MikeK »

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #13 on: April 01, 2011, 02:28:27 PM »
well there are two possible solutions here.  The first is that the PWM simply can't handle the required change.  That's entirely possible (for instance, if I want my motor to turn at 5000 RPM, it might need more power than I have.  My motor can't turn that fast no matter what the PID says.)

Second, let's say that when the PWM is at 255, the motor is turning at 3000 RPM.  We now need to compute the percentage of time that the PWM will be on.  To do this, we'll use the output of the PID (let's just assume for now that the PID output is in RPM of the motor.  This is weird, but for an explanation purposes it should do).

so if the PID requests an output of 1500, the PWM should be on for (1500/3000 * 100%) = 50% of the PWM cycle. (In reality, it doesn't really scale like this, but that's just because the PWM output only really affects the power into the motor, and THAT affects the speed, but again for our purposes its fine).

So we set the PWM output to 127, which is 50% of 255.

I should point out that the user named "Billy" provided an algorithm that would not work, and that may be the source of your confusion.  You set the PWM based on a percentage of the requested output compared to the maximum output, you don't just set the PWM according to that requested output.

Does that explain it?

MIKE
Current project: tactile sensing systems for multifingered robot hands

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #14 on: April 01, 2011, 02:50:14 PM »
Oh.  Yes, that's what I didn't understand...How to get from the sensor measurement to the PWM value.

Then it seems that before you can implement PID you have to at least measure the max sensor value when PWM is at max?

You set the PWM based on a percentage of the requested output compared to the maximum output, you don't just set the PWM according to that requested output.

This is the elusive scaling.   Thanks.
« Last Edit: April 01, 2011, 02:54:42 PM by MikeK »

#### rbtying

• Supreme Robot
• Posts: 452
##### Re: PID motor control
« Reply #15 on: April 01, 2011, 03:41:50 PM »
Then it seems that before you can implement PID you have to at least measure the max sensor value when PWM is at max?

That would be a good idea, yes.

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #16 on: April 02, 2011, 10:17:53 AM »
It seems to be more than a good idea, but a requirement.  Otherwise how can you calculate the proper scaling?

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #17 on: April 02, 2011, 10:42:59 AM »
I just thought of something that may have been obvious, but I didn't realize it until now...

Since my sensor reads a 16-bit value and my PWM is an 8-bit value, I should be able to scale the sensor value down by dividing by 8 and then the errors and PID output translate directly to a PWM setting.  Yes?

Of course, this assumes linearity in both domains, but it at least puts everything into the same range.

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #18 on: April 02, 2011, 10:47:29 AM »
Well...you don't need to know it 100% exact...just get close enough :-P  For instance, my PID controller would output a maximum value of 125.  What does 125 mean?  I have no idea.  So I set my PWM max to 150 just in case the number was calculated wrong, and it worked fine.

A really easy thing in webbotlib is to just set the PID limits to +/- 100.  That way the PID *is* the PWM setting.  Of course, this can't work all the time, but...

One thing to notice with controllers is that unless you're doing something that needs super accurate, repeatable results, you have a lot more leeway than you think when it comes to tuning them or dealing with scaling.

Here is how I usually do this if I don't know what the maximum is:

Start with a really low value.  The worst thing that can happen here is nothing -- the motors won't turn.  If you started with a really high value, then you might accidentally damage something (well, I'm always cautious that way...).

Run the robot and see what it does.  If it didn't even move, increase the maximum a lot.  If it moved but slowly, increase it a little.  Just tune it until the robot works well on a wide number of possible inputs.

Why would I do this instead of figure out a maximum?  Well, for one thing I don't *know* the maximum.  I'm doing force AND position control on a robot finger.  Position is easy, but force is a function of the torque at the joints, which I can't measure and which changes depending on the speed of the motor anyway.  The other reason is that if it doesn't seem to work quite right, I can always just tune my gains.

You CAN go into the theory of PWM (In fact, I strongly recommend it!) and learn exactly how to measure and set maximums and so on, but most control engineering is a lot of rules of thumb and trial and error.  And trust me, once you've got a few controllers under your belt, you'll really have an intuitive feel of how to tune them for most simple systems.  Just practice!

Also, no, don't scale your sensor at all.  Since you're computing a percentage of time that the PWM should be on in each cycle, it won't matter.  If your sensor values say you need 50.3% on-time, you'll never be able to make it exact on an 8-bit PWM, but having more sensor resolution may be useful later.  (otherwise, why would you use a 16-bit sensor value in the first place?)

MIKE
Current project: tactile sensing systems for multifingered robot hands

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #19 on: April 02, 2011, 12:21:33 PM »
Ugh.  I'm getting confused again.

The sensor doesn't tell me I need a 50.3% duty cycle.  The sensor tells me how fast the wheel is moving.  In my case it's an inverse relationship, because it's a measurement of time between wheel pulses.  So, it seems to me that the value does indeed need to be scaled, because I have to go from a sensor value of X to a duty cycle of Y.  If I don't scale it, it has no meaning.

#### mstacho

• Supreme Robot
• Posts: 376
##### Re: PID motor control
« Reply #20 on: April 02, 2011, 01:11:26 PM »
Yeh, sorry that was my lack of clarity.

The sensor needs to be scaled by whatever you choose as your maximum value.  My point was that you shouldn't try to lose precision, since it's a percentage anyway.  So if your sensor is 16-bit, then your maximum value should *also* be 16 bit.  This is because if the sensor is x and the max. is y, then x/y <= 1 always, right?  But this would be true if x and y were 8 bit, 16 bit, or whatever.  As long as x and y are the SAME precision, this will work (if they're different precision, it will fail almost always :-P )

Now if your PWM is 8-bit, then you'll be sending it 255 to make it go to maximum on-time.  So you do x/y*255 to get the amount of time it should be on during a cycle.  If x/y > 1 (for example, if you chose the wrong maximum and it was too small), then just make a little if statement:

if (x > y)
x = y;

this way you ensure it's never going to ask for more than the PWM can give, even accidentally.

Note that, in C, it's possible that x/y*255 will return a double.  This is bad.  So once you have x and y, this is how you choose the PWM on time:

pwmOnTime = (int)x/y*255; //or char, or Byte, or whatever it is that the PWM functions need to take. In short, you have to cast!

So the precision used to figure out x and y is not relevant to the precision of the PWM on-time.  It is, however, relevant to how fast your uC can handle it.  If you don't NEED 16 bit precision, don't USE 16 bit precision.  when the number of sensors is small it doesn't really matter, but with a lot of DAC going on, it'll eat up processing power like no tomorrow.  But if you need it, use it!

MIKE
Current project: tactile sensing systems for multifingered robot hands

#### MikeK

• Full Member
• Posts: 97
##### Re: PID motor control
« Reply #21 on: April 02, 2011, 01:36:30 PM »
if the sensor is x and the max. is y...you do x/y*255 to get the amount of time it should be on during a cycle.

Yes!  This is what I was trying to understand.  Took us a while, but we got there.  Thanks, I can sleep tonight.

#### mstacho

• Supreme Robot
• Posts: 376