PGM Example - PGM Class to assist with solving sensitive PID control loops
Jump to navigation
Jump to search
Navigation: PGMs ➔ Example PGM Files ➔ PGM Example - PGM Class to assist with solving sensitive PID control loops
Related Links: Defining a Class
;This class is used to optimise the value of the gain for a PID controller
DropList Options{"Maximum Gain", "Minimum Gain", "Geometric Mean"}
Class Class_OptimiseGain
ClassGridColumnWidth 20 ;if you want multiple optimisers displayed as a grid, set this value so that the column displays are wide enough, search for ClassGrid for more details
TextLabel ," ======== Optimise PID Gain ========"
Integer ClassAsArray
String UnitNameTag@{Tag}
Integer PID_Number*<<1>>
String PID_Name@{Tag} ;full name of the PID controller
String PID_Description@ ;description given to the controller by the user
Memo PID_Description2@
CheckBox Optimiser_On*<<1>>
CheckBox SetOutput_MinMax*<<0>>
Textbreak
Options InitGain*<<2>>{Comment("Initial Gain (if RelError > 0.1%)")}
Real MaxGain*<<0.05>><1e-12,> ;the maximum gain that will be used
Real MinGain*<<0.0001>><1e-12,> ;the minimum gain that will be used (also used as the initial value)
Real CurGain@ ;current gain
Real MinPB@@{Comment("1/MaxGain")}, MaxPB@@{Comment("1/MinGain")}, CurPB@@{Comment("1/CurGain")}
Integer ItersBetweenGainDecrease*<<5>> ; iterations between gain decrease
Integer ItersBetweenGainIncrease*<<5>> ; iterations between gain increase
Real AdjustmentFactor*<<2>><1.1,10> ; adjustment factor for division or multiplication
Textbreak
Real OutputMin**, OutputMax**<<10>>
String GainTag@@{Tag}, SPTag@@{Tag}, MeasTag@@{Tag}, RelErrorTag@@{Tag}, OutMinTag@@{Tag}, OutMaxTag@@{Tag}
Real OldDiff ;holds the previous error
Real Diff ;holds the current error
Integer classtag_length, ItersSinceLastDecrease, ItersSinceLastIncrease
Bit IsFirstIteration, SetOutputState
Sub Initialise()
;Check if the Class is defined as an array, if so, need to remove [index] from the ClassTag()
ClassAsArray = StrFind(ClassTag(), "[" )
if ClassAsArray == -1
UnitNameTag = ClassTag()
Else
classtag_length = StrLen(ClassTag())
UnitNameTag = Left(ClassTag(), ClassAsArray)
Endif
;calculate and store the PID tags
PID_Name = Concatenate(UnitNameTag,".Cfg.[", InttoStr(PID_Number),"]")
GainTag = Concatenate(PID_Name,".Gain")
SPTag = Concatenate(PID_Name,".SptUsed")
MeasTag = Concatenate(PID_Name,".Meas")
RelErrorTag = Concatenate(PID_Name,".RelError (%)")
OutMinTag = Concatenate(PID_Name,".OutMin")
OutMaxTag = Concatenate(PID_Name,".OutMax")
;initialise key values
ItersSinceLastDecrease = 0
ItersSinceLastIncrease = 0
SetConcealedState(OutputMin, (SetOutput_MinMax==False))
SetConcealedState(OutputMax, (SetOutput_MinMax==False))
SetOutputstate = SetOutput_MinMax
IsFirstIteration = True
PID_Description = [Concatenate(UnitNameTag,".Cfg.[",InttoStr(PID_Number),"].Name")]
PID_Description2 = [Concatenate(UnitNameTag,".Cfg.[",InttoStr(PID_Number),"].Description")]
EndSub
Sub Optimise()
If (Optimiser_On)
If (IsFirstIteration)
If (Abs([RelErrorTag]) > 0.1) ;if not currently converged
If InitGain == 0 ;start at max gain
[GainTag] = MaxGain
ElseIf InitGain == 1 ;start at min gain
[GainTag] = MinGain
ElseIf InitGain == 2 ;start at geometric mean
[GainTag] = Sqrt(MinGain * MaxGain)
EndIf
EndIf
CurGain = [GainTag]
OldDiff = [RelErrorTag]
IsFirstIteration = False ;reset flag
EndIf
;grab current error
Diff = [RelErrorTag]
If (Diff * OldDiff < 0) ;error has switched sign (oscillating around SP) - decrease gain
If (ItersSinceLastDecrease > ItersBetweenGainDecrease)
CurGain = Max(CurGain/AdjustmentFactor, MinGain)
[GainTag] = CurGain
ItersSinceLastDecrease = 0
EndIf
Else ;error has the same sign (approaching SP) - increase gain
If (ItersSinceLastIncrease > ItersBetweenGainIncrease)
CurGain = Min(CurGain*AdjustmentFactor, MaxGain)
[GainTag] = CurGain
ItersSinceLastIncrease = 0
EndIf
EndIf
;update counter and previous error
ItersSinceLastDecrease = ItersSinceLastDecrease + 1
ItersSinceLastIncrease = ItersSinceLastIncrease + 1
OldDiff = Diff
EndIf
;update concealed state of output min/max if changed
If SetOutput_MinMax <> SetOutputState
SetConcealedState(OutputMin, (SetOutput_MinMax==False))
SetConcealedState(OutputMax, (SetOutput_MinMax==False))
SetOutputState = SetOutput_MinMax
EndIf
;update PID output min/max
If SetOutput_MinMax
[OutMinTag] = OutputMin
[OutMaxTag] = OutputMax
EndIf
CurPB = 1/CurGain
MaxPB = 1/MinGain
MinPB = 1/MaxGain
EndSub
EndClass
;Please make sure there is no dollar sign or end of file marker here for this to be an include file.
Adding the OptimiseGain class to PGM file.
>>OptimiseGain.pgm
;==================================================================
;Main Program
PageLabel "OptimisePIDs"
Textbreak
;Define the class instances
;For PID Controller with a single control block requiring optimisation, simply define the class instance using the unit tag name.
Class_OptimiseGain Autoclave2_Steam
;For PID Controller with multiple control blocks requiring optimisation, define the class instance using the unit tag name in an array.
Class_OptimiseGain NonOxidising_Leach_Control[2]
;Define class list for use in class macros or class functions
ClassList PIDs{Autoclave2_Steam, NonOxidising_Leach_Control}
;Display results in Grid format
ClassGrid PIDs
;initialise the class tags
Sub PreStart()
ForEachSub(PIDs, Initialise())
EndSub
;execute the optimise sub routine.
ForEachSub(PIDs, Optimise())
$ ; --- end of file ---
Setting up the Access Window: For example, user can add the above PGM class and PGM file to the Nickel Copper Project.
NOTE:
|