Announcement

Collapse
No announcement yet.

Example Click PID

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts


  • Example Click PID

    This is a Click program (the 'Main' is actually empty) with a PID calculation in the interrupt subroutine. It is called based on a timed interrupt. This is set up according to the PDF referenced in this posting

    You may want to check the claculation of the error in the first math box. Different types of PID (forward versus reverse acting) will calculate this in the opposite manner.
    Attached Files
    thePLCguy

    Bernie


  • #2
    A couple of typos..

    Here is a correction to this program. I would just like to correct the errors since it might drive a newbie nuts.
    Attached Files

    Comment



    • #3
      I have tried this loop program and it doesn't seem to work. If there are lines in the main program that need to be there please post those also.

      In a flow control application, using a throttling valve, as the process variable and the setpoint reach parity the output goes to zero. I have done PID loops before in several different PLC's and first observation this appeared to be what I needed. I have a 4-20ma generator and when I went to test my loop it did not respond as expected.

      Comment



      • #4
        You will have to be a little more specific than "it doesn't seem to work".

        Are you sending the Process Variable to DF1?
        Do you have proportional, integral and derivative gains set?
        What type of numbers do you get in the Control variable?

        All these are functions which are specific to your application. This is only a generalized routine.
        The movement of the Information from you measuring device into the Process Variable and the movement of the value from the Control Variable to your actuation device are up to you.

        Be specific please.

        "it did not respond as expected. "

        Exactly how did it respond?
        Last edited by bcarlton; 09-05-2011, 09:33 AM.
        thePLCguy

        Bernie

        Comment



        • #5
          i am also reading thru the PID without a phd that you had the link to.

          Comment



          • #6
            i am using df1 as my position input and have it scaled 4-20ma between 0-100, i am guessing that would be between 0-100%. i am not using the derivative term in my calculations. loops that i have done before, siemens plc's, have not needed it. i have a 0-20ma generator that i am using as my input. if i have my setpoint at 50 and my in put at 12ma the signal to my output will go to 0. if i have it either just under or just over it will go to the max in the opposite direction, using a reverse acting loop. i have put in the gain anywhere from .001 to 1 and it doesn't make any difference.

            Comment



            • #7
              I'm new to the Click and I'm evaluating it's use for a control system. I found this "PID revised.zip" file and looked it over. I see the key areas of interest, as

              DF1 = process variable input,
              DF2 = set point input,
              DF4 = calculated control output,
              DF6 = I max windup input,
              DF7 = I min windup input,
              DF8 = P gain input,
              DF9 = I gain input,
              DF10 = D gain input

              The time base is set by how often this interrupt is processed. In the downloaded file, in the downloaded file, it's hard coded to once every 100mS. This hard coded can be changed during compile time, however it appears to me like it is hard coded.

              I see this is a parallel algorithm, so changing the gain of P does not effect the gain of I or D. Also a gain of I or D of 0, will simply cancel out those effects.

              Can that 100mS be accessed via a rung? I have used the D06 series PLC many times, I have often allowed OIT adjustments of the PID and time base. Could I allow an adjustable time base via OIT some how?

              I also see that DF20 and DF21 appear to be used somewhere, but I don't know where, or why they might be used. Can someone point me to where they are used? Perhaps they are stray address that should be removed? I'm not sure.

              I do not currently have a Click, however I will likely pickup the C0-00DD2-D in the near future.

              Comment



              • #8
                >>I also see that DF20 and DF21 appear to be used somewhere

                In the Click software, look under Function - CPU Built in I/O setup and look at the analog I/O. They AI's are assigned to use DF20 and 21, the outputs use DF3 and 4.

                Honestly I don't know why you would want to put the PID cycle time on an OIT and the interrupt setting is set via the Click programming software. However you could program it such that even though the interrupt is triggered ever .1 seconds that the PID loop was only executed every other other interupt or every third interrupt etc.

                The PID works ok for simple tasks and you can always add to it to incorporate limits, etc. It is hard to beat the Click PLC on value if it meets your needs.

                Comment



                • #9
                  I know this is an old thread, but pre-sales, I'm trying to see if I can do what I need to with a CLICK PLC - they are very impressive devices for sure. I wrote a PID slightly different but with essentially the same output, the derivative calculation in mine uses PV delta instead of PE delta to avoid Derivative Kick. The problem is with input and output scaling - If I use the RTD module with a PT100, what does the PV look like? I'm storing the output of RTD CH 1-4 in DF1-4, and everything I'm reading says the value stored is the actual temperature as a float, not the 16 bit AD signal. If I feed that value into the PID as the PV, and have a pGain of 2, and iGain of .02, and a dGain of two, with a SP of 350 and a PV of 70, I get 561.6 as the output of the PID - If I'm controlling a discrete output, how do I convert 561 into a duty cycle? What scale is 561 in? It's rather arbitrary, unless I set a lower and upper temperature limit, like 70F for the low end, and 212 for the high end, since I'm heating water. My SP will always be between 105 and 212 F. Since in my model I have the PV at 70F and a SP of 350, I can safely assume that 561 is 100% output, and even may be outside the bounds of the output. I have not set an iMax or iMin value, so 561 is un-bounded.
                  Last edited by nik.martin; 08-04-2013, 11:46 AM.

                  Comment



                  • #10
                    Originally posted by nik.martin View Post
                    I wrote a PID slightly different

                    First of all, we don't really need to know what you are controling (see http://forum.automationdirect.com/sh...0&postcount=11) just that you want a time proportioned discrete output (I'll just assume you have a completly seperate comercial flame safety and high limit controls and are not relying on any PLC from Automation Direct for any safety critical function)

                    In the "module setup" for the RTD module you can chose either Celcius of Fahrenhiet, and the output will be, as you say "the actual temperature as a float". I don't think the CLICK gives you acess to the raw ADC output, if for some reason you really want it, I suppose one could "reverse" scale the number they do give you.

                    There are probably a number of ways to convert an analog value into a time proportioned discrete output, I'd think one would want to start with a timer, and then either a compare function or a second timer.

                    Since you "wrote a PID slightly different" it would probably help if you either posted your code or at least a detailed description of it. Even small differences in an alogorithm can make a large diference in the output, so it seems to me it would be hard to answer your question about the number you are getting without seeing how you are getting it.


                    EDIT:
                    Well, I ran your numbers through Dave911's version of the alogorithim, and the first pass gave an output of 565.6, pertty much just your prop gain * the (large) error, since there was only one iteration and a 0.02 integral gain the other terms are pretty much negligable.
                    2nd EDIT, Opps, I screwed up my calculation, on the first iteration the Current_derivited is uninitilzed (presumably 0) so the Derivative_term = 2 (Dgain) * (0 - 70) = -140
                    Proportional_term (2 * error = 560) + Derivative_term (-140) (ignoringthe small integral_term (small on the first iteration anyway, but will rapidly increse) = 420, nothing like your number, but then the first iteration with uniitialzed varaibles is pretty useless. So, I'm curious how you got your numbers, without limiting, multiple iterations will result in a rapid integral wind up

                    "I have not set an iMax or iMin value, so 561 is un-bounded."
                    That could be a problem if you ran the program for real, while a 32bit float can hold a pretty darn large value, it could result in unwieldy values.

                    "I can safely assume that 561 is 100% output"
                    And then some; if you want to call 561, 100%, (though I think calling 1, or maybe 100, 100% would be more convienent) one could do:
                    output_ratio = control varaible / 561 (in this case that would result in 1, but if unbounded it will be greater than unity on the next iteration) note that if 1 = 100%, one could skip this step
                    one example of converting to time proprtional
                    trigger_level = control_period * output_ratio
                    start a timer for control_period
                    if timer_currentvalue < trigger_level turn phisical output on
                    if timer has timed out, reset timer and repeat (for example, one could use a CLICK "retained" timer and use its own output to reset it, or a conventional timer and a C bit or two
                    Last edited by Tinker; 08-02-2013, 11:11 PM. Reason: addition

                    Comment



                    • #11
                      >>First of all, we don't really need to know what you are controlling

                      Tinker is right... we need to know what you are controlling.

                      Most gas valves are either on or off, unless you have some type of modulating gas valve to vary gas flow and heat input to the water heater. If that is the case (you have an on off valve), then you really need thermostat type control vs a PID loop. That is how most residential, smaller commercial water heaters operate since the gas valve is usually either on or off. Some bigger heaters might have multiple burners and multiple gas valves to vary capacity.. but again we don't know what you really have.

                      Dave

                      Comment



                      • #12
                        Originally posted by Tinker View Post
                        First of all, we don't really need to know what you are controling
                        Agreed. Fixed in OP
                        Originally posted by Tinker View Post
                        Since you "wrote a PID slightly different" it would probably help if you either posted your code or at least a detailed description of it. Even small differences in an alogorithm can make a large diference in the output, so it seems to me it would be hard to answer your question about the number you are getting without seeing how you are getting it.
                        Since Click IDE doesn't have a handy way of copying ladder code, I've expressed it here as 1 line = 1 rung:
                        Each PID loop is an interrupt routine on a 1 second interrupt, so there aren't any sampling time calculations, since sample time is constant @1sec.
                        As a reminder, pGain = 2, iGain = .02, dGain = 2 in this example. Totally arbitrary, but used to make calculations easier to test.
                        1. Calculate PE: SP - PV -> Store in var 'PE'
                        2. Calculate pTerm: PE * pGain -> Store in var 'pTerm'
                        3. Calculate Integral= PE + Integral -> Store in var Integral
                        4. Calculate iTerm = Integral * iGain - Store in var iTerm
                        5. Calculate dTerm = (PV - Derivative) * dGain -> Store in dTerm
                        6. Calculate Derivative: Derivative = PV -> Store in var Derivative
                        7. Calculate PID Control Output: pTerm + iTerm - dTerm -> Store in var PIDOUT


                        Originally posted by Tinker View Post
                        EDIT:
                        Well, I ran your numbers through Dave911's version of the alogorithim, and the first pass gave an output of 565.6, pertty much just your prop gain * the (large) error, since there was only one iteration and a 0.02 integral gain the other terms are pretty much negligable.
                        2nd EDIT, Opps, I screwed up my calculation, on the first iteration the Current_derivited is uninitilzed (presumably 0) so the Derivative_term = 2 (Dgain) * (0 - 70) = -140
                        Proportional_term (2 * error = 560) + Derivative_term (-140) (ignoringthe small integral_term (small on the first iteration anyway, but will rapidly increse) = 420, nothing like your number, but then the first iteration with uniitialzed varaibles is pretty useless. So, I'm curious how you got your numbers, without limiting, multiple iterations will result in a rapid integral wind up
                        Using the function described, I made a spreadsheet using a SP of 350, and initial PV of 70, assuming PV is never 0 (that PV is initialized by the RTD module before PID loop runs), here is the first ten loops as calculated by a spreadsheet:
                        Code:
                        SP	PV	PE	pGain	Pt	I		Igain	It	D	dGain	Dt	PID	% OUT	Time ON
                        350	70.00	280.00	2	560.00	280.00		0.02	5.60	0.00	2.00	0.00	565.60	1.00	30.00
                        350	77.17	272.83	2	545.67	272.83		0.02	5.46	7.17	2.00	14.33	536.79	0.95	28.47
                        350	84.33	265.67	2	531.33	538.50		0.02	10.77	7.17	2.00	14.33	527.77	0.93	27.99
                        350	91.50	258.50	2	517.00	797.00		0.02	15.94	7.17	2.00	14.33	518.60	0.92	27.51
                        350	98.67	251.33	2	502.66	1,048.33	0.02	20.97	7.17	2.00	14.33	509.30	0.90	27.01
                        350	105.84	244.17	2	488.33	1,292.49	0.02	25.85	7.17	2.00	14.33	499.85	0.88	26.51
                        350	113.00	237.00	2	474.00	1,529.49	0.02	30.59	7.17	2.00	14.33	490.25	0.87	26.00
                        350	120.17	229.83	2	459.66	1,759.32	0.02	35.19	7.17	2.00	14.33	480.51	0.85	25.49
                        350	127.34	222.66	2	445.33	1,981.99	0.02	39.64	7.17	2.00	14.33	470.63	0.83	24.96
                        350	134.50	215.50	2	430.99	2,197.49	0.02	43.95	7.17	2.00	14.33	460.61	0.81	24.43
                        So, from my earlier post, if I assume that MAX SP/PV of 350, then scaling the output to output/MAXPID will give me a percentage output which can easily be turned into a control output duty cycle, but it will change as the PID gains are tuned, so I may want to dynamically calculate MAXPID by taking max setpoint and use the current gains to set MAXPID

                        Am I waaaay off?

                        Comment



                        • #13
                          >>First of all, we don't really need to know what you are controling
                          Ooops I inverted my logic there didn't I .. my mistake.

                          You want to limit your final Iterm contribution so that you cannot drive the output beyond 100% to avoid windup. The I term cannot be unbounded.

                          So if the maximum loop output is 100 and the I gain is .1, then you want to limit the gain contribution to 1000. (100/0.1=1000) Just clamp it.. if it exceeds 1000 in the calculations - set it equal to 1000. That right there will limit your output to an extent and keep things reasonable. Do that limit calculation when you first run the loop and every time you change the I term.

                          After you do that everything becomes a lot easier.

                          You will also want to figure out what you want your initial output to be when you turn on the loop and then back calculate that to an initial Integral value. Maybe you want the output to start at 50 when you flip on the PID loop, and your I gain is .1, then you want to initialize your Iterm contribution to (50 / 0.1 = 500) before you run the loop calculations for the first time. If you are controlling some devices position (like valve position) and you have the current device position while the loop is not running (in manual mode) then you can back calculate that so you have a bumpless (the output doesn't swing as the loop stabilizes) transfer when going from manual mode (loop not running) to auto mode (loop running).

                          You can make all of this as complicated or simple as needed.

                          Dave

                          Comment



                          • #14
                            Hey I need help asap. OK never done a PID ever. I`m controlling a temp out put 4-20 ma. I have C0-02DR-D PLC I`m using df1 as heater input,df2 air leaving heater,df3 output to control valve,df4 not used. can someone get me a sample pid that will work. tried using the one posted but since the df1,2,3,4 already n use guess it wouldn't work. This dryer went down had an old symax sq d controller on it and it died got everything but the steam PID ready for test. Hope someone can help me. Thanks

                            Comment



                            • #15
                              The program should work, just need to change nicknames/tag names.

                              Open the PID program
                              Open the nickname picker
                              Move the names from DF1-DF14 to sequential DF locations that are unused in your existing program. Say DF101-DF114.
                              Use Replace to change the code in the PID program from DF1-DF14 to the new DF locations.
                              Highlight the lines of code in the PID program and paste them into the existing program.

                              Comment

                              Working...
                              X