HTBasic Help
×
Menu
Index

Example: PID Controller

 
10     ! *********************************************************************
20     ! Example: PID Controller
30     !
40     ! This example program simulates a PID Controller.
50     !
60     ! **************************************************************
70     !
80     DIM Points(3),Errors(64),Enum$(2)[10]
90     !
100   ! Construct the panel that controls the PID itself.
110   ! The panel indicates the current error and whether the loop is locked.
120   !
130   ASSIGN @Pid_panel TO WIDGET "PANEL";SET ("X":0,"Y":0,"WIDTH":400,"HEIGHT":245,"TITLE":"PID Controller","RESIZABLE":0,"MAXIMIZABLE":0)
140   CONTROL @Pid_panel;SET ("TITLE":" Example: PID Controller")
150   CONTROL @Pid_panel;SET ("SYSTEM MENU":"Quit")
160   ON EVENT @Pid_panel,"SYSTEM MENU" GOTO Finis
170   !
180   ! Slider to control Kp
190   !
200   ASSIGN @Kp_slider TO WIDGET "SLIDER";PARENT @Pid_panel,SET ("X":5,"Y":30,"WIDTH":70,"HEIGHT":180,"DECIMAL DIGITS":2)
210   CONTROL @Kp_slider;SET ("MINIMUM":0,"MAXIMUM":1,"MINOR INCREMENT":.01)
220   ASSIGN @Kp_note TO WIDGET "STRING";PARENT @Pid_panel,SET ("X":5,"Y":0,"WIDTH":70,"HEIGHT":20,"VALUE":"   Kp")
230   !
240   ! Slider to control Ki
250   !
260   ASSIGN @Ki_slider TO WIDGET "SLIDER";PARENT @Pid_panel,SET ("X":80,"Y":30,"WIDTH":70,"HEIGHT":180,"DECIMAL DIGITS":2)
270   CONTROL @Ki_slider;SET ("MINIMUM":0,"MAXIMUM":1,"MINOR INCREMENT":.01)
280   ASSIGN @Ki_note TO WIDGET "STRING";PARENT @Pid_panel,SET ("X":80,"Y":0,"WIDTH":70,"HEIGHT":20,"VALUE":"   Ki")
290   !
300   ! Slider to control Kd
310   !
320   ASSIGN @Kd_slider TO WIDGET "SLIDER";PARENT @Pid_panel,SET ("X":155,"Y":30,"WIDTH":70,"HEIGHT":180,"DECIMAL DIGITS":2)
330   CONTROL @Kd_slider;SET ("MINIMUM":0,"MAXIMUM":1,"MINOR INCREMENT":.01)
340   ASSIGN @Kd_note TO WIDGET "STRING";PARENT @Pid_panel,SET ("X":155,"Y":0,"WIDTH":70,"HEIGHT":20,"VALUE":"   Kd")
350   !
360   ! Meter that displays the error
370   !
380   ASSIGN @Error_meter TO WIDGET "METER";PARENT @Pid_panel,SET ("X":235,"Y":30,"WIDTH":150,"HEIGHT":140,"MINIMUM":-1,"MAXIMUM":1,"AUTOSCALE":0)
390   ASSIGN @Meter_note TO WIDGET "STRING";PARENT @Pid_panel,SET ("X":235,"Y":0,"WIDTH":150,"HEIGHT":20,"VALUE":"      Error")
400   !
410   ! String that displays whether the loop is locked or unlocked
420   !
430   ASSIGN @Lock_indicate TO WIDGET "STRING";PARENT @Pid_panel,SET ("X":270,"Y":180,"VALUE":"UNLOCKED","WIDTH":80,"HEIGHT":30,"BACKGROUND":2)
440   !
450   ! Slider that sets the set point for the loop
460   !
470   ASSIGN @Setpt_slider TO WIDGET "SLIDER";SET ("X":410,"Y":0,"WIDTH":150,"TITLE":"Set Point","DECIMAL DIGITS":2)
480   CONTROL @Setpt_slider;SET ("MINIMUM":0,"MAXIMUM":1,"MAJOR INCREMENT":.01,"MINOR INCREMENT":.1)
490   !
500   ! Strip chart to plot the set point and actual value
510   !
520   ASSIGN @Graph TO WIDGET "STRIPCHART";SET ("X":0,"Y":245,"TRACE COUNT":2,"SHARED X":1,"HEIGHT":235,"RESIZABLE":0,"MAXIMIZABLE":0)
530   CONTROL @Graph;SET ("CURRENT AXIS":"Y","ORIGIN":-.25,"RANGE":1.5)
540   CONTROL @Graph;SET ("CURRENT AXIS":"X","ORIGIN":0,"RANGE":100)
550   CONTROL @Graph;SET ("CURRENT TRACE":1,"TRACE LABEL":"Set point")
560   CONTROL @Graph;SET ("CURRENT TRACE":2,"TRACE LABEL":"Actual")
570   CONTROL @Graph;SET ("TITLE":" Set Point Value")
580   !
590   ! Cyclic control for the order of the load
600   !
610   Enum$(0)="1st"
620   Enum$(1)="2nd"
630   Load_order=1
640   ASSIGN @Load TO WIDGET "PUSHBUTTON";SET ("X":410,"Y":250,"WIDTH":150,"HEIGHT":50)
650   CONTROL @Load;SET ("TITLE":"Load Order","RESIZABLE":0,"MAXIMIZABLE":0,"LABEL":Enum$(Load_order))
660   ON EVENT @Load,"ACTIVATED",1 GOSUB Load_change
670   !
680   ! Initialize the sliders that control the PID
690   !
700   Ki=.17
710   CONTROL @Ki_slider;SET ("VALUE":Ki)
720   Kp=.4
730   CONTROL @Kp_slider;SET ("VALUE":Kp)
740   Kd=.37
750   CONTROL @Kd_slider;SET ("VALUE":Kd)
760   !
770   ! Initialize the setpoint slider
780   !
790   Setpt=.9
800   CONTROL @Setpt_slider;SET ("VALUE":Setpt)
810   !
820   ! Enable the event handling for the sliders
830   !
840   ON EVENT @Ki_slider,"DONE",2 GOSUB Ki_input
850   ON EVENT @Kp_slider,"DONE",2 GOSUB Kp_input
860   ON EVENT @Kd_slider,"DONE",2 GOSUB Kd_input
870   ON EVENT @Setpt_slider,"DONE",2 GOSUB Setpt_input
880   !
890   ! Initialize the actual value of the output and the array
900   ! that contains previous error values
910   !
920   Actual=0
930   FOR I=0 TO 62
940     Errors(I)=0
950   NEXT I
960   Sample=0
970   LOOP
980     Avg=0
990     FOR I=62 TO 0 STEP -1
1000      Avg=Avg+Errors(I)
1010      Errors(I+1)=Errors(I)
1020    NEXT I
1030    Errors(0)=Setpt-Actual
1040    Avg=(Avg+Errors(0))/64
1050    To_load=(Kp*Errors(0)+Ki*Avg+Kd*(Errors(0)-Errors(1)))
1060    SELECT Load_order
1070    CASE 0
1080    !
1090    ! First order load
1100    !
1110      Actual=(To_load*1.7)+Actual
1120    CASE 1
1130    !
1140    ! Second order load
1150    !
1160      Temp=To_load*5+Temp
1170      Actual=(Temp*.52+Actual)/2
1180    END SELECT
1190    Points(0)=Setpt
1200    Points(1)=Actual
1210    CONTROL @Graph;SET ("POINT LOCATION":Sample,"VALUES":Points(*))
1220    Sample=Sample+1
1230    CONTROL @Error_meter;SET ("VALUE":Errors(0))
1240    IF ABS(Errors(0))+ABS(Errors(1))<.02 THEN
1250      CONTROL @Lock_indicate;SET ("VALUE":"LOCKED","BACKGROUND":4)
1260    ELSE
1270      CONTROL @Lock_indicate;SET ("VALUE":"UNLOCKED","BACKGROUND":2)
1280    END IF
1290  END LOOP
1300 Ki_input: STATUS @Ki_slider;RETURN ("VALUE":Ki)
1310  Ki=PROUND(Ki,-2)
1320  RETURN
1330 Kp_input: STATUS @Kp_slider;RETURN ("VALUE":Kp)
1340  Kp=PROUND(Kp,-2)
1350  RETURN
1360 Kd_input: STATUS @Kd_slider;RETURN ("VALUE":Kd)
1370  Kd=PROUND(Kd,-2)
1380  RETURN
1390 Setpt_input: STATUS @Setpt_slider;RETURN ("VALUE":Setpt)
1400  Setpt=PROUND(Setpt,-2)
1410  RETURN
1420 Load_change: Load_order=Load_order+1
1430  IF Load_order>1 THEN Load_order=0
1440  CONTROL @Load;SET ("LABEL":Enum$(Load_order))
1450  RETURN
1460 Finis:  !
1470  ASSIGN @Pid_panel TO *                                ! Delete PANEL widget
1480  END