EmbeddedRelated.com
Forums
The 2026 Embedded Online Conference

PID Without a PhD, Finally

Started by Tim Wescott April 14, 2016
On 04/15/2016 02:59 PM, Tim Wescott wrote:
> 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 Hobbs > > That 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. >
http://tinyurl.com/gpyb3kh ;) 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
On 15.4.2016 &#1075;. 20:32, 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 think derivative is better, it is about the first derivative of the feedback signal after all. Since it is the result of differentiation "differential" gets in use but in electronics differential is used a lot as in "differential signalling", which has little to do with that. Unless I got it totally wrong this is what causes some confusion (not much though, anyone who wants to dig into it and understand what you are teaching will figure it out and if not it will be hopeless anyway). Dimiter
On 15.4.2016 &#1075;. 21:53, Tim Wescott wrote:
>.... > > 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.
I think this is the best approach anyway. Whoever will be reading your pdf will not be an idiot and will think of such implications. I went through the thing - for may be 5 minutes - and never did I stop and think "this should have been done otherwise". Flooding it with less relevant details will harm it I think. Then the speed implication is not always true - on one FPU I am familiar with multiplication costs 2 cycles vs. 1 (dual vs. single). On another core I am considering at the moment it is 1 cycle in both cases. Well if the FPU is some 32-bit only cripple and using 64-bit fp will result in some emulation which takes forever things are much worse of course, but you are teaching PID with the paper, not the basics of programming. Dimiter
On Fri, 15 Apr 2016 23:40:59 +0300, Dimiter_Popoff wrote:

> On 15.4.2016 &#1075;. 21:53, Tim Wescott wrote: >>.... >> >> 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. > > I think this is the best approach anyway. Whoever will be reading your > pdf will not be an idiot and will think of such implications. I went > through the thing - for may be 5 minutes - and never did I stop and > think "this should have been done otherwise". > > Flooding it with less relevant details will harm it I think. > > Then the speed implication is not always true - on one FPU I am familiar > with multiplication costs 2 cycles vs. 1 (dual vs. single). > On another core I am considering at the moment it is 1 cycle in both > cases. Well if the FPU is some 32-bit only cripple and using 64-bit fp > will result in some emulation which takes forever things are much worse > of course, but you are teaching PID with the paper, not the basics of > programming.
What data type to use when is actually not a trivial decision, and it pretty much boils down to benchmarking candidates on your target system. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
On 4/15/2016 1:57 PM, Tim Wescott wrote:
> On Fri, 15 Apr 2016 13:51:41 -0400, rickman wrote: > >> On 4/15/2016 12:31 PM, 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). >> >> Yes, I understand a real system may be more complicated. But as I've >> said before, if I can't understand what an equation means, I have a very >> hard time understanding how to use it. I just need to "get" the >> equations you use as examples. This one eludes me and you seem to be >> saying you sort of made it up without a physical basis. You said you >> invented not one, but two time constants. > > Here's how you use that equation within the intended context of the paper: > > * Look at it. > * Say "oh, it's math". > * move on. > > Seriously. If you're not trying to duplicate the examples, you _do not > need the math_. That's the point of the paper.
Then there is no point in including it is there? I run into this sort of thing in reviewing presentations. An item is inserted, but not clearly. I point out the shortcoming and get the reply that it isn't important to the presentation. I ask them why it's in there then. I'm not trying to duplicate the examples, I'm trying to understand them. The math, presented in a clear way, helps. It doesn't have to be exhaustive, but it at least needs to be clear. Including equations that can't be easily found other places with an explanation only confuses the matter. Or did I miss some sources I should have found? -- Rick
On Thu, 14 Apr 2016 17:03:53 -0500, 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
I want to thank all who have commented. I've incorporated some of your suggestions, allowed other suggestions to color what I've done, and chosen not to implement others. But all of your suggestions were considered, and I'm grateful for your help. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
On 16/04/16 06:27, Dimiter_Popoff wrote:
> On 15.4.2016 &#1075;. 20:32, 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 think derivative is better, it is about the first derivative of the > feedback signal after all. Since it is the result of differentiation > "differential" gets in use but in electronics differential is used a lot > as in "differential signalling", which has little to do with that. > Unless I got it totally wrong this is what causes some confusion > (not much though, anyone who wants to dig into it and understand what > you are teaching will figure it out and if not it will be hopeless > anyway).
I would have thought that derivative is just differential as dt->0. When dt > 0 you have a difference equation, as in digital control. If you implement PID in analog and have a true derivative, call it that. Clifford Heath.
On 16/04/16 04:59, Tim Wescott wrote:
> On Fri, 15 Apr 2016 14:48:03 -0400, Phil Hobbs wrote: >> assert(sizeof(real_t) >= 8); >> Phil Hobbs > That 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).
A port of C to the Control Data CDC Cyber used the entire 60-bit word for a character. I thought it was terribly wasteful at the time, but now it's obvious that if you were stupid enough to want to write a word processor for one, you'd write code that packed 10 6-bit chars into a word solely for bulk text. Clifford Heath.
On 4/14/2016 5:03 PM, 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 tiny nit in the opening sentences: "I both consult and teach in the area of digital control. Through both of these efforts..." May I suggest: I consult and teach in the area of digital control. Through these efforts...
Am 15.04.16 um 00:03 schrieb Tim Wescott:
> 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 >
I've had a cursory look. I'm a physicist myself with only basic knowledge of PID control, so for me the math boxes were helpful. You did not define all variables there, particularly the dependent variables. In equation (1), I wondered whether theta_m is the angle or angular velocity of the motor. That t is time seems fairly obvious, but I'd put both in for clarification. Same for equation (2). Your plots need some typographical adjustment. The lines are too thin and the fonts are too small. I would also put the variables on the axis, i.e. "Time t in seconds" etc. The complete controller is a short function which fits in one page. Maybe it is better to put it at the beginning, giving different colours to the proportinal, integral and derivative term, and then explain it. While reading the code snippets, I was wondering what are the fields in the pid structure etc. For some reason, I find the code on paper quite hard to read. Maybe it's the syntax highlighting that I'm used to when reading on the screen. You can do some basic highlighting using the listings package to improve on that. Christian
The 2026 Embedded Online Conference