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
TextLabel ," ======== Optimise PID Gain ========"
Long ClassAsArray
String UnitNameTag@{Tag}
Integer PID_Number*<<1>>
String PID_Name@{Tag} ;full name of the PID controller
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
long classtag_length
Integer 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 = StrStr(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
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 Version Check (optional) This will ensure SysCAD is in the correct version to use the latest PGM syntax / functions.
Const long VersionNumber =
32530
Sub CheckVersion()
Bit BuildOK
BuildOK = PM.Version(0)>=9 AND PM.Version(1)>=3 AND PM.Version(2)>=139 AND PM.Version(3)>=VersionNumber
If NOT BuildOK
StopSolver("Incorrect version of SysCAD, needs SysCAD9.3 Build139.", IntToStr(VersionNumber)," or later.")
Endif
EndSub
'''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()
CheckVersion()
ForEachClass(PIDs, Initialise())
EndSub
;execute the optimise sub routine.
ForEachClass(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:
|