Shop OBEX P1 Docs P2 Docs Learn Events
PID and the derivative — Parallax Forums

PID and the derivative

Zap-oZap-o Posts: 452
edited 2009-08-14 17:52 in Propeller 1
derivative in a PID is confusing me. I am trying to reach a give value using the PID and the derivative is always negative or zero. In my head I thought that the derivative was the slope as in :

Y2-Y1 / X2-X1   




and in Andys PID its written as this:

[code]

' Derivative
temp := f.FSub(E, Ep) ' ΔE = (now) - E(old)
temp := f.FDiv(E, dt) ' ΔE/Δt
D := f.FMul(kd, temp) ' D = kd

Comments

  • ElectricAyeElectricAye Posts: 4,561
    edited 2009-08-14 03:11
    Zap,

    Funny, I was working on a PID today. I used Andy's code to help me along but, as is usually the case anytime I encounter anything from the OBEX, I was depressed by the lack of comments and variable definitions - an ongoing and ancient gripe of mine.

    I don't have Andy's code with me right now, but Ep might represent "error present" or "error previous". Who knows? In any case, as I understand the PID routine, you are always subtracting the previous error from the present error. To keep myself from getting lost, I re-named all the variables in Andy's code with long names like ErrorPresent and ErrorPrevious and then did the math the way you would probably guess it would be done. I haven't tested any of it yet, though.

    Toward the back of the manual in the following link, I found a nice description of the PID control process:

    http://www.parallax.com/Portals/0/Downloads/docs/prod/sic/Web-PC-v1.0.pdf

    And there is also this link:

    http://forums.parallax.com/showthread.php?p=529609

    which supposedly (I think?) made use of/or reference to the code you are looking at. But, depressingly, the method used in Basic isn't exactly the approach Andy cranked out in Spin, etc. so it might confuse you a little.

    Anyway, I hope this helps.

    Good luck,

    Mark

    smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Watching the world pass me by, one photon at a time.

    Post Edited (ElectricAye) : 8/14/2009 3:16:34 AM GMT
  • ElectricAyeElectricAye Posts: 4,561
    edited 2009-08-14 03:37
    Okay, I just got off my butt and went to my other computer to check Andy's code. At the top of his PID.spin I see where he defines E - Ep as "current error - previous error".

    But I think where you're making a mistake is that you are using a variable "temp" when he is using "de". Your second "temp" is not using the results of the first "temp".

    Don't be afraid of using long descriptive names for your variables. Really, there's no shame in it. I'm not happy unless I'm pushing 28 characters. It helps prevent confusion.

    I hope that helps,

    Mark
    smile.gif
  • Zap-oZap-o Posts: 452
    edited 2009-08-14 13:00
    Electric Aye. Thanks for this open discussion;

    I found the error after you stated stated
    Electric Aye said...
    "you are always subtracting the previous error from the present error."

    In the version of code that I have I spotted that indeed this was backwards.

    temp := f.FSub(E, Ep)                         ' ΔE = (now) - E(old)
    
    



    He even comments that "now - old" this is incorrect and the changes I have made are working perfectly.

    Thank you for taking time to set me at ease.
  • Peter NachtweyPeter Nachtwey Posts: 9
    edited 2009-08-14 15:03
    You should avoid doing as much math as possible during run time. Never multiply and divide when you can just multiply. This will save a lot of time since the math function are emulated. In stead you should simply by doing this
    ' At initialization
    K0:=Kp+Ki*Δt+Kd/Δt
    K1:=-Kp-2*Kd/Δt
    k2:=Kd/Δt

    'At Run Time
    e2:=e1
    e1:=e0
    e0:=target-actual
    u:=u+K0*e0+K1*e1+K2*e2
    u is the current output and should be limited so it doesn't over flow a 32 bit signed int. The limit should be a binary number such as +/- 65536 or even +/- 2^24 . The control signal can then be easily shifted to fit the digital to analog converter. For speed I would use signed fixed point math for speed.

    This form of PID is good for motion control and doesn't suffer from integrator windup but the integrator gain Ki must be used.
    I am a DSP programmer sometimes. I am a lurker that knows a lot about PID control. I am looking for an excuse to use a propellor chip.
  • Zap-oZap-o Posts: 452
    edited 2009-08-14 16:16
    Thanks Peter for the heads up but quite frankly this is about the D in pid and not the math process itself. I am doing floating point math and have to do it throughout the code.
  • mparkmpark Posts: 1,305
    edited 2009-08-14 16:21
    Zap-o said...
    ...[code]

    temp := f.FSub(E, Ep) ' ΔE = (now) - E(old)
    temp := f.FDiv(E, dt) ' ΔE/Δt
    D := f.FMul(kd, temp) ' D = kd
  • ElectricAyeElectricAye Posts: 4,561
    edited 2009-08-14 16:41
    mpark said...
    Zap-o said...


    ...
    [code]


    temp := f.FSub(E, Ep) ' ΔE = (now) - E(old)
    temp := f.FDiv(E, dt) ' ΔE/Δt
    D := f.FMul(kd, temp) ' D = kd
  • Zap-oZap-o Posts: 452
    edited 2009-08-14 17:00
    Well this is the code
    [code]

    {{
    PID.spin

    Performs PID calculations.

    ┌──────────────────┬────────────────────────┬────────┬────────────────┬────────┐
    │ PID.spin │ (C)2006 Parallax, Inc. │ V0.90 │ by Andy Lindsay│ Mar 08 │
    │ │ │ │ │ │
    ├───────────────────────────────────────────┴────────┴────────────────┴────────┤
    │ │
    │ Relies on Cam Thompson's Float32 object, which is available for download │
    │ from the Propeller Object Exchange. │
    │ │
    └──────────────────────────────────────────────────────────────────────────────┘

    }}


    OBJ

    f : "Float32"

    VAR

    long kp, ki, kd, sp, off, Amax, Amin
    long a, tp, Ep

    PUB init (_Kp, _Ki, _Kd, setPoint, offset, maxArea, minArea)
    f.start
    '' Set vdalues of kp, ki, etc.
    longmove(@kp, @_Kp, 7)

    PUB calculate(in) :out | temp, E, P, I, D, da, t, dt, Et

    '' Returns PID (out)put based on (in)put and stored values.

    ' Calculate Δt = [noparse][[/noparse] cnt(now) - cnt(previous) ] / clkfreq
    t := cnt ' t(now) = cnt
    dt := t - tp ' Δcnt = t - tp
    dt := f.fDiv(f.FFloat(dt), f.FFloat(clkfreq)) ' Δt = Δcnt
  • ElectricAyeElectricAye Posts: 4,561
    edited 2009-08-14 17:39
    Zap-o said...
    ...I just swapped the E, Ep like you stated.

    Zap,

    Hmmm... maybe we were looking at different versions of the same object, but I never said to swap E and Ep. My suggestion was to make sure you DEFINE what E and Ep represent in your code based on the correct mathematics for PID. In any case, what you are doing with your "temp" variable makes no sense. Think about what the value of temp is at every step of the execution. If I say temp = a, then I say temp = b, then I do something with temp, the value of temp is now going to be b, not a. Look at Andy's original code and look at how you have replaced his de with temp.

    Try using descriptive variable names like "ErrorPresent" "ErrorPrevious" etc. to help clear up what the code is doing.

    I'm guessing that your code would have worked okay the first time you tried your PID had you not used temp the way you are still using it now.

    I hope that helps,
    Mark

    smile.gif
  • Zap-oZap-o Posts: 452
    edited 2009-08-14 17:50
    Wow. I must need glasses cause what you see is now what I see. Thanks.
  • James NewmanJames Newman Posts: 133
    edited 2009-08-14 17:52
    If that change did anything, than something is definitely wrong. What your doing with temp in that line doesn't matter since you overwrite it's value in the next line without using it. It's like this:

    A = 5
    A = 24
    B = 3
    C = A + B

    C is 27. Change the first assignment to A to whatever you want... the result is the same. What people are telling you, is that you've made an error when you renamed the variables from the other persons code.

    Now just looking that the code, E probably means error, EP is Prevoius Error, and the 'DE' that you replaced with temp is Delta Error. (Change in error, ie E-EP).

    Go back, look at the original code, and see where you missed or changed something when renaming variables.

    [noparse][[/noparse]edit] ehh looks like you replied before I finished tongue.gif
Sign In or Register to comment.