View unanswered posts | View active topics It is currently Thu Sep 19, 2019 10:18 pm



Reply to topic  [ 106 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 11  Next
PID control discussion 
Author Message
Post Whore!
User avatar

Joined: Sat Feb 16, 2008 12:11 am
Posts: 629
Location: Sunny San Diego
muythaibxr wrote:
In any case, it works as well as it can given the PWM output problem, so I'm done arguing it. The wonderful thing about PID controllers is that they can be done different ways. I chose the way I chose, it works for everyone who's tried it aside from you and the odd few who recently ran into bugs that were unrelated to the PID loop itself, so I'm done discussing it. If you don't like the way it works, go write some code that works the way you want it to. My code is a PID controller, and it does work the way it's supposed to. I'd fix the code if anything you said made me think it was broken, as I don't want bugs in my code.

Ken

Ken,
I want to second everyone else's comments, thanks for taking the time to talk through this - between here and MS forums, I know there is an awful lot of time invested. It's my own fault since I don't let things go if I'm not convinced, but I feel this (in the end) creates the best output of any development project.

One more thing before the meat of it, I'm not saying this is a 'bug' in that the code is broken, and does things which it shouldn't. I'm saying it's not a PID controller, and (in my and others' experience) tuning your three "P, I, and D" constants as you would in a genuine PID controller doesn't yield the right results. I've done it 'by feel', and it didn't work too well, and then I did it 'by the book' and again I had issues. And the math doesn't support it either.

I'm appreciative for the help in getting my own car working. And if there's more to it, then I'd like to know, for my own edification.



muythaibxr wrote:
Quote:
OK so next iteration of the loop, I now have a valve position of 54%, and lets say RPM dropped to 1200, because the valve closed some on the last iteration..
Now you have to be kidding me. Your motor was at 1600 rpm. That's 26 revolutions per second, or 37milliseconds per revolution. Now I forget if you run 200 ms loop time or 100, but either way, you expect me to believe in 5 revolutions you dropped 400 RPM, all from cracking a valve a couple percent? I can kill the ignition and my motor won't drop 400 revolutions per second.


That doesn't matter, the point is that no matter how much engine speed changes, eventually with only a P term set, the delta will reach 0. The only reason it wouldn't is if your P term is too high, and it overcorrects, overshooting the target. This is EXACTLY what can happen with a P term that's too high.

I don't want to repeat myself from the other forum, but the very first part of any PID lesson says
output = Kp * error
for a P controller. It's inherently not going to settle, except for 'drag' in the system (say fluid resistance, heating of a spring, etc, dampening energy out). Changing P should only effect the magnitude. P is your spring in a harmonic oscillator.

And, think about it, what's the purpose of the "I" term? The I term is in there to remove DC offsets from the P term controller.

The point is, with a proper proportional controller, you get a quick response, as well as a natural braking as you approach your setpoint. Not 'prediction', just what you would naturally do. If you have your foot on the throttle, and you're trying to get to 50 mph, as you get from 40 to 45 mph, do you back off, or press harder? I back off, since my error is now small.

OUTPUT += Kp * error
Will press harder.


And this will allow a rapid response to something like a sudden unexpected load (turning on headlights or AC), by having a much larger P term. I'm pretty convinced now that P is MUCH smaller than it should be, because in order to make something stable with your system, if must have a small P to work.

When you have a system TOTALLY timescale independent if Ki and Kd are = 0, then you'll be in the ballpark.


Thu Apr 24, 2008 6:05 pm
Profile ICQ YIM
Moderator
User avatar

Joined: Tue Jan 15, 2008 2:31 pm
Posts: 15332
Location: Home sweet home!
With regards the output thing, RPM is the input, the calculations are based on that only, and the difference in duty is the output. So, the duty is some amount, say 50% and the RPMs are a bit low, say 700 and you want them to be 800, then the loop if its tuned very very well will make the difference say 5% duty and add that to the 50% to get 55% which might produce another 100 RPM and make the target.

You don't get an output DC from this code, you get a difference in output DC right?

The way that relates to RPM depends on the valve and engine and tuning of normal parameters and tuning of PID parameters.

The error that you += onto the DC could be negative so 50 += -5 = 45 etc

Correct me if I'm wrong.

Admin.

_________________
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!


Thu Apr 24, 2008 6:14 pm
Profile WWW
LQFP112 - Up with the play

Joined: Thu Apr 10, 2008 5:51 pm
Posts: 205
Admin wrote:
With regards the output thing, RPM is the input, the calculations are based on that only, and the difference in duty is the output. So, the duty is some amount, say 50% and the RPMs are a bit low, say 700 and you want them to be 800, then the loop if its tuned very very well will make the difference say 5% duty and add that to the 50% to get 55% which might produce another 100 RPM and make the target.

You don't get an output DC from this code, you get a difference in output DC right?

The way that relates to RPM depends on the valve and engine and tuning of normal parameters and tuning of PID parameters.

The error that you += onto the DC could be negative so 50 += -5 = 45 etc

Correct me if I'm wrong.

Admin.


You've quite accurately described a pure integral controller. The previous output is a sum of all the previous errors (times Ki), then you take the current sample, multiply it by Ki, add it to the previous sum, and set the output to the new value.

There is not a whole lot technically wrong with a pure integral controller. One niggle is if you want it to have a decent rise time, you end up with a lot of overshoot and oscillation.

I define proportional, integral, and derivative as the following:
Proportional = "get it close"
Integral = "get it exact"
Derivative = "keep it there"

We combine all three components to optimize all three characteristics: rise time, overshoot, and oscillation. You first tune proportional to get a decent rise time. This leaves you with a steady-state error that is constant. You then feed in some integral to reduce the steady-state error to zero. Then you very slightly add some derivative to reduce the oscillation.

There is another type of controller, the inside-loop/outside-loop controller that consists of two proportional gains and a differentiator (or integrator depending on what you are trying to control) and it extremely easy to tune. You tune the inside loop for optimal damping, then you tune the outside loop until you get a system that goes full-on/full-off to exactly the output to you need to hold steady-state, without any outputs of different values.

I don't know the math off hand for that one, but I have done it. It's pretty neat to watch a high-speed electric motor turn exactly 90 degrees and stop in 20ms with zero overshoot. The control goes full forward, then full reverse, then no output (in that case), with the motor exactly in position.

_________________
Keith MacDonald
Control Engineering (Systems) Technologist


Thu Apr 24, 2008 11:29 pm
Profile
LQFP112 - Up with the play

Joined: Tue Apr 08, 2008 9:14 pm
Posts: 160
I'm happy to see discussion on this. It's a bit beyond my level but it illustrates a key point in that there are many ways to skin a cat. Just because something works doesn't mean it's right and just because it's right doesn't mean it works.

That's the irony in all things supposedly absolute.

I'm interested to get my hands dirty in this a little more. :D


Fri Apr 25, 2008 12:47 am
Profile
Post Whore!
User avatar

Joined: Sat Feb 16, 2008 12:11 am
Posts: 629
Location: Sunny San Diego
thebigmacd wrote:
[We combine all three components to optimize all three characteristics: rise time, overshoot, and oscillation. You first tune proportional to get a decent rise time. This leaves you with a steady-state error that is constant. You then feed in some integral to reduce the steady-state error to zero. Then you very slightly add some derivative to reduce the oscillation.

That sounds like every lecture I've ever read or attended on PID controllers. Shame no one is around to see it.

Quote:
There is another type of controller, the inside-loop/outside-loop controller that consists of two proportional gains and a differentiator (or integrator depending on what you are trying to control) and it extremely easy to tune. You tune the inside loop for optimal damping, then you tune the outside loop until you get a system that goes full-on/full-off to exactly the output to you need to hold steady-state, without any outputs of different values.

I don't know the math off hand for that one, but I have done it. It's pretty neat to watch a high-speed electric motor turn exactly 90 degrees and stop in 20ms with zero overshoot. The control goes full forward, then full reverse, then no output (in that case), with the motor exactly in position.

Oh, hey, that sounds pretty good. I like it, is it particularly computationally expensive? From what you said it's hard to say if it's good for a dynamic system (though it sounds it), more I wonder if it's too sensitive to it's own variables (i.e. a motor's response to idle valve movement depends on the load on it. Boost's response to opening the valve depends on the spark tables that day, etc)
-Abe.


Fri Apr 25, 2008 2:55 am
Profile ICQ YIM
LQFP112 - Up with the play

Joined: Thu Apr 10, 2008 5:51 pm
Posts: 205
8InchesFlacid wrote:
Oh, hey, that sounds pretty good. I like it, is it particularly computationally expensive? From what you said it's hard to say if it's good for a dynamic system (though it sounds it), more I wonder if it's too sensitive to it's own variables (i.e. a motor's response to idle valve movement depends on the load on it. Boost's response to opening the valve depends on the spark tables that day, etc)
-Abe.


Inside/Outside loop is not computationally intensive at all.

I'll try to describe it in a nutshell, then provide some pseudocode:
(I love OpenOffice)
Image

Code:
Position[1] = Position[0]
Position[0] = Position_Sensor
Speed = (Position[0] - Position[1]) / Sample_Period  // Find the 1st derivative of position to get speed
Position_Error = Position_Requested - Position[0] // Find the position error
Speed_Requested = Position_Error * Kpp // Feed the position control to the speed controller
Speed_Error = Speed_Requested - Speed // Find the speed error
Output = Speed_Error * Kps // Feed the speed control to the motor


To tune this part you first disable the outer loop by feeding an arbitrary requested speed (step function) to the speed controller and tuning Kps to get close to speed as fast as possible without overshooting. Then you enable the outer loop and change Kpp until you get the controller to slam the motor into place perfectly and quickly.

This is not practical for EFI, but it works nicely for electric motor control where you have an encoder for position feedback and a fixed or known load.

Say the motor is stopped at the initial position. Change its requested position. First, it determines the difference between actual and requested positions and multiplies this value by a gain to determine the speed the motor should be going in response. The farther the position from where it should be, the faster the motor should be turning towards the target. The inner loop then determines the difference between actual and requested speed and using another proportional gain determines how much voltage to apply to the motor.

I forget the math, but the two loops combined can cause the position to end up exactly at setpoint, and a whole lot more quickly than with a PID. With zero overshoot to boot.

_________________
Keith MacDonald
Control Engineering (Systems) Technologist


Fri Apr 25, 2008 4:24 am
Profile
Moderator
User avatar

Joined: Tue Jan 15, 2008 2:31 pm
Posts: 15332
Location: Home sweet home!
Ummmm, so, I didn't specify that history was or was not included in what I said. I just said that the output (however it is defined with math and code) is a difference to be applied to the position. Is that correct? Or is it an absolute position?

That was my point, not how to get there. Do you see what I mean?

Admin.

_________________
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!


Fri Apr 25, 2008 8:08 am
Profile WWW
LQFP112 - Up with the play

Joined: Thu Apr 10, 2008 5:51 pm
Posts: 205
Admin wrote:
Ummmm, so, I didn't specify that history was or was not included in what I said. I just said that the output (however it is defined with math and code) is a difference to be applied to the position. Is that correct? Or is it an absolute position?

That was my point, not how to get there. Do you see what I mean?

Admin.



To answer your question directly:

MegaSquirt generates an offset to the previous output.

PID generates an absolute new output. It appears to be adding a difference to the previous output, but what it is doing is stripping the previous proportional and derivative components out of the previous output which leaves it with the integral component only. It then adds new proportional and derivative components back in to get a new absolute value. It saves having a separate accumulator for keeping track of the integral.

The key here is that in MS2 they are taking what they call a PID and adding it to the previous output. Even with a Ki of zero, what should be a proportional controller ends up being an integral controller. When Ki is introduced they are in effect double-integrating, since they are maintaining a sum of all previous errors and adding it to the output, which already contains the sum of all previous errors. Except that they aren't, because they are taking Kp, Ki, and Kd, adding them together and using the sum as a gain in a proportional controller :D

If you take my formula and put it into Megasquirt, and set Ki to zero but leave Kp in, the engine rpm will always settle out but slower than desired due to load. This is true proportional control, as the output is entirely generated from scratch every cycle and reaches an equilibrium where the load cancels the applied output without fully satisfying rpm. From what I understand, the MS code does not do this (I run MS1extra with no idle control).

What a PID does sometimes have is a fixed offset that is always added to the output, which is called BIAS. What happens in this case is at T0, or the first cycle where control is asserted, the output equals the BIAS. This handy for idle control where rather than building up from 0% pulsewidth every time control is needed, the PW immediately begins at 50% (or some other defined value for bias) so the engine doesn't stall before equilibirum is reached. If the control system is a true PID, we throw the BIAS in at the end every cycle.

Output[0] = Alpha*Error[0] - Beta*Error[1] + Gamma*Error[2] + Output[1] + BIAS

A good method of determining a number to use for bias is it should equal your stabilized idle control PW with full accessory load. In other words, set BIAS to 100%, turn your A/C on, let your car idle, and record the output PW that it settles down to. This should be your bias. Every time you go into idle mode now, the output will jump immediately to the bias value so the engine doesn't stall, then work from there.

_________________
Keith MacDonald
Control Engineering (Systems) Technologist


Fri Apr 25, 2008 12:41 pm
Profile
Moderator
User avatar

Joined: Tue Jan 15, 2008 2:31 pm
Posts: 15332
Location: Home sweet home!
Awesome post, Thank you very much for sharing with us!! :-)

_________________
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!


Fri Apr 25, 2008 1:22 pm
Profile WWW
Banned!

Joined: Sat Mar 08, 2008 3:57 am
Posts: 92
Location: Sydney, NSW, AU
I deal with PID control in my work as plant engineer. My experience with PID control is using Allen-Bradley PLCs.
thebigmacd wrote:
Output = Kp*Error is a proportional controller.
I agree with Keith. That's how the PID function works in the PLC.

thebigmacd wrote:
If the control system is a true PID, we throw the BIAS in at the end every cycle.
If you know your output needs to respond a certain way to an outside disturbance, you can model that response in the bias of the control loop. For example, A/C turned on, idle valve bias can be increased from 40% to 60% to compensate for the extra load. You know the load is going to increase when you turn on the A/C so bump up the output now before you measure the rpm slowing.

_________________
previously: ca7


Fri Apr 25, 2008 3:27 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 106 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 11  Next

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software for PTF. ColorizeIt.