unit Controller_UnRolling; interface uses MMTimer, Controllers; const cDataSignature='UnRolling'; cBasePort=$ED00; cValidPorts=[$B1..$B3]; cValidWriteports=[$B1..$B3]; cValidReadports=[$B2,$B3]; cRoll_mks_PerImpuls=16; cRollMaxCounterUpLimit=900000; cRollMaxCounterLoLimit=90000; cRollMaxCounter=750000; cRollMaxCounterNoise=30000; cRollBoundOverload=20000; cRollOverloadMaxTime=20; {ms} cRollCounterMassCoefficient=1.288E-9; cRollCounterdC=0; type tRollCounter=0..cRollMaxCounterUpLimit; // состояние tFlagState=(fsInProgress, fsAllowUp, fsAllowDown, b3, b4, b5, b6, b7); tFlagsState= set of tFlagState; tData=record MaxCounter :tRollCounter; RollCounter :tRollCounter; DeltaCounter :byte; FlagsState :tFlagsState; AutoTuning :boolean; LoBoundOverload :tRollCounter; UpBoundOverload :tRollCounter; OverLoadTime :cardinal; end; tTmpData=record Direction :0..2; ResetRequred :boolean; end; tUnRolling=class(tController) private Data :tData; TmpData :tTmpData; Timer :TMMTimer; procedure SetDeltaCounter(b:byte); procedure Start(b:byte); procedure SetFlagState(AFlag: tFlagState; AState: boolean); function Operational:boolean; procedure SetOverload(c:tRollCounter; d:byte); procedure StartTimer; procedure SetAutoTuning(b:byte); function GetState:byte; procedure OnMyTimer(Sender:tObject); public constructor Create; destructor Destroy; override; procedure Init; override; function InB(Port:word):byte; override; procedure OutB(b:byte; Port:word); override; function ValidPort(Port:word; BasePort:word):boolean; override; function ValidReadPort(Port:word):boolean; override; function ValidWritePort(Port:word):boolean; override; function DataSize:cardinal; override; function SetData(aData:Pointer):boolean; override; function GetData(aData:Pointer):boolean; override; function SubPath:string; override; function GetMass:cardinal; procedure SetCounter(Value:tRollCounter); function GetCounter:tRollCounter; end; implementation uses Math, Windows, messages, SysUtils, Peak, Hardware, uMainForm; //***************************************************************************** // //***************************************************************************** //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- constructor tUnRolling.Create; begin Timer:=tMMTimer.Create; Timer.Resolution:=10; Timer.OnTimer:=OnMyTimer; Timer.TimerType:=ttOnce; Timer.Enabled:=true; inherited; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- destructor tUnRolling.Destroy; begin Timer.Enabled:=false; FreeAndNil(Timer); inherited; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.Init; begin Data.LoBoundOverload:=cRollBoundOverload; Data.MaxCounter:=cRollMaxCounter+(Random(2*cRollMaxCounterNoise)-cRollMaxCounterNoise); Data.UpBoundOverload:=Data.MaxCounter-Data.LoBoundOverload; Data.FlagsState:=[b3, b4, b5, b6, b7]; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.OutB(b:byte; Port:word); begin case Port of $B1:begin SetDeltaCounter(b); end; $B2:begin Start(b); MI1201AGM.UpdateSignal; end; end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.InB(Port:word):byte; begin case Port of $B2:begin // Timer.Clear; // Init; end; $B3:begin Result:=GetState; end; end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.ValidPort(Port:word; BasePort:word):boolean; begin Result:=(Port in cValidPorts) and (BasePort=cBasePort); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.ValidReadPort(Port:word):boolean; begin Result:=Port in cValidReadPorts; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.ValidWritePort(Port:word):boolean; begin Result:=Port in cValidWritePorts; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.SetDeltaCounter(b:byte); begin Data.DeltaCounter:=b; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.Start(b:byte); begin if Operational then begin if TmpData.Direction<>b then begin case b of 2: SetFlagState(fsAllowUP, true); 1: SetFlagState(fsAllowDown, true); end; TmpData.Direction:=b; end; case b of 2:begin if Data.RollCounter(Data.MaxCounter-Data.DeltaCounter) then begin Data.RollCounter:=Data.MaxCounter; SetFlagState(fsAllowUp,FALSE); exit; end; Inc(Data.RollCounter, Data.DeltaCounter); if Data.RollCounter>Data.UpBoundOverload then begin SetOverload(Data.RollCounter-Data.UpBoundOverload,b); end else begin SetOverload(0,b); end; StartTimer; end; end; end; MainForm.stRollCounter.Caption:=format('%d',[Data.RollCounter]); MainForm.stMassCounter.Caption:=format('%d',[GetMass]); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.SetFlagState(AFlag:tFlagState; AState:boolean); begin if AState<>(AFlag in Data.FlagsState) then begin if AState then Include(Data.FlagsState, AFlag) else Exclude(Data.FlagsState, AFlag); end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.Operational:boolean; begin Result:=not( (fsInProgress in Data.FlagsState) and TmpData.ResetRequred ); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.SetOverload(c:tRollCounter; d:byte); var t:cardinal; begin t:=((((c*1000) div Data.LoBoundOverload)*cRollOverloadMaxTime) div 1000); if tcRollOverloadMaxTime then t:=cRollOverloadMaxTime; Data.OverLoadTime:=t; if c<>0 then begin case d of 1: begin SetFlagState(fsAllowUp,FALSE); end; 2: begin SetFlagState(fsAllowDown,FALSE); end; else begin end; end; end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.StartTimer; var pTime:cardinal; begin Include(Data.FlagsState, fsInProgress); pTime:=(Data.DeltaCounter*cRoll_mks_PerImpuls)div 1000 +Data.OverLoadTime; if pTime>0 then Timer.Interval:=pTime else Timer.Interval:=1; Timer.UpdateTimer; // OnMyTimer(self); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.SetAutoTuning(b:byte); begin if not (b>1) then begin Data.AutoTuning:=boolean(b); end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.GetState:byte; begin Result:=byte(Data.FlagsState); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.GetMass:cardinal; var x:tRollCounter; begin x:=Data.RollCounter; Result:=Round((Params.CounterMassCoef*Power(x+Params.CounterdC,2))*cMassScale); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.DataSize:cardinal; begin Result:=SizeOf(tData); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.SetData(aData:Pointer):boolean; begin Result:=false; try Move(aData^, Data, DataSize); Result:=True; except end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.GetData(aData:Pointer):boolean; begin Result:=false; try Move(Data, aData^, DataSize); Result:=True; except end; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.SubPath:string; begin Result:=cDataSignature; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.SetCounter(Value:tRollCounter); begin Data.RollCounter:=Value; end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- procedure tUnRolling.OnMyTimer(Sender:TObject); begin SetFlagState(fsInProgress, false); end; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- function tUnRolling.GetCounter:tRollCounter; begin Result:=Data.RollCounter; end; end.