DUTs
GVLs
Global_Version
{attribute 'TcGenerated'}
{attribute 'no-analysis'}
{attribute 'linkalways'}
// This function has been automatically generated from the project information.
VAR_GLOBAL CONSTANT
{attribute 'const_non_replaced'}
stLibVersion_KFE_ARBITER : ST_LibVersion := (iMajor := 2, iMinor := 4, iBuild := 1, iRevision := 0, nFlags := 1, sVersion := '2.4.1');
END_VAR
GVL
VAR_GLOBAL
{attribute 'pytmc' := '
pv: @(PREFIX)Arbiter:01
'}
g_fbArbiter1 : FB_Arbiter(25);
ReqBP : ST_BeamParams; //Currently the placeholder for the fully arbitrated BP set
//Example implementation of the FFO
{attribute 'pytmc' := '
pv: @(PREFIX)FFO:01
'}
{attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[FFO]^Channel 1^Output'}
g_FastFaultOutput1 : FB_HardwareFFOutput := (bAutoReset:=TRUE);
{attribute 'pytmc' := '
pv: @(PREFIX)FFO:02
'}
{attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[FFO]^Channel 2^Output'}
g_FastFaultOutput2 : FB_HardwareFFOutput := (bAutoReset:=TRUE);
g_rTestingVelocity : LREAL := PMPS_GVL.VISIBLE_TEST_VELOCITY;
AttemptReset : BOOL; // For testing
END_VAR
VAR_GLOBAL CONSTANT
MAX_FAST_FAULTS : UINT := 100;
//Judgement factor constants (administrative mode)
nBeamIntensity : INT :=5;//mj
MaxDuration : REAL :=12;
END_VAR
GVL_CheckBounds
{attribute 'qualified_only'}
VAR_GLOBAL
nTooLow : UDINT;
nTooHigh : UDINT;
nDivByZero : UDINT;
END_VAR
POUs
CheckBounds
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckBounds : DINT
VAR_INPUT
index, lower, upper: DINT;
END_VAR
// User defined local variables
VAR
sMessageLow : STRING := 'CheckBounds: Index too low (%d)';
sMessageHigh : STRING := 'CheckBounds: Index too high (%d)';
END_VAR
// Index too low
IF index < lower THEN
CheckBounds := lower;
// Increase global counter
GVL_CheckBounds.nTooLow := GVL_CheckBounds.nTooLow + 1;
// Log message
ADSLOGDINT(msgCtrlMask := ADSLOG_MSGTYPE_WARN,
msgFmtStr := sMessageLow,
dintArg := index);
// Index too high
ELSIF index > upper THEN
CheckBounds := upper;
// Increase global counter
GVL_CheckBounds.nTooHigh := GVL_CheckBounds.nTooHigh + 1;
// Log message
ADSLOGDINT(msgCtrlMask := ADSLOG_MSGTYPE_WARN,
msgFmtStr := sMessageHigh,
dintArg := index);
// Index OK
ELSE
CheckBounds := index;
END_IF
{flow}
END_FUNCTION
- Related:
CheckRangeSigned
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckRangeSigned : DINT
VAR_INPUT
value, lower, upper: DINT;
END_VAR
// Implicitly generated code : Only an Implementation suggestion
IF (value < lower) THEN
CheckRangeSigned := lower;
ELSIF(value > upper) THEN
CheckRangeSigned := upper;
ELSE
CheckRangeSigned := value;
END_IF
{flow}
END_FUNCTION
CheckRangeUnsigned
// Implicitly generated code : DO NOT EDIT
FUNCTION CheckRangeUnsigned : UDINT
VAR_INPUT
value, lower, upper: UDINT;
END_VAR
// Implicitly generated code : Only an Implementation suggestion
{noflow}
IF (value < lower) THEN
CheckRangeUnsigned := lower;
ELSIF(value > upper) THEN
CheckRangeUnsigned := upper;
ELSE
CheckRangeUnsigned := value;
END_IF
{flow}
END_FUNCTION
CurrentBPUpdate
PROGRAM CurrentBPUpdate
VAR
{attribute 'pytmc' := '
pv: @(PREFIX)K:Rate
link: IOC:BSY0:MP01:BYKIKS_RATE
field: EGU RateEnum
'}
fbBYKIK_Rate : FB_LREALFromEPICS := (
iMaximumValidSeverity := 2);
{attribute 'pytmc' := '
pv: @(PREFIX)
'}
fbEPICS_KRate : FB_RateFromEPICS;
{attribute 'pytmc' := '
pv: @(PREFIX)L:BC
link: SIOC:SYS0:MP03:SC_SXR_BC
field: EGU BCEnum
'}
fbMPS_BeamClass : FB_LREALFromEPICS := (
iMaximumValidSeverity := 2);
{attribute 'pytmc' := '
pv: @(PREFIX)
'}
fbEPICSKBeamClass : FB_BeamClassFromEPICS;
{attribute 'pytmc' := '
pv: @(PREFIX)K:Mode
link: SIOC:FEES:MP01:FACMODE_RBV
'}
fbSXR_MachineMode : FB_LREALFromEPICS := (
iMaximumValidSeverity := 2);
{attribute 'pytmc' := '
pv: @(PREFIX)
'}
fbEPICSLMachineMode : FB_MachineModeFromEPICS;
{attribute 'pytmc' := '
pv: @(PREFIX)PE
'}
fbKPhotonEnergy : FB_KPhotonEnergy;
// Photon energy for the masses
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^IO Outputs^rPhotonEnergy'}
{attribute 'TcLinkTo' := 'TIIB[plc-rix-mot]^IO Outputs^rPhotonEnergy'}
{attribute 'TcLinkTo' := 'TIIB[plc-rix-optics]^IO Outputs^rPhotonEnergy'}
q_rPhotonEnergy AT %Q* : REAL;
// Stoppers
{attribute 'TcLinkTo' := '
.i_StopperInLS:=TIIB[PPS Stoppers 1]^Channel 1^ST3K4 IN;
.i_StopperOutLS:=TIIB[PPS Stoppers 1]^Channel 2^ST3K4 OUT;
.q_StopperIN_Relay:=TIIB[PMPS_Premp]^Channel 12^ST3K4 RELAY IN;
'}
st3k4Watcher : FB_KStopper(
PMPS.K_Stopper.ST3K4,
'ST3K4');
{attribute 'TcLinkTo' := '
.i_StopperInLS:=TIIB[PPS Stoppers 1]^Channel 3^ST1K2 IN;
.i_StopperOutLS:=TIIB[PPS Stoppers 1]^Channel 4^ST1K2 OUT;
.q_StopperIN_Relay:=TIIB[PMPS_Premp]^Channel 14^ST1K2 RELAY IN;
'}
st1k2Watcher : FB_KStopper(
PMPS.K_Stopper.ST1K2,
'ST1K2');
// MR1K1 Veto
////////////////////////
{attribute 'TcLinkTo' := 'TIIB[plc-rix-optics]^IO Inputs^MR1K1_Y_ENC'}
i_MR1K1_ENC AT %I* : UDINT; // MR1K1 encoder from the rix optics system
cMR1K1_IN_UpperLimit : UDINT := 33411000;
cMR1K1_IN_LowerLimit : UDINT := 31911000;
cMR1K1_OUT_UpperLimit : UDINT := 14173400;
{attribute 'TcLinkTo' := 'TIIB[PMPS_Premp]^Channel 13^MR1K1 IN'}
q_MR1K1_VETO AT %Q* : BOOL; // Signal to accel. MPS that MR1K1 is in
fbMR1K1VetoDevice : FB_KVetoDevice(
eVetoDeviceIN := K_Stopper.MR1K1_IN,
eVetoDeviceOUT := K_Stopper.MR1K1_OUT,
sVetoDeviceName := 'MR1K1');
// ST4K4 Photon Terminator Veto
{attribute 'TcLinkTo' := '
.i_StopperInLS:=TIIB[plc-tmo-mot]^IO Inputs^bST4K4_IN;
.i_StopperOutLS:=TIIB[plc-tmo-mot]^IO Inputs^bST4K4_OUT;
'}
st4k4Watcher : FB_KStopper(
PMPS.K_Stopper.ST4K4,
'ST4K4');
END_VAR
// Acquiring K-line rate
fbEPICS_KRate(BP:=PMPS_GVL.stCurrentBeamParameters, fbBYKIK_Rate:=fbBYKIK_Rate, FFO:=GVL.g_FastFaultOutput1);
// Acquiring photon energy
fbKPhotonEnergy(BP:=PMPS_GVL.stCurrentBeamParameters);
q_rPhotonEnergy := LREAL_TO_REAL(fbKPhotonEnergy.fbSXU.fCurrentPhotonEnergy);
//Update current photon energy
PMPS_GVL.stCurrentBeamParameters.neV := LREAL_TO_REAL(fbKPhotonEnergy.fbSXU.fCurrentPhotonEnergy);
// Acquiring K-line BeamClass
fbEPICSKBeamClass(BP:=PMPS_GVL.stCurrentBeamParameters, fbMPS_BeamClass:=fbMPS_BeamClass, FFO:=GVL.g_FastFaultOutput1);
// Acquiring K-line Machine Mode
fbEPICSLMachineMode(BP:=PMPS_GVL.stCurrentBeamParameters, fbMPS_MachineMode:=fbSXR_MachineMode, FFO:=GVL.g_FastFaultOutput1);
// Stopper readbacks
st3k4Watcher(stCurrentBP:=PMPS_GVL.stCurrentBeamParameters);
st1k2Watcher(stCurrentBP:=PMPS_GVL.stCurrentBeamParameters);
// MR1K1 Veto
////////////////////////
fbMR1K1VetoDevice(
i_bIn := cMR1K1_IN_LowerLimit < i_MR1K1_ENC AND i_MR1K1_ENC < cMR1K1_IN_UpperLimit,
i_bOut := i_MR1K1_ENC < cMR1K1_OUT_UpperLimit,
q_bIN => q_MR1K1_VETO,
stCurrentBP:= PMPS_GVL.stCurrentBeamParameters);
// ST4K4 Photon Terminator Veto
st4k4Watcher(stCurrentBP:=PMPS_GVL.stCurrentBeamParameters);
END_PROGRAM
- Related:
CXDisplay
PROGRAM CXDisplay
VAR
DisplayStats : FB_CXSetTextDisplayUSB := (nPort:=28928);
fbFormat : FB_FormatString;
bError : BOOL;
nErrID : UDINT;
sOut : T_MaxString;
END_VAR
(*
DisplayStats.bExecute S= NOT DisplayStats.bBusy AND NOT DisplayStats.bError;
DisplayStats.bExecute R= DisplayStats.bBusy OR DisplayStats.bError;
DisplayStats.sLine1 := 'PMPS-ARBITER-K';
fbFormat(sFormat := 'Fast Faults: %d', arg1:=F_ULINT(PMPS_GVL.AccumulatedFF), sOut=>DisplayStats.sLine2, bError => bError, nErrID => nErrID );
DisplayStats(eMode:=E_CX2100_DisplayModesWr.eCX2100_WriteLines);
*)
END_PROGRAM
Fast_Faults_Evaluate
PROGRAM Fast_Faults_Evaluate
VAR
FFO : FB_FastFault :=(
i_Desc := 'Fault occurs when the beamline valves on qrixs are not in open state',
i_TypeCode := 16#1010);
i_xFastFaultOut_qrix_vac AT %I*: BOOL;
END_VAR
FFO(
io_fbFFHWO := g_FastFaultOutput2,
i_xOK := i_xFastFaultOut_qrix_vac,
i_xAutoReset := TRUE);
g_FastFaultOutput2.EvaluateOutput(bAutoReset:=TRUE);
END_PROGRAM
FB_BeamClassOutputs
(*
Sets the beam class assertion lines for a given beam class.
*)
FUNCTION_BLOCK FB_BeamClassOutputs
VAR_INPUT
BP : ST_BeamParams;
END_VAR
VAR_OUTPUT
END_VAR
VAR
nBeamClass : BYTE;
wBeamClass : BYTE;
InitCounter: BYTE;
counter : INT;
// Beam class lines are restricted to 8 channels in the current design, since
// there are no plans to use all 16. Channels 1-7 may be allocated to any other
// beam classes so long as they are ordered least to greatest.
// Channel 8 is reserved for full beam.
{attribute 'pytmc' := 'pv: BeamClassChannel
io: i
field: DESC Hardwire channel state'}
epicsBitmap : WORD;
{attribute 'TcLinkTo' := '[1] := TIIB[PMPS_Premp]^Channel 1^Output;
[2] := TIIB[PMPS_Premp]^Channel 2^Output;
[3] := TIIB[PMPS_Premp]^Channel 3^Output;
[4] := TIIB[PMPS_Premp]^Channel 4^Output;
[5] := TIIB[PMPS_Premp]^Channel 5^Output;
[6] := TIIB[PMPS_Premp]^Channel 6^Output;
[7] := TIIB[PMPS_Premp]^Channel 7^Output;
'} // 8 - Full beam
q_BC_ASSERTION_LINES AT %Q* : ARRAY [1..MAX_BEAM_CLASS_LINES] OF BOOL;
END_VAR
VAR CONSTANT
MAX_BEAM_CLASS_LINES : BYTE := 8;
BC_1HZ : BYTE := 1;
BC_10HZ : BYTE := 2;
BC_FULL : BYTE := 16;
END_VAR
// Determine BC
IF BP.nRate >= 120 THEN
nBeamClass := BC_FULL;
ELSIF BP.nRate >= 10 THEN
nBeamClass := BC_10HZ;
ELSIF BP.nRate >= 1 THEN
nBeamClass := BC_1HZ;
ELSE
nBeamClass := 0;
END_IF
//Assert Beam Class
////////////////////////////////////
//0x0 = 0000 0000 0000 0000
//0x1 = 0000 0000 0000 0001
//0xF = 1111 1111 1111 1111
//Initialize BC lines to zero on every pass
FOR InitCounter := 1 TO MAX_BEAM_CLASS_LINES DO
q_BC_ASSERTION_LINES[InitCounter] := FALSE;
END_FOR
//Set BC lines according to beam class
//A BC of 0x0 would pass over this loop, setting none of the lines high
// , as FOR loops check the initialized variable at the top to see if it's >
// than the "TO" variable.
FOR wBeamClass:=1 TO MIN(MAX_BEAM_CLASS_LINES-1, nBeamClass) DO
q_BC_ASSERTION_LINES[wBeamClass] := TRUE;
END_FOR
q_BC_ASSERTION_LINES[8] := nBeamClass = 16; //Set channel 8 true if BC is 16
// Readbacks for EPICS
epicsBitmap.0 := q_BC_ASSERTION_LINES[1];
epicsBitmap.1 := q_BC_ASSERTION_LINES[2];
epicsBitmap.2 := q_BC_ASSERTION_LINES[3];
epicsBitmap.3 := q_BC_ASSERTION_LINES[4];
epicsBitmap.4 := q_BC_ASSERTION_LINES[5];
epicsBitmap.5 := q_BC_ASSERTION_LINES[6];
epicsBitmap.6 := q_BC_ASSERTION_LINES[7];
epicsBitmap.7 := q_BC_ASSERTION_LINES[8];
END_FUNCTION_BLOCK
MachineSimulation
PROGRAM MachineSimulation
VAR
fbMachine : FB_MachineSimulator; //Simulates attenuator as well
fbeVSimulator : FB_eVSimulator := (NoiseLevel := 1);
END_VAR
// reV Simulator
fbeVSimulator();
// Machine simulator
fbMachine(
i_stAssertedParams := PMPS_GVL.stRequestedBeamParameters,
iq_stMachineParams := PMPS_GVL.stCurrentBeamParameters,
i_xFault := NOT GVL.g_FastFaultOutput1.q_xFastFaultOut,
xEnableAtt := false,
xEnablePE := false
);
//PMPS_GVL.stCurrentBeamParameters.neVRange := F_eVRangeCalculator(fbeVSimulator.eV, PMPS_GVL.stCurrentBeamParameters.neVRange);
//PMPS_GVL.stCurrentBeamParameters.neVRange := 0;
END_PROGRAM
- Related:
MAIN
PROGRAM MAIN
VAR
Initialize : BOOL := TRUE;
fbLogHandler : FB_LogHandler;
fbEcatDiag : FB_EcatDiagWrapper;
{attribute 'pytmc' := '
pv: @(PREFIX)BeamParamCntl
'}
fbBPControl : FB_BPControlDevice(nID:=16#FFFF);
PERanges : PE_Ranges;
{attribute 'TcLinkTo' := 'TIIB[PMPS_Premp]^Channel 8^Output;'}
bM1K1_OUT_Override AT %Q* : BOOL; // Using this book to completely overrule the last bit of the BC interface.
//System Time
{attribute 'pytmc' := '
pv: @(PREFIX)SystemDT
io: i
'}
SystemTime:DINT;
fbTime : FB_LocalSystemTime := ( bEnable := TRUE, dwCycle := 1 ); //Get current system time, used for override
fbTime_to_UTC: FB_TzSpecificLocalTimeToSystemTime;
fbGetTimeZone: FB_GetTimeZoneInformation;
END_VAR
//Arbiter PLC
IF Initialize THEN
Initialize := FALSE;
END_IF
// Ethercat Diagnostics
fbEcatDiag();
// PMPS Functionality
CurrentBPUpdate();
///////////////////////////////////////////////////
// This code should be disabled or removed in deployment
// Might have a switch to change to simulation mode
MachineSimulation();
//Testing();
///////////////////////////////////////////////////
// Dummy device for controling pmps beam parameters
fbBPControl(Arbiter:=g_fbArbiter1);
PMPS_Arbiter();
P_AT1K0_SL1K0();
P_SATT();
bM1K1_OUT_Override := PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.K_Stopper.MR1K1_OUT];
fbLogHandler();
A_SystemTime();
Fast_Faults_Evaluate();
END_PROGRAM
ACTION A_SystemTime:
//Get local System Time
fbTime(sNetID:='');
//Get Time Zone
fbGetTimeZone(sNetID:='',bExecute:=TRUE,tTimeout:=T#10S);
//change local time to UTC to be compatible with unix time epoch widget
fbTime_to_UTC(in:= fbTime.systemTime , tzInfo:=fbGetTimeZone.tzInfo);
SystemTime:= TO_DINT(TO_DT(SystemTime_TO_DT(fbTime_to_UTC.out)));
END_ACTION
ACTION Initialize:
END_ACTION
P_AT1K0_SL1K0
PROGRAM P_AT1K0_SL1K0
VAR
// Transmisison request and status with plc-kfe-gatt
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^IO Outputs^Requested Transmission'}
q_nTranToAT1K0Req AT %Q* : ST_PMPS_Attenuator_IO; // Transmission request to AT1K0
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^IO Inputs^Current Transmission'}
i_nTranToAT1K0Stat AT %I* : ST_PMPS_Attenuator_IO; // Transmission request to AT1K0
// plc-kfe-gatt interface diagnostics
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^WcState^WcStateOut'}
i_bWcStateOut_AT1K0 AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^WcState^WcStateIn'}
i_bWcStateIn_AT1K0 AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-gatt]^InfoData^State'}
i_nState_AT1K0 AT %I* : UINT;
// Apterure request and status to plc-kfe-motion
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^IO Outputs^AptArrayReq'}
q_stAptArrayReq AT %Q* : ARRAY [1..4] OF ST_PMPS_Aperture_IO;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^IO Inputs^AptArrayStatus'}
i_stAptArrayStat AT %I* : ARRAY [1..4] OF ST_PMPS_Aperture_IO;
// plc-kfe-motion interface diagnostics
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^WcState^WcStateOut'}
i_bWcStateOut_KFEMOT AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^WcState^WcStateIn'}
i_bWcStateIn_KFEMOT AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^InfoData^State'}
i_nState_KFEMOT AT %I* : UINT;
idx : UINT;
ffKFEMotConnection : FB_FastFault := (
i_DevName := 'PMPS Arbiter',
i_Desc := 'EtherCAT interface watcher, for connection to KFE Motion systems for SL1K0 size requests. Very rare. Make a note, and if it can be reset, go ahead.',
i_TypeCode := 16#5);
ffKFEGattConnection : FB_FastFault := (
i_DevName := 'PMPS Arbiter',
i_Desc := 'EtherCAT interface watcher, for connection to KFE Gas Att. systems for Transmission requests. Very rare. Make a note, and if it can be reset, go ahead.',
i_TypeCode := 16#5);
bSimApt: BOOL;
// Administrative mode for beam intensity
{attribute 'pytmc' := '
pv: @(PREFIX)IntensityJF
'}
nBeamIntensityJF: REAL :=GVL.nBeamIntensity;
{attribute 'pytmc' := '
pv: @(PREFIX)ApplyJF
'}
bApplyJF: BOOL:=FALSE;
{attribute 'pytmc' := '
pv: @(PREFIX)CancelJF
'}
bCancelJF: BOOL:=FALSE;
{attribute 'pytmc' := '
pv: @(PREFIX)DurationJF
'}
rDurationJF: REAL:=GVL.MaxDuration;//hours
{attribute 'pytmc' := '
pv: @(PREFIX)TimeRemainJF
'}
rTimeRemainJF: REAL:=GVL.MaxDuration;//hours
tDuration:TIME;
tonDuration:TON;
END_VAR
//Beam intensity factor implemenation
// No diff by zero
IF (nBeamIntensityJF =0) OR (nBeamIntensityJF > GVL.nBeamIntensity ) THEN nBeamIntensityJF:=GVL.nBeamIntensity; END_IF
//Check it it has expired or is cancelled and reset to defaults
IF(tonDuration.Q OR bCancelJF)
THEN
nBeamIntensityJF:=GVL.nBeamIntensity;
bCancelJF := FALSE;
bApplyJF := FALSE;
END_IF
// Maximum duration is 12 hours
rDurationJF := LIMIT(0,rDurationJF,MaxDuration);
//check if it is applied
tDuration:= TO_TIME(rDurationJF*60*60*1000);//to msec
tonDuration(IN:=bApplyJF,PT:=tDuration,ET=>);
rTimeRemainJF:= rDurationJF - (TO_REAL(tonDuration.ET)/60/60/1000);//to hours
// If interface with plc-kfe-gatt OK carry out exchange
IF i_bWcStateOut_AT1K0 = 0 AND i_bWcStateIn_AT1K0 = 0 AND i_nState_AT1K0 = 8 THEN
// Send request from this arbiter to the gas attenuator
IF (bApplyJF) THEN
q_nTranToAT1K0Req.nTran := LIMIT(0,(GVL.nBeamIntensity/nBeamIntensityJF)*PMPS_GVL.stRequestedBeamParameters.nTran*PMPS_GVL.TRANS_SCALING_FACTOR,1);
ELSE
q_nTranToAT1K0Req.nTran := PMPS_GVL.stRequestedBeamParameters.nTran*PMPS_GVL.TRANS_SCALING_FACTOR;
END_IF
q_nTranToAT1K0Req.xAttOK := 16#FF;
//Update with judgement factor
//Calculate the new requested transmission
IF (bApplyJF) THEN
PMPS_GVL.stCurrentBeamParameters.nTran := i_nTranToAT1K0Stat.nTran *(nBeamIntensityJF/GVL.nBeamIntensity);//REAL_TO_UINT(UINT_TO_REAL(i_nTranToAT1K0Stat.nTran)*0.01);
ELSE
PMPS_GVL.stCurrentBeamParameters.nTran := i_nTranToAT1K0Stat.nTran;//REAL_TO_UINT(UINT_TO_REAL(i_nTranToAT1K0Stat.nTran)*0.01);
END_IF
ffKFEGattConnection.i_xOK := TRUE;
ELSE
// Fast fault
ffKFEGattConnection.i_xOK := FALSE;
PMPS_GVL.stCurrentBeamParameters.nTran := PMPS_GVL.TRANS_SCALING_FACTOR;//100;
END_IF
ffKFEGattConnection(io_fbFFHWO := g_FastFaultOutput1);
// If interface with plc-kfe-motion OK, carry out exchange
IF i_bWcStateIn_KFEMOT = 0 AND i_bWcStateOut_KFEMOT = 0 AND i_nState_KFEMOT = 8 THEN
// Send request from this arbiter to kfe-mot
MEMCPY( ADR(q_stAptArrayReq) , ADR(PMPS_GVL.stRequestedBeamParameters.astApertures) , PMPS_GVL.MAX_APERTURES * SIZEOF(ST_PMPS_Aperture_IO) );
// Recieve current apreture state for broadcast
MEMCPY( ADR(PMPS_GVL.stCurrentBeamParameters.astApertures) , ADR(i_stAptArrayStat) , PMPS_GVL.MAX_APERTURES * SIZEOF(ST_PMPS_Aperture_IO) );
ffKFEMotConnection.i_xOK := TRUE;
ELSIF bSimApt THEN
PMPS_GVL.stCurrentBeamParameters.astApertures := PMPS_GVL.stRequestedBeamParameters.astApertures;
ELSE
// Fast fault
ffKFEMotConnection.i_xOK := FALSE;
// Set broadcast apterture states to not OK
FOR idx := 1 TO PMPS_GVL.MAX_APERTURES DO
PMPS_GVL.stCurrentBeamParameters.astApertures[idx].xOK := FALSE;
END_FOR
END_IF
ffKFEMotConnection(io_fbFFHWO := g_FastFaultOutput1);
END_PROGRAM
- Related:
P_SATT
PROGRAM P_SATT
VAR
//All Sold attenuators requests are summerrized into this one output
q_SattArrayReq AT %Q* : ARRAY [1..PMPS_GVL.AUX_ATTENUATORS] OF ST_PMPS_Attenuator_IO; // Transmission request to ALL PLCs
//Per PLC current satt trans
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^IO Inputs^SattArrayStatus'}
i_SattArrayStatus_KFE AT %I* : ARRAY [1..PMPS_GVL.AUX_ATTENUATORS] OF ST_PMPS_Attenuator_IO; // Transmission request to KFE MOT PLC
{attribute 'TcLinkTo' := 'TIIB[plc-rix-mot]^IO Inputs^SattArrayStatus'}
i_SattArrayStatus_RIX AT %I* : ARRAY [1..PMPS_GVL.AUX_ATTENUATORS] OF ST_PMPS_Attenuator_IO; // Transmission request to RIX MOT PLC
// plc-tmo-mot interface diagnostics
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^WcState^WcStateOut'}
i_bWcStateOut_kfe_mot AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^WcState^WcStateIn'}
i_bWcStateIn_kfe_mot AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-kfe-motion]^InfoData^State'}
i_nState_kfe_mot AT %I* : UINT;
// plc-rix-mot interface diagnostics
{attribute 'TcLinkTo' := 'TIIB[plc-rix-mot]^WcState^WcStateOut'}
i_bWcStateOut_rix_mot AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-rix-mot]^WcState^WcStateIn'}
i_bWcStateIn_rix_mot AT %I* : BOOL;
{attribute 'TcLinkTo' := 'TIIB[plc-rix-mot]^InfoData^State'}
i_nState_rix_mot AT %I* : UINT;
//FFO Connection per PLC
ffkfeConnection : FB_FastFault := (
i_DevName := 'PMPS Arbiter',
i_Desc := 'EtherCAT interface watcher, for tmo-mot connection to systems for attenuation requests. Very rare. Make a note, and if it can be reset, go ahead.',
i_TypeCode := 16#5);
ffRixConnection : FB_FastFault := (
i_DevName := 'PMPS Arbiter',
i_Desc := 'EtherCAT interface watcher, for rix-mot connection to systems for attenuation requests. Very rare. Make a note, and if it can be reset, go ahead.',
i_TypeCode := 16#5);
END_VAR
// Send request from this arbiter to all satts
MEMCPY( ADR(q_SattArrayReq) , ADR(PMPS_GVL.stRequestedBeamParameters.astAttenuators) , PMPS_GVL.AUX_ATTENUATORS * SIZEOF(ST_PMPS_Attenuator_IO) );
//TMO motion PLC SATT current trans update
IF i_bWcStateIn_kfe_mot = 0 AND i_bWcStateOut_kfe_mot = 0 AND i_nState_kfe_mot = 8 THEN
// Recieve current transmission of the satt
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT1K4].nTran := i_SattArrayStatus_KFE[PMPS.K_Attenuators.AT1K4].nTran;
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT1K4].xAttOK := i_SattArrayStatus_KFE[PMPS.K_Attenuators.AT1K4].xAttOK;
ffkfeConnection.i_xOK := TRUE;
ELSE
// Fast fault
ffkfeConnection.i_xOK := FALSE;
END_IF
ffkfeConnection(io_fbFFHWO := g_FastFaultOutput1);
//RIX motion PLC SATT current trans update
IF i_bWcStateIn_rix_mot = 0 AND i_bWcStateOut_rix_mot = 0 AND i_nState_rix_mot = 8 THEN
// Recieve current transmission of the satt
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT1K2].nTran := i_SattArrayStatus_RIX[PMPS.K_Attenuators.AT1K2].nTran;
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT1K2].xAttOK := i_SattArrayStatus_RIX[PMPS.K_Attenuators.AT1K2].xAttOK;
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT2K2].nTran := i_SattArrayStatus_RIX[PMPS.K_Attenuators.AT2K2].nTran;
//PMPS_GVL.stCurrentBeamParameters.astAttenuators[PMPS.K_Attenuators.AT2K2].xAttOK := i_SattArrayStatus_RIX[PMPS.K_Attenuators.AT2K2].xAttOK;
ffRixConnection.i_xOK := TRUE;
ELSE
// Fast fault
ffRixConnection.i_xOK := FALSE;
END_IF
ffRixConnection(io_fbFFHWO := g_FastFaultOutput1);
END_PROGRAM
PMPS_Arbiter
PROGRAM PMPS_Arbiter
VAR
fbSetPE : PE_Ranges;
fbBPRequestor : FB_BPRequestor; // Updates global PMPS RequestedBeamParams
{attribute 'pytmc' := '
pv: @(PREFIX)PhotonEnergyWatcher
'}
fbPhotonEnergyWatcher : FB_PhotonEnergyWatcher;
{attribute 'pytmc' := '
pv: @(PREFIX)BeamClassWatcher
'}
fbBeamClassWatcher : FB_BeamClassWatcher;
{attribute 'pytmc' := '
pv: @(PREFIX)BeamClassOutputs
'}
fbMPSInterface : FB_BeamClassOutputs_BCD;
{attribute 'pytmc' := '
pv: @(PREFIX)CuRateOutputs
'}
fbCuInterface : FB_CTLS_Outputs;
(* Subsystem requests use this FB and a pragma link to pass their requests to the arbiter.
The fb is called on each cycle and updates the arbiter with the current BP set requested
from the subsystem PLC.*)
//<TODO> make this so it does input and output to the IF
(*{attribute 'pytmc' := '
pv: @(PREFIX):PLC1
'}*)
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-kfe-motion]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-kfe-motion]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-kfe-motion]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-kfe-motion]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-kfe-motion]^SYNC Inputs^TxPDO state;
'}
plc_kfe_motion_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#FF0F);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-kfe-vac]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-kfe-vac]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-kfe-vac]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-kfe-vac]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-kfe-vac]^SYNC Inputs^TxPDO state;
'}
plc_kfe_vac_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#FF11);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-kfe-gatt]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-kfe-gatt]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-kfe-gatt]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-kfe-gatt]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-kfe-gatt]^SYNC Inputs^TxPDO state;
'}
plc_kfe_gatt_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#FF12);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-kfe-gmd-vac-01]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-kfe-gmd-vac-01]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-kfe-gmd-vac-01]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-kfe-gmd-vac-01]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-kfe-gmd-vac-01]^SYNC Inputs^TxPDO state;
'}
plc_kfe_gmd_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#FF13);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-kfe-xgmd-vac-01]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-kfe-xgmd-vac-01]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-kfe-xgmd-vac-01]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-kfe-xgmd-vac-01]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-kfe-xgmd-vac-01]^SYNC Inputs^TxPDO state;
'}
plc_kfe_xgmd_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#FF14);
//////////////////////////////////////////////
// TMO PLCs
/////////////////////////////////////////////
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-tmo-mot]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-tmo-mot]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-tmo-mot]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-tmo-mot]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-tmo-mot]^SYNC Inputs^TxPDO state;
'}
plc_tmo_motion_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F100);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-tmo-optics]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-tmo-optics]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-tmo-optics]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-tmo-optics]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-tmo-optics]^SYNC Inputs^TxPDO state;
'}
plc_tmo_optics_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F101);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-tmo-vac]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-tmo-vac]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-tmo-vac]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-tmo-vac]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-tmo-vac]^SYNC Inputs^TxPDO state;
'}
plc_tmo_vacuum_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F102);
count : CTU;
//////////////////////////////////////////////
// RIX PLCs
/////////////////////////////////////////////
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-rix-vac]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-rix-vac]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-rix-vac]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-rix-vac]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-rix-vac]^SYNC Inputs^TxPDO state;
'}
plc_rix_vac_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F200);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-rix-optics]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-rix-optics]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-rix-optics]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-rix-optics]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-rix-optics]^SYNC Inputs^TxPDO state;
'}
plc_rix_optics_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F201);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-rix-mot]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-rix-mot]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-rix-mot]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-rix-mot]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-rix-mot]^SYNC Inputs^TxPDO state;
'}
plc_rix_mot_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F202);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-crix-mot]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-crix-mot]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-crix-mot]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-crix-mot]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-crix-mot]^SYNC Inputs^TxPDO state;
'}
plc_crix_mot_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F203);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-crix-vac]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-crix-vac]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-crix-vac]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-crix-vac]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-crix-vac]^SYNC Inputs^TxPDO state;
'}
plc_crix_vac_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F205);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-qrix-mot]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-qrix-mot]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-qrix-mot]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-qrix-mot]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-qrix-mot]^SYNC Inputs^TxPDO state;
'}
plc_qrix_mot_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F206);
{attribute 'TcLinkTo' := '.i_RequestedBP:=TIIB[plc-qrix-vac]^IO Inputs^RequestedBP;
.o_CurrentBP:=TIIB[plc-qrix-vac]^IO Outputs^CurrentBP;
.i_Connected:=TIIB[plc-qrix-vac]^SYNC Inputs^External device not connected;
.i_WcState:=TIIB[plc-qrix-vac]^WcState^WcStateIn;
.i_TxPDOState:=TIIB[plc-qrix-vac]^SYNC Inputs^TxPDO state;
'}
plc_qrix_vac_PMPS_IO : FB_ArbiterToSubSys_IO := (RequestingSystemID := 16#F204);
END_VAR
// Updating arbiter with subsystem requests.
///////////////////////////
// KFE
plc_kfe_motion_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'KFE MOTION');
plc_kfe_vac_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'KFE VACUUM');
plc_kfe_gatt_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'KFE GATT');
///////////////////////////
// TMO
plc_tmo_motion_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset , sName:= 'TMO MOTION');
plc_tmo_optics_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'TMO OPTICS');
plc_tmo_vacuum_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'TMO VACUUM');
//////////////////////////
// RIX
plc_rix_mot_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'RIX MOTION');
plc_rix_vac_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'RIX VACUUM');
plc_rix_optics_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'RIX OPTICS');
plc_crix_mot_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'CRIX MOTION');
plc_crix_vac_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'CRIX VACUUM');
plc_qrix_vac_PMPS_IO(Arbiter:=GVL.g_fbArbiter1, fbFFHWO:=GVL.g_FastFaultOutput1, Reset:=GVL.AttemptReset, sName:= 'QRIX VACUUM');
///////////////////////////
////////////////////////////
// Beam parameter requestor
fbBPRequestor(Arbiter:=GVL.g_fbArbiter1, q_ReqBP => PMPS_GVL.stRequestedBeamParameters);
// Request beam class
fbMPSInterface(BP := PMPS_GVL.stRequestedBeamParameters);
// Request Cu beam rate
fbCuInterface(BP := PMPS_GVL.stRequestedBeamParameters);
// Keep an eye on the photon energy
fbPhotonEnergyWatcher(i_stCurrentBeamParams := PMPS_GVL.stCurrentBeamParameters,
i_stRequestedBeamParams := PMPS_GVL.stRequestedBeamParameters,
io_fbFFHWO:= GVL.g_FastFaultOutput1,
i_xReset := GVL.AttemptReset);
// Keep an eye on the beam class
fbBeamClassWatcher(i_stCurrentBeamParams := PMPS_GVL.stCurrentBeamParameters,
i_stRequestedBeamParams := PMPS_GVL.stRequestedBeamParameters,
io_fbFFHWO:= GVL.g_FastFaultOutput1,
i_xAutoReset := TRUE);
// Evaluate fast fault vetos
g_FastFaultOutput1.Execute();
END_PROGRAM
- Related:
Testing
PROGRAM Testing
VAR
AttemptReset : TON := (PT:=T#1s);
gAttemptReset : TON := (PT:=T#500ms);
testFF : FB_FastFault;
cycle : INT;
END_VAR
// Trip a fast fault periodically
testFF(io_fbFFHWO:= g_FastFaultOutput1);
//testFF.i_xOK := (cycle mod 1000) = 0;
//cycle := cycle + 1;
//Periodically try to reset the photon energy fault.
AttemptReset(IN:=PMPS_Arbiter.fbPhotonEnergyWatcher.xPhotonEnergyWithinBounds, Q=>GVL.AttemptReset);
gAttemptReset(IN:=GVL.g_FastFaultOutput1.xOK, Q=>GVL.g_FastFaultOutput1.i_xReset);
END_PROGRAM
- Related: