PID controller help

I have been trying to learn PID but all the websites I have looked at seem overly complicated. I am trying to implement it into my flywheel programming and I only have a limited understanding of it to where I can get it to operate, but I am still trying to figure out how to find good values for P and D and any other simple additions that can make the programming the most efficient. Does anyone have any tips, links, or effective PID tutorials that you have found helpful to your team?

1 Like

when I started looking into PID loops I could not find any good tutorials, so I made one,

this one goes over how to tune the loops control the integral term and some others that will help

Just remember this is basically what a PID loop boils down to:
error = targetVelocity - actualVelocity

Proportional = error * Kp

totalError += error
Intergral = totalError * Ki

Derivative = (error - lastError) * Kd

motorspeed = Proportional + Integral + Derivative

The video above is also really helpful as it contains quite a useful explanation of the basics of PID.

Just in addition. One of our forum members wrote a nice guide to pid that I like. I refer to it whenever I need to explain PID to people at school.

Out of all the PID videos I have seen, this one is probably the best. However, I am still confused about a couple of things. In this video, you made your motor powers = P+I+D. In my code, I made the motor powers += P+I+D which makes more sense to me and has seemed to be working well. But after watching the video, I am doubting myself. I know that making the motor powers = P+I+D works for driving, but is it the same when working with flywheels?

the answer here is that you want it to be motor power = P+I+D, it seems really counter intuitive, but that’s true. I had some problems figuring out why this was true when I started as well. This seems counter intuitive, because what we then get is that you grantee oscillations, and you grantee that the fly wheels will never be spinning at the exact velocity you want them to, however this is still better than the alternative.

here’s why, when power = P+I+D, the program will settle at a power value that causes a speed slightly lower than targeted value( because of the P term, when error = a certain value the power coming out of the P term will keep the wheels stable at that speed), then the integral term slowly accumulates over time and pulls it up the to the desired speed, and settles there, at your desired speed, hopefully with little to no oscillation if your PID tuning is perfect.

the reason this is better than the += method is that as stay away from your desired speed the value for power (if power=+P+I+D) accumulates very very quickly, and you will over shoot your target speed like mad. the problem here is that, the motors will reach 127 power very quickly but power could very well equal 500000 or some crazy number, then you over shoot and power de-accumulates, and eventulay hits negative, then your shooter starts slowing down, and power gets to -50000000 and you undershoot. Essentially what this method does is it treat all of ā€œP+I+Dā€ like the integral term meaning it accumulates over time, which causes oscillation and large overshoots. if really cancels out the effect of the D term, because while the D term might take away 5 every time, the P term will add 50, and so if you do 45+45+45+45, your numbers get way to big way to fast

It depends on whether you are doing position or velocity control. In simple terms

motor_power = P + I + D (where P = error*Kp etc.)
This is because when the error is 0 you want motor power to be 0 also.

for velocity control
motor_power = motor_power + (P + I + D)
When the error is 0 you want to maintain the motor power you have determined.

There’s more to it than this, but hopefully it explains it a little.

For those of you wondering more about why this is:

In the PID loop that most are used to, ( power = PID(pos_error) ) we are simply controlling the position of something. With flywheels and other similar subsystems, we want to control the velocity of the subsystems, rather than the position.

Since velocity is the derivative of position, we cannot control it the same way. Some sort of modification must be made to our positional PID controller in order to control velocity. There two ways to go about this.

Approach number 1 would be to use the integral term as a way to ensure that a constant power value is traveling to the motor. The integral would be large and essentially carry the PID loop. The D term would still dampen, but the P term would essentially only work to ramp up the shooter since it would return a low value when the error is small. Essentially, I is doing everything. While this may work, it is not the best approach, because now the I term will not be focused on steady state error. Thus, steady state error may become a problem.

Approach number 2 is to use the += method described above. It makes the most sense mathematically when you consider that you are now controlling the derivative of position, which is velocity. To get velocity (at a basic level), we subtract the last position from the current position, hence giving the rate that the position is changing. The same concept can be applied to change the error of the position to the error of velocity. This is equal to simply PID(pos_error - pos_last_error). but we aren’t done yet.

The PID is now returning the rate of change, or slope, of the power instead of just what to set the power to. ā€œoutput - output_lastā€ is the rate of change of the power. As a result, the following is what our control system will look like:
output - output_last = PID(pos_error - pos_last_error)
or simplified:
output = output_last + PID(vel_error)

Hope I explained everything right and helped someone out.

Oldest series on my channel about a simple position PID controller. It’s my first tutorial attempt so it’s just not there yet… but hope you can get some inspiration from it. Or just look at the code posted below videos and look at the parts you don’t understand.

Didn’t actually get a chance to make a velocity controller tutorial. Will do that is the future if possible.

Also, go take a look at Mr. Pearman’s take back half algorithm for flywheel velocity. Amazing stuff.

ok, so from what I see, I have been doing this the wrong way, but heres the problem I’ve been having, when I do power+= P+I+D, I get way larger occilations than when I do power = P+I+D, why might this be, have I tuned the constants inccorectly, or might there be some other problem?

Most likely your constants are not tuned correctly. Getting kP, kI, and kD just right in an application like this can be difficult. You may want to start with just P

Assuming that you are correctly implementing PID, the problem would then be tuning I would think. If you have oscillation, then you should dampen your system more. Also, the constants for positional PID and velocity PID will not be the same (or even similar) for the same subsystem. The velocity constants tend to be much smaller since you are adding up all of the PID values over time.

I’m using ā€˜approach #2’ but I’m not entirely sure if I’m doing it right. It looks to me like you are making the acceleration of the power equal to the acceleration of the PID of the speed which is confusing. My code says: flyPower += errorpGain + changeInErrordGain;
in which the error is the desired speed of the flywheels - the calculated speed of the flywheels. What would I need to change/add if I wanted to make my code consistent with your method?

Don’t use +=, it’s a bad habit even if it feels intuitive, it’s incorrect.
If you are trying to do velocity control:

  1. measure the number of counts at a specific periodic time interval
  2. the accuracy of your time interval is important, error in this is the same as error in your integral gain. although if it dithers it will average out.
  3. compare this against your target counts for that interval (velocity)
  4. use output = P + I + D + C
  5. everyone seems to leave C out, it’s a constant if you need one, like the offset these motors may need (15 or so) to go from 0 to just moving. Your integrator may absorb this value, but it can’t immediately handle a transition from say 15 to -15.

using += turns the P in your equation into an integrator o you have no good instantaneous response. By trying to get it you may turn up the gain, which is actually turning up an integrator gain, and you will oscillate. You need a proper P in the system to give you instantaneous response.

D will rarely be needed, although may in some circumstances. problem is that it is a great noise generator and very dependent upon the resolution of the sensor and time interval.

BTW, the P portion of the output can be updated as quickly as you want (simulate an analog error amp). So you may update your output every 10ms by updating the P portion, while updating the I portion only every 50ms. Sometimes this will give you better response.

Great being with you guys in Worlds Finals last year :slight_smile:

I disagree.

So if measured and target counts are equal then the error is 0. If I, D and C are zero (for the sake of argument) then output will also be 0. But then the motors are not moving, that would seem to be a problem. Are you assuming that output is not driving the motor directly?

I won’t be 0, it will be the output value required to get the error to 0.

Unless you are standing still and your target is 0

But with velocity control the error will be zero when the ā€œvelocity errorā€ is 0. If you want to run at 200 counts/second and you measure 200 counts/second then the error will be 0. This then means maintain that output that you already have, ie. the required change to the drive is 0.

Exactly, but you had to have error to get to 0 error, that output was wound up in the integrator, so it has the output value you needed to get to the velocity that gives you 0 error.

At this point, P contributes nothing, although it contributed a lot at the start from 0 velocity.

By using the += you’ve turned the P into what the I is supposed to do. However, by doing this, you’ve lost the P. That is, the part of the equation that acts on the system only for the ā€œtickā€ (10ms, etc…) is gone because you’ve given it infinite history in the overall equation by adding in for the next ā€œtickā€. So the ability to have instantaneous response, up or down, is defeated.

So in this implementation Ki can never be 0 and therefore the tuning will be a little different. I have to admit I’ve never done it this way, but that’s probably because I’ve almost never needed to use velocity PID in the past.

It’s the same for position as it is for velocity, if you have an opposing force, and want a 0 error, then the integrator needs to be used.

For example, if you had a position controller on a vex bot lift, the integrator is what would wind up to the motor power required to hold the lift at the proper position opposing the downward force of whatever was being lifted (a weight). You could get some position to work with just P, but it would not have 0 error (correct position) unless you had an infinite Kp (proportional constant). A P only control will always have error, by definition the output = 0 when the error = 0.