On 04/15/2016 09:31 AM, Paul wrote:> In article <wpydnbi9wr9Ujo3KnZ2dnUU7-WXNnZ2d@giganews.com>, > seemywebsite@myfooter.really says... >> >> Embedded Systems Design (or whatever they call themselves) kept moving >> this around -- so I've revamped it, updated it, and posted it on the web. >> >> Take a gander. Please comment on anything you like/don't like. I'm not >> sure if the way that I'm setting off the math is a Really Good Idea or a >> Really Bad Idea -- I'm trying to make it easy for the math-averse to skip >> over it, without breaking up the flow too much for folks who can read >> math without breaking stride. >> >> http://wescottdesign.com/articles/pid/pidWithoutAPhd.pdf > > Well in general good other comments people have stated I would add these > points - > > 1/ Code layout on page 14 of the integral state is UGLY, belongs in > obfuscated C better laid out out that is easier to read at a glance > is better for those trying to understand. > > 2/ Sampling time and loop delay, the closed loop problem that many > people overlook is not mentioned in any manner until into the maths. > Most people forget that digital control systems have a time lag and > time between calculations, sampling and worst of all ALL systems > have a delay between command -> error -> drive -> feedback > Each part has its own intrinsic delays/inertia and other effects > that most people never MEASURE. > > Increasing sampling rate or precision does NOT guarantee being able > to get to target faster. > > A classic problem I saw was a remotely operated vehicle, with a video > link and command back to vehicle. Everybody was annoyed that it could > not be driven faster than 30 mph so were looking at using 3D cameras > to make it faster. No one had obviously measured delays in system > > Camera frame integration time > Camera frame transmission time > Camera frame acquisition time > frame compression encryption time > frame radio link transmission time > frame receive time (missed/corrupt data) > frame decryption time > frame network transfer time (multi-computer setup) > Frame ROTATION by 90 degrees time > Frame mixing with other graphics > Frame buffer switching > > Then > Operator response time > Controls delay to data time > Controls network transfer > Controls radio link transmission > Controls receive time (what about missed/corrupt data) > Controls entered as new commands into drive control loops > Controls being applied > Vehicle lag to changes in drive > > So how was 2 video feeds going to speed this upSee "A Meeting with Medusa" by Arthur Clarke. (Really a good story.) Cheers Phil Hobbs (who's not qualified to comment on Tim's magnum opus.) ;) -- Dr Philip C D Hobbs Principal Consultant ElectroOptical Innovations LLC Optics, Electro-optics, Photonics, Analog Electronics 160 North State Road #203 Briarcliff Manor NY 10510 hobbs at electrooptical dot net http://electrooptical.net
PID Without a PhD, Finally
Started by ●April 14, 2016
Reply by ●April 15, 20162016-04-15
Reply by ●April 15, 20162016-04-15
On 15/04/16 15:31, Paul wrote:> In article <wpydnbi9wr9Ujo3KnZ2dnUU7-WXNnZ2d@giganews.com>, > seemywebsite@myfooter.really says... >> >> Embedded Systems Design (or whatever they call themselves) kept moving >> this around -- so I've revamped it, updated it, and posted it on the web. >> >> Take a gander. Please comment on anything you like/don't like. I'm not >> sure if the way that I'm setting off the math is a Really Good Idea or a >> Really Bad Idea -- I'm trying to make it easy for the math-averse to skip >> over it, without breaking up the flow too much for folks who can read >> math without breaking stride. >> >> http://wescottdesign.com/articles/pid/pidWithoutAPhd.pdf > > Well in general good other comments people have stated I would add these > points - > > 1/ Code layout on page 14 of the integral state is UGLY, belongs in > obfuscated C better laid out out that is easier to read at a glance > is better for those trying to understand. >I would not have said it was obfuscated - but it certainly could be a little better (as could the code on page 22). So far, I have only looked at the style of the code - I haven't actually looked at the details to see what it does, nor have I had time to read the whole paper. Hopefully I will do so some time - but perhaps by then there will be a second version from feedback from others in this thread! As this code is for embedded systems, it should be written in a manner close to that used in common embedded coding standards such as MISRA. Here are some points here that I think would make the code clearer, as well as more compatible with things like MISRA, and more suitable for flexible use in embedded systems: 1. MISRA does not approve of native types such as "double", because the precision is implementation defined and can vary between C compilers and targets. I agree with that regarding integers (so use <stdint.h> types rather than "int" or "short"), but the use of 32-bit and 64-bit IEEE formats for "float" and "double" is so close to universal that I think it is unnecessary. However, many people using code like this will want to use "float" for speed, while others will want "double" for precision. I would recommend starting the code with: typedef double real_t; // Use "float" or "double" as desired Then use "real_t" throughout, instead of "double". (It may be interesting to have a small section discussing the merits of these options - on something like a Cortex-M4F with hardware single-precision floating point, the speed difference could easily be a factor of 100. It may even be worth mentioning things like compiler flags - while most people know about basic optimisation flags, they may not know the huge difference "-ffast-math" can have on code like this. You may also want to discuss using integers instead of floating point, especially considering errors, scaling, rounding, and overflows.) 2. Do not give identifiers names such as "dState" and "iState". There are, unfortunately, a good many programmers who have totally misunderstood the point of "Hungarian notation" and will think that these mean a variable "state" with type "double", and another variable "state" with type "int". 3. Do not give identifiers names that are almost the same. Do not abbreviate the important part of the name (the "differential" or "integrator" part) to a single letter. It's fine to have shorter names for local variables within a function, but names that are visible over a wider range (such as the struct fields) should be self-explanatory. 4. If you need a comment to tell you what an identifier is, then the identifier name is bad. It is the identifier's name that says what it is - a comment may be used to add extra information such as scaling, or when it is used. 5. Always use the "one true brace" style. Every "if" and "else" should have brackets. 6. Do not declare more than one identifier in the same declaration. 7. Even the most conservative and backwards development companies have heard of C99. Declare your variables when you need them, in the smallest reasonable scope. Full marks for good character spacing! typedef double real_t; // Use "float" or "double" as desired typedef struct { real_t lastPosition; real_t integrator; real_t integratorLimitMax; real_t integratorLimitMin; real_t integralGain; real_t proportionalGain; real_t derivativeGain; } pid_s; real_t updatePID(pid_s * pid, real_t error, real_t position) { // The "P" part real_t pTerm = pid->proportionalGain * error; // The "I" part pid->integrator += error; if (pid->integrator > pid->integratorLimitMax) { pid->integrator = pid->integratorLimitMax; } else if (pid->integrator < pid->integratorLimitMin) { pid->integrator = pid->integratorLimitMin; } real_t iTerm = pid->integratorGain * pid->integrator; // The "D" part real_t dTerm = pid->derivativeGain * (pid->lastPosition - position); pid->lastPosition = position; // Combined PID result return pTerm + iTerm + dTerm; } Note that almost no comments are needed - the functionality is clear from the names used in the code. Regarding the typesetting, I recommend using the "listings" package rather than just a verbatim environment: <https://www.ctan.org/pkg/listings> <https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings> The setup I use for C code is something like this: \lstset{ language=C, formfeed=\newpage, tabsize=4, basicstyle=\small, numbers=left, numberstyle=\tiny, firstnumber=1, numberfirstline=true, stepnumber=5, numbersep=5pt, extendedchars=true, showstringspaces=false, breakatwhitespace=false, identifierstyle=\color{Black}\itshape, commentstyle=\color{Gray}\itshape, stringstyle=\color{Green} } (I vary it a little according to the document in question, but this is probably fine to get you started.)
Reply by ●April 15, 20162016-04-15
On 4/15/2016 5:28 AM, Tauno Voipio wrote:> On 15.4.16 02:11, rickman wrote: >> >> Page 4, equation 1, you might explain the basis of this equation. I >> assume the voltage actually controls the torque. Friction force is a >> result of velocity and the acceleration is from the excess force until >> the motor speeds up. Contrasted to the equation for the frictionless >> platform. > > > Rick: > > Every motor is also a generator. For a motor with constant > magnetization, the back EMF is proportional to the speed and > the motor torque is proportional to the current. > > You can model such a motor with a series connection of the > supply voltage, the motor (and line) resistance and the back > EMF. The motor settles to a speed near such speed that the > difference between supply voltage and back EMF runs just enough > current in the circuit to compensate for torque needed to keep > the speed. > > If you feed a constant-magnetized motor with a constant current > supply, the torque stays constant until the compliance limit > of the feed supply.Ok, that all makes sense and is what is being described in the paper. The drive is current rather than voltage and will produce the result shown in the diagram until the max voltage of the supply is reached. Thanks. I still don't get equation 3. I searched a bit and could not find anything similar. All the other references I found on the web use the Laplace transform to perform the math and don't produce a similar equation. Trying to find info on the web for control theory really opens a rabbit hole, lol. -- Rick
Reply by ●April 15, 20162016-04-15
rickman <gnuarm@gmail.com> Wrote in message:> On 4/15/2016 5:28 AM, Tauno Voipio wrote: >> On 15.4.16 02:11, rickman wrote: >>> >>> Page 4, equation 1, you might explain the basis of this equation. I >>> assume the voltage actually controls the torque. Friction force is a >>> result of velocity and the acceleration is from the excess force until >>> the motor speeds up. Contrasted to the equation for the frictionless >>> platform. >> >> >> Rick: >> >> Every motor is also a generator. For a motor with constant >> magnetization, the back EMF is proportional to the speed and >> the motor torque is proportional to the current. >> >> You can model such a motor with a series connection of the >> supply voltage, the motor (and line) resistance and the back >> EMF. The motor settles to a speed near such speed that the >> difference between supply voltage and back EMF runs just enough >> current in the circuit to compensate for torque needed to keep >> the speed. >> >> If you feed a constant-magnetized motor with a constant current >> supply, the torque stays constant until the compliance limit >> of the feed supply. > > Ok, that all makes sense and is what is being described in the paper. > The drive is current rather than voltage and will produce the result > shown in the diagram until the max voltage of the supply is reached. > Thanks. > > I still don't get equation 3. I searched a bit and could not find > anything similar. All the other references I found on the web use the > Laplace transform to perform the math and don't produce a similar equation. > > Trying to find info on the web for control theory really opens a rabbit > hole, lol. > > -- > > Rick >Thermal systems are generally far more complex than equation 3 implies. That one really should be taken just add the equation used to generate the plant model, nothing more. Pragmatically, if you need to wrap a control loop around a thermal plant, you should probably close your eyes to the theory and either tune it up by the seat of your pants (as in that paper), or you should use measured responses (which I cover briefly in another paper, and at length in my book). -- www.wescottdesign.com ----Android NewsGroup Reader---- http://usenet.sinaapp.com/
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 11:23:26 +0200, o pere o wrote:> On 15/04/16 00:03, Tim Wescott wrote: >> Embedded Systems Design (or whatever they call themselves) kept moving >> this around -- so I've revamped it, updated it, and posted it on the >> web. >> >> Take a gander. Please comment on anything you like/don't like. I'm >> not sure if the way that I'm setting off the math is a Really Good Idea >> or a Really Bad Idea -- I'm trying to make it easy for the math-averse >> to skip over it, without breaking up the flow too much for folks who >> can read math without breaking stride. >> >> http://wescottdesign.com/articles/pid/pidWithoutAPhd.pdf >> > A very nice work. I seem to remember that you already had a previous > version of it, didn't you?Yes. It was published in Embedded Systems Design magazine back in 2000 or something. For years I've just pointed to their version in my website, but they keep moving it around as their priorities change.> It was a surprise to see that the D box input (and pehaps P) is taken > from the feedback and not the error signal, as os usual in most > textbooks. For constant or slow varying commands, it makes no > difference. Is this arrangement an empirical result?Textbooks make things easy to understand. Practitioners make things work well. (Snarkity-snark). I kind of allude to this in the text -- I could add a section. Basically, if you feed the entire error signal to the PID controller then when you have a step-change in the input you just hammer the output driver of the controller. Sometimes this is a good thing, because you get snappier response from the plant. Sometimes this is a bad thing, because if you've got a lot of extraneous changes in the command you can heat up (or wear out, or whatever) your output driver. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 03:46:40 -0700, Peter Mairhofer wrote:> On page 14 in the code, it should be pid->iState instead of iState > right? >Argh! yes. Thank you. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 17:25:58 +0200, David Brown wrote:> On 15/04/16 15:31, Paul wrote: >> In article <wpydnbi9wr9Ujo3KnZ2dnUU7-WXNnZ2d@giganews.com>, >> seemywebsite@myfooter.really says... >>> >>> Embedded Systems Design (or whatever they call themselves) kept moving >>> this around -- so I've revamped it, updated it, and posted it on the >>> web. >>> >>> Take a gander. Please comment on anything you like/don't like. I'm >>> not sure if the way that I'm setting off the math is a Really Good >>> Idea or a Really Bad Idea -- I'm trying to make it easy for the >>> math-averse to skip over it, without breaking up the flow too much for >>> folks who can read math without breaking stride. >>> >>> http://wescottdesign.com/articles/pid/pidWithoutAPhd.pdf >> >> Well in general good other comments people have stated I would add >> these points - >> >> 1/ Code layout on page 14 of the integral state is UGLY, belongs in >> obfuscated C better laid out out that is easier to read at a glance >> is better for those trying to understand. >> >> > I would not have said it was obfuscated - but it certainly could be a > little better (as could the code on page 22). So far, I have only > looked at the style of the code - I haven't actually looked at the > details to see what it does, nor have I had time to read the whole > paper. Hopefully I will do so some time - but perhaps by then there > will be a second version from feedback from others in this thread! > > As this code is for embedded systems, it should be written in a manner > close to that used in common embedded coding standards such as MISRA. > Here are some points here that I think would make the code clearer, as > well as more compatible with things like MISRA, and more suitable for > flexible use in embedded systems: > > 1. MISRA does not approve of native types such as "double", because the > precision is implementation defined and can vary between C compilers and > targets. I agree with that regarding integers (so use <stdint.h> types > rather than "int" or "short"), but the use of 32-bit and 64-bit IEEE > formats for "float" and "double" is so close to universal that I think > it is unnecessary. However, many people using code like this will want > to use "float" for speed, while others will want "double" for precision. > I would recommend starting the code with: > > typedef double real_t; // Use "float" or "double" as desired > > Then use "real_t" throughout, instead of "double". > > (It may be interesting to have a small section discussing the merits of > these options - on something like a Cortex-M4F with hardware > single-precision floating point, the speed difference could easily be a > factor of 100. It may even be worth mentioning things like compiler > flags - while most people know about basic optimisation flags, they may > not know the huge difference "-ffast-math" can have on code like this. > You may also want to discuss using integers instead of floating point, > especially considering errors, scaling, rounding, and overflows.) > > > 2. Do not give identifiers names such as "dState" and "iState". There > are, unfortunately, a good many programmers who have totally > misunderstood the point of "Hungarian notation" and will think that > these mean a variable "state" with type "double", and another variable > "state" with type "int". > > 3. Do not give identifiers names that are almost the same. Do not > abbreviate the important part of the name (the "differential" or > "integrator" part) to a single letter. It's fine to have shorter names > for local variables within a function, but names that are visible over a > wider range (such as the struct fields) should be self-explanatory. > > 4. If you need a comment to tell you what an identifier is, then the > identifier name is bad. It is the identifier's name that says what it > is - a comment may be used to add extra information such as scaling, or > when it is used. > > 5. Always use the "one true brace" style. Every "if" and "else" should > have brackets. > > 6. Do not declare more than one identifier in the same declaration. > > 7. Even the most conservative and backwards development companies have > heard of C99. Declare your variables when you need them, in the > smallest reasonable scope. > > Full marks for good character spacing! > > > typedef double real_t; // Use "float" or "double" as desired > > typedef struct { > real_t lastPosition; > real_t integrator; > real_t integratorLimitMax; > real_t integratorLimitMin; > real_t integralGain; > real_t proportionalGain; > real_t derivativeGain; > } pid_s; > > real_t updatePID(pid_s * pid, real_t error, real_t position) { > // The "P" part real_t pTerm = pid->proportionalGain * error; > > // The "I" part pid->integrator += error; > if (pid->integrator > pid->integratorLimitMax) { > pid->integrator = pid->integratorLimitMax; > } else if (pid->integrator < pid->integratorLimitMin) { > pid->integrator = pid->integratorLimitMin; > } > real_t iTerm = pid->integratorGain * pid->integrator; > > // The "D" part real_t dTerm = pid->derivativeGain * > (pid->lastPosition - position); > pid->lastPosition = position; > > // Combined PID result return pTerm + iTerm + dTerm; > } > > > Note that almost no comments are needed - the functionality is clear > from the names used in the code. > > > > Regarding the typesetting, I recommend using the "listings" package > rather than just a verbatim environment: > > <https://www.ctan.org/pkg/listings> > <https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings> > > The setup I use for C code is something like this: > > \lstset{ > language=C, > formfeed=\newpage, > tabsize=4, > basicstyle=\small, > numbers=left, > numberstyle=\tiny, > firstnumber=1, > numberfirstline=true, > stepnumber=5, > numbersep=5pt, > extendedchars=true, showstringspaces=false, breakatwhitespace=false, > identifierstyle=\color{Black}\itshape, > commentstyle=\color{Gray}\itshape, stringstyle=\color{Green} > } > > (I vary it a little according to the document in question, but this is > probably fine to get you started.)Hi David: Thank you for your pertinent comments. I think I'll apply most of them. The only scary part of your comments are the "if someone uses the code" -- I originally meant this code to be for illustrative purposes only, not for use in production systems. My assumption was that people would read the article, grok the material, then go off and write code from scratch. Thus, the first time I got feedback along the lines of "we copied your code into our production software and it works GREAT!" my response was "WHAT!?! NOOOO!" So I would be tempted to take your real_t and change it to do_not_use_this_for_real_t. I have a question, since you brought it up and since I'm lazy. In many control systems, 32-bit IEEE floating point is inadequate, because a 24 bit significand just doesn't cut it. So the choice of double, with its bigger significand, is usually necessary. Is there a better way to express the "you damned well need 'double' here, bub" in code than just using "double", or a comment to that effect? -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 14:43:03 +0100, Paul wrote:> In article <wpydnbi9wr9Ujo3KnZ2dnUU7-WXNnZ2d@giganews.com>, > seemywebsite@myfooter.really says... >> >> Embedded Systems Design (or whatever they call themselves) kept moving >> this around -- so I've revamped it, updated it, and posted it on the >> web. >> >> Take a gander. Please comment on anything you like/don't like. I'm >> not sure if the way that I'm setting off the math is a Really Good Idea >> or a Really Bad Idea -- I'm trying to make it easy for the math-averse >> to skip over it, without breaking up the flow too much for folks who >> can read math without breaking stride. >> >> http://wescottdesign.com/articles/pid/pidWithoutAPhd.pdf > > OOps just spotted a terminology blunder > > Page 2 > The "PID" in "PID Control" stands for "Proportional, Integral, > Derivative". > > Page 19 > > Section Title is "Differential" Should be "Derivative" > > From there on you interchange differential and derivavtive all over the > place.That calls for clarification. "Derivative" is the correct term if you're doing the work with continuous-time hardware (i.e. op-amps, resistors and capacitors). "Differential" is the correct term if you're doing the work in sampled time. So I need to figure out how to work that in. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 09:31:49 -0700, Tim Wescott wrote:> rickman <gnuarm@gmail.com> Wrote in message: >> On 4/15/2016 5:28 AM, Tauno Voipio wrote: >>> On 15.4.16 02:11, rickman wrote: >>>> >>>> Page 4, equation 1, you might explain the basis of this equation. I >>>> assume the voltage actually controls the torque. Friction force is a >>>> result of velocity and the acceleration is from the excess force >>>> until the motor speeds up. Contrasted to the equation for the >>>> frictionless platform. >>> >>> >>> Rick: >>> >>> Every motor is also a generator. For a motor with constant >>> magnetization, the back EMF is proportional to the speed and the motor >>> torque is proportional to the current. >>> >>> You can model such a motor with a series connection of the supply >>> voltage, the motor (and line) resistance and the back EMF. The motor >>> settles to a speed near such speed that the difference between supply >>> voltage and back EMF runs just enough current in the circuit to >>> compensate for torque needed to keep the speed. >>> >>> If you feed a constant-magnetized motor with a constant current >>> supply, the torque stays constant until the compliance limit of the >>> feed supply. >> >> Ok, that all makes sense and is what is being described in the paper. >> The drive is current rather than voltage and will produce the result >> shown in the diagram until the max voltage of the supply is reached. >> Thanks. >> >> I still don't get equation 3. I searched a bit and could not find >> anything similar. All the other references I found on the web use the >> Laplace transform to perform the math and don't produce a similar >> equation. >> >> Trying to find info on the web for control theory really opens a rabbit >> hole, lol. >> >> -- >> >> Rick >> >> > Thermal systems are generally far more complex than equation 3 > implies. That one really should be taken just add the equation used to > generate the plant model, nothing more. > > Pragmatically, if you need to wrap a control loop around a thermal > plant, you should probably close your eyes to the theory and either > tune it up by the seat of your pants (as in that paper), > or you should use measured responses (which I cover briefly in another > paper, and at length in my book).I double-checked, and I kind of allude to this but I need to SAY this in the text. Thermal systems are generally sluggish with lots of high- frequency roll-off. The model chosen is sluggish with lots of high- frequency roll-off. That's about the extent of the accuracy of the model, in general. On a good day the chosen model may actually match a real thermal system well enough to work with -- but it's not to be taken as a generally accurate model, where equations 1 and 2 are generally much more applicable. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On 4/15/2016 1:30 PM, Tim Wescott wrote:> > Thank you for your pertinent comments. I think I'll apply most of them. > The only scary part of your comments are the "if someone uses the code" > -- I originally meant this code to be for illustrative purposes only, not > for use in production systems. My assumption was that people would read > the article, grok the material, then go off and write code from scratch. > > Thus, the first time I got feedback along the lines of "we copied your > code into our production software and it works GREAT!" my response was > > "WHAT!?! NOOOO!"That is why papers often use pseudo code rather than real code that can be copied.> So I would be tempted to take your real_t and change it to > do_not_use_this_for_real_t. > > I have a question, since you brought it up and since I'm lazy. In many > control systems, 32-bit IEEE floating point is inadequate, because a 24 > bit significand just doesn't cut it. So the choice of double, with its > bigger significand, is usually necessary. > > Is there a better way to express the "you damned well need 'double' here, > bub" in code than just using "double", or a comment to that effect?How about a comment that you shouldn't be doing this unless you actually understand what is happening? -- Rick







