On 4/15/2016 2:00 PM, Tim Wescott wrote:> On Fri, 15 Apr 2016 13:47:18 -0400, rickman wrote: > >> On 4/15/2016 1:32 PM, Tim Wescott wrote: >>> 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. >> >> I was going to make that comment, but then I recalled the term my >> professor actually used was "difference equations". "Differential >> equations" means something else, no? I couldn't find any sources on >> this, so I didn't make the comment. It's been far too long to trust my >> memory. > > "Differential equations" are what you need to describe things in a > continuous-time world (the three equations in the paper are differential > equations). > > "Difference equations" are what you need to describe things in a discrete- > time world.So is the use of the title "Differential" correct or not? I'm a bit confused. Above you say "Derivative" is the term for use with continuous time systems and "Differential" is for sampled time systems. Here you say "Differential" is the correct term for use with continuous time systems and "Difference" is used with sampled time systems. -- Rick
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 04/15/2016 01:30 PM, Tim Wescott wrote:> 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? >assert(sizeof(real_t) >= 8); Cheers Phil Hobbs -- 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
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 20:37:34 +0200, David Brown wrote:> On 15/04/16 19:30, Tim Wescott wrote: > <snip> >> 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!" > > You might want to give that section a better title than "The Complete > Controller", with the program description "Here is the full text of the > PID controller code" :-) Perhaps a big warning in red that this is > example code to get started. > > >> 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? >> >> > In a good many systems, double is not good enough either - it will be > too slow. The developer needs to use some sort of scaled integers to > get 32 bits of precision (especially in the integrator), and may even > need to use 64-bit integer arithmetic for intermediary results. > > It would be nice if there were some equivalent to <stdint.h> that > defined types like float32_t and float64_t, but there isn't one. There > are some macros in <float.h> defining aspects of floating point types, > but they are a bit ugly - and since you are always going to have 32-bit > IEEE floats and 64-bit IEEE doubles (unless your compiler cheats by > using 32-bit doubles, as you sometimes see on small micros), there is > nothing there worth checking. If 32-bit IEEE is not good enough, just > write "double" - and make a note that it has to be a /real/ double, not > a non-standard 32-bit version.I should make sure that the speed problems with double are pointed out -- I think I mention it, but I may have been so totally focused on just showing the implementation in the simplest way possible that I forget. 32 bit fixed-point is more than adequate for nearly anything, although you do sometimes have to take care with the integrator to make sure that this holds up with real code. If you need more, and you're not building LIGO-III, then you may well be sampling horrendously faster than you need to. My preference if I'm doing a complicated control system is to use a fractional arithmetic type, where the underlying storage is twos compliment integers but the functional type has values that range from almost -1 to almost +1. You grab integer data, scale it to a fractional, do all the control calculations in fractional, and then convert back to integer to apply to a DAC or PWM generator or whatever. Implementation can be in either C or C++, although you can make more readable code with C ++. I cover various data types (including ints, fractional, and the pitfalls of floating point) in my book. There's enough to fill a chapter. You do need to have a good understanding of what's happening to the data under the hood if you're going to do controls or signal processing. Which reminds me -- at some point I remember seeing that fractional arithmetic was a suggested type for C, but I never kept track of whether it went someplace useful or is a dead end. For all that, there are useful control loops to be closed out there that can profitably use double-precision floating point on a PIC or an 8051 -- just not too many of them. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 14:48:03 -0400, Phil Hobbs wrote:> On 04/15/2016 01:30 PM, Tim Wescott wrote: >> 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? >> >> > assert(sizeof(real_t) >= 8); > > Cheers > > Phil HobbsThat would give a false alarm on some DSP chips, because sizeof returns the number of characters your variable or type fits into, and if the processor can't handle data in chunks as small as 8 bits a character is bigger (usually 16 or 24, but I believe that it was 32 or 64 in some Cray machines). Fortunately, in a compliant compiler this is captured in CHAR_BIT: assert(sizeof(real_t) * CHAR_BIT >= 64) I oversaw the introduction of the TMS320F2812 into a product line where we had code that had worked for YEARS, which broke because of the implicit assumption that the number of bits in a character was 8. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 14:42:00 -0400, rickman wrote:> On 4/15/2016 2:00 PM, Tim Wescott wrote: >> On Fri, 15 Apr 2016 13:47:18 -0400, rickman wrote: >> >>> On 4/15/2016 1:32 PM, Tim Wescott wrote: >>>> 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. >>> >>> I was going to make that comment, but then I recalled the term my >>> professor actually used was "difference equations". "Differential >>> equations" means something else, no? I couldn't find any sources on >>> this, so I didn't make the comment. It's been far too long to trust >>> my memory. >> >> "Differential equations" are what you need to describe things in a >> continuous-time world (the three equations in the paper are >> differential equations). >> >> "Difference equations" are what you need to describe things in a >> discrete- >> time world. > > So is the use of the title "Differential" correct or not? I'm a bit > confused. Above you say "Derivative" is the term for use with > continuous time systems and "Differential" is for sampled time systems. > Here you say "Differential" is the correct term for use with > continuous time systems and "Difference" is used with sampled time > systems.A differential equation uses derivatives. A difference equation uses delays, but relies heavily on the concept of a first difference (x_n - x_{n-1}) if you're modeling real-world phenomenon. Please don't blame me for the terminology -- folks have been using this since before I was born, I'm just the messenger. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
Am 15.04.2016 um 20:48 schrieb Phil Hobbs:> assert(sizeof(real_t) >= 8);That won't actually work reliably. Remember that sizeof's result is in "bytes", as in: whatever size "unsigned char" is on the target platform. Which might be bigger than the usual 8 bits, particularly on DSPs. Not all the world's a VAX, and a byte is not 8 bits everywhere. So if your goal is to insist on a 64-bit floating-point 'real_t', you'll really have to say assert((sizeof(real_t) * CHAR_BIT) >= 64u); and maybe, while at it, also make sure it's a floating-point type: assert(0 != (real_t)0.1); And for good measure, better make those static_assert()s so they trigger at compile time, instead of trying to abort at run time with a message--- which in an embedded system often has nowhere to go.
Reply by ●April 15, 20162016-04-15
On Thu, 14 Apr 2016 19:09:26 -0400, DJ Delorie wrote:> You leave out math but include C code, I think that's defeating the > purpose. If you can't explain it in non-technical words or a simple > picture... well, try harder :-) > > You spend only one page on tuning, and give no examples of "If you see > this, try this" which is much more useful to the practical user. > > You don't mention feed-forward terms at all. > > In short, it looks much like all the other PID papers out there, and > wouldn't have helped me "get" PID back when I was trying to figure it > out. > > The section on I - the last paragraph should go first, since the point > of the I term is to correct for long-term errors, and you don't even > mention it in the first paragraph. > > The second paragraph in D should be first, and is probably the most > useful paragraph in the paper, if you don't already understand PID. > > The other thing I always hated about PID papers is that they never gave > solid examples of the difference between controlling speed and > controlling position, or the more complicated case of > torque/speed/position nested PID loops for CNC control. > > I'm reminded of a YouTube video about how NOT to weld - the guy would > intentionally do it wrong various ways so you could compare his results > with your results, so you could figure out what you were doing wrong and > how to fix it. Something like that for PID would be more useful than > showing an ideal situation.D'oh -- why, of course I'll include an appendix or something on how to do this with op-amps. It should have occurred to me immediately. -- www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On 4/15/2016 3:02 PM, Tim Wescott wrote:> On Fri, 15 Apr 2016 14:42:00 -0400, rickman wrote: > >> On 4/15/2016 2:00 PM, Tim Wescott wrote: >>> On Fri, 15 Apr 2016 13:47:18 -0400, rickman wrote: >>> >>>> On 4/15/2016 1:32 PM, Tim Wescott wrote: >>>>> 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. >>>> >>>> I was going to make that comment, but then I recalled the term my >>>> professor actually used was "difference equations". "Differential >>>> equations" means something else, no? I couldn't find any sources on >>>> this, so I didn't make the comment. It's been far too long to trust >>>> my memory. >>> >>> "Differential equations" are what you need to describe things in a >>> continuous-time world (the three equations in the paper are >>> differential equations). >>> >>> "Difference equations" are what you need to describe things in a >>> discrete- >>> time world. >> >> So is the use of the title "Differential" correct or not? I'm a bit >> confused. Above you say "Derivative" is the term for use with >> continuous time systems and "Differential" is for sampled time systems. >> Here you say "Differential" is the correct term for use with >> continuous time systems and "Difference" is used with sampled time >> systems. > > A differential equation uses derivatives. > > A difference equation uses delays, but relies heavily on the concept of a > first difference (x_n - x_{n-1}) if you're modeling real-world phenomenon.I am familiar with the terminology, you seem to be using the terms irregularly. What you say here is correct, but it doesn't clarify the confusion of your other statements. Here you use both differential and derivative in the continuous time domain. Elsewhere you have used the term differential for the discrete (sampled) time domain. -- Rick
Reply by ●April 15, 20162016-04-15
On Fri, 15 Apr 2016 21:19:50 +0200, Hans-Bernhard Bröker wrote:> Am 15.04.2016 um 20:48 schrieb Phil Hobbs: > >> assert(sizeof(real_t) >= 8); > > That won't actually work reliably. Remember that sizeof's result is in > "bytes", as in: whatever size "unsigned char" is on the target platform. > Which might be bigger than the usual 8 bits, particularly on DSPs. > Not all the world's a VAX, and a byte is not 8 bits everywhere. > > So if your goal is to insist on a 64-bit floating-point 'real_t', you'll > really have to say > > assert((sizeof(real_t) * CHAR_BIT) >= 64u); > > and maybe, while at it, also make sure it's a floating-point type: > > assert(0 != (real_t)0.1); > > And for good measure, better make those static_assert()s so they trigger > at compile time, instead of trying to abort at run time with a > message--- which in an embedded system often has nowhere to go.Most of my embedded systems will at least make a light blink oddly when you hit an assert -- but that's not a Good Thing normally. -- www.wescottdesign.com
Reply by ●April 15, 20162016-04-15
On 04/15/2016 04:05 PM, Tim Wescott wrote:> On Fri, 15 Apr 2016 21:19:50 +0200, Hans-Bernhard Bröker wrote: > >> Am 15.04.2016 um 20:48 schrieb Phil Hobbs: >> >>> assert(sizeof(real_t) >= 8); >> >> That won't actually work reliably. Remember that sizeof's result is in >> "bytes", as in: whatever size "unsigned char" is on the target platform. >> Which might be bigger than the usual 8 bits, particularly on DSPs. >> Not all the world's a VAX, and a byte is not 8 bits everywhere. >> >> So if your goal is to insist on a 64-bit floating-point 'real_t', you'll >> really have to say >> >> assert((sizeof(real_t) * CHAR_BIT) >= 64u); >> >> and maybe, while at it, also make sure it's a floating-point type: >> >> assert(0 != (real_t)0.1); >> >> And for good measure, better make those static_assert()s so they trigger >> at compile time, instead of trying to abort at run time with a >> message--- which in an embedded system often has nowhere to go. > > Most of my embedded systems will at least make a light blink oddly when > you hit an assert -- but that's not a Good Thing normally. >Well, I'm of the old school, where you define NDEBUG in your production code, rather than using assert() as a shorthand for fatal runtime errors. Cheers Phil Hobbs -- 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







