PID제어 데모 프로그램입니다. 이 프로그램을 실행시켜보기 위해서는 StampPlot 라는 프로그램이 필요합니다.
미국 유저가 작성한 소스라서 설명이 온통 영어네요. ㅠ
AD420 DA칩을 써서, PID 제어 출력 결과를 0~5V로 출력하는 프로그램입니다. 화면에 StampPlot를 띄우고 RS232C를 연결해서 추적과정을 볼 수 있게 해 놓았습니다.
' ============================================================================================================== 'File: Cubloc_CB2xx_PID_Voltage_R1.cul 'Purpose: Demonstrates PID Close Loop Voltage Control on the CB220 / CB280 / CB290 PLCs. ' A simple Real Time Operating System using TimeSlice on the CB2xx PLCs. ' "Analog Process Functions" used in PID control. ' Floating math routines in PID control. ' Proper "safety" programming in PID process control. ' PID design and engineering hints. ' PID Basics. ' '============================================================================ 'This PID Voltage Demo outputs a voltage from a voltage DAC onto the A/D input 'for feedback indication. The process speed is very fast. This application can 'expanded and be used in power supply designs. '============================================================================= ' 'Author: Unknown 'E-mail: 'Started: 10/05/2005 'Updated: 10/05/2005 'Revision: R1.0B - Beta - Prototype - NOT FINAL!!!! 'Device used with test code: CB280 with Study Board 1 'Devices that can be used: CB2xx 'Code Tested: Yes - OK ' 'CUBLOC Version: 1.2F 'Date: 10/26/2005 'CUBLOC Studio: 1.2F ' ' ' '=============================================================================================================== ' ' [Code Revisions] 'Rev. 1.0B 10/24/05 (Beta) ' ' '=============================================================================================================== ' Disclaimer ***** Disclaimer ******* Disclaimer ******* Disclaimer ******** Disclaimer ******** Disclaimer ' ' If you use this prototype PID algorithm and your house burns down, your dog dies and your wife and children ' become homeless or worst yet, you destroy all your Cubloc CB2xx equipment, do not hold me responsible for your actions!!! ' ' Disclaimer ***** Disclaimer ******* Disclaimer ******* Disclaimer ******** Disclaimer ******** Disclaimer '=============================================================================================================== ' ' [PID Demo "Close Loop" Lighting Control] ' ' ' ' Process: Power ' Process Driver: CB2xx AD420 0-5 VDC (Voltage DAC) driving CB2xx Analog Input AD(2) P26 ' Process Sensor: Voltage ' Process Feedback: DAC ' Process Speed: Fast ' ' Calibration: No calibration is needed on the feedback and on the precison current DAC AD420. ' ' Feedback Sensor Range: 0 - 5 VDC ' '=============================================================================================================== ' ' [Wiring Diagram between CB2xx & AD420 ] ' [*See spec sheet for details] ' ' ----- ------ ' / | | | ' | -- | ' | AD420ANZ-32 | ' | U1 | ' C3 NC------| 1 24 |------NC ' 0.1 uf | | ***** Warning - Do not connect to 5VDC*** ' To Gnd o--| |------------o------| 2 VLL Vcc 23 |------o--------o----o- *****Connect to +24 VDC Vcc***** ' | | | | ' NC o------| 3 Fault 22 |------NC 0.01uf| | 0.1 uf ' | | C1 | ___ ' Gnd *-----------------------| 4 Rng #1 21 |------o--| |---o ___ C4 ' [0-5VDC Select] | | C2 | | ' Gnd *-----------------------| 5 Rng #2 20 |------o--| |---o | ' | | 0.01uf ----- To Gnd ' NC o------| 6 CLr Bst 19 |------NC --- ' | | ' To CB2XX P12 o------| 7 Lch Iout 18 |------NC ' | | ' To CB2XX P15 o------| 8 Clock 17 |------o [Driver 0-5VDC) To CB2xx P25 AD(2) [Feedback] ' | | ' To CB2XX P11 o------| 9 Data 16 |------NC ' | | ' ------| 10 Rin 15 |------o ' | | | Jumper ' To Gnd------| 11 Gnd Rout14 |------o pins ' | | 14-15 ' NC------| 12 13 |------NC ' | | ' -------------- ' Standard Configuration for 0-5VDC output ' NC = No Connect ' (Fault and Clear usage is optional) ' ' ' ' Digikey Parts: ' 1 C1 0.01uf NPO Cap 399-1976-ND $1.11 ' 1 C2 0.01uf NPO Cap 399-1976-ND $1.11 ' 1 C3 0.1uf Cap 399-2143-ND $0.16 ' 1 C4 0.1uf Cap 399-2143-ND $0.16 ' 1 U1 16 Bit DAC AD420ANZ-32-ND $18.98 ' ' ' ' * Notes: Check spec sheet for PCB layout considerations, grounding & components. ' Other range options include 4-20 ma, 0-24ma , 0-20ma, 0-10VDC, +-5 VDC & +-10 VDC - see spec sheet. ' To "industrialize" this device opto-isolators are needed between the CB2xx and the AD420. ' Connect both the +24VDC Ground and the 5 VDC grounds together BUT NOT THE AD420 VCC +24 VDC TO 5 VDC! - see spec sheet. ' Zero and Span pots can be added for additional output adjustment. (See spec sheet) ' ' ' Additional Equipment: ' 1 Cubloc Study Board 1 - For easy prototyping of circuits ' 1 Cubloc USB to RS232 cable for plotting PID variables ' 1 +24 VDC 0.5 amp regulated power supply (Fused) ' ' ' ' ' '================================================================================================================== '================================================================================================================== ' ' [Program Operation / Description / PID Crash Course] ' '================================================================================================================== ' ' PID (Proportional, Integral & Derivative) The most dreaded three letter word in PLC Control! ' ' PID is complex because a person would need to know software, hardware interfacing, and process control. ' ' The reason why PID is not common in small microprocessors is the "floating point overhead" and instruction speed. ' Cubloc CB2xx PLC series has both floating point math and instruction speed of 36,000 instructions/second. ' ' PID control mimics an electrical opamp. ' ' PID Control is a "close loop system" e.g. a feedback is provided to the control loop to monitor the process being ' controlled. ' ' Considerable expertise is required to properly design a system to avoid oscillations or sluggish responses. ' This PID algorithm compares the feedback from the process sensor and the setpoint to determine the appropriate ' analog 0-100% output variable. This output could drive PWM (Pulse Width Modulation) 0-5 VDC output or a DAC normally ' 4-20 ma. or 0-10 VDC. Typical driven outputs could connect to thermal, motion, lighting, flow and power. ' The controller drive is automatically adjusted until the measured sensor signal matches the desired setpoint. ' ' The CB220 or CB2xx sends a setpoint signal to the PID subroutine. The PID subroutine then calls the PID function, ' which is made up of three elements: the Proportional, Integral, and Derivative routines. The Proportional routine ' creates an output signal proportional to the difference (error) between the measurement taken and the setpoint. ' The Integral routine produces an output proportional to the length and amount of time the error signal is present. ' The Derivative routine creates an output signal proportional to the rate of change of the error signal. ' ' The input transducer generates an output signal from the process being controlled and feeds the measured value to ' the PID subroutine. Analog inputs (4-20ma) are normally used to acquire the feedback signal. The difference between ' the setpoint generated by the CB2xx PLC and the measure value coming from the input transducer is the Error signal. ' Some sort of correcting device such as a motor control, valve control, or amplifier takes the error signal and ' uses it to control the correction sent to the process being controlled. ' ' Possible processes for PID control/simulation are: ' ' [Process] [Driver] [Speed] [Sensor] [Sensor Feedback] ' Power Bridge Fast Voltage Voltage to A/D ' Motion Amplifier Fast Position Encoder,frequency(magnetic pickup,Hall effect pickup) ' Thermal FET (PWM) Very Slow Temperature RTD,Thermocuple,Thermistor, ' Solid State Temp.Sensor (LM34,AD590,AD592) ' Lighting Triac Slow Intensity Digital Light Sensor TSL230, Cadmium Sulfide PhotoCell ' Flow Buffer Fast Rate Turbine flowmeter/counter ' '================================================================================================================== ' ' ' Just having the PID algorithm software is not enough. Careful thought is needed in designing the control loop around ' the process - NOT the other way around! ' ' Items to consider when designing and engineering a "closed PID Loop" for control: ' ' #1. Is the control loop "control action" forward or reverse acting? ' This Voltage PID control action is forward acting - an increase in the control output will increase the feedback ' voltage. ' ' #2. Range of feedback sensor? ' Too small of range will cause the control loop to become unstable and untunable. ' Extreme care should be taken to have the proper range for the process feedback. ' ' #3. Will the control output driver work properly with the process e.g. Pulse Width Modulation? / Voltage? / Current? ' PWM is well suited for heating control and other slow processes. For precision "non pulsing" control you need ' a true precision current/voltage output DAC. ' The smooth output from the 16 Bit AD420 current DAC is well suited for this application. ' ' #4. Is the driver output failsafe? ' This Voltage control is failsafe because if the output wire is opened or the driver fails the voltage source will ' not function and goes to a safe condition as oppose to "100% full control action" ' ' #5. How will the calibration be performed on the control loop driver and feedback? ' No calibration is needed for this PID voltage close control loop demo. ' Note: The output 16 bit precison current DAC has the option of being trimmed with a zero and span pots. ' ' #6. How will you filter the feedback signal? ' Analog feedback signals are easier to filter than a "counter input" signal. ' No filtering is required for this application. ' ' #7. How fast of integral scan rate do you need? ' In this Voltage PID control, the control action is fast, so the scan rate can also be fast. ' The fixed scan time, for this control, is 40ms or PID update time of 25 times per second. This process ' scan rate can even run at a much faster rate. ' ' #8. How will you view the process to tune it with the "P" "I" variables? ' I took care of that - a plotting interface to the FREE StampPlotPro version 3.6 was designed into Comm 1. ' The feedback, setpoint, error and control outputs are all visible at the same time. This software will work ' for ten minutes and will quit. Just close the window out and restart the program via icon or buy the license for $20. ' (Have the icon on your window handy) ' Note: When using PWM, the control action is so fast that you cannot see it "all" in the plotting software. ' ' ' #9. How fast is the process feedback? ' Don't violate Nyquest therom. The sample rate of the process feedback should be 2x. ' For example, if you are reading RPM and the hertz feedback is 365 hz for 8000 rpms then the integral scan time ' should be 2 x 365 = 730 hz or 1/730hz = 1.3ms. ' ' #10. How will you read the feedback - by Analog? or by Digital? ' Analogs can be scanned and filtered easily. ' Digital counter inputs (Counter 0 or 1 inputs) are hard to filter in a fixed scanned timeslice RTOS. ' ' #11. On a feedback sensor failure what should you do to the control output? ' You should disable the control output to zero. (No control output @ 0%) ' Safety is the TOP PRIORITY in any PID close control loop design. ' ' #12. On a mis-tuned or faulty control loop how will you know if there is a problem? ' Use the deviation error setpoint along with the error flag LED. ' ' #13. What is PID windup? ' The PID checks the difference between the feedback and setpoint and multiplies the "P" gain of this error for ' the control output. The intregral resets or reads this PID calculation every 40ms times the "I" tuning variable. ' This sum error plus the gain error is added together for the control output signal. If the control loop is ' un-responsive, mis-tuned or have a hardware failure, the control output will try increase the control output ' to bring the feedback and setpoint equal. This sum error will keep increasing in value (single = +3.402823E+38) ' until it sees the feedback signal equal the setpoint. Since this delay is dependent on the scan rate, the ' response would be erratic or sluggest or hard to tune. ' ' #14. How do you slow down the output PID control action? ' Decrease the "P" gain value and / or ' Decrease the "I" integral value. ' Note: Warning ... The above PID tuning parameters all interact with each other!!!!! ' ' #15. How do you increase the output PID control action? ' Increase the "P" gain value and / or ' Increase the "I" integral value. ' Note: Warning ... The above PID tuning parameters all interact with each other!!!!! ' '================================================================================================================== '****************************************************************************************************************** ' If you do not have a clear understanding of the PID basics above, please do not continue! Crack open some PID books. ' If you do, please call the fire department and put them "on standby" and, please do, continue on. '****************************************************************************************************************** '================================================================================================================== ' ' The operation of the PID close loop Voltage Control has only has two commands "Voltage_Feedback via AD(2)" ' and "gosub PID1" ' The rest of the code supports these two commands.(3.906k flash & 423 bytes ram) You set the voltage setpoint from ' 0 - 100%. The software will read the feedback voltage, then computes the error and then outputs ' a 0-5 VDC output to bring the process in control (Voltage setpoint = Feedback Voltage). The PID will ' only control when there is an error between the setpoint and feedback, if the feedback is above the setpoint there ' will be no control output. (0%) ' ' Start your testing by adjusting the setpoint (~line 832) up / down. Check the response by plotting the PID variables. ' ' ' The tuning is simple, just adjust the "P" or "I" constants. ' (Do not adjust the 'D" The D is the rate of change which in most PID control applications is not used.) ' Check for overshoot, slow response or too fast of control response using the plotting software. This process is very ' slow and very forgiving when tuning the "P" And "I" terms. The key in PID tuning is to make the output control action ' output smooth (not erratic) yet responsive to setpoint step changes. ' After going thru all the possible combinations, you will become THE PID EXPERT! ' '================================================================================================================== ' ' Suggested Do's and Do Nots ' ' Do read every line of this code to form a complete understanding on how the PID controller works. ' Do extensive PID plotting to anaylize the PID process. ' Do connect the grounds from both the protoboard and the external power supply. ' Do be careful in modifying this code. ' Do use RTOS timeclass 1 or 2 for the basic debug command not timeclass 0. ' (adds delays, timeclass overruns, and tuning problems) ' Do the test "4 channel analog plot" from the website to make sure the plotting software will work. ' Do connect the timeclass LEDs and PID error LEDs for troubleshooting. ' Do try changing the plotting variables for different PID values. ~ line # 576. ' Do try making multiple copies of this original program for different PID testing values. ' ' Do not combine the 5VDC from the protoboard and external 24 VDC regulated FUSED power supply! ' Do not add any code that delays the timing of the two gosub main routines in the 40ms timeclass 0. ' Do not edit the PID macro (using notepad) for the plotting software unless you know what you are doing. ' '================================================================================================================== '================================================================================================================== '================================================================================================================== ' ' [Beginning of Basic/Ladder Code] ' ' '================================================================================================================== ' ' [Device Set] ' Const Device = CB280 ' Set Device '================================================================================================================== ' '================================================================================================================== ' ' [Device Ram Clear] ' Ramclear ' Clear All Ram variables on power up '================================================================================================================== ' ' [Basic / Ladder Debugging] ' Set Debug Off ' Disable all basic debug commands in basic code (Ladder monitor power flow enable) 'Set Debug On ' Enable all basic debug commands in basic code (Ladder monitor power flow disable) ' Ladder monitor and basic debug cannot be used at the same time! ' Choose one or the other '================================================================================================================== ' '================================================================================================================== ' ' [Basic Variables Defines] ' '=============================Timeslice=========================================================================== ' ' ' PID control needs a constant fixed scan rate to update the PID calculations. Tuning would be impossible if the ' basic program was to "run free". Any additions or deletions to the code size would alter the tuning constants for ' the PID calcuation. That is why this Timeslice RTOS was created. ' ' With the Timeslice code you can do the following: ' #1 Execute any number of tasks at regular intervals. (e.g. every 40 ms / 100ms / 500 ms) ' #2 You can choose the frequency of executing each task by altering the Time_Class_x_Counter_Max. ' #3 You can choose the order of execution by having the most important task first in the interrupt service routine. ' #4 You can have the slow, infrequent tasks run in the background in the CB2xx "Main Do / Loop". ' ' Basic command "On Timer Gosub Tick_Interrupt" will trigger a 40ms interrupt service routine. ' There are three intervals in this program but only two should be adjusted in the constant table. 40ms ' is the minimum for the first / time class 0 interval. The other are multiples of 40 ms. e.g. 100ms and 500ms. ' The counters in the interrupt service routine, when they reach their Time_Class_x_Counter_Max, will run the ' code provided by the user. The slowest task runs in the background in the Basic "Main Do /Loop". ' Diagnostic flags in the Ladder program indicate the time class execution - infrequent tasks will show nothing unless ' you fill lots of code into them. You eyes cannot see at 10ms in the Ladder monitoring mode but you will see 'hits' ' ' Hints in CB2xx Timeslicing: ' Put the fastest code in Time Class 0 (40ms) - code that will be executed every 40ms. ' Put other "medium" user code into Time Class 1 (100ms) ' Put other user code into the Basic Main Do/Loop. (500ms) Code like math code that does not need the fast execution. ' Put user executing code in proper order - code like "read digital inputs", "read analog inputs", "PID*", ' "write digital outputs", "write analog outputs". ' '************************************************************************************************************* ' DO NOT OVERRUN / OVERFLOW THE TIME CLASSES! ALL Time Classes (all 3) ALL USER CODE WILL HAVE TO RUN WITHIN 40ms! ' At 36,000 Basic Instructions/sec this means about ONLY 1440 Basic instructions! (1000ms/40ms = 25 36,000/25 = 1440) ' Note: You can change the interrupt time to vary the number of instructions executed per interrupt time. ' Note: Use no pauses or delays in code! '************************************************************************************************************* Time_Class_0_Counter Var Integer Time_Class_1_Counter Var Integer Time_Class_2_Counter Var Integer Time_Class_0_Enable Var Byte Time_Class_1_Enable Var Byte Time_Class_2_Enable Var Byte Time_Class_2_Run Var Byte ' '==============================PID1================================================================================ ' LastError1 Var Single 'Error[-1] PrevError1 Var Single 'Error[-2] SumError1 Var Single 'SumError + Error (Sum of Errors) dError1 Var Single 'LastError - PrevError Error1 Var Single 'Error = Setpoint - PID Feedback PIDOutput1 Var Single 'PID Calc Output 0-100% Feedback1 Var Single 'PID Feedback - Input from process sensor ' 'PID Feedback Scaled to 0-100% from process transducer ' eng. units range. See scaled feedback below. Fwd_Actuator1 Var Single 'Actuator Output - Forward Acting Control 0-100% Rev_Actuator1 Var Single 'Actuator Output - Reverse Acting Control 100-0% Scale_Feedback1 Var Single 'Calc from feedbact range to 0-100% - to PID input Setpoint1 Var Single 'Process setpoint scaled to 0-100% - to PID input Scale_Setpoint1 Var Single 'Calc from setpoint range to 0-100% - to PID input Scale_Setpointx1 Var Single 'Setpoint scaled going to PID calc function PID_Output_Raw1 Var Single 'PID calculation - not clamped or limited to 0-100% Proportion1s Var Single 'Limited Proportion1 value between 0.0 - 1.0 Integral1s Var Single 'Limited Integral1 value between 0.0 - 1.0 Derivative1s Var Single 'Limited Derivative1 value between 0.0 - 1.0 Proportion1x Var Single 'Limited Proportion1 value between 0.0 - 1.0 Integral1x Var Single 'Limited Integral1 value between 0.0 - 1.0 Derivative1x Var Single 'Limited Derivative1 value between 0.0 - 1.0 PID1_Deviation_Error Var Single 'Deviation Error % from PID PID1_Error Var Single 'PID1 Deviation Error Flag 1 = True PID1_Control_Enable Var Single 'Enable PID control output enable = 1 PID1_Control_Output Var Single Plot_Value Var String *15'String with 15 chars for plotting PID1_LB_Test Var String 'PID loop back test variable Voltage_Feedback Var Single 'DAC 0-5 VDC feedback Data_AD420 Var Integer 'AD420 0-20 VDC Data_AD420x Var Integer '================================================================================================================= ' ' [Basic Constants Defines] ' '======================================Timeslice================================================================== ' Const Time_Class_0_Counter_Max = 1 '40 ms (1 x 40ms) MINIMUM TASK SPEED - DO NOT CHANGE! Const Time_Class_1_Counter_Max = 2 '80 ms (2 x 40ms) Adjustable by user. Const Time_Class_2_Counter_Max = 2.5 '100 ms (2.5 x 40ms) Adjustable by user. ' '================================================================================================================= ' ' ' '===================================[PID Tuning Values - Adjustable] ============================================= '================================================================================================================= ' Const Proportion1 = 0.1 '[Default 0.1] Use within range between > 0.0 - 1 ' 0.1 = 10% gain [Error = Setpoint - Feedback] [Error * Proportion] is added to output. 'The Proportional routine creates an output signal proportional to the difference (Error) between the measurement 'taken and the setpoint. 'Note: The larger the Proportion number the larger the gain! (1 = 100% and .1 = 10%) ' Const Integral1 = 0.01 '[Default 0.01 @ 25/sec] Use within range between > 0.0 - 1 ' (.01 = .01 x times the SumError @ 40ms) ' Usable Range --> .999( 0.999 x sumerror) to .001(0.001 x sumerror) (0.1 = 10% Integral) 'Integral routine produces an output proportional to the length and amount of time the Error signal is present. 'Note: The larger the Integral number, the larger the output signal number. (Integral * SumError) 'Note: Changing the 40ms scan time will change the integral (Sum error) Please retune all PID parameters. ' Const Derivative1 = 0.0 '[Default 0] Keep at 0. This adjustment stays at zero because "PI" of PID is normally only used in control. 'Derivative routine creates an output signal proportional to the "Rate Of Change" of the Error signal. '(dError = LastError - PrevError) (Derivative * dError) 'Note: Warning ... The above PID tuning parameters all interact with each other!!!!! (Even the PWM frequency) Const PID1_Deviation_Error_Setpoint = 3.0 'Deviation Error Setpoint in % -> ABS(Setpoint - Feedback) '================================================================================================================ '================================================================================================================ ' Const TC0_LED = 0 'Time Class 0 LED Indicator - Please hook up. Const TC1_LED = 1 'Time Class 1 LED Indicator - Please hook up. Const TC2_LED = 2 'Time Class 2 LED Indicator - Please hook up. Const PID1_Error_LED = 4 'PID Error (Deviation alarm) and sensor failure combined. Please hook up. Const Voltage_Input = 26 'Analog 2 for voltage feedback Const Plot_Delay = 20 'Delay for Plotting (You might need to increase this if there are setup problems) Const AD420_Clock = 15 Const AD420_Clear = 14 'Optional - needed only in failsafe control Const AD420_Fault = 13 'Optional - needed only in failsafe control Const AD420_Latch = 12 Const AD420_Data = 11 ' Const MSBFIRST_Mode_1 = 1 'Shiftout mode for AD420 '=================================================================================================================== ' ' [Constant Array Defines - Program Flash ' ' '=================================================================================================================== ' ' [Ladder Assignments For Pins] ' [Alias(s) for Ladder - Do not modify] 'Diagnostic Indicators from Timeslice Alias M504 = Test_TC1 'TC0 M Output Alias M505 = TC0 'TC0 Indication Alias M506 = Test_TC0 'TC1 M Output Alias M507 = TC1 'TC1 Indication Alias M508 = Test_TC2 'TC2 M Output Alias M509 = TC2 'TC2 Indication Alias M510 = Test_Int 'Interrupt Indication Alias M511 = Int 'Int. M Output ' ' '=================================================================================================================== ' ' [Start Ladder] Set Ladder On 'Set Ladder On ' '=================================================================================================================== '=================================================================================================================== '=================================================================================================================== '=================================================================================================================== ' ' [Start Of Basic Code] ' ' Cycle RTOS Timeclass LED indicators on power-up High TC0_LED High TC1_LED High TC2_LED High PID1_Error_LED Pause 1000 Low TC0_LED Low TC1_LED Low TC2_LED Low PID1_Error_LED Gosub Timeslice_Init ' Timeslice Init Gosub PID1_Init ' Init PID variables Gosub Study_Board_Init ' Init Study board Gosub Plot_Init ' Initilize serial port #1 for plotting. Gosub AD420_Init '=================================================================================================================== ' ' [40 ms Interrupt using Timer] ' On Timer(4) Gosub Tick_Interrupt ' 4 x 10ms '=================================================================================================================== Do 'Main Basic Loop If Time_Class_2_Run = 1 Then Time_Class_2_Run = 0 ' ' User Code - Runs in background every 100ms - can be changed. ' '======================================[Time Class 2 User Code @100ms]============================================= '================================================================================================================== '================================================================================================================== 'Debug "Code Executing Time Class 2 at 100ms",cr '================================================================================================================ ' ' [Four channel PID plot --> Stamp Plot Pro ver 3.6] ' If Bfree(1,1) > 30 Then 'Check Comm 1 buffer Pause Plot_Delay Plot_Value = Float Scale_Setpoint1 Putstr 1,"!ACHN 0,", Plot_Value Putstr 1,"," Putstr 1,"(BLUE)",CR Pause Plot_Delay Plot_Value = Float Scale_Feedback1 Putstr 1,"!ACHN 1,", Plot_Value Putstr 1,"," Putstr 1,"(GREEN)",CR Pause Plot_Delay Plot_Value = Float Error1 'Sumerror1 Putstr 1,"!ACHN 2,", Plot_Value Putstr 1,"," Putstr 1,"(Black)",CR Pause Plot_Delay Plot_Value = Float Fwd_Actuator1 'Data_AD420 Putstr 1,"!ACHN 3,", Plot_Value Putstr 1,"," Putstr 1,"(Red)",CR Pause Plot_Delay End If '================================================================================================================== '================================================================================================================== '================================================================================================================== Reverse TC2_LED _M(509) = 0 'TC2 Ladder Indicator ' Debug " Time Class 2 - 500 ms",cr End If Loop ' Loop forever '================================================================================================================== '================================================================================================================== ' ' [End of Basic Code] ' '================================================================================================================== '================================================================================================================== ' ' [Interrupt Service Routine 40 ms @ 1520 Instructions] ' Tick_Interrupt: _M(511) = 1 'Interrupt started flag - for ladder '============ 'TIME CLASS 0 '============ Incr Time_Class_0_Counter If Time_Class_0_Counter >= Time_Class_0_Counter_Max Then 'This task executes every 20 ms _M(505) = 1 'TC0 Ladder Indicator Time_Class_0_Counter = 0 If Time_Class_0_Enable = 1 Then ' Do high freq task in 10 ms - do not adjust below 10ms. ' Insert User Code Here! ' '=============================================[Time Class 0 User Code @ 40ms]==================================== '================================================================================================================ '================================================================================================================ 'Debug "Code Executing Time Class 0 at 40ms",cr 'Gosub Get_Analogs-always get input analogs for PID before PID calculation! Voltage_Feedback = Adin(2) 'has x 10 amp Voltage_Feedback = Voltage_Feedback * 0.048828125 Gosub PID1 ' Calculate PID from PID Tuning constants and fixed input variables. '================================================================================================================= '================================================================================================================= '================================================================================================================= Reverse TC0_LED _M(505) = 0 'TC0 Ladder Indicator 'Debug " Time Class 0 - 10 ms",cr End If End If '============ 'TIME CLASS 1 '============ Incr Time_Class_1_Counter If Time_Class_1_Counter >= Time_Class_1_Counter_Max Then 'This task executes every 100 ms _M(507) = 1 'TC1 Ladder Indicator Time_Class_1_Counter = 0 If Time_Class_1_Enable = 1 Then ' Do medium freq task in 100 ms ' Insert User Code Here! ' '======================================[Time Class 1 User Code @80ms]=========================================== '================================================================================================================ '================================================================================================================ 'Debug "Code Executing Time Class 1 at 80ms",cr 'Debug Float voltage_feedback, " vf",cr '================================================================================================================ '================================================================================================================ '================================================================================================================ Reverse TC1_LED _M(507) = 0 'TC1 Ladder Indicator 'Debug " Time Class 1 - 100 ms",cr End If End If '============ 'TIME CLASS 2 '============ Incr Time_Class_2_Counter If Time_Class_2_Counter >= Time_Class_2_Counter_Max Then 'This task executes every 100 ms _M(509) = 1 'TC2 Ladder Indicator Time_Class_2_Counter = 0 If Time_Class_2_Enable = 1 Then ' Do slow freq task in 500 ms - using code placed in the Main Do/Loop ' Do not insert any code here! Time_Class_2_Run = 1 'Enable Time Class 2 code in Main Do/Loop End If End If _M(511) = 0 'Interrupt finished flag- for ladder Return 'End of interrupt '================================================================================================================= ' ' [Beginning Of Basic Subroutines] ' '================================================================================================================= ' Study_Board_Init: ' Low TC0_LED 'high = LED on Low TC1_LED Low TC2_LED Low PID1_Error_LED Input Voltage_Input Return ' ' '================================================[Timeslice Init]=================================================== Timeslice_Init: 'Init timeslice variables Time_Class_0_Counter = 0 Time_Class_1_Counter = 0 Time_Class_2_Counter = 0 Time_Class_0_Enable = 1 Time_Class_1_Enable = 1 Time_Class_2_Enable = 1 Time_Class_2_Run = 0 Return ' '================================================================================================================= ' '===============================================[PID Init]========================================================== PID1_Init: dError1 = 0 Error1 = 0 LastError1 = 0 PrevError1 = 0 SumError1 = 0 PID1_Deviation_Error = 0 PID1_Error = 0 PID1_Control_Enable = 1 Return '================================================================================================================ ' PID1_Reset: dError1 = 0 Error1 = 0 LastError1 = 0 PrevError1 = 0 SumError1 = 0 PID1_Deviation_Error = 0 PID1_Error = 0 Return ' '================================================================================================================= ' ' [AD420 Initialization] ' '================================================================================================================= ' ' AD420_Init: Low AD420_Clock 'Keep low during DAC updates Low AD420_Clear 'Keep low for normal operation. Input AD420_Fault 'Low = True = current loop broken or opened. (10 Kohm - Pulled high by hardware) Low AD420_Latch 'Keep low during serial loading Low AD420_Data 'SPI Data input. Return ' '================================================================================================================ ' ' '================================================================================================================= ' ' Output_AD420_Data: '16 bit precision DAC range (0 -65535) Low AD420_Clock 'Keep clock low Low AD420_Latch 'Keep latch low Shiftout AD420_Clock, AD420_Data, MSBFIRST_Mode_1, Data_AD420, 16 Low AD420_Clock 'Keep clock low Pause 1 High AD420_Latch 'Latch Data to AD420 Pause 1 Low AD420_Latch 'Bring latch low Return ' '================================================================================================================ '================================================================================================================ ' ' [PID1 Subroutine General Notes] ' ' The PID1 subroutine below has the following: ' ' #1. All inputs and outputs to / from the PID are scaled from 0-100 %. ' #2. The feedback from the sensor (in this case a fixed number 0-5VDC) is re-scaled to 0-100% for PID ' #3. The setpoint for the PID is rescaled to 0-100% for PID. ' #4. Both feedback and setpoint are "clamped" and "limited" (For safety protection) ' #5. All PID "tuning constants" are "clamped" or "limited" between 0-1 (For safety protection and operator malfunction) ' #6. The PID Output is "clamped" or "limited" between 0-100% ' #7. There is a control enable bit to enable the output control. In case of "downscale" or "upscale" sensor burnout ' this enable/disable bit can prevent the PID output from controlling. (PID output equal to 0) There is no reason ' to control on a bad sensor input! ' Note: The logic is programmed in for this demo. ' #8. There is a PID error flag to indicate that the PID control loop is not tuned properly or just the failure ' of the control loop to make the feedback match the setpoint.(external problems in control loop e.g. wiring, bad ' actuators etc.) This "deviation setpoint error" is adjustable in constants. (Set at 3%) ' #9. The control output is from 0-100% for the forward actuator. If a heater was connected to this output, the ' more control e.g. 25,50,75 - 100% will cause the heater control to produce more heat directly proportional to ' the PID output signal. This is called "forward acting" control. Let's say that there was a device connected ' at full control e.g. 100% that the temperature decreased. This control action is call "reverse acting control" ' You have both options to choose from for the main actuator control output. ([0-5vdc or 5-0vdc using PWM] or ' [4-20ma or 20-4 ma using a milliamp DAC] or [0-10VDC or 10 VDC-0 using a voltage DAC] ' Keep in mind that a control output failure due to a driver problem, open wire etc. SHOULD cause the actuator ' to control less - not run wide open! e.g. Make it failsafe! '#10. The code is modular. Replacing the suffix with a 2 instead of 1 will create another PID. ' ' Note: It's very important in a scan based RTOS to First read the "analogs in" (setpoint & feedback), Second do the PID ' calculations and Third output the signal to the Pwm, Dac/4-20ma last. ' ' '================================================================================================================= ' ' [PID1 Subroutine] PID1: Feedback1 = Voltage_Feedback '0 - 50 (0-5 VDC) 'PID1_LB_Test Scale_Feedback1 = ScaleX (Feedback1,0,50,0,100) 'Scale Feedback to range of 0-5VDC to PID range of 0 - 100% Scale_Feedback1 = Limit_100(Scale_Feedback1) 'Limit Feedback between 0-100% Setpoint1 = 50 ' The setpoint of 50% = .50 of 5VDC = 2.5 VDC Max range is 100% Scale_Setpoint1 = ScaleX (Setpoint1,0,100,0,100) 'Scale Setpoint from range 0-100 to PID range of 0 - 100% Scale_Setpoint1 = Limit_100(Scale_Setpoint1) 'Limit Setpoint between 0-100% Proportion1s = Proportion1 'From constant table Integral1s = Integral1 'From constant table Derivative1s = Derivative1 'From constant table Proportion1x = Limit_1(Proportion1s) 'Limit Proportion between 0 - 1 Integral1x = Limit_1(Integral1s) 'Limit Integral between 0 - 1 Derivative1x = Limit_1(Derivative1s) 'Limit Deviation between 0 - 1 '====================================================================================================================== PIDOutput1 = PIDCalc1(Proportion1x,Integral1x,Derivative1x,Scale_Setpoint1,Scale_Feedback1) 'Calculate PID - Top Secret '====================================================================================================================== ' PID_Output_Raw1 = PIDOutput1 If Feedback1 >= 10000000000.0 Then ' PID shutdown setpoint - Not used PID1_Control_Enable = 0 High PID1_Error_LED End If If PID1_Control_Enable = 1 Then Fwd_Actuator1 = PIDOutput1 ' Output to actuator Fwd_Actuator1 = Limit_100(Fwd_Actuator1) ' Clamp or Limit PID_Output between 0-100% - Forward Acting Control '=============================================================================================================== 'Integral anti-windup code 'This occurs when the control output trys to correct and goes to maximum and stays there. The PID loop 'then keeps integrating the sumerror when the feedback is below the setpoint. (Winds-up) If Fwd_Actuator1 = 0 Then Gosub PID1_Reset 'Prevents windup on the low end. (Please Keep) 'If PID1_Control_Output >= (65535) Then Gosub PID1_Reset 'Prevents windup on the top end. (optional) 'Enabling the above statement will prevent any error indication during plotting. '================================================================================================================ Rev_Actuator1 = (100 - Fwd_Actuator1) ' Compute reverse acting control output - 100%-0% Else Fwd_Actuator1 = 0 ' Output zero to actuator when PID1_Control_Enable = 0 Fwd_Actuator1 = Limit_100(Fwd_Actuator1) ' Clamp or Limit PID_Output between 0-100% - Forward Acting Control Rev_Actuator1 = (100 - Fwd_Actuator1) ' Compute reverse acting control output - 100%-0% End If PID1_Deviation_Error = Abs(Scale_Setpoint1 - Scale_Feedback1) If PID1_Deviation_Error >= PID1_Deviation_Error_Setpoint Then PID1_Error = 1 High PID1_Error_LED 'PID deviation error - LED on Else PID1_Error = 0 Low PID1_Error_LED 'No PID deviation error - LED off End If Data_AD420x = ScaleX (Fwd_Actuator1,0,100,0,65535) Data_AD420 = Data_AD420x 'Data_AD420 = 0 'Output test for AD420 (range 0 - 65535 = 0 - 5 VDC) Gosub Output_AD420_Data '==========================================PID Internal Loopback Test======================================================= 'PID1_LB_Test = ScaleX (Fwd_Actuator1,0,100,0,50) 'loopback test '=========================================================================================================================== Return 'End of PID1 Subroutine '========================================================================================================== ' '==========================================Stamp Plot Lite / Pro Init====================================== Plot_Init: Opencom 1,19200,3,64,64 ' Set comm 1 to 19,200, 8 N 1 - make sure StampPlot_Lite'Pro has the same settings. Bclr 1,1 ' xmit buf clr Pause 1000 Return ' '================================================================================================================= ' '================================================================================================================= '================================================================================================================= End 'End of all programs '================================================================================================================= '================================================================================================================= '================================================================================================================= ' ' [Functions] ' '================================================================================================================= ' ' ' '=============================[Top Secret --> PID1 Function <--Top Secret]======================================== Function PIDCalc1 (Proportion1 As Single,Integral1 As Single,Derivative1 As Single,Setpointx1 As Single,PIDFeedback1 As Single) As Single ' All variables are zero'd on program init ' Error1 = Setpointx1 - PIDFeedback1 SumError1 = SumError1 + Error1 dError1 = LastError1 - PrevError1 PrevError1 = LastError1 LastError1 = Error1 PIDCalc1 = (Proportion1 * Error1) + (Integral1 * SumError1) + (Derivative1 * dError1) End Function ' '================================================================================================================ '=============================================================================================================== Function Limit_100(Value_100 As Single) As Single 'Rev. 1.0b 'Keeps the variable between 0 - 100 % Dim Limit_Low_x As Single Dim Limit_High_x As Single Limit_Low_x = 0 Limit_High_x = 100 If Value_100 < Limit_Low_x Then Limit_100 = Limit_Low_x Exit Function End If If Value_100 > Limit_High_x Then Limit_100 = Limit_High_x Exit Function End If If Value_100 <= Limit_High_x Or Value_100 >= Limit_Low_x Then Limit_100 = Value_100 Exit Function End If End Function ' '=============================================================================================================== ' '=============================================================================================================== Function Limit_1(Value_1 As Single) As Single 'Rev. 1.0b 'Keeps the variable between 0 - 100 % Dim Limit_Low_x As Single Dim Limit_High_x As Single Limit_Low_x = 0 Limit_High_x = 1 If Value_1 < Limit_Low_x Then Limit_1 = Limit_Low_x Exit Function End If If Value_1 > Limit_High_x Then Limit_1 = Limit_High_x Exit Function End If If Value_1 <= Limit_High_x Or Value_1 >= Limit_Low_x Then Limit_1 = Value_1 Exit Function End If End Function ' '=============================================================================================================== '=============================================================================================================== ' Function ScaleX (ScaleY As Single,Ylow As Single,Yhigh As Single,Xlow As Single, Xhigh As Single) As Single 'Rev. 1.0b 'y = mx + b - basic linear formula - the change in x will be proportional to the change in y 'x = (Y-Yl)/(Yh-Yl)*(Xh-Xl)+Xl 'This formula works better than a ratio or proportion equation. It can even compute on negative range values. 'ScaleY = y units Input parameter value ' yl = y units Low value ' yh = y units High value 'ScaleX = x units Value to solve for ' xl = x units Low value ' xh = x units High value ' 'Example: x = ScaleY (5,0,10,50,100) ' x = 75 ScaleX = (ScaleY-Ylow)/(Yhigh-Ylow)*(Xhigh-Xlow)+Xlow End Function ' '============================================================================================================== ' '============================================================================================================== ' 'End of functions ' '==============================================================================================================
좀더 심플하게 만든 PID예제 프로그램
Const Device = CB280 LastError1 Var Single 'Error[-1] PrevError1 Var Single 'Error[-2] SumError1 Var Single 'SumError + Error (Sum of Errors) dError1 Var Single 'LastError - PrevError Error1 Var Single 'Error = Setpoint - PID Feedback Dim adv As Integer Dim advf As Single Dim pidv As Single Ramclear Do adv = Adin(0) advf = adv pidv = PIDcalc1(0.01, 0.1, 0.0, 1000.0, advf) Debug "Ad : ",Dec adv Debug " ---- PID cal : " , Float pidv,Cr Wait 100 Loop End Function PIDCalc1 (Proportion1 As Single,Integral1 As Single,Derivative1 As Single,Setpointx1 As Single,PIDFeedback1 As Single) As Single ' All variables are zero'd on program init. ' Error1 = Setpointx1 - PIDFeedback1 SumError1 = SumError1 + Error1 dError1 = LastError1 - PrevError1 PrevError1 = LastError1 LastError1 = Error1 PIDCalc1 = (Proportion1 * Error1) + (Integral1 * SumError1) + (Derivative1 * dError1) End Function