DUTs

E_GasType

TYPE E_GasType :
(
    none := 0,
    Nitrogen,
    Argon
);
END_TYPE
Related:

E_HomeState

TYPE E_HomeState :
(
    H_READY,
    H_INIT,
    H_RESET_LL,
    H_RESET_HL,
    H_ENABLE,
    H_MOVING,
    H_MOVING2,
    H_CHECK,
    H_RESET,
    H_SET_POS,
    H_ERROR,
    H_WRITE_LL,
    H_WRITE_HL,
    H_DONE

) UDINT;
END_TYPE

E_MAA_States

TYPE E_MAA_States :
(
    Unknown := 0,
    Aprt1 := 1, //smallest
    Aprt2 := 2,
    Aprt3 := 3,
    Aprt4 := 4
);
END_TYPE

E_MAA_States_X

TYPE E_MAA_States_X :
(
    Unknown := 0,
    Centered:=1
);
END_TYPE

E_MoveState

TYPE E_MoveState :
(
    ABORT,
    INIT,
    ENABLE,
    FORWARD,
    BACKWARDS,
    READY,
    MOVING,
    NEWTARGETPOSITION,
    NEWTARGETPOSITION2,
    ERROR,
    RESET,
    HALT,
    HOME
) UDINT;
END_TYPE

E_State

{attribute 'qualified_only'}
{attribute 'strict'}
TYPE E_State :
(
    unknown,
    error,
    warning,
    ok
);
END_TYPE

ST_DRL

TYPE ST_DRL :
STRUCT
    {attribute 'pytmc' := ' pv: TEMP '}
    TEMP AT%I*: UINT;
    {attribute 'pytmc' := ' pv: SV '}
    SV  AT%I*: UINT;
    {attribute 'pytmc' := ' pv: SC '}
    SC  AT%I*: UINT;
END_STRUCT
END_TYPE

ST_VGP

TYPE ST_VGP :
STRUCT

    {attribute 'pytmc' := '
    pv: POS_RBV;
    io: i;
    '}
    // Inputs
    i_iPosition     :       REAL; //Encoder position readback (if it exists)
    {attribute 'pytmc' := '
    pv: ENC_RBV;
    io: i;
    '}
    // Inputs
    rEnoder_Position        :       REAL; //Encoder position readback (if it exists)
    {attribute 'pytmc' := '
    pv: ERROR;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: i;
    '}
    // Inputs
    pv_xError       :       BOOL;

    {attribute 'pytmc' := '
    pv: IS_HOMED;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: i;
    '}
    // Inputs
    pv_xHomed       :       BOOL :=false;


    //Softvariables
    {attribute 'pytmc' := '
    pv: ILK_OK;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: i;
    '}
    xIlkOK  :       BOOL := FALSE; // Interlock Bit
    //Manually Pressing valve "Open/Close" on EDM
    {attribute 'pytmc' := '
    pv: OPN_SW;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: io;
    '}
    pv_xOPN_SW      : BOOL;

    {attribute 'pytmc' := '
    pv: GO_SW;
    field: ZNAM FALSE;
    field: ONAM TRUE;
    io: io;
    '}
    pv_xGo_SW       : BOOL;

    {attribute 'pytmc' := '
    pv: HOME_SW;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: io;
    '}
    pv_xHome_SW     : BOOL;

    {attribute 'pytmc' := '
    pv: Reset_SW;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: io;
    '}
    pv_xReset_SW    : BOOL;

    {attribute 'pytmc' := '
    pv: Busy;
    field: ZNAM FALSE;
     field: ONAM TRUE;
    io: io;
    '}
    xBusy   : BOOL;

    {attribute 'pytmc' := '
    pv: ABORT;
     field: ZNAM FALSE;
     field: ONAM TRUE;
    io: io;
    '}
    pv_xABORT_SW    : BOOL;


    {attribute 'pytmc' := '
    pv: POS_CTRL;
    io: io;
    '}
    rReqPosition    :       REAL;
    // Outputs
    {attribute 'pytmc' := '
    pv: POS_DES;
    io: io;
    '}
    q_iRawPosition  :       INT; //Position control
    {attribute 'pytmc' := '
    pv: STATE;
    type: mbbi ;
    field: ZRST CLOSE ;
    field: ONST OPEN;
    field: TWST PRESS CNTRL ;
    field: THST MANUAL CNTRL ;
    io: io;
    '}
    eValveControl   :       E_VCN := CloseValve; // Valve control state
    /// state machine state
    {attribute 'pytmc' := '
    pv: Axis_STATE;
    io: io;
    '}
    eState: E_MoveState; //Axis Move state
    ftIlk   :       F_TRIG;
    {attribute 'pytmc' := '
    pv: ERR_ID;
    io: i;
    '}
    nErrorID: UDINT;

    {attribute 'pytmc' := '
    pv: ERR_MSG;
    io: i;
    '}
    sErrorMessage : STRING;

END_STRUCT
END_TYPE
Related:

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_GATT : ST_LibVersion := (iMajor := 0, iMinor := 3, iBuild := 1, iRevision := 0, nFlags := 1, sVersion := '0.3.1');
END_VAR

GVL_Devices

VAR_GLOBAL
(*AT1K0*)
/// Injector
//Valves
    {attribute 'pytmc' :=' pv: AT1K0:GAS:VCN:70 '}
    VCN_70 : FB_VCN;

    {attribute 'pytmc' :=' pv: AT1K0:GAS:VVC:71 '}
    VVC_71 : FB_VVC;

    {attribute 'pytmc' :=' pv: AT1K0:GAS:VVC:72 '}
    VVC_72 : FB_VVC;


    {attribute 'pytmc' :=' pv: AT1K0:GAS:VGP:80 '}
    VGP_80 : FB_VGP;

//Gauges
    {attribute 'pytmc' :=' pv: AT1K0:GAS:GCM:70 '}
    GCM_70: FB_GCM;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:GCM:80 '}
    GCM_80: FB_GCM;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:GCM:81 '}
    GCM_81: FB_GCM;
    (*Pseudo gauge device Structure to combine the readings of two GCM gauges*)
    {attribute 'pytmc' :=' pv: AT1K0:GAS:GCM:82  '}
    GCM_82 : ST_VG;


/////////////////////////////


    //////////////////////////////////
// MKS275 Gauges

{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:111 '}
fb_AT1K0_GAS_GPI_111 : FB_MKS275;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:121 '}
fb_AT1K0_GAS_GPI_121 : FB_MKS275;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:141 '}
fb_AT1K0_GAS_GPI_141 : FB_MKS275;

// FB_MKS317

{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:10 '}
fb_AT1K0_GAS_GPI_10 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:20 '}
fb_AT1K0_GAS_GPI_20 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:11 '}
fb_AT1K0_GAS_GPI_11 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:30 '}
fb_AT1K0_GAS_GPI_30 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:40 '}
fb_AT1K0_GAS_GPI_40 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:50 '}
fb_AT1K0_GAS_GPI_50 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:60 '}
fb_AT1K0_GAS_GPI_60 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:51 '}
fb_AT1K0_GAS_GPI_51 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:80 '}
fb_AT1K0_GAS_GPI_80 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:90 '}
fb_AT1K0_GAS_GPI_90 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:100 '}
fb_AT1K0_GAS_GPI_100 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:110 '}
fb_AT1K0_GAS_GPI_110 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:120 '}
fb_AT1K0_GAS_GPI_120 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:130 '}
fb_AT1K0_GAS_GPI_130 : FB_MKS317;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:140 '}
fb_AT1K0_GAS_GPI_140 : FB_MKS317;

// FB_MKS422

{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:10 '}
fb_AT1K0_GAS_GCC_10 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:20 '}
fb_AT1K0_GAS_GCC_20 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:30 '}
fb_AT1K0_GAS_GCC_30 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:40 '}
fb_AT1K0_GAS_GCC_40 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:50 '}
fb_AT1K0_GAS_GCC_50 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:60 '}
fb_AT1K0_GAS_GCC_60 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:80 '}
fb_AT1K0_GAS_GCC_80 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:90 '}
fb_AT1K0_GAS_GCC_90 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:100 '}
fb_AT1K0_GAS_GCC_100 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:110 '}
fb_AT1K0_GAS_GCC_110 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:120 '}
fb_AT1K0_GAS_GCC_120 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:130 '}
fb_AT1K0_GAS_GCC_130 : FB_MKS422;
{attribute 'pytmc' := ' pv: AT1K0:GAS:GCC:140 '}
fb_AT1K0_GAS_GCC_140 : FB_MKS422;




// FB_VRC

{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:10 '}
fb_AT1K0_GAS_VRC_10 : FB_VRC_EBD;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:20 '}
fb_AT1K0_GAS_VRC_20 : FB_VRC_EBD;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:30 '}
fb_AT1K0_GAS_VRC_30 : FB_VRC_EBD;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:40 '}
fb_AT1K0_GAS_VRC_40 : FB_VRC_EBD;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:50 '}
fb_AT1K0_GAS_VRC_50 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:60 '}
fb_AT1K0_GAS_VRC_60 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:70 '}
fb_AT1K0_GAS_VRC_70 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:80 '}
fb_AT1K0_GAS_VRC_80 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:90 '}
fb_AT1K0_GAS_VRC_90 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:100 '}
fb_AT1K0_GAS_VRC_100 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:110 '}
fb_AT1K0_GAS_VRC_110 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:120 '}
fb_AT1K0_GAS_VRC_120 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:130 '}
fb_AT1K0_GAS_VRC_130 : FB_VRC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:140 '}
fb_AT1K0_GAS_VRC_140 : FB_VRC;

// PUMPS
// Turbos
// FB_PTM_Ebara_010M
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:10 '}
fb_AT1K0_GAS_PTM_10 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:20 '}
fb_AT1K0_GAS_PTM_20 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:30 '}
fb_AT1K0_GAS_PTM_30 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:40 '}
fb_AT1K0_GAS_PTM_40 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:80 '}
fb_AT1K0_GAS_PTM_80 : FB_PTM_TwisTorr;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:120 '}
fb_AT1K0_GAS_PTM_120 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:130 '}
fb_AT1K0_GAS_PTM_130 : FB_PTM_Ebara_010M;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:140 '}
fb_AT1K0_GAS_PTM_140 : FB_PTM_Ebara_010M;
// FB_PTM_Ebara_011M
{attribute 'pytmc' := ' pv: AT1K0:GAS:PTM:110 '}
fb_AT1K0_GAS_PTM_110 : FB_PTM_Ebara_011M;

// Roughing
// FB_EbaraDryPump
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:10 '}
fb_AT1K0_GAS_PMF_10 : FB_ScrollPump;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:60 '}
fb_AT1K0_GAS_PMF_60 : FB_ScrollPump;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:90 '}
fb_AT1K0_GAS_PMF_90 : FB_EbaraDryPump;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:100 '}
fb_AT1K0_GAS_PMF_100 : FB_EbaraDryPump;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:110 '}
fb_AT1K0_GAS_PMF_110 : FB_EbaraEVA;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:120 '}
fb_AT1K0_GAS_PMF_120 : FB_EbaraEVA;
{attribute 'pytmc' := ' pv: AT1K0:GAS:PMF:140 '}
fb_AT1K0_GAS_PMF_140 : FB_EbaraEVA;

//Roughing DC Valves
{attribute 'pytmc' := ' pv: AT1K0:GAS:VCP:110 '}
//{attribute 'TcLinkTo' :=  '.q_xOPN_DO     :=      TIIB[=+-EL2212_06_25]^DOX Control Channel 1^Control^Output'}
{attribute 'TcLinkTo' :=    '.q_xOPN_DO     :=      TIIB[=+-ES2004_05_02]^Channel 3^Output'}
fb_AT1K0_GAS_VVC_110 : FB_VVC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VCP:120 '}
//{attribute 'TcLinkTo' :=  '.q_xOPN_DO     :=      TIIB[=+-EL2212_06_25]^DOX Control Channel 2^Control^Output'}
{attribute 'TcLinkTo' :=    '.q_xOPN_DO     :=      TIIB[=+-ES2004_05_02]^Channel 4^Output'}
fb_AT1K0_GAS_VVC_120 : FB_VVC;
{attribute 'pytmc' := ' pv: AT1K0:GAS:VCP:140 '}
//{attribute 'TcLinkTo' :=  '.q_xOPN_DO     :=      TIIB[=+-EL2212_04_18]^DOX Control Channel 1^Control^Output'}
{attribute 'TcLinkTo' :=    '.q_xOPN_DO     :=      TIIB[=+-ES2004_05_04]^Channel 3^Output'}
fb_AT1K0_GAS_VVC_140 : FB_VVC;

//PTM 80 VRC back stream valve
{attribute 'pytmc' := ' pv: AT1K0:GAS:VVC:80 '}
{attribute 'TcLinkTo' :=    '.q_xOPN_DO     :=      TIIB[=+-EL2212_04_18]^DOX Control Channel 2^Control^Output'}
fb_AT1K0_GAS_VVC_80 : FB_VVC;
//NEW added Valve instead of the manual valve at the roughing line in the EBD
{attribute 'pytmc' := ' pv: AT1K0:GAS:VRC:11 '}
{attribute 'TcLinkTo' :=    '.q_xOPN_DO     :=      TIIB[=+-ES2008_02_14]^Channel 1^Output;
                            .i_xClsLS       :=      TIIB[=+-ES1004_03_21]^Channel 2^Input;
                            .i_xOpnLS       :=      TIIB[=+-ES1004_03_21]^Channel 1^Input'}


fb_AT1K0_GAS_VRC_11 : FB_VRC_EBD;

{attribute 'pytmc' := ' pv: AT1K0:GAS:GPI:12 '}
{attribute 'TcLinkTo' :=    '.i_iPRESS_R    :=      TIIB[=+-ES3064_01_09]^AI Standard Channel 4^Value'}
fb_AT1K0_GAS_GPI_12 : FB_MKS317;

END_VAR
Related:

GVL_GATT

VAR_GLOBAL

fbLogHandler: FB_LogHandler;
fbLogger : FB_LogMessage := (eSubsystem:=E_SubSystem.MPS,nMinTimeViolationAcceptable:=10,nLocalTripThreshold := T#500ms);
fbEcatDiagWrapper : FB_EcatDiagWrapper;

END_VAR

GVL_MOT

VAR_GLOBAL


END_VAR

GVL_PMPS

VAR_GLOBAL

//MPS
    {attribute 'pytmc' := '
    pv: PLC:KFE:GATT:FFO:01
    '}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[=+-ES2202_00_07]^Channel 1^Output'}
    g_FastFaultOutput1  :   FB_HardwareFFOutput :=(i_sNetID:='172.21.92.73.1.1');

    {attribute 'pytmc' := '
    pv: PLC:KFE:GATT:FFO:02
    '}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[=+-ES2202_00_07]^Channel 2^Output'}
    g_FastFaultOutput2  :   FB_HardwareFFOutput :=(i_sNetID:='172.21.92.73.1.1');

    {attribute 'pytmc' := '
     pv: PLC:KFE:GATT:FF_RESET;
     field: ZNAM FALSE;
     field: ONAM TRUE;
     io: io;
    '}
    xFastFaultReset :   BOOL;
    {attribute 'pytmc' := '
    pv: PLC:KFE:GATT:ARB:01
    '}
    fbArbiter1   :   FB_Arbiter(1);
    {attribute 'pytmc' := '
    pv: PLC:KFE:GATT:ARB:02
    '}
    fbArbiter2   :   FB_Arbiter(2);

    {attribute 'pytmc' := '
    pv: AT1K0:GAS:MODE ;
     field: ZNAM Local;
    field: ONAM PMPS;
     io: io;
    '}
    xPMPSMode       :BOOL;

    {attribute 'TcLinkTo' := ':=TIIB[PMPS_PRE]^IO Inputs^Requested Transmission'}
    Req_Trans AT%I*: ST_PMPS_Attenuator_IO;

     {attribute 'TcLinkTo' := ':=TIIB[PMPS_PRE]^IO Outputs^Current Transmission'}
    Cur_Trans AT%Q*: ST_PMPS_Attenuator_IO;
    {attribute 'pytmc' := '
    pv: AT1K0:GAS:PhotonEnergy
    '}

    rPhotonEnergy : REAL;

    stStatus: ST_AttenuatorStatus;
    {attribute 'TcLinkTo' := ':=TIIB[PMPS_PRE]^IO Outputs^bGattStatus'}
    bStatus  AT%Q*:Byte;


END_VAR

GVL_Variables

VAR_GLOBAL

(*Transmission related variables*)
    {attribute 'pytmc' := '
    pv: AT1K0:GAS:GAS_TYPE ;
    type: mbbi ;
    field: ZRST none ;
    field: ONST N2;
    field: TWST Ar ;
    io: i
    '}
    SelectedGas: E_GasType;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:CALC_SP;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    field: EGU "TORR";
    '}
    rRequiredPressureSP: REAL;
     {attribute 'pytmc' := '
        pv:  AT1K0:GAS:MAA:GET;
        io: i;
        field: ZRST Unknown;
        field: ONST 5.5mm;
        field: TWST 8mm;
        field: THST 10mm;
        field: FRST 13mm;
    '}
    eSelectedAprt:E_MAA_States;
    {attribute 'pytmc' := '
        pv:  AT1K0:GAS:MAA:SET;
        io: i;
        field: ZRST Unknown;
        field: ONST 5.5mm;
        field: TWST 8mm;
        field: THST 10mm;
        field: FRST 13mm;
    '}
    eSetAprt:E_MAA_States;
    {attribute 'pytmc' := '
    pv: AT1K0:GAS:TRANS;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    io:i;
    '}
    rCalculatedTransmissionValue: REAL:=1;
    {attribute 'pytmc' := '
    pv: AT1K0:GAS:TRANS_REQ;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    io:i;
    '}
    rRequestedTransmission: REAL:=1;
    {attribute 'pytmc' := '
    pv: AT1K0:GAS:TRANS_SP;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    io:io;
    '}
    rTransmissionSP: REAL:=1;


    {attribute 'pytmc' := '
    pv:  AT1K0:GAS:STATE;
    field: ZRST unknown;
    field: ONST error;
    field: TWST warning;
    field: THST ok;
    io: i;
    '}
    eState:E_State;

    TransmissionValue: REAL;
    OldTransmissionValue: REAL;
    rtNewTrans : R_TRIG;
    bChangeAperture: BOOL:=FALSE;
    bChangeGas:BOOL:=FALSE;



    (* EPS and Interlock Variables*)
    {attribute 'pytmc' := 'pv: AT1K0:GAS:VAC:OVRD_ON ;
     field: ZNAM Override OFF;
    field: ONAM Override ON;
     io: io;'}
    xSystemOverrideMode     :       BOOL; (* Global system override for the GATT*)


    //VRC ILK setpoints to OPEN
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:US:SP;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    field: EGU "TORR";
    '}
    rVRC_US_SP :REAL:=0.001;

    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:DS:SP;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    field: EGU "TORR";
    '}
    rVRC_DS_SP :REAL:=0.001;

    {attribute 'pytmc' := '
    pv: AT1K0:GAS:MODE:PressureControl ;
     field: ZNAM Local;
    field: ONAM PMPS;
     io: io;
    '}
    xPressureControlMode    :BOOL := FALSE;

    {attribute 'pytmc' := '
    pv: AT1K0:GAS:AtTarget ;
     field: ZNAM FALSE;
    field: ONAM TRUE;
     io: io;
    '}
    xAtTarget       :BOOL := FALSE;

    {attribute 'pytmc' := '
    pv: AT1K0:GAS:Moving ;
     field: ZNAM FALSE;
    field: ONAM TRUE;
     io: io;
    '}
    xMoving :BOOL := FALSE;

    {attribute 'pytmc' := '
    pv: AT1K0:GAS:OK ;
     field: ZNAM FALSE;
    field: ONAM TRUE;
     io: io;
    '}
    xOK     :BOOL := FALSE;


    (* Interlock related bits, local to the PLC*)
    US_MAA_OK:  BOOL;
    US_Turbo_Valves_Open:  BOOL;
    DS_MAA_OK: BOOL;
    DS_Turbo_Valves_Open:  BOOL;
    US_Turbo_Running:  BOOL;
    DS_Turbo_Running:  BOOL;
    TwinscrewPumps_Valves_Closed: BOOL;
    US_Roughing_Valves_Open : BOOL;
    DS_Roughing_Valves_Open : BOOL;
    US_Aperture_Closed: BOOL;
    DS_Aperture_Closed: BOOL;

END_VAR
Related:

Main

VAR_GLOBAL

    //MAA EBD
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_X:MMS:1'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-ES7041_02_05]^STM Status^Status^Digital input 1;
                               .bLimitBackwardEnable := TIIB[=+-ES7041_02_05]^STM Status^Status^Digital input 2'}
                            //  .nRawEncoderINT         :=  TIIB[=+-E3054_02_17]^AI Standard Channel 1^Value'}
    M1: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_X:MMS:1');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_Y:MMS:1'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-ES7041_02_06]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-ES7041_02_06]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_02_07]^Channel 3^Output'}
                              //.nRawEncoderINT       := TIIB[=+-E3054_02_17]^AI Standard Channel 2^Value'}
    M2: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_Y:MMS:1');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_X:MMS:2'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-ES7041_02_09]^STM Status^Status^Digital input 1;
                               .bLimitBackwardEnable := TIIB[=+-ES7041_02_09]^STM Status^Status^Digital input 2'}
                             // .nRawEncoderINT       :=  TIIB[=+-E3054_02_17]^AI Standard Channel 3^Value'}
    M3: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_X:MMS:2');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_Y:MMS:2'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-ES7041_02_10]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-ES7041_02_10]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_02_07]^Channel 4^Output'}
                             // .nRawEncoderINT       :=  TIIB[=+-E3054_02_17]^AI Standard Channel 4^Value'}
    M4: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_Y:MMS:2');
    //MAA FEE

    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_X:MMS:3'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-EL7041_04_07]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-EL7041_04_07]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_04_09]^Channel 1^Output'}
                             // .nRawEncoderINT       :=  TIIB[=+-E3054_04_12]^AI Standard Channel 1^Value'}
    M5: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_X:MMS:3');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_Y:MMS:3'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-EL7041_04_08]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-EL7041_04_08]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_04_09]^Channel 2^Output'}
                             // .nRawEncoderINT       :=  TIIB[=+-E3054_04_12]^AI Standard Channel 2^Value'}
    M6: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_Y:MMS:3');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_X:MMS:4'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-EL7041_04_10]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-EL7041_04_10]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_04_09]^Channel 3^Output'}
                              //.nRawEncoderINT       :=  TIIB[=+-E3054_04_12]^AI Standard Channel 3^Value'}
    M7: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_X:MMS:4');
    {attribute 'pytmc' := 'pv: AT1K0:GAS_MA_Y:MMS:4'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[=+-EL7041_04_11]^STM Status^Status^Digital input 2;
                               .bLimitBackwardEnable := TIIB[=+-EL7041_04_11]^STM Status^Status^Digital input 1;
                              .bBrakeRelease        := TIIB[=+-ES2004_04_09]^Channel 4^Output'}
                            //  .nRawEncoderINT       :=  TIIB[=+-E3054_04_12]^AI Standard Channel 4^Value'}
    M8: DUT_MotionStage := (sName := 'AT1K0:GAS_MA_Y:MMS:4');

END_VAR

POUs

DIAGNOSTICS

PROGRAM DIAGNOSTICS
VAR
    //Change the PLC String Name to the actual PLC NAME
    sPLCName :STRING := 'PLC-KFE_GATT';
    //Link the sAMSNetID to the Etherat Master netID
    i_sAMSNetID AT %I*: AMSNETID;
    // DO NOT CHANGE
    sAMSNetID : STRING; //used for EPICS PV
    sLibVersion_LCLS_General : STRING;(* := stLibVersion_LCLS_General.sVersion*) ;
    fbEcatDiag:FB_EcatDiag;
    bAllSlaveStateGood : BOOL;
    bMasterStateGood :BOOL;
    iMasterState: WORD;
    sMasterState:STRING;
    nSlaveNumber : UINT;
    aiSlaveStates: ARRAY[1..256] OF BYTE;
    aEcSlaveInfo :  ARRAY[1..256] OF ST_EcDevice;


    // Infor Data from Diagnostics terminals
    {attribute 'pytmc' := ' pv: AT1K0:GAS:DRL:04 '}
    {attribute 'TcLinkTo' :=        '.TEMP  :=      TIIB[=+-EL2212_04_18]^DOX Synchron info data Channel 1^Info data 1;
                                 .SV        :=      TIIB[=+-EL2212_04_18]^DOX Synchron info data Channel 1^Info data 2;
                                 .SC        :=      TIIB[=+-EL2212_04_18]^DOX Synchron info data Channel 2^Info data 1'}
    DRL_04 : ST_DRL;
    {attribute 'pytmc' := ' pv: AT1K0:GAS:DRL:05 '}
    {attribute 'TcLinkTo' :=        '.TEMP  :=      TIIB[=+-EL2212_05_09]^DOX Synchron info data Channel 1^Info data 1;
                                 .SV        :=      TIIB[=+-EL2212_05_09]^DOX Synchron info data Channel 1^Info data 2;
                                 .SC        :=      TIIB[=+-EL2212_05_09]^DOX Synchron info data Channel 2^Info data 1'}
    DRL_05 : ST_DRL;
    {attribute 'pytmc' := ' pv: AT1K0:GAS:DRL:06 '}
    {attribute 'TcLinkTo' :=        '.TEMP  :=      TIIB[=+-EL2212_06_25]^DOX Synchron info data Channel 1^Info data 1;
                                 .SV        :=      TIIB[=+-EL2212_06_25]^DOX Synchron info data Channel 1^Info data 2;
                                 .SC        :=      TIIB[=+-EL2212_06_25]^DOX Synchron info data Channel 2^Info data 1'}
    DRL_06 : ST_DRL;
END_VAR
// Instaniating a call to the fbEcatDiag
fbEcatDiag(
    I_AMSNetId:=i_sAMSNetID ,
    i_xFirstPass:= _TaskInfo[1].FirstCycle,
    q_xAllSlaveStatesGood=> bAllSlaveStateGood ,
    q_anTermStates=> aiSlaveStates,
    q_xMasterStateGood=>bMasterStateGood ,
    q_nMasterState=> iMasterState,
    q_sMasterState=> sMasterState ,
    q_astEcConfSlaveInfo=> aEcSlaveInfo ,
    q_nSlaves=> nSlaveNumber);

END_PROGRAM
Related:

F_COEF_AR

FUNCTION F_COEF_AR : REAL
VAR_INPUT
END_VAR
VAR

END_VAR


END_FUNCTION

FB_ILK_TEST

FUNCTION_BLOCK FB_ILK_TEST
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR


END_FUNCTION_BLOCK

FB_MAA

FUNCTION_BLOCK FB_MAA
VAR_IN_OUT
    fbArbiter: FB_Arbiter;
    fbFFHWO: FB_HardwareFFOutput;
    stYStage: DUT_MotionStage;
    stXStage: DUT_MotionStage;

END_VAR
VAR_INPUT
     {attribute 'pytmc' := '
        pv: :PMPS:AribterEnabled
        io: io
    '}
    bArbiterEnabled: BOOL:=TRUE;;
     nTransitionAssertionID: UDINT;
    stAprt1: DUT_PositionState;
    stAprt2: DUT_PositionState;
    stAprt3: DUT_PositionState;
    stAprt4: DUT_PositionState;
    stXCen: DUT_PositionState;
    i_DevName: STRING:= 'AT1K0-MAA';
     {attribute 'pytmc' := '
        pv: Y:STATE:SET;
        io: io;
        field: ZRST Unknown;
        field: ONST 5.5mm;
        field: TWST 8mm;
        field: THST 10mm;
        field: FRST 13mm;
    '}
     enumSet: E_MAA_states;
    sPmpsDeviceName: STRING;
    sTransitionKey: STRING;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
        pv: Y:STATE
        io: io
    '}
    fbStates: FB_MAA_States;

    {attribute 'pytmc' := '
        pv: X:STATE
        io: io
    '}
    fbStates_X: FB_MAA_States_X;
END_VAR
VAR

    fbYStage: FB_MotionStage;
    fbXStage: FB_MotionStage;


//  fSize1: REAL:=3.0; //mm
//  fSize2: REAL:=7.0; //mm
//  fSize3: REAL:=8.5; //mm
//  fSize4: REAL:=9.0; //mm



    bInit:BOOL := TRUE;
    tArbiterTimeout: TIME:= T#10S;
    FFO    :    FB_FastFault :=(
        i_DevName := 'AT1K0-MAA',
        i_Desc := 'Fault occurs when the PMPS Aribter is switched off for the aperture plate states BPTM',
        i_TypeCode := 16#AAFF);

END_VAR
if(bInit) THEN
    stYStage.bHardwareEnable := TRUE;
    stYStage.bPowerSelf := FALSE;
    stYStage.nBrakeMode := ENUM_StageBrakeMode.IF_MOVING;
    stXStage.bHardwareEnable := TRUE;
    stXStage.bPowerSelf := FALSE;
    stXStage.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    bInit:=FALSE;

    // States settings
    //stAprt1.nRequestAssertionID := nTransitionAssertionID+1;
    //stAprt1.stBeamParams := PMPS_GVL.cstFullBeam;
    //stAprt1.stBeamParams.astApertures[1].Height := fSize1;
    //stAprt1.stBeamParams.astApertures[1].Width := fSize1;
    stAprt1.bUseRawCounts := FALSE;
    stAprt1.bValid := TRUE;
    stAprt1.stPMPS.sPmpsState := CONCAT(sPmpsDeviceName,'-APERTURE1');

    //stAprt2.nRequestAssertionID := nTransitionAssertionID+2;
    //stAprt2.stBeamParams := PMPS_GVL.cstFullBeam;
    //stAprt2.stBeamParams.astApertures[1].Height := fSize2;
    //stAprt2.stBeamParams.astApertures[1].Width :=fSize2;
    stAprt2.bUseRawCounts := FALSE;
    stAprt2.bValid := TRUE;
    stAprt2.stPMPS.sPmpsState := CONCAT(sPmpsDeviceName,'-APERTURE2');

    //stAprt3.nRequestAssertionID := nTransitionAssertionID+3;
    //stAprt3.stBeamParams := PMPS_GVL.cstFullBeam;
    //stAprt3.stBeamParams.astApertures[1].Height := fSize3;
    //stAprt3.stBeamParams.astApertures[1].Width := fSize3;
    stAprt3.bUseRawCounts := FALSE;
    stAprt3.bValid := TRUE;
    stAprt3.stPMPS.sPmpsState := CONCAT(sPmpsDeviceName,'-APERTURE3');

    //stAprt4.nRequestAssertionID := nTransitionAssertionID+4;
    //stAprt4.stBeamParams := PMPS_GVL.cstFullBeam;
    //stAprt4.stBeamParams.astApertures[1].Height := fSize4;
    //stAprt4.stBeamParams.astApertures[1].Width := fSize4;
    stAprt4.bUseRawCounts := FALSE;
    stAprt4.bValid := TRUE;
    stAprt4.stPMPS.sPmpsState := CONCAT(sPmpsDeviceName,'-APERTURE4');

    //stXCen.nRequestAssertionID := nTransitionAssertionID+6;
    //stXCen.stBeamParams := PMPS_GVL.cstFullBeam;
    stXCen.bUseRawCounts := FALSE;
    stXCen.bValid := TRUE;
    stXCen.stPMPS.sPmpsState := CONCAT(sPmpsDeviceName,'-XCENTER');

    FFO.i_DevName := i_DevName;

END_IF


fbYStage(stMotionStage:=stYStage);
fbXStage(stMotionStage:=stXStage);

fbStates(
    fbArbiter:=fbArbiter,
    fbFFHWO:=fbFFHWO,
    //nTransitionAssertionID:=nTransitionAssertionID,
    //stTransitionBeam:= PMPS_GVL.cst0RateBeam,
    bArbiterEnabled := bArbiterEnabled,
    tArbiterTimeout :=tArbiterTimeout,
    stMotionStage:=stYStage,
    bEnable:=TRUE,
    stAprt1:=stAprt1,
    stAprt2:=stAprt2,
    stAprt3:=stAprt3,
    stAprt4:=stAprt4,
    enumSet:= enumSet,
    sPmpsDeviceName:=sPmpsDeviceName,
    sTransitionKey:=CONCAT(sTransitionKey,'_Y'),
    bBPOKAutoReset := TRUE);

fbStates_X(
    fbArbiter:=fbArbiter,
    fbFFHWO:=fbFFHWO,
    tArbiterTimeout := tArbiterTimeout,
    stMotionStage:=stXStage,
    bEnable:=TRUE,
    stXCen:=stXCen,
    sPmpsDeviceName:=sPmpsDeviceName,
    sTransitionKey:=CONCAT(sTransitionKey,'_X'),
    bBPOKAutoReset := TRUE);


(*FAST FAULT*)
FFO(i_xOK := bArbiterEnabled,
    i_xReset := ,
    i_xAutoReset := TRUE,
    io_fbFFHWO := fbFFHWO);

END_FUNCTION_BLOCK
Related:

FB_MAA_States

FUNCTION_BLOCK FB_MAA_States EXTENDS FB_PositionStateBase_WithPMPS
VAR_IN_OUT
    enumSet: E_MAA_states;
END_VAR
VAR_INPUT
    bStatesLock: BOOL;
    stAprt1: DUT_PositionState;
    stAprt2: DUT_PositionState;
    stAprt3: DUT_PositionState;
    stAprt4: DUT_PositionState;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
        pv: GET
        io: i
        field: ZRST Unknown;
        field: ONST 5.5mm;
        field: TWST 8mm;
        field: THST 10mm;
        field: FRST 13mm;
    '}
    enumGet: E_MAA_States;
END_VAR
VAR
    bStatesInit: BOOL := TRUE;
    fDelta1: LREAL := 0.5; //only for commissioning should change to more conservative values
    fDelta2: LREAL := 0.5;
    fDelta3: LREAL := 0.5;
    fDelta4: LREAL := 3;

END_VAR
VAR CONSTANT
    fVelocity: LREAL := 1;
    fAccel: LREAL := 200;
    fDecel: LREAL := 25;
END_VAR
IF bStatesInit THEN
    bStatesInit := FALSE;

    stAprt1.sName := '5.5mm';
    stAprt1.fVelocity := fVelocity;
    stAprt1.fDelta := fDelta1;
    stAprt1.fAccel := fAccel;
    stAprt1.fDecel := fAccel;
    stAprt1.bMoveOk := TRUE;

    stAprt2.sName := '8mm';
    stAprt2.fVelocity := fVelocity;
    stAprt2.fDelta := fDelta2;
    stAprt2.fAccel := fAccel;
    stAprt2.fDecel := fAccel;
    stAprt2.bMoveOk := TRUE;

    stAprt3.sName := '10mm';
    stAprt3.fVelocity := fVelocity;
    stAprt3.fDelta := fDelta3;
    stAprt3.fAccel := fAccel;
    stAprt3.fDecel := fAccel;
    stAprt3.bMoveOk := TRUE;

    stAprt4.sName := '13mm';
    stAprt4.fVelocity := fVelocity;
    stAprt4.fDelta := fDelta4;
    stAprt4.fAccel := fAccel;
    stAprt4.fDecel := fAccel;
    stAprt4.bMoveOk := TRUE;



    arrStates[1] := stAprt1;
    arrStates[2] := stAprt2;
    arrStates[3] := stAprt3;
    arrStates[4] := stAprt4;
END_IF


setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK
Related:

FB_MAA_States_X

FUNCTION_BLOCK FB_MAA_States_X EXTENDS FB_PositionStateBase_WithPMPS
VAR_INPUT
    {attribute 'pytmc' := '
        pv: SET;
        io: io;
        field: ZRST Unknown;
        field: ONST Centered;
    '}
    enumSet: E_MAA_states_X;
    bStatesLock: BOOL;
    stXCen: DUT_PositionState;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
        pv: GET
        io: i
        field: ZRST Unknown;
        field: ONST Centered;
    '}
    enumGet: E_MAA_states_X;
END_VAR
VAR
    bStatesInit: BOOL := TRUE;
    fDelta: LREAL := 0.5;
END_VAR
VAR CONSTANT
    fVelocity: LREAL := 0.1;
    fAccel: LREAL := 25;
    fDecel: LREAL := 25;
END_VAR
IF bStatesInit THEN
    bStatesInit := FALSE;
    stXCen.sName := 'Centered';
    stXCen.fVelocity := fVelocity;
    stXCen.fDelta := fDelta;
    stXCen.fAccel := fAccel;
    stXCen.fDecel := fAccel;
    stXCen.bMoveOk := TRUE;

    arrStates[1] := stXCen;
END_IF


setState := enumSet;
Exec();
enumGet := getState;
enumSet := setState;

END_FUNCTION_BLOCK

FB_VCN_Lin

(* This function implements the Basic functions for the Pfeiffer EVR 116 needle valve*)
FUNCTION_BLOCK FB_VCN_Lin EXTENDS FB_Valve
VAR_INPUT
    i_xExtIlkOK     :       BOOL; //External Interlock, SET to TRUE if not used
    i_ReqPos        :       REAL; //Requested position
    i_xPurge        : BOOL:= FALSE;// When purge is set the maximum threshold is ignored, has to be set evey cycle.
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
    pv:
    '}
    iq_stVCN        :       ST_VCN; //Needle valve structure
END_VAR
VAR CONSTANT
    rOpenVoltage    :       REAL := 9.1; // From the EVR 116 manual, A Voltage of 9V it is completely Open
    rCloseVoltage   :       REAL := 0.4;// a voltage <0.5 V the valve is closed
END_VAR
VAR
    // Requested voltage
    {attribute 'pytmc' := '
    pv: POS_AO;
    io: i ;
    '}
    rReqVoltage: REAL := 0;
    //iResolution: INT :=16;
    //
    (*IO*)
    q_iRawPosition AT%Q* :INT;

    //CONTROL
    stCTRL_LIN_INTERPOLATION_PARAMS         : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_LIN_INTERPOLATION                                        : FB_CTRL_LIN_INTERPOLATION;
    arrTable : ARRAY[1..10,1..2] OF FLOAT;
    arrTable_RBV : ARRAY[1..10,1..2] OF FLOAT;
    //Readdback
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV     : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_LIN_INTERPOLATION_RBV                                    : FB_CTRL_LIN_INTERPOLATION;
    eMode           : E_CTRL_MODE;
    iCounter:INT;
    bInit :BOOL :=TRUE;
END_VAR
VAR PERSISTENT
    rUpperLimit     :       REAL;
END_VAR
(* Needle valve control FB
A. Wallace 2016-7-21

This FB should be used as a low level control block.

It provides:

Valve position ceiling
Interlock
Scaling

It is not intended for:
Closed-loop control

It could be used for:
Valve position/flow linearization

Note: Raw position calc is based on 0.5 to 9V span, 32767 bits
*)


iq_stVCN.rUpperLimit :=  LIMIT(0, iq_stVCN.rUpperLimit, 100);

// Interlocking
iq_stVCN.xIlkOK := i_xExtIlkOK;
(*Checking which Control mode is selected*)
IF iq_stVCN.xIlkOK THEN
    IF iq_stVCN.eValveControl = OpenValve THEN
        iq_stVCN.rReqPosition := iq_stVCN.rUpperLimit;(*Percentage*)
    ELSIF iq_stVCN.eValveControl = CloseValve THEN
        iq_stVCN.rReqPosition := 0; (*Percentage*)
    ELSIF (iq_stVCN.eValveControl = ManualControl) (*AND (iq_stVCN.xOPN_SW)*) THEN
        iq_stVCN.rReqPosition := LIMIT(0, iq_stVCN.rReqPosition, iq_stVCN.rUpperLimit);
    ELSIF iq_stVCN.eValveControl = PressureControl THEN
        IF (i_xPurge) THEN
        iq_stVCN.rReqPosition := LIMIT(0, i_ReqPos, 100);
        ELSE iq_stVCN.rReqPosition := LIMIT(0, i_ReqPos, iq_stVCN.rUpperLimit);
        END_IF
    END_IF
ELSE
    iq_stVCN.rReqPosition := 0;
    iq_stVCN.eValveControl := CloseValve;
END_IF


//Raw position calc
iq_stvcn.q_iRawPosition := REAL_TO_INT( 32767/10 * rReqVoltage);

(*SOft IO Mapping*)
ACT_IO();

(*Load or save the persistent variables*)
ACT_Persistent();

ACT_INIT();

END_FUNCTION_BLOCK

ACTION ACT_INIT:
{attribute no_check}
IF bInit THEN


    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable[1,1] := 0;                     arrTable[1,2] := 0;
    arrTable[2,1] := 15;            arrTable[2,2] := 1.4;
    arrTable[3,1] := 19;            arrTable[3,2] := 1.75;
    arrTable[4,1] :=  25;       arrTable[4,2] := 2.25;
    arrTable[5,1] :=  31;       arrTable[5,2] := 2.8;
    arrTable[6,1] := 39;            arrTable[6,2] := 3.55;
    arrTable[7,1] := 49;            arrTable[7,2] := 4.45;
    arrTable[8,1] := 62;        arrTable[8,2] := 5.65;
    arrTable[9,1] := 78;        arrTable[9,2] := 7.1;
    arrTable[10,1] := 100;          arrTable[10,2] := 9.1;


    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS.tCtrlCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.tTaskCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_NumberOfRows         := INT_TO_UINT(10);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS.pDataTable_ADR                  := ADR(arrTable);
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_SIZEOF               := SIZEOF(arrTable);

    (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_ACTIVE;


    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
     FOR iCounter:=1 TO 10 BY 1 DO
        arrTable_RBV[iCounter,1] := arrTable[iCounter,2];
        arrTable_RBV[iCounter,2] := arrTable[iCounter,1];
     END_FOR;


    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV.tCtrlCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV.tTaskCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV.nDataTable_NumberOfRows             := INT_TO_UINT(10);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV.pDataTable_ADR                      := ADR(arrTable_RBV);
    stCTRL_LIN_INTERPOLATION_PARAMS_RBV.nDataTable_SIZEOF           := SIZEOF(arrTable_RBV);

    (* reset the init flag *)
    bInit                                                   := FALSE;

END_IF;
END_ACTION

ACTION ACT_IO:
(*outputs*)
q_iRawPosition := iq_stVCN.q_iRawPosition;
(*inputs*)
iq_stVCN.i_iPosition := iq_stvcn.q_iRawPosition;
END_ACTION

ACTION ACT_LIN_INTERPOLATION:
{attribute 'no_check'}
fbCTRL_LIN_INTERPOLATION(
    fIn:=  iq_stVCN.rReqPosition ,
    fManValue:= 0,
    bExtrapolate:= ,
    eMode:= eMode,
    fOut=> ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> ,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS );

// Requested Voltage calculation
//rReqVoltage := iq_stVCN.rReqPosition * (rOpenVoltage-rCloseVoltage)/100 + rCloseVoltage;
rReqVoltage := LREAL_TO_REAL(LIMIT(rCloseVoltage, fbCTRL_LIN_INTERPOLATION.fOut, rOpenVoltage)); //The requested voltage should remain within this range

fbCTRL_LIN_INTERPOLATION_RBV(
    fIn:= rReqVoltage ,
    fManValue:= 0,
    bExtrapolate:= ,
    eMode:= eMode,
    fOut=>  ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> ,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS_RBV );
// iq_stVCN.rReqPosition := LREAL_TO_REAL(fbCTRL_LIN_INTERPOLATION_RBV.fOut);
END_ACTION

ACTION ACT_Logger:
// ILK logger

IF NOT (iq_stVCN.xIlkOK ) AND NOT(ePrevState = CloseValve) THEN
         fbLogger(sMsg:='Lost interlock ok bit while valve was open.', eSevr:=TcEventSeverity.Critical);
END_IF


//Control STATE Logger
IF ePrevState <> iq_stVCN.eValveControl THEN
      CASE iq_stVCN.eValveControl OF
        ManualControl:
            fbLogger(sMsg:='Valve in manual control mode', eSevr:=TcEventSeverity.Warning);
        OpenValve:
            fbLogger(sMsg:='Valve Open.', eSevr:=TcEventSeverity.Info);
        PressureControl:
            fbLogger(sMsg:='Valve in pressure control mode.', eSevr:=TcEventSeverity.Info);
        CloseValve:
            fbLogger(sMsg:='Valve closed.', eSevr:=TcEventSeverity.Info);
      END_CASE
      ePrevState := iq_stVCN.eValveControl;
  END_IF


// Log valve open
tAction(CLK:= (iq_stVCN.eValveControl = OpenValve) );
IF tAction.Q THEN fbLogger(sMsg:='Valve commanded to fully open', eSevr:=TcEventSeverity.Info); END_IF
END_ACTION

ACTION ACT_Persistent:
(*On first PLC pass, load the persistent value into the structrue variable*)
IF (bRestorePersistentData) THEN
    bRestorePersistentData  := FALSE;
    IF (rUpperLimit <> 0) THEN
        iq_stVCN.rUpperLimit := rUpperLimit;
    END_IF;

END_IF
(*Check if a new value has been written in the structure variable copy it to the persistent variable*)
IF NOT (iq_stVCN.rUpperLimit = rUpperLimit) THEN
    rUpperLimit := iq_stVCN.rUpperLimit;
    //fbWritePersistentData(NETID:='', PORT:=851, START:=TRUE, TMOUT:=T#1s );
ELSE
     // fbWritePersistentData( START:=FALSE);
END_IF;
END_ACTION

METHOD M_SetThrottle : BOOL
VAR_INPUT
    rUpperLimit     :       REAL;
END_VAR
iq_stVCN.rUpperLimit := LIMIT(0, rUpperLimit, 100);
END_METHOD

METHOD M_ValveControl : BOOL
VAR_INPUT
    state:E_VCN; // Close, Open, Pressure, Manual
END_VAR
iq_stVCN.eValveControl := state;
END_METHOD

FB_VGP

(* This function implements the Basic functions for the Vat Motorized valve*)
{attribute 'no_check'}
FUNCTION_BLOCK FB_VGP
VAR_INPUT
    i_xExtIlkOK     :       BOOL; //External Interlock, SET to TRUE if not used
    i_xOpenIlkOK: BOOL; //Interlock Bit that allows the valve to open
    i_xCloseIlkOK: BOOL; //Interlock Bit that allows the valve to Close

    i_ReqPos        :       REAL; //Requested position

    arrTable        : ARRAY[1..14,1..2] OF FLOAT;
END_VAR
VAR_OUTPUT
    {attribute 'pytmc' := '
    pv:
    '}
    q_stVGP :       ST_VGP; // valve structure
END_VAR
VAR_IN_OUT

END_VAR

VAR CONSTANT
    rUpperLimit     :       REAL:=100;      //Percentage Upper limit on valve open
    rClosePosition : REAL:=0; // Encoder Min. Fully Closed
    rMaxDiffPressure: REAL:= 22.5; //Torr
END_VAR

VAR
    rOpenPosition: REAL:=1680; // Encoder MAX. Fully Open
    rTargetPosition : REAL;
    rTargetVelocity: REAL:=30;
    rHomingVelocity: REAL:=10;
    rHomingDistance: REAL:=-20;//every 150 is 10% , 1%  is 14.975
    rOldTargetPosition: REAL;
    rHyst:REAL :=10;
    //
    /// axis reference data structure
    Axis: AXIS_REF;
    //
    InfoData_State AT %I*: UINT ;

    // Axis MC functions

    fbPowerAxis: MC_Power;
    /// debug function block output data
    PowerAxisOut: ST_McOutputs;
    fbMoveAxisABS: MC_MoveAbsolute;
    /// debug function block output data
    MoveAbsoluteOut: ST_McOutputs;
    fbMoveAxisABS2: MC_MoveAbsolute;
    /// debug function block output data
    MoveAbsoluteOut2: ST_McOutputs;

    fbReset: MC_Reset;
    /// debug function block output data
    ResetOut: ST_McOutputs;
    MoveAxisREL: MC_MoveAbsolute;
    MoveRelativeOut: ST_McOutputs;



    rOverride: LREAL := 100;
    fbHalt: MC_Halt;


    // Homing Functions
    bGo:BOOL := FALSE; //to execute motion
    bHome:BOOL :=FALSE; // should be set to true
    bEnable:Bool; //to be removed
    fbMoveRel: MC_MoveRelative;
    fbSetPosition: MC_SetPosition;
    fbWriteParameter: MC_WriteBoolParameter;
    HomeState: E_HomeState;

    // For Monitoring while Axis moving
    rPrevEncoderPosition : REAL;
    // interpolation
    bInit : BOOL := TRUE;
    eMode           : E_CTRL_MODE;
    iCounter:INT;
    //CONTROL
    stCTRL_LIN_INTERPOLATION_PARAMS         : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_LIN_INTERPOLATION                                        : FB_CTRL_LIN_INTERPOLATION;
    arrTable_ENC : ARRAY[1..14,1..2] OF FLOAT;
    //Readdback
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC             : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_LIN_INTERPOLATION_ENC                                    : FB_CTRL_LIN_INTERPOLATION;

    // Logger
     // For logging
    fbLogger : FB_LogMessage := (eSubsystem:=E_SubSystem.VACUUM);
    ePrevState : E_VCN;
    tErrorPresent : R_TRIG;
    tAction : R_TRIG; // Primary action of this device (OPN_DO, PUMP_RUN, etc.)

    rt_close :R_TRIG;
    rt_Open :R_TRIG;
END_VAR
/// Interpolation  function initialization
ACT_INIT();

// Interlocking
q_stVGP.xIlkOK := i_xExtIlkOK;
(*Checking which Control mode is selected*)
IF i_xExtIlkOK AND NOT (q_stVGP.pv_xError) THEN
    IF q_stVGP.eValveControl = OpenValve THEN
        q_stVGP.rReqPosition := rUpperLimit;
    ELSIF q_stVGP.eValveControl = CloseValve THEN
        q_stVGP.rReqPosition := 0;
    ELSIF q_stVGP.eValveControl = ManualControl THEN
        q_stVGP.rReqPosition := LIMIT(0, q_stVGP.rReqPosition, rUpperLimit);
    ELSIF q_stVGP.eValveControl = PressureControl THEN
         q_stVGP.rReqPosition := LIMIT(0, i_ReqPos, rUpperLimit);
    END_IF
ELSIF NOT i_xExtIlkOK THEN
    q_stVGP.rReqPosition := 0;
    q_stVGP.eValveControl := CloseValve;//CloseValve;
END_IF

rt_close (CLK:= q_stVGP.eValveControl = CloseValve);
rt_Open (CLK:= q_stVGP.eValveControl = OpenValve);

IF (rt_close.Q) OR (rt_Open.Q) THEN
    q_stVGP.pv_xGo_SW:=TRUE;
END_IF
//Check the Drive State

IF (*(InfoData_State<>16#8) OR*) (q_stVGP.eState = ERROR) THEN
    q_stVGP.pv_xError:=TRUE;
ELSE
    q_stVGP.pv_xError:=FALSE;
    // Call function to execute move
    // call motion function blocks???
END_IF


IF (q_stVGP.pv_xABORT_SW ) THEN
    q_stVGP.pv_xABORT_SW := FALSE;
    q_stVGP.eState:= ABORT;
    HomeState:= H_READY;
END_IF


ACT_LIN_INTERPOLATION();
ACT_AXIS();
ACT_HOME();
ACT_MONITOR();

END_FUNCTION_BLOCK

ACTION ACT_AXIS:
//update the axis status
AXIS();
q_stVGP.rEnoder_Position := LREAL_TO_REAL(Axis.NcToPlc.ActPos); // encoder position


(*IF NOT (i_xExtIlkOK) THEN
    q_stVGP.eState := NEWTARGETPOSITION;
END_IF*)
//Homing STATE is missing

// state machine for axis motion
    (* move axis using a state machine *)
    CASE q_stVGP.eState OF

        INIT :      (* initialisation *)
            (* initialize all function blocks *)
            fbMoveAxisABS.Execute := FALSE;
            fbMoveAxisABS2.Execute := FALSE;
            fbReset.Execute := FALSE;
            fbHALT.Execute :=FALSE;//
            q_stVGP.eState := ENABLE; // Check homing first
            HomeState:= H_READY;

        ENABLE :
            fbPowerAxis.Enable :=  TRUE;
            fbPowerAxis.Enable_Positive := TRUE;
            fbPowerAxis.Enable_Negative := TRUE;
            IF fbPowerAxis.Status THEN
                q_stVGP.eState := READY;
            ELSIF fbPowerAxis.Error THEN
                q_stVGP.eState := ERROR;
            END_IF

        READY: // waiting for move command
            IF NOT fbPowerAxis.Status THEN
                q_stVGP.eState := ENABLE;
            ELSIF fbPowerAxis.Error THEN
                q_stVGP.eState := ERROR;
            END_IF
            IF (HomeState = H_READY) AND (q_stVGP.pv_xHome_SW) THEN
                    HomeState:= H_INIT;
                    q_stVGP.pv_xHome_SW:=false;
                    q_stVGP.eState := HOME;
                    ELSE
                    q_stVGP.eState := READY;
                END_IF
            IF (q_stVGP.pv_xGo_SW) AND q_stVGP.pv_xHomed(* AND( rOldTargetPosition <> rTargetPosition) *) THEN
                q_stVGP.pv_xGo_SW := false;
                q_stVGP.eState := NEWTARGETPOSITION;
                rOldTargetPosition:= rTargetPosition;
            END_IF


        HOME:
                if (HomeState = H_DONE) THEN
                     q_stVGP.eState := INIT;
                     q_stVGP.pv_xHomed := TRUE;
                     HomeState := H_READY;
                END_IF

                if (HomeState = H_ERROR) THEN
                    q_stVGP.eState := ERROR;
                      q_stVGP.pv_xHomed := FALSE;
                END_IF

        NEWTARGETPOSITION:
            fbMoveAxisABS.Position := rTargetPosition;
            fbMoveAxisABS.Velocity := rTargetVelocity;
            //fbMoveAxisABS.BufferMode := MC_BlendingNext;
            fbMoveAxisABS.Execute := TRUE;
            IF fbMoveAxisABS.Active  THEN
                (* axis is executing job but is not yet finished *)
                fbMoveAxisABS.Execute := FALSE;
                (* leave this state and buffer a second command *)
                q_stVGP.eState := MOVING;
            ElSIF fbMoveAxisABS.Done THEN
                fbMoveAxisABS.Execute := FALSE;
                q_stVGP.eState := READY;
            ELSIF fbMoveAxisABS.CommandAborted OR fbMoveAxisABS.Error THEN
                q_stVGP.eState := ERROR;
            END_IF


        MOVING://
            IF fbMoveAxisABS.CommandAborted OR fbMoveAxisABS.Error THEN
                q_stVGP.eState := ERROR;
            END_IF
            IF NOT ( Axis.Status.Moving) OR (fbMoveAxisABS.Done) THEN //(fbMoveAxisABS.Done) AND (fbMoveAxisABS2.Done) THEN
                q_stVGP.eState := READY;
            END_IF


        HALT:
            fbHALT.Execute :=TRUE;
            IF Axis.Status.Error THEN
                q_stVGP.eState := RESET;    (* axis error requires reset *)
            ELSE
                q_stVGP.eState := INIT;             (* function block errors don't need a reset *)
            END_IF

        ERROR :
            IF HomeState = H_READY THEN
                q_stVGP.eState := RESET;
            ELSE
                q_stVGP.eState := HOME;
            END_IF

        RESET :
            //fbReset.Execute := TRUE;
            IF fbReset.Done THEN q_stVGP.eState :=INIT;
            //      HomeState := H_READY;
            ELSIF fbReset.Error THEN
                q_stVGP.eState := ERROR; (* keep trying to reset*)
            END_IF

        ABORT:
            fbMoveAxisABS.Execute := FALSE;
            fbMoveAxisABS2.Execute := FALSE;
            fbReset.Execute := FALSE;
            (* save target position*)
            rOldTargetPosition :=   q_stVGP.i_iPosition;
            fbHALT.Execute :=FALSE;
            fbPowerAxis.Enable := FALSE;
            fbPowerAxis.Enable_Positive := FALSE;
            fbPowerAxis.Enable_Negative := FALSE;
            q_stVGP.eState := ENABLE; // Check homing first

    END_CASE






/// Motion Function Blocks
(* AXIS POWER*)
fbPowerAxis(
    Axis:= Axis,
    Enable:= ,
    Enable_Positive:= i_xOpenIlkOK,
    Enable_Negative:= ,
    Override:= rOverride,
    BufferMode:= ,
    Options:= ,
    Status=>  ,
    Busy=> PowerAxisOut.Busy ,
    Active=> PowerAxisOut.Active ,
    Error=> PowerAxisOut.Error,
    ErrorID=> PowerAxisOut.ErrorID);
(* AXIS MOVE ABSOLUTE*)
fbMoveAxisABS(
    Axis:= Axis ,
    Execute:= ,
    Position:= ,
    Velocity:= ,
    Acceleration:= ,
    Deceleration:= ,
    Jerk:= ,
    BufferMode:= MC_BlendingNext ,
    Options:= ,
    Done=>MoveAbsoluteOut.Done,
    Busy=> MoveAbsoluteOut.Busy,
    Active=> MoveAbsoluteOut.Active,
    CommandAborted=> MoveAbsoluteOut.CommandAborted ,
    Error=> MoveAbsoluteOut.Error,
    ErrorID=> MoveAbsoluteOut.ErrorID);
    (* AXIS MOVE ABSOLUTE*)
fbMoveAxisABS2(
    Axis:= Axis ,
    Execute:= ,
    Position:= ,
    Velocity:= ,
    Acceleration:= ,
    Deceleration:= ,
    Jerk:= ,
    BufferMode:= MC_BlendingNext ,
    Options:= ,
    Done=>MoveAbsoluteOut2.Done,
    Busy=> MoveAbsoluteOut2.Busy,
    Active=> MoveAbsoluteOut2.Active,
    CommandAborted=> MoveAbsoluteOut2.CommandAborted ,
    Error=> MoveAbsoluteOut2.Error,
    ErrorID=> MoveAbsoluteOut2.ErrorID);
(*AXIS RESET*)
fbReset(
    Axis:= Axis,
    Execute:= This^.q_stVGP.pv_xReset_SW ,
    Done=>ResetOut.Done ,
    Busy=>ResetOut.Busy ,
    Error=> ResetOut.Error,
    ErrorID=> ResetOut.ErrorID);

(*HALT*)
fbHalt(
    Axis:= Axis,
    Execute:= ,
    Deceleration:= ,
    Jerk:= ,
    BufferMode:= MC_BlendingNext ,
    Options:= ,
    Done=> ,
    Busy=> ,
    Active=> ,
    CommandAborted=> ,
    Error=> ,
    ErrorID=> );


/// ERROR
IF Axis.Status.Error  THEN
    q_stVGP.eState := ERROR;
END_IF;

// Error Handling
if( fbPowerAxis.Error and fbPowerAxis.Active ) then
    This^.q_stVGP.pv_xError:= fbPowerAxis.Error;
    This^.q_stVGP.nErrorID:= fbPowerAxis.ErrorID;
END_IF
if( fbMoveAxisABS.Error and fbMoveAxisABS.Active ) then
    This^.q_stVGP.pv_xError:= fbMoveAxisABS.Error;
    This^.q_stVGP.nErrorID:= fbMoveAxisABS.ErrorID;
END_IF

IF This^.q_stVGP.pv_xReset_SW THEN This^.q_stVGP.pv_xReset_SW:=FALSE; END_IF
(*Convert nErrorID to string*)
This^.q_stVGP.sErrorMessage:=WORD_TO_HEXSTR(in:=TO_WORD(This^.q_stVGP.nErrorID) , iPrecision:= 4, bLoCase:=0 );

This^.q_stVGP.xBusy := (NOT(q_stVGP.eState = READY) AND (HomeState = H_READY));
END_ACTION

ACTION ACT_HOME:
CASE HomeState OF
    H_READY:
        fbSetPosition.Execute := FALSE;
        fbWriteParameter.Execute := FALSE;
        fbMoveRel.Execute := FALSE;

    H_INIT:
    HomeState:=H_RESET_LL;


    H_RESET_LL:
        // disable soft limits in order to be able to move the drive
        fbWriteParameter.ParameterNumber := MC_AxisParameter.EnableLimitNeg;//EnableLimitPos;// .EnableLimitNeg;
        fbWriteParameter.Value := FALSE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_RESET_HL;
        END_IF

    H_RESET_HL:
        // disable soft limits in order to be able to move the drive
        fbWriteParameter.ParameterNumber := MC_AxisParameter.EnableLimitPos;
        fbWriteParameter.Value := FALSE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_ENABLE;
        END_IF

    H_ENABLE:
        // Make Sure drive is enabled
        fbPowerAxis.Enable :=  TRUE;
        fbPowerAxis.Enable_Positive := TRUE;
        fbPowerAxis.Enable_Negative := TRUE;
        IF fbPowerAxis.Status THEN
            HomeState:= H_MOVING;
        ELSIF fbPowerAxis.Error THEN
            HomeState := H_ERROR;
        END_IF

    H_MOVING:
        fbMoveRel.Execute := TRUE;
        IF fbMoveRel.Active  THEN
            (* axis is executing job but is not yet finished *)
            fbMoveRel.Execute := FALSE;
            (* leave this state and buffer a second command *)
            HomeState := H_MOVING2;
        ElSIF fbMoveRel.Done THEN
            fbMoveRel.Execute := FALSE;
            HomeState := H_MOVING;//2?
        ELSIF fbMoveRel.CommandAborted OR fbMoveRel.Error THEN
            fbMoveRel.Execute := FALSE;
            HomeState := H_CHECK;
        END_IF

    H_MOVING2:
        IF fbMoveRel.CommandAborted OR fbMoveRel.Error THEN
            HomeState := H_CHECK;
        END_IF
        IF NOT ( Axis.Status.Moving) OR (fbMoveRel.Done) THEN //(fbMoveAxisABS.Done) AND (fbMoveAxisABS2.Done) THEN
            HomeState := H_MOVING;
            fbMoveRel.Execute := FALSE;
        END_IF

    H_CHECK:
        //Check position lag monitoring error
        if (Axis.Status.ErrorID = 16#00004550)THEN
            This^.q_stVGP.pv_xReset_SW := TRUE;
            HomeState := H_RESET;
        ELSE
            HomeState := H_ERROR;
        END_IF

    H_RESET:
        IF fbReset.Done THEN
            This^.q_stVGP.pv_xReset_SW := FALSE;
            HomeState := H_SET_POS;
        END_IF

    H_SET_POS:
     // Set Current Position
        fbSetPosition.Position := 0;
        fbSetPosition.Execute := TRUE;
        IF ( fbSetPosition.Done ) THEN
            fbSetPosition.Execute := FALSE;
            HomeState:= H_WRITE_LL;
        ELSIF (fbSetPosition.Error) THEN
            HomeState := H_ERROR;
        END_IF


    H_WRITE_LL:
    // Re Enable the Soft limits
        fbWriteParameter.ParameterNumber := MC_AxisParameter.AxisEnMinSoftPosLimit;//AxisEnMaxSoftPosLimit;// .AxisEnMinSoftPosLimit;
        fbWriteParameter.Value := TRUE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_WRITE_HL;
        END_IF

    H_WRITE_HL:
    // Re Enable the Soft limits
        fbWriteParameter.ParameterNumber := MC_AxisParameter.AxisEnMaxSoftPosLimit;
        fbWriteParameter.Value := TRUE;
        fbWriteParameter.Execute := TRUE;
        if (fbWriteParameter.Done) THEN
            fbWriteParameter.Execute := FALSE;
            HomeState:= H_DONE;
        END_IF


    H_ERROR:
        //taken care of in the axis motion state machine
    H_DONE:
        //taken care of in the axis motion state machine

END_CASE

// Move backward to fully closed
fbMoveRel(
    Axis:= Axis ,
    Execute:= ,
    Distance:= rHomingDistance ,
    Velocity:= rHomingVelocity,
    Acceleration:= ,
    Deceleration:= ,
    Jerk:= ,
    BufferMode:= MC_BlendingNext,
    Options:= ,
    Done=> ,
    Busy=> ,
    Active=> ,
    CommandAborted=> ,
    Error=> ,
    ErrorID=> );

// Set Encoder Position
fbSetPosition(
    Axis:= Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE, //Absolute
    Options:= ,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

// Write Parameters
fbWriteParameter(
    Axis:= Axis ,
    Execute:= ,
    ParameterNumber:= ,
    Value:= ,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

If ( fbWriteParameter.Error) OR (fbSetPosition.Error)(* OR (fbMoveRel.Error) *)THEN
    HomeState:= H_ERROR;
    q_stVGP.eState := ERROR;
END_IF
END_ACTION

ACTION ACT_INIT:
{attribute no_check}
IF bInit THEN

(*
    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable[1,1] := 0;                     arrTable[1,2] := 0;
    arrTable[2,1] := 5;                 arrTable[2,2] := 135;
    arrTable[3,1] := 10;            arrTable[3,2] := 245;
    arrTable[4,1] :=  20;       arrTable[4,2] := 405;
    arrTable[5,1] :=  30;       arrTable[5,2] := 535;
    arrTable[6,1] := 40;            arrTable[6,2] := 689;
    arrTable[7,1] := 50;            arrTable[7,2] := 830;
    arrTable[8,1] := 60;        arrTable[8,2] := 960;
    arrTable[9,1] := 70;        arrTable[9,2] := 1095;
    arrTable[10,1] := 80;           arrTable[10,2] := 1225;
    arrTable[11,1] := 90;           arrTable[11,2] := 1415;
    arrTable[12,1] := 95;           arrTable[12,2] := 1495;
    arrTable[13,1] := 98;           arrTable[13,2] := 1559;
    arrTable[14,1] := 100;          arrTable[14,2] := 1645;
    *)

    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS.tCtrlCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.tTaskCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_NumberOfRows         := INT_TO_UINT(14);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS.pDataTable_ADR                  := ADR(arrTable);
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_SIZEOF               := SIZEOF(arrTable);

    (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_ACTIVE;


    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
     FOR iCounter:=1 TO 14 BY 1 DO
        arrTable_ENC[iCounter,1] := arrTable[iCounter,2];
        arrTable_ENC[iCounter,2] := arrTable[iCounter,1];
     END_FOR;
    (*
    arrTable_ENC[1,1] := 0;                 arrTable_ENC[1,2] := 0;
    arrTable_ENC[2,1] := 135;                   arrTable_ENC[2,2] := 5;
    arrTable_ENC[3,1] := 245;               arrTable_ENC[3,2] := 10;
    arrTable_ENC[4,1] :=  405;          arrTable_ENC[4,2] := 20;
    arrTable_ENC[5,1] :=  535;          arrTable_ENC[5,2] := 30;
    arrTable_ENC[6,1] := 689;               arrTable_ENC[6,2] := 40;
    arrTable_ENC[7,1] := 830;               arrTable_ENC[7,2] := 50;
    arrTable_ENC[8,1] := 960;           arrTable_ENC[8,2] := 60;
    arrTable_ENC[9,1] := 1095;          arrTable_ENC[9,2] := 70;
    arrTable_ENC[10,1] := 1225;             arrTable_ENC[10,2] := 80;
    arrTable_ENC[11,1] := 1415;             arrTable_ENC[11,2] := 90;
    arrTable_ENC[12,1] := 1495;             arrTable_ENC[12,2] := 95;
    arrTable_ENC[13,1] := 1559;             arrTable_ENC[13,2] := 98;
    arrTable_ENC[14,1] := 1645;             arrTable_ENC[14,2] := 100;*)


    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.tCtrlCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.tTaskCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.nDataTable_NumberOfRows             := INT_TO_UINT(14);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.pDataTable_ADR                      := ADR(arrTable_ENC);
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.nDataTable_SIZEOF           := SIZEOF(arrTable_ENC);

    (* reset the init flag *)
    bInit                                                   := FALSE;

END_IF;
END_ACTION

ACTION ACT_LIN_INTERPOLATION:
{attribute 'no_check'}
fbCTRL_LIN_INTERPOLATION(
    fIn:= q_stVGP.rReqPosition ,
    fManValue:= 0,
    bExtrapolate:= ,
    eMode:= eMode,
    fOut=> ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> ,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS );

// Target position Calculation
rTargetPosition := LREAL_TO_REAL(fbCTRL_LIN_INTERPOLATION.fOut);
//rTargetPosition := LIMIT(rClosePosition, rTargetPosition, rOpenPosition);

fbCTRL_LIN_INTERPOLATION_ENC(
    fIn:= Axis.NcToPlc.ActPos ,
    fManValue:= 0,
    bExtrapolate:= ,
    eMode:= eMode,
    fOut=>  ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> ,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS_ENC );
q_stVGP.i_iPosition := LREAL_TO_REAL(fbCTRL_LIN_INTERPOLATION_ENC.fOut);
END_ACTION

ACTION ACT_MONITOR:
IF (This^.q_stVGP.xBusy) THEN
    rPrevEncoderPosition:= This^.q_stVGP.rEnoder_Position;
ELSIF NOT((rPrevEncoderPosition < This^.q_stVGP.rEnoder_Position +rHyst) AND (rPrevEncoderPosition > This^.q_stVGP.rEnoder_Position -rHyst)) AND NOT( q_stVGP.eState =HOME)  AND NOT( q_stVGP.eState =ERROR) THEN
      q_stVGP.eState := ERROR;
      q_stVGP.pv_xHomed := FALSE;
      This^.q_stVGP.pv_xError := TRUE;
      This^.q_stVGP.sErrorMessage := 'Encoder Position Error';

END_IF

tErrorPresent(CLK:=q_stVGP.pv_xError);
IF tErrorPresent.Q THEN fbLogger(sMsg:=q_stVGP.sErrorMessage, eSevr:=TcEventSeverity.Error); END_IF

// Log valve motion
tAction(CLK:= q_stVGP.pv_xGo_SW);
IF tAction.Q THEN fbLogger(sMsg:='Valve commanded to move', eSevr:=TcEventSeverity.Info); END_IF


IF ePrevState <> q_stVGP.eValveControl THEN
      CASE q_stVGP.eValveControl OF

        CloseValve:
            fbLogger(sMsg:='Valve set to Close.', eSevr:=TcEventSeverity.Info);
          OpenValve:
            fbLogger(sMsg:='Valve set to Open.', eSevr:=TcEventSeverity.Info);
        PressureControl:
            fbLogger(sMsg:='Valve set to pressure control mode.', eSevr:=TcEventSeverity.Info);
        ManualControl:
            fbLogger(sMsg:='Valve set to manual control mode.', eSevr:=TcEventSeverity.Info);
      END_CASE
      ePrevState := q_stVGP.eValveControl;
  END_IF
END_ACTION

METHOD ConfigEncoder : BOOL
VAR_INPUT
    EncoderMax: REAl; // Maximum encoder reading from fully closed to fully open
    invert: Bool; // Invert Encoder Counting Direction
END_VAR
VAR
    fbWriteParameter1: MC_WriteBoolParameter;
END_VAR
rOpenPosition := EncoderMax;

// fEncScaleFactor  -  AxisEncoderScalingFactor

// bEncIsInverse  -
if (invert) THEN
    fbWriteParameter1.ParameterNumber :=  MC_AxisParameter.AxisEncoderDirectionInverse;
    fbWriteParameter1.Value := True;
END_IF

// Write Parameters
fbWriteParameter1(
    Axis:= Axis ,
    Execute:= ,
    ParameterNumber:= ,
    Value:= ,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
END_METHOD

METHOD M_INIT : BOOL
VAR_INPUT
    arrTable        : ARRAY[1..14,1..2] OF FLOAT;
    arrTable_ENC : ARRAY[1..14,1..2] OF FLOAT;
END_VAR
(* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable[1,1] := 0;                     arrTable[1,2] := 0;
    arrTable[2,1] := 5;                 arrTable[2,2] := 135;
    arrTable[3,1] := 10;            arrTable[3,2] := 245;
    arrTable[4,1] :=  20;       arrTable[4,2] := 405;
    arrTable[5,1] :=  30;       arrTable[5,2] := 535;
    arrTable[6,1] := 40;            arrTable[6,2] := 689;
    arrTable[7,1] := 50;            arrTable[7,2] := 830;
    arrTable[8,1] := 60;        arrTable[8,2] := 960;
    arrTable[9,1] := 70;        arrTable[9,2] := 1095;
    arrTable[10,1] := 80;           arrTable[10,2] := 1225;
    arrTable[11,1] := 90;           arrTable[11,2] := 1415;
    arrTable[12,1] := 95;           arrTable[12,2] := 1495;
    arrTable[13,1] := 98;           arrTable[13,2] := 1559;
    arrTable[14,1] := 100;          arrTable[14,2] := 1645;


    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS.tCtrlCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.tTaskCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_NumberOfRows         := INT_TO_UINT(14);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS.pDataTable_ADR                  := ADR(arrTable);
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_SIZEOF               := SIZEOF(arrTable);

    (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_ACTIVE;


    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable_ENC[1,1] := 0;                 arrTable_ENC[1,2] := 0;
    arrTable_ENC[2,1] := 135;                   arrTable_ENC[2,2] := 5;
    arrTable_ENC[3,1] := 245;               arrTable_ENC[3,2] := 10;
    arrTable_ENC[4,1] :=  405;          arrTable_ENC[4,2] := 20;
    arrTable_ENC[5,1] :=  535;          arrTable_ENC[5,2] := 30;
    arrTable_ENC[6,1] := 689;               arrTable_ENC[6,2] := 40;
    arrTable_ENC[7,1] := 830;               arrTable_ENC[7,2] := 50;
    arrTable_ENC[8,1] := 960;           arrTable_ENC[8,2] := 60;
    arrTable_ENC[9,1] := 1095;          arrTable_ENC[9,2] := 70;
    arrTable_ENC[10,1] := 1225;             arrTable_ENC[10,2] := 80;
    arrTable_ENC[11,1] := 1415;             arrTable_ENC[11,2] := 90;
    arrTable_ENC[12,1] := 1495;             arrTable_ENC[12,2] := 95;
    arrTable_ENC[13,1] := 1559;             arrTable_ENC[13,2] := 98;
    arrTable_ENC[14,1] := 1645;             arrTable_ENC[14,2] := 100;


    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.tCtrlCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.tTaskCycleTime                                      := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.nDataTable_NumberOfRows             := INT_TO_UINT(14);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.pDataTable_ADR                      := ADR(arrTable_ENC);
    stCTRL_LIN_INTERPOLATION_PARAMS_ENC.nDataTable_SIZEOF           := SIZEOF(arrTable_ENC);
END_METHOD

METHOD M_SetGoSw : BOOL
VAR_INPUT
    bGo:BOOL;
END_VAR
q_stVGP.pv_xGo_SW:=bGo;
END_METHOD

METHOD M_ValveControl : BOOL
VAR_INPUT
    state:E_VCN; // Close, Open, Pressure, Manual
END_VAR
q_stVGP.eValveControl := state;
END_METHOD

METHOD PUBLIC SetEncoderMax : BOOL
VAR_INPUT
    EncoderMax: REAl;
END_VAR
rOpenPosition := EncoderMax;
END_METHOD
Related:

PRG_1_PlcTask

PROGRAM PRG_1_PlcTask
VAR

bDebug : Bool := FALSE;
bMotionTest : Bool := FALSE;
fb_ADS_WATCHDOG:FB_ADS_WATCHDOG;
sVarName : STRING:='GVL_VAC_INTF.n_AT1K0_VAC_counter';
END_VAR
//GVL_VAC_INTF.n_AT1K0_VAC_counter
fb_ADS_WATCHDOG(sNetId:='172.21.92.61.1.1' , nPort:=851 , sVarName:=sVarName,bError=> );
(*Ethercat Diagnostics*)
DIAGNOSTICS();
// Vacuum and differential pumping
PRG_GATT();

if (NOT bDebug)Then
    // Motorised valve
    PRG_VGP();
END_IF
if (bMotionTest)Then
    // Functionblock for PTP motion between different appertures
    PRG_Motors_Test();
ELSE
    PRG_Motion();
END_IF


PRG_ILK();
//PMPS
PRG_PMPS();
PRG_GasSelection();
PRG_Transmission();
// Injector
PRG_INJ();
//Logger
fbLogHandler();
fbEcatDiagWrapper();

END_PROGRAM
Related:

PRG_GasSelection

PROGRAM PRG_GasSelection
VAR
    N2LowerEdge: REAL := 300;
    N2UpperEdge: REAL := 450;
    rDelta: REAL :=20;
    ArEdge:REAL:=2300;
END_VAR
(*Gas Selection*)
IF(VVC_71.M_IsOpen()) THEN  SelectedGas := E_GasType.Argon;
    ELSIF (VVC_72.M_IsOpen()) THEN  SelectedGas := E_GasType.Nitrogen;
END_IF

IF (xPMPSMode) AND (bChangeGas) THEN
    IF(rPhotonEnergy >=N2LowerEdge-rDelta) AND (rPhotonEnergy <=N2UpperEdge-rDelta)(* AND   NOT (SelectedGas = E_GasType.Argon)*) THEN
        //Block N2
        VVC_72.M_Set_OPN_SW (false);
        IF VVC_72.M_IsClosed() THEN
            VVC_71.M_Set_OPN_SW (TRUE);
            bChangeGas := FALSE;
            fbLogger(sMsg:='AT1K0 switched to Ar', eSevr:=TcEventSeverity.Verbose);
            END_IF;
    ELSIF  ((rPhotonEnergy <= 220) OR (rPhotonEnergy >=2300)) (*AND  NOT (SelectedGas = E_GasType.Nitrogen)*)  THEN
        //Block Ar
        VVC_71.M_Set_OPN_SW (false);
        IF VVC_71.M_IsClosed() THEN
            VVC_72.M_Set_OPN_SW (TRUE);
            bChangeGas := FALSE;
            fbLogger(sMsg:='AT1K0 switched to N2', eSevr:=TcEventSeverity.Verbose);
        END_IF;
    ELSE
        VVC_72.M_Set_OPN_SW (TRUE);
        bChangeGas := FALSE;
        //fbLogger(sMsg:='AT1K0 switched to N2', eSevr:=TcEventSeverity.Verbose);
    END_IF
    ELSE
        bChangeGas := FALSE;
END_IF

END_PROGRAM
Related:

PRG_GATT

PROGRAM PRG_GATT
VAR
    timer:TON;
    vvcTimer:TON;
    PG: ST_VG;
    rPRESS : REAL := 0.001;
    rPRESS_11 : REAL := 1;
    fb_ADS_WATCHDOG:FB_ADS_WATCHDOG;
    rTrig_11: R_TRIG;
END_VAR
// this function block writes the watchdog bit to the remote PLC reading the treaty valves and/or gauge
fb_ADS_WATCHDOG(sNetId:='172.21.88.32.1.1' , nPort:=851 , sVarName:='GVL_Devices.iWatchdog',bError=> );


// GAUGES
// MKS275 Gauges
fb_AT1K0_GAS_GPI_111(PG=>);
fb_AT1K0_GAS_GPI_121(PG=>);
fb_AT1K0_GAS_GPI_141(PG=>);
// FB_MKS317
fb_AT1K0_GAS_GPI_10(PG=>);
fb_AT1K0_GAS_GPI_20(PG=>);
fb_AT1K0_GAS_GPI_11(PG=>);
fb_AT1K0_GAS_GPI_12(PG=>);
fb_AT1K0_GAS_GPI_30(PG=>);
fb_AT1K0_GAS_GPI_40(PG=>);
fb_AT1K0_GAS_GPI_50(PG=>);
fb_AT1K0_GAS_GPI_51(PG=>);
fb_AT1K0_GAS_GPI_60(PG=>);
fb_AT1K0_GAS_GPI_80(PG=>);
fb_AT1K0_GAS_GPI_90(PG=>);
fb_AT1K0_GAS_GPI_100(PG=>);
fb_AT1K0_GAS_GPI_110(PG=>);
fb_AT1K0_GAS_GPI_120(PG=>);
fb_AT1K0_GAS_GPI_130(PG=>);
fb_AT1K0_GAS_GPI_140(PG=>);

// FB_MKS422

fb_AT1K0_GAS_GCC_10(PG := fb_AT1K0_GAS_GPI_10.PG);
fb_AT1K0_GAS_GCC_20(PG := fb_AT1K0_GAS_GPI_20.PG);
fb_AT1K0_GAS_GCC_30(PG := fb_AT1K0_GAS_GPI_30.PG);
fb_AT1K0_GAS_GCC_40(PG := fb_AT1K0_GAS_GPI_40.PG);
fb_AT1K0_GAS_GCC_50(PG := fb_AT1K0_GAS_GPI_50.PG);
fb_AT1K0_GAS_GCC_60(PG := fb_AT1K0_GAS_GPI_60.PG);
fb_AT1K0_GAS_GCC_80(PG := fb_AT1K0_GAS_GPI_80.PG);
fb_AT1K0_GAS_GCC_90(PG := fb_AT1K0_GAS_GPI_90.PG);
fb_AT1K0_GAS_GCC_100(PG := fb_AT1K0_GAS_GPI_100.PG);
fb_AT1K0_GAS_GCC_110(PG := fb_AT1K0_GAS_GPI_110.PG);
fb_AT1K0_GAS_GCC_120(PG := fb_AT1K0_GAS_GPI_120.PG);
fb_AT1K0_GAS_GCC_130(PG := fb_AT1K0_GAS_GPI_130.PG);
fb_AT1K0_GAS_GCC_140(PG := fb_AT1K0_GAS_GPI_140.PG);


//VALVES
// Pump Isolation Valves
// FB_VRC
//EBD Side
//TURBO
fb_AT1K0_GAS_VRC_10(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_10.iq_stPtm,fb_AT1K0_GAS_GPI_10.PG)AND fb_AT1K0_GAS_PTM_10.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_20(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_20.iq_stPtm,fb_AT1K0_GAS_GPI_20.PG)AND fb_AT1K0_GAS_PTM_20.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_30(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_30.iq_stPtm,fb_AT1K0_GAS_GPI_30.PG)AND fb_AT1K0_GAS_PTM_30.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_40(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_40.iq_stPtm,fb_AT1K0_GAS_GPI_40.PG)AND fb_AT1K0_GAS_PTM_40.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);

// Auto open the VRC when pressure if ok
rTrig_11(CLK := ( fb_AT1K0_GAS_GPI_11.PG.xPRESS_OK AND fb_AT1K0_GAS_GPI_11.PG.rPRESS < 0.01));
IF (rTrig_11.Q) THEN
    fb_AT1K0_GAS_VRC_11.M_Set_OPN_SW (TRUE);
END_IF
fb_AT1K0_GAS_VRC_11(i_xExtILK_OK := (fb_AT1K0_GAS_GPI_11.PG.xPRESS_OK AND fb_AT1K0_GAS_GPI_11.PG.rPRESS < rPRESS_11) , i_xOverrideMode := xSystemOverrideMode);
//EBD
fb_AT1K0_GAS_VRC_50(i_xExtILK_OK := F_VRC_DIODE_ILK_OK(fb_AT1K0_GAS_GPI_50.PG,fb_AT1K0_GAS_GPI_51.PG), i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_60(i_xExtILK_OK := F_VRC_DIODE_ILK_OK(fb_AT1K0_GAS_GPI_60.PG,fb_AT1K0_GAS_GPI_51.PG), i_xOverrideMode := xSystemOverrideMode);
//FEE Side
PG.xPRESS_OK := TRUE;
PG.rPRESS := rPRESS;
fb_AT1K0_GAS_VRC_70(i_xExtILK_OK := fb_AT1K0_GAS_PMF_90.stPump.i_xMPStatus AND (F_VRC_DIODE_ILK_OK(fb_AT1K0_GAS_GPI_80.PG,PG) AND VVC_71.M_IsClosed() AND VVC_72.M_IsClosed()), i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_90(i_xExtILK_OK := fb_AT1K0_GAS_PMF_90.stPump.i_xMPStatus AND (F_VRC_DIODE_ILK_OK(fb_AT1K0_GAS_GPI_90.PG,PG)), i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_100(i_xExtILK_OK := fb_AT1K0_GAS_PMF_100.stPump.i_xMPStatus AND (F_VRC_DIODE_ILK_OK(fb_AT1K0_GAS_GPI_100.PG,PG)), i_xOverrideMode := xSystemOverrideMode);
//TURBO
fb_AT1K0_GAS_VRC_110(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_110.iq_stPtm,fb_AT1K0_GAS_GPI_110.PG) AND fb_AT1K0_GAS_PTM_110.iq_stPtm.eState = pumpRUNNING  , i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_120(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_120.iq_stPtm,fb_AT1K0_GAS_GPI_120.PG) AND fb_AT1K0_GAS_PTM_120.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_130(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_130.iq_stPtm,fb_AT1K0_GAS_GPI_130.PG) AND fb_AT1K0_GAS_PTM_130.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
fb_AT1K0_GAS_VRC_140(i_xExtILK_OK := F_TurboGateValve_ILK(fb_AT1K0_GAS_PTM_140.iq_stPtm,fb_AT1K0_GAS_GPI_140.PG) AND fb_AT1K0_GAS_PTM_140.iq_stPtm.eState = pumpRUNNING, i_xOverrideMode := xSystemOverrideMode);
//N2 valve
//INL VCN, VGP and VRC_70 are closed.
fb_AT1K0_GAS_VRC_80.i_xExtILK_OK := fb_AT1K0_GAS_VRC_90.iq_stValve.i_xClsLS AND VCN_70.iq_stVCN.rReqPosition <0.4 AND VVC_71.M_IsClosed() AND VVC_72.M_IsClosed() ; //AND VGP is closed;
fb_AT1K0_GAS_VRC_80( i_xOverrideMode := xSystemOverrideMode);


// Turbo Pumps
// FB_PTM_Ebara_010M
//EBD SIDE
fb_AT1K0_GAS_PTM_10(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_10.iq_stPtm, fb_AT1K0_GAS_GPI_12.PG, fb_AT1K0_GAS_GPI_10.PG,fb_AT1K0_GAS_PMF_10.iq_stPFO));// AND fb_AT1K0_GAS_VRC_11.M_IsOpen() );
fb_AT1K0_GAS_PTM_20(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_20.iq_stPtm, fb_AT1K0_GAS_GPI_12.PG, fb_AT1K0_GAS_GPI_20.PG,fb_AT1K0_GAS_PMF_10.iq_stPFO));// AND fb_AT1K0_GAS_VRC_11.M_IsOpen() );
fb_AT1K0_GAS_PTM_30(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_30.iq_stPtm, fb_AT1K0_GAS_GPI_12.PG, fb_AT1K0_GAS_GPI_30.PG,fb_AT1K0_GAS_PMF_10.iq_stPFO));// AND fb_AT1K0_GAS_VRC_11.M_IsOpen() );
fb_AT1K0_GAS_PTM_40(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_40.iq_stPtm, fb_AT1K0_GAS_GPI_12.PG, fb_AT1K0_GAS_GPI_40.PG,fb_AT1K0_GAS_PMF_10.iq_stPFO));// AND fb_AT1K0_GAS_VRC_11.M_IsOpen() );
//FEE Side
fb_AT1K0_GAS_PTM_110(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_110.iq_stPtm, fb_AT1K0_GAS_GPI_111.PG,fb_AT1K0_GAS_GPI_110.PG,fb_AT1K0_GAS_PMF_110.stPump));
fb_AT1K0_GAS_PTM_120(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_120.iq_stPtm, fb_AT1K0_GAS_GPI_121.PG, fb_AT1K0_GAS_GPI_120.PG,fb_AT1K0_GAS_PMF_120.stPump));
fb_AT1K0_GAS_PTM_130(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_130.iq_stPtm, fb_AT1K0_GAS_GPI_121.PG,fb_AT1K0_GAS_GPI_130.PG,fb_AT1K0_GAS_PMF_120.stPump));
fb_AT1K0_GAS_PTM_140(i_xExtILKOk := F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_140.iq_stPtm, fb_AT1K0_GAS_GPI_141.PG,fb_AT1K0_GAS_GPI_140.PG,fb_AT1K0_GAS_PMF_140.stPump));


// Injector side
fb_AT1K0_GAS_VVC_80.i_xExtILK_OK:= (fb_AT1K0_GAS_GPI_111.PG.rPRESS <= fb_AT1K0_GAS_PTM_80.iq_stPtm.rBackingPressureSP) AND NOT (fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpFAULT)  AND  (fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpRUNNING  OR  fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpSTARTING )AND  (fb_AT1K0_GAS_PMF_110.stPump.eState = pumpRUNNING  OR  fb_AT1K0_GAS_PMF_110.stPump.eState = pumpSTARTING );
fb_AT1K0_GAS_VVC_80(i_xOverrideMode:= xSystemOverrideMode , iq_stValve=> );
IF (fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpRUNNING) AND fb_AT1K0_GAS_VVC_80.M_IsClosed() THEN
     if (timer.Q) THEN fb_AT1K0_GAS_PTM_80.i_xExtILKOk := fb_AT1K0_GAS_VVC_80.M_IsOpen() AND F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_80.iq_stPtm, fb_AT1K0_GAS_GPI_111.PG,fb_AT1K0_GAS_GPI_80.PG,fb_AT1K0_GAS_PMF_110.stPump);//fb_AT1K0_GAS_PTM_80.i_xExtILKOk := FALSE;
 END_IF;
ELSE
    fb_AT1K0_GAS_PTM_80.i_xExtILKOk :=  F_TurboExtILKLogic_2(fb_AT1K0_GAS_PTM_80.iq_stPtm, fb_AT1K0_GAS_GPI_111.PG,fb_AT1K0_GAS_GPI_80.PG,fb_AT1K0_GAS_PMF_110.stPump);
END_IF
fb_AT1K0_GAS_PTM_80();
timer(IN:= (fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpRUNNING), PT:=T#1S);



//Rouging pumps
// FB_EbaraDryPump
//EBD SIDE
fb_AT1K0_GAS_PMF_10(xExtIlk :=TRUE,TurboIsOn := TRUE);
fb_AT1K0_GAS_PMF_60(xExtIlk :=TRUE,TurboIsOn := TRUE);
//FEE SIDE
fb_AT1K0_GAS_PMF_90(i_stBPGauge := fb_AT1K0_GAS_GPI_90.PG, i_xVlvOpn := TRUE, i_xExtIlkOK := TRUE);
fb_AT1K0_GAS_PMF_100(i_stBPGauge := fb_AT1K0_GAS_GPI_100.PG, i_xVlvOpn := TRUE, i_xExtIlkOK := TRUE);
fb_AT1K0_GAS_PMF_110(i_xExtIlkOK:= TRUE (*Interlock Timer on the Rough Valve*) , stPump=> );
fb_AT1K0_GAS_PMF_120(i_xExtIlkOK:= TRUE(*Interlock Timer on the Rough Valve*), stPump=> );
fb_AT1K0_GAS_PMF_140(i_xExtIlkOK:= TRUE(*Interlock Timer on the Rough Valve*), stPump=> );
if( fb_AT1K0_GAS_PMF_110.stPump.eState = pumpSTARTING ) OR ( fb_AT1K0_GAS_PMF_110.stPump.eState = pumpRUNNING ) THEN fb_AT1K0_GAS_VVC_110.M_Open(TRUE); END_IF
if( fb_AT1K0_GAS_PMF_120.stPump.eState = pumpSTARTING ) OR ( fb_AT1K0_GAS_PMF_120.stPump.eState = pumpRUNNING ) THEN fb_AT1K0_GAS_VVC_120.M_Open(TRUE); END_IF
if( fb_AT1K0_GAS_PMF_140.stPump.eState = pumpSTARTING ) OR ( fb_AT1K0_GAS_PMF_140.stPump.eState = pumpRUNNING ) THEN fb_AT1K0_GAS_VVC_140.M_Open(TRUE); END_IF
fb_AT1K0_GAS_VVC_110(i_xExtILK_OK:= (fb_AT1K0_GAS_PMF_110.stPump.eState = pumpRUNNING  OR  fb_AT1K0_GAS_PMF_110.stPump.eState = pumpSTARTING ), i_xOverrideMode:= , iq_stValve=> );
fb_AT1K0_GAS_VVC_120(i_xExtILK_OK:= (fb_AT1K0_GAS_PMF_120.stPump.eState = pumpRUNNING  OR  fb_AT1K0_GAS_PMF_120.stPump.eState = pumpSTARTING ), i_xOverrideMode:= , iq_stValve=> );
fb_AT1K0_GAS_VVC_140(i_xExtILK_OK:= (fb_AT1K0_GAS_PMF_140.stPump.eState = pumpRUNNING  OR  fb_AT1K0_GAS_PMF_140.stPump.eState = pumpSTARTING ), i_xOverrideMode:= , iq_stValve=> );

END_PROGRAM
Related:

PRG_ILK

PROGRAM PRG_ILK
VAR
END_VAR
(*Evaluate Global Interlocks*)

US_Roughing_Valves_Open := (fb_AT1K0_GAS_VRC_50.M_IsOpen() AND fb_AT1K0_GAS_VRC_60.M_IsOpen());
DS_Roughing_Valves_Open := (fb_AT1K0_GAS_VRC_90.M_IsOpen() AND( fb_AT1K0_GAS_PMF_90.stPump.eState = pumpRUNNING)) OR   (fb_AT1K0_GAS_VRC_100.iq_stValve.i_xOpnLS AND (fb_AT1K0_GAS_PMF_100.stPump.eState = pumpRUNNING ));
US_Turbo_Valves_Open := fb_AT1K0_GAS_VRC_10.M_IsOpen() AND  fb_AT1K0_GAS_VRC_20.M_IsOpen() AND fb_AT1K0_GAS_VRC_30.M_IsOpen() AND fb_AT1K0_GAS_VRC_40.M_IsOpen();
DS_Turbo_Valves_Open := fb_AT1K0_GAS_VRC_110.M_IsOpen() AND  fb_AT1K0_GAS_VRC_120.M_IsOpen() AND fb_AT1K0_GAS_VRC_130.M_IsOpen()AND fb_AT1K0_GAS_VRC_140.M_IsOpen();
US_Turbo_Running := (fb_AT1K0_GAS_PTM_10.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_20.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_30.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_40.iq_stPtm.eState = pumpRUNNING);
DS_Turbo_Running := (fb_AT1K0_GAS_PTM_110.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_120.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_130.iq_stPtm.eState = pumpRUNNING) AND (fb_AT1K0_GAS_PTM_140.iq_stPtm.eState = pumpRUNNING);

(* Link The correct override bit to the correct vacuum section*)



(*P/MPS FF*)

END_PROGRAM

PRG_INJ

PROGRAM PRG_INJ
VAR
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:SP;
    field: HOPR 1000;
    field: LOPR 0;
    field: PREC 2;
    field: EGU "TORR";
    '}
    fSetpointValue :REAL;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:ON;
     field: ZNAM STOP;
     field: ONAM START;
     io: io;
    '}
    bGo: BOOL:=FALSE;
     {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:RESET;
     field: ZNAM FALSE;
     field: ONAM TRUE;
     io: io;
     '}
    bReset : BOOL;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:ERROR;
    field: ZNAM FALSE;
     field: ONAM TRUE;
     io: io;
     '}
    bError : BOOL;
    // different gains for different apertures
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Kp1 '}
    fKp1 : REAL:= 0.4;//0.7;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Kp2 '}
    fKp2 : REAL:= 0.7;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Kp3 '}
    fKp3 : REAL:= 2;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Kp4 '}
    fKp4 : REAL:= 1;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Tn1 '}
    fTn1 : REAL:= 0.5;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:Tn2 '}
    fTn2 : REAL:= 0.5;
    arrTable        : ARRAY[1..15,1..2] OF FLOAT;
    arrTableAprt1   : ARRAY[1..15,1..2] OF FLOAT;
    arrTableAprt2   : ARRAY[1..15,1..2] OF FLOAT;
    arrTableAprt3   : ARRAY[1..15,1..2] OF FLOAT;
    arrTableAprt4   : ARRAY[1..15,1..2] OF FLOAT;
    fManValue                                                                                       : FLOAT;
    bExtrapolate                                                                            : BOOL;
    eMode                                                   : E_CTRL_MODE;
    stCTRL_PID_PARAMS               : ST_CTRL_PID_PARAMS;
    bSync                                                   : BOOL;
    bHold                                                   : BOOL;
    eErrorId                                                : E_CTRL_ERRORCODES;
    bARWactive                                      : BOOL;
    (* controller *)
    fbCTRL_PID                                      : FB_CTRL_PID;
    bInit                                                   : BOOL  := TRUE;
    fbCTRL_LIN_INTERPOLATION                                        : FB_CTRL_LIN_INTERPOLATION;
    //stCTRL_LIN_INTERPOLATION_PARAMS               : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    stCTRL_LIN_INTERPOLATION_PARAMS : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_DEADBAND                                         : FB_CTRL_DEADBAND;
    stCTRL_DEADBAND_PARAMS                  : ST_CTRL_DEADBAND_PARAMS;

    pid_on :TON;
    wait : time := T#10S;
    FTrig: F_TRIG;
    fTrig_PMPS: F_TRIG;
    rTrig_PMPS: R_TRIG;

    rtAction : R_TRIG;
    rtTrans: R_TRIG;

    rLimit1 : REAL:= 78;
    rLimit2 : REAL:= 78;
    rLimit3 : REAL:= 78;
    rLimit4 : REAL:= 62;
    rLimit:REAL:=78;
    rDelta:REAL:=5;

    tSettle: TON;
    tSettleTime: Time := T#5S;

    tExceed: TON;
    tExceedTime: Time := T#500mS;

    tMoving: TON;
    tMovingTime: Time := T#1S;

    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:TransPerc '}
    rTransPerc : REAL;
    {attribute 'pytmc' :=' pv: AT1K0:GAS:CNTRL:PressPerc '}
    rPressPerc : REAL;

    rPressThresholdHigh : REAL:=2.455e-1;
    rPressThresholdLow : REAL :=7.733e-2;
    iGauge:INT:=0;
    //FFO
        TRANS_FFO    :    FB_FastFault :=(
        i_DevName := 'AT1K0-GAS',
        i_Desc := 'Fault occurs when the current transmission exceeds the requested transmission by 20%',
        i_TypeCode := 16#AFF);
END_VAR
(* The gas injection conrol loop is augmented with a feed forward table, where FF provide the major portion of the
 controller output and the PI(D) controller conpensate for the remaining error.*)

//Devices and Interlock
// Valves
VCN_70(i_xExtIlkOK := (US_MAA_OK AND US_Turbo_Valves_Open AND US_Turbo_Running)
                        AND (DS_MAA_OK AND DS_Turbo_Valves_Open AND DS_Turbo_Running),
                        i_ReqPos:=);

VVC_71(i_xExtILK_OK:= VVC_72.M_IsClosed() AND (((*US_MAA_OK AND*) (*US_Roughing_Valves_Open AND*) US_Turbo_Valves_Open AND US_Turbo_Running)
                        AND ((*DS_MAA_OK AND *)(*DS_Roughing_Valves_Open AND*) DS_Turbo_Valves_Open AND DS_Turbo_Running)), i_xOverrideMode:= , iq_stValve=> );
VVC_72(i_xExtILK_OK:= VVC_71.M_IsClosed() AND (((*US_MAA_OK AND *) (*US_Roughing_Valves_Open AND *)US_Turbo_Valves_Open AND US_Turbo_Running)
                        AND ((*DS_MAA_OK AND *)(*DS_Roughing_Valves_Open AND *)DS_Turbo_Valves_Open AND DS_Turbo_Running)), i_xOverrideMode:= , iq_stValve=> );

//Gauges
GCM_70.M_SetBits(30518);
GCM_80.M_SetBits(30518);
GCM_81.M_SetBits(30518);
GCM_70(PG=> , i_rFULL_SCALE:= 2000);
GCM_80(PG=> , i_rFULL_SCALE:= 20);
GCM_81(PG=> , i_rFULL_SCALE:= 0.25);

(* Gauge selection *)
(*Assign reading to psuedo gauge*)
(*
IF (fSetpointValue <= 0.0001) AND (fb_AT1K0_GAS_GCC_80.IG.rPRESS >0) THEN GCM_82 := fb_AT1K0_GAS_GCC_80.IG;
    ELSIF (fSetpointValue < 0.0029) AND (fb_AT1K0_GAS_GPI_80.PG.rPRESS > 0.0001) THEN GCM_82 := fb_AT1K0_GAS_GPI_80.PG;
        ELSIF ( GCM_81.PG.rPRESS < 0.25 ) THEN GCM_82 := GCM_81.PG;
            ElSE GCM_82 := GCM_80.PG;
END_IF*)
(* MG: removed August shutdown 2021
IF (fb_AT1K0_GAS_GCC_80.IG.rPRESS <=0.0009) AND (fb_AT1K0_GAS_GCC_80.IG.rPRESS >0) THEN GCM_82 := fb_AT1K0_GAS_GCC_80.IG;
    ELSIF ( GCM_81.PG.rPRESS < 0.25 ) THEN GCM_82 := GCM_81.PG;
            ElSE GCM_82 := GCM_80.PG;
END_IF*)

//MG: Added to avoid sudden switching
IF (fb_AT1K0_GAS_GCC_80.IG.rPRESS <=0.0009) AND (fb_AT1K0_GAS_GCC_80.IG.rPRESS >0) THEN iGauge := 0;//GCM_82 := fb_AT1K0_GAS_GCC_80.IG;
    ELSIF (GCM_80.PG.rPRESS <= rPressThresholdLow ) THEN iGauge := 1;//GCM_82 := GCM_81.PG;
        ELSIF (GCM_81.PG.rPRESS >= rPressThresholdHigh ) THEN iGauge := 2;//GCM_82 := GCM_80.PG;
            //ElSIF (GCM_82.rPRESS = fb_AT1K0_GAS_GCC_80.IG.rPRESS) THEN iGauge := 0;//GCM_82 := GCM_81.PG ;
END_IF

CASE iGauge OF
    0: GCM_82 := fb_AT1K0_GAS_GCC_80.IG;
    1: GCM_82 := GCM_81.PG ;
    2: GCM_82 := GCM_80.PG;
    ELSE GCM_82 := GCM_80.PG;
END_CASE



(*Automation of other devices*)
(*When to Open the VRC Valves to the MAA chambers*)
(*When PID is ON*)
IF (bGo) THEN
    (*VRC US*)
    IF ( fb_AT1K0_GAS_GPI_40.PG .rPRESS >= rVRC_US_SP ) THEN
        IF (fb_AT1K0_GAS_VRC_50.M_IsOpen()) THEN fb_AT1K0_GAS_VRC_60.M_Set_OPN_SW (TRUE);
            ELSE fb_AT1K0_GAS_VRC_50.M_Set_OPN_SW (TRUE);
        END_IF
    END_IF

    (*VRC DS*)
    IF ( fb_AT1K0_GAS_GPI_110.PG .rPRESS >= rVRC_DS_SP ) THEN
        IF (fb_AT1K0_GAS_VRC_100.M_IsOpen()) THEN fb_AT1K0_GAS_VRC_90.M_Set_OPN_SW (TRUE);
            ELSE fb_AT1K0_GAS_VRC_100.M_Set_OPN_SW (TRUE);
        END_IF
    END_IF
END_IF

//Try to switch on the GCC in the Gas cell for accurate transmission calculation
IF  NOT(fb_AT1K0_GAS_GCC_80.IG.i_xHV_ON) AND (fb_AT1K0_GAS_GPI_80.PG.rPRESS <= 1.1E-4) THEN fb_AT1K0_GAS_GCC_80.M_HVE(TRUE); END_IF;

(* On change transmission reset *)
rtNewTrans(CLK:=  (OldTransmissionValue <> TransmissionValue) OR (fTrig_PMPS.Q) OR (rTrig_PMPS.Q));
IF(rtNewTrans.Q) THEN
    OldTransmissionValue := TransmissionValue;
    bChangeAperture:=TRUE;
    bChangeGas := TRUE;
    fbLogger(sMsg:='AT1K0 new transmission request.', eSevr:=TcEventSeverity.Info);
    IF NOT (tSettle.IN) THEN
        stStatus.AtTarget := 0;
    END_IF
    stStatus.Moving := 1;
END_IF
// change setpoint
// As calculated by the PRG_INJ
IF NOT (xPressureControlMode) THEN
    fSetpointValue := rRequiredPressureSP;
END_IF

(*Setpoint Validation*)
fSetpointValue:= LIMIT(0,fSetpointValue,10);


ACT_init();
ACT_Cntrl();
ACT_Logger();
ACT_FFO();
ACT_STATE();

END_PROGRAM

ACTION ACT_Cntrl:
// Turn the PID on rising edge of the PMPSMode and off at falling edge
fTrig_PMPS(CLK:= xPMPSMode);
rTrig_PMPS(CLK:= xPMPSMode);
IF (xPMPSMode) THEN bGo := TRUE; xPressureControlMode:=FALSE; END_IF
IF (fTrig_PMPS.Q) THEN
     bGo := FALSE;
     bChangeAperture:=FALSE;
     bChangeGas := FALSE;
     rTransmissionSP:=1;
END_IF
//IF (rTrig_PMPS.Q) THEN bGo := TRUE; END_IF

if (bGo) THEN
    //VCN_70.i_ReqPos:= LREAL_TO_REAL(fbCTRL_LIN_INTERPOLATION.fOut + fbCTRL_PID.fOut);
    VCN_70.i_ReqPos:= LREAL_TO_REAL(fbCTRL_LIN_INTERPOLATION.fOut + fbCTRL_PID.fOut);
    IF (bReset) THEN
    (* set the mode to RESET*)
    eMode                                                   := eCTRL_MODE_RESET   ;
    VCN_70.M_ValveControl(CloseValve);
    //bReset := False;
    ELSE
        (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_ACTIVE   ;
     VCN_70.M_ValveControl(PressureControl);
    END_IF
END_IF
FTRIG(CLK := bGo);
IF(FTrig.Q)THEN
        eMode                                                       := eCTRL_MODE_PASSIVE;
        VCN_70.M_ValveControl(CloseValve);
        fSetpointValue :=0;
END_IF
(*Interlock setpoint reset*)
if (VVC_71.M_IsClosed() AND VVC_72.M_IsClosed() ) THEN
        //eMode     := eCTRL_MODE_PASSIVE;
        fSetpointValue :=0;
END_IF

(*Switch PID Mode to passive if VCN is interlocked*)
IF NOT (VCN_70.i_xExtIlkOK) THEN
        eMode       := eCTRL_MODE_PASSIVE;
END_IF

fbCTRL_LIN_INTERPOLATION(
    fIn:= fSetpointValue ,
    fManValue:= fManValue ,
    bExtrapolate:= bExtrapolate,
    eMode:= eMode,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS,
    fOut=> ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> );


(* call controller *)
fbCTRL_PID(         fSetpointValue          := fSetpointValue,//TransmissionValue,//fSetpointValue,
                    fActualValue            := GCM_82.rPRESS,//rCalculatedTransmissionValue,//GCM_82.rPRESS ,
                    fManSyncValue   := ,
                    bSync                           := bSync,
                    eMode                           := eMode,
                    bHold                           := bHold,
                    stParams                        := stCTRL_PID_PARAMS,
                    fOut                            => ,
                    bARWactive              => bARWactive,
                    eErrorId                        => eErrorId,
                    bError                          =>
                );


(*deadband/clipper *)

(* call function block *)
stCTRL_DEADBAND_PARAMS.fThreshold   :=  fSetpointValue*0.0016 ;
(*fbCTRL_DEADBAND   (       fIn                                     := ,
                    stParams                        := stCTRL_DEADBAND_PARAMS,
                    bInIsUnderThreshold => ,
                    eErrorId                        => ,
                    bError                          =>
                );*)

bError := fbCTRL_PID.bError OR fbCTRL_LIN_INTERPOLATION.bError;
END_ACTION

ACTION ACT_FFO:
TRANS_FFO.i_xOK := (rCalculatedTransmissionValue <= (TransmissionValue + (TransmissionValue*20/100))) OR NOT tExceed.Q;

//auto reset true
(*FAST FAULT*)
TRANS_FFO(i_xOK := ,//NOT tExceed.Q,
    i_xReset :=  ,
    i_xAutoReset := TRUE,
    io_fbFFHWO := GVL_PMPS.g_FastFaultOutput1);
END_ACTION

ACTION ACT_Init:
//control Loop and FeedForward table initialisation
(*Iniitialization*)
IF bInit
THEN
    (* Feed forward table records 9 disticnt positions of the needle valves, breaking the *)
    (* the needle valve profile into disticnt nearly linear segments*)
    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable[1,1] := 0;             arrTable[1,2] := 12;
    arrTable[2,1] := 0.000001;      arrTable[2,2] := 15;
    arrTable[3,1] := 0.000024;      arrTable[3,2] := 19;
    arrTable[4,1] :=  0.0001;       arrTable[4,2] := 25;
    arrTable[5,1] :=  0.001;        arrTable[5,2] := 28;
    arrTable[6,1] := 0.0082;        arrTable[6,2] := 31;
    arrTable[7,1] := 0.04;          arrTable[7,2] := 34;
    arrTable[8,1] := 0.062; arrTable[8,2] := 39;
    arrTable[9,1] := 0.09;          arrTable[9,2] := 44;
    arrTable[10,1] := 0.112;                arrTable[10,2] := 49;
    arrTable[11,1] := 0.6;                  arrTable[11,2] := 55;
    arrTable[12,1] := 1.34;         arrTable[12,2] := 62;
    arrTable[13,1] := 4;                    arrTable[13,2] := 70;
    arrTable[14,1] := 7.27;         arrTable[14,2] := 78;
    arrTable[15,1] := 20;                   arrTable[15,2] := 100;

    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTableAprt1[1,1] := 0;                arrTableAprt1[1,2] := 12;
    arrTableAprt1[2,1] := 0.000001; arrTableAprt1[2,2] := 15;
    arrTableAprt1[3,1] := 0.000024; arrTableAprt1[3,2] := 19;
    arrTableAprt1[4,1] :=  0.0001;  arrTableAprt1[4,2] := 25;
    arrTableAprt1[5,1] :=  0.001;   arrTableAprt1[5,2] := 28;
    arrTableAprt1[6,1] := 0.0082;   arrTableAprt1[6,2] := 31;
    arrTableAprt1[7,1] := 0.04;             arrTableAprt1[7,2] := 34;
    arrTableAprt1[8,1] := 0.062;    arrTableAprt1[8,2] := 39;
    arrTableAprt1[9,1] := 0.09;             arrTableAprt1[9,2] := 44;
    arrTableAprt1[10,1] := 0.112;           arrTableAprt1[10,2] := 49;
    arrTableAprt1[11,1] := 0.6;                     arrTableAprt1[11,2] := 55;
    arrTableAprt1[12,1] := 1.34;            arrTableAprt1[12,2] := 62;
    arrTableAprt1[13,1] := 4;                       arrTableAprt1[13,2] := 70;
    arrTableAprt1[14,1] := 7.27;            arrTableAprt1[14,2] := 78;
    arrTableAprt1[15,1] := 20;                      arrTableAprt1[15,2] := 100;

    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTableAprt2[1,1] := 0;                    arrTableAprt2[1,2] := 12;
    arrTableAprt2[2,1] := 0.000001;         arrTableAprt2[2,2] := 15;
    arrTableAprt2[3,1] := 0.000024;         arrTableAprt2[3,2] := 19;
    arrTableAprt2[4,1] :=  0.000072;        arrTableAprt2[4,2] := 25;
    arrTableAprt2[5,1] :=  0.0059;      arrTableAprt2[5,2] := 28;
    arrTableAprt2[6,1] := 0.0059;           arrTableAprt2[6,2] := 31;
    arrTableAprt2[7,1] := 0.0099;           arrTableAprt2[7,2] := 34;
    arrTableAprt2[8,1] := 0.034;            arrTableAprt2[8,2] := 39;
    arrTableAprt2[9,1] := 0.051;            arrTableAprt2[9,2] := 44;
    arrTableAprt2[10,1] := 0.074;           arrTableAprt2[10,2] := 49;
    arrTableAprt2[11,1] := 0.2;                     arrTableAprt2[11,2] := 55;
    arrTableAprt2[12,1] := 0.598;           arrTableAprt2[12,2] := 62;
    arrTableAprt2[13,1] := 1;                       arrTableAprt2[13,2] := 70;
    arrTableAprt2[14,1] := 3.34;            arrTableAprt2[14,2] := 78;
    arrTableAprt2[15,1] := 20;                      arrTableAprt2[15,2] := 100;
    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTableAprt3[1,1] := 0;                    arrTableAprt3[1,2] := 12;
    arrTableAprt3[2,1] := 0.000001;         arrTableAprt3[2,2] := 15;
    arrTableAprt3[3,1] := 0.000024;         arrTableAprt3[3,2] := 19;
    arrTableAprt3[4,1] :=  0.000062;        arrTableAprt3[4,2] := 25;
    arrTableAprt3[5,1] :=  0.001;       arrTableAprt3[5,2] := 28;
    arrTableAprt3[6,1] := 0.005;            arrTableAprt3[6,2] := 31;
    arrTableAprt3[7,1] := 0.01;                     arrTableAprt3[7,2] := 34;
    arrTableAprt3[8,1] := 0.029;            arrTableAprt3[8,2] := 39;
    arrTableAprt3[9,1] := 0.036;            arrTableAprt3[9,2] := 44;
    arrTableAprt3[10,1] := 0.058;           arrTableAprt3[10,2] := 49;
    arrTableAprt3[11,1] := 0.2;                     arrTableAprt3[11,2] := 55;
    arrTableAprt3[12,1] := 0.363;           arrTableAprt3[12,2] := 62;
    arrTableAprt3[13,1] := 1;                       arrTableAprt3[13,2] := 70;
    arrTableAprt3[14,1] := 1.95;            arrTableAprt3[14,2] := 78;
    arrTableAprt3[15,1] := 20;                      arrTableAprt3[15,2] := 100;

    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTableAprt4[1,1] := 0;                    arrTableAprt4[1,2] := 10;
    arrTableAprt4[2,1] := 0.000001;         arrTableAprt4[2,2] := 12;
    arrTableAprt4[3,1] := 0.000024;         arrTableAprt4[3,2] := 17;
    arrTableAprt4[4,1] :=  0.000071;        arrTableAprt4[4,2] := 23;
    arrTableAprt4[5,1] :=  0.00036;     arrTableAprt4[5,2] := 26;
    arrTableAprt4[6,1] :=  0.005;       arrTableAprt4[6,2] := 29;
    arrTableAprt4[7,1] := 0.0073;           arrTableAprt4[7,2] := 32;
    arrTableAprt4[8,1] := 0.028;            arrTableAprt4[8,2] := 37;
    arrTableAprt4[9,1] := 0.04;                     arrTableAprt4[9,2] := 42;
    arrTableAprt4[10,1] := 0.0535;          arrTableAprt4[10,2] := 47;
    arrTableAprt4[11,1] := 0.083;           arrTableAprt4[11,2] := 53;
    arrTableAprt4[12,1] := 0.3;                     arrTableAprt4[12,2] := 60;
    arrTableAprt4[13,1] := 1;                       arrTableAprt4[13,2] := 68;
    arrTableAprt4[14,1] := 1.95;            arrTableAprt4[14,2] := 76;
    arrTableAprt4[15,1] := 20;                      arrTableAprt4[15,2] := 98;



    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS.tCtrlCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.tTaskCycleTime                                  := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_NumberOfRows         := INT_TO_UINT(15);

    (*FBCNTRL*)
    (* init parameter struct *)
    stCTRL_PID_PARAMS.tCtrlCycleTime                := T#250ms;
    stCTRL_PID_PARAMS.tTaskCycleTime                := T#10ms;
    stCTRL_PID_PARAMS.fKp                                   := fKp1;                        (* proportional gain Kp                         *)
    stCTRL_PID_PARAMS.tTn                                   := T#500ms;             (*  Tn                                                                  *)
    stCTRL_PID_PARAMS.tTv                                   := T#200ms;     (*  Tv                                                                  *)
    stCTRL_PID_PARAMS.tTd                                   := T#500ms;     (*  Td                          200                                     *)
    stCTRL_PID_PARAMS.fOutMaxLimit                  :=  25;                 (* maximum output limit                         *)
    stCTRL_PID_PARAMS.fOutMinLimit                  :=  -100;                       (* minimum output limit                         *)

    (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_PASSIVE   ;

    (*set the upper limit on the VCN*)
    VCN_70.M_SetThrottle(rLimit);

    (* reset the init flag *)
    bInit                                                   := FALSE;
END_IF
(* set the addresses *)
(* Gain selection *)
(* VCN limit *)
IF (bGo) THEN
    CASE eSelectedAprt of
         E_MAA_States.Aprt1:
            arrTable := arrTableAprt1;
            stCTRL_PID_PARAMS.fKp   := fKp1;
            //rLimit:= rLimit1;
            //VCN_70.M_SetThrottle(78);
         E_MAA_States.Aprt2:
            arrTable := arrTableAprt2;
            stCTRL_PID_PARAMS.fKp   := fKp2;
            //rLimit:= rLimit2;
            //VCN_70.M_SetThrottle(78);
         E_MAA_States.Aprt3:
            arrTable := arrTableAprt3;
            stCTRL_PID_PARAMS.fKp   := fKp3;
            //rLimit:= rLimit3;
            //VCN_70.M_SetThrottle(78);
         E_MAA_States.Aprt4:
            arrTable := arrTableAprt4;
            stCTRL_PID_PARAMS.fKp   := fKp4;
            //rLimit:= rLimit4;
            //VCN_70.M_SetThrottle(78);
    END_CASE
END_IF

stCTRL_LIN_INTERPOLATION_PARAMS.pDataTable_ADR                      := ADR(arrTable);
stCTRL_LIN_INTERPOLATION_PARAMS.nDataTable_SIZEOF   := SIZEOF(arrTable);
END_ACTION

ACTION ACT_Logger:
rtAction(CLK:=eSelectedAprt <>  eSetAprt);

IF (fTrig_PMPS.Q) THEN fbLogger(sMsg:='AT1K0 switched to local mode.', eSevr:=TcEventSeverity.Info);  END_IF
IF (rTrig_PMPS.Q) THEN fbLogger(sMsg:='AT1K0 switched to PMPS mode.', eSevr:=TcEventSeverity.Info);   END_IF

IF (rtAction.Q) THEN  fbLogger(sMsg:='AT1K0-MAA current aperture size mismatch, change aperture state or switch to local mode', eSevr:=TcEventSeverity.Critical);   END_IF
END_ACTION

ACTION ACT_STATE:
IF tExceed.Q THEN
    eState := E_State.error;
    stStatus.AtTarget := 0;
ELSIF tSettle.Q THEN
    // ok
    eState := E_State.ok;
    // At Target
    stStatus.AtTarget := 1;
    stStatus.Moving := 0;
ELSIF (rCalculatedTransmissionValue < (TransmissionValue - (TransmissionValue*20/100))) THEN
    //warning
    eState := E_State.warning;
ELSE eState := E_State.unknown;
END_IF
// State ok when the Transmission is within the acceptable range and the MAA are not in errors
stStatus.OK := (*TRANS_FFO.i_xOK AND*) US_MAA_OK AND DS_MAA_OK AND US_Turbo_Valves_Open
                    AND DS_Turbo_Valves_Open AND US_Turbo_Running AND DS_Turbo_Running;  ;


bStatus.0 := stStatus.AtTarget;
bStatus.1 := stStatus.Moving;
bStatus.2 := stStatus.LocalMode;
bStatus.3 := stStatus.PMPSMode;
bStatus.4 := stStatus.OK;
bStatus.5 := stStatus.Toggle;
bStatus.6 := stStatus.Include;

stStatus.Moving := NOT tMoving.Q;
xAtTarget :=  stStatus.AtTarget;
xMoving :=  stStatus.Moving;
xOK :=  stStatus.OK;

IF (TransmissionValue >0) THEN rTransPerc:= rCalculatedTransmissionValue*100/TransmissionValue; END_IF
IF (fSetpointValue >0) THEN rPressPerc:= GCM_82.rPRESS*100/fSetpointValue; END_IF

tSettle(IN:= (rCalculatedTransmissionValue <= (TransmissionValue + (TransmissionValue*20/100))) AND (rCalculatedTransmissionValue >= (TransmissionValue - (TransmissionValue*20/100))),
    PT := tSettleTime);

tMoving(IN:= (rCalculatedTransmissionValue <= (TransmissionValue + (TransmissionValue*5/100))) AND (rCalculatedTransmissionValue >= (TransmissionValue - (TransmissionValue*10/100))),
    PT := tMovingTime);

tExceed(IN:= (rCalculatedTransmissionValue > (TransmissionValue + (TransmissionValue*20/100))),
    PT := tExceedTime);
END_ACTION
Related:

PRG_Motion

PROGRAM PRG_Motion
VAR
    bInit: BOOL := TRUE;
    nTransitionAssertionRootID: UDINT :=1000;
    nUnknownAssertionRootID: UDINT :=9000;
    bAllGo : Bool := false;



    /////
    {attribute 'pytmc' := '
        pv: AT1K0:GAS_MAA:01
        io: io
    '}
    fbMAA_1_States: FB_MAA;
    {attribute 'pytmc' := '
        pv: AT1K0:GAS_MAA:02
        io: io
    '}
    fbMAA_2_States: FB_MAA;
    {attribute 'pytmc' := '
        pv:  AT1K0:GAS_MAA:03
        io: io
    '}
    fbMAA_3_States: FB_MAA;
    {attribute 'pytmc' := '
        pv: AT1K0:GAS_MAA:04
        io: io
    '}
    fbMAA_4_States: FB_MAA;



END_VAR
IF (bInit) THEN
    bInit := False;

    /// PMPS
    //MAA 1 Y
    //fbMAA_1_States.nTransitionAssertionID := 43536;// nTransitionAssertionRootID+10;
    //fbMAA_1_States.nUnknownAssertionID := nUnknownAssertionRootID;
    // Aperture 1
    fbMAA_1_States.stAprt1.fPosition :=  -0.78;//-1.4;
    // Aperture 2
    fbMAA_1_States.stAprt2.fPosition := -16.1;
    // Aperture 3
    fbMAA_1_States.stAprt3.fPosition := -30.93;
    // Aperture 4
    fbMAA_1_States.stAprt4.fPosition := -48.7;
    // X Cen
    fbMAA_1_States.stXCen.fPosition := 1;//1.5;// 0;// -2.083;


    //MAA 2 Y
    //fbMAA_2_States.nTransitionAssertionID := 43552;//nTransitionAssertionRootID+20;
    //fbMAA_1_States.nUnknownAssertionID := nUnknownAssertionRootID;
    // Aperture 1
    fbMAA_2_States.stAprt1.fPosition :=  -1;//-1.4;
    // Aperture 2
    fbMAA_2_States.stAprt2.fPosition := -16.5;
    // Aperture 3
    fbMAA_2_States.stAprt3.fPosition := -30.9;
    // Aperture 4
    fbMAA_2_States.stAprt4.fPosition := -48.96;
    // X Cen
    fbMAA_2_States.stXCen.fPosition :=1.5;//0.475;//0;//-0.77;


    //MAA 3 Y
    //fbMAA_3_States.nTransitionAssertionID := 43568;//nTransitionAssertionRootID+30;
    //fbMAA_1_States.nUnknownAssertionID := nUnknownAssertionRootID;
    // Aperture 1
    fbMAA_3_States.stAprt1.fPosition :=  -0.35;//-1.15;
    // Aperture 2
    fbMAA_3_States.stAprt2.fPosition := -16.2;
    // Aperture 3
    fbMAA_3_States.stAprt3.fPosition := -30.8;
    // Aperture 4
    fbMAA_3_States.stAprt4.fPosition := -48.95;
    // X Cen
    fbMAA_3_States.stXCen.fPosition :=1;//-0.4064;//0;//2.031;


    //MAA 4 Y
    //fbMAA_4_States.nTransitionAssertionID := 43584;//nTransitionAssertionRootID+40;
    //fbMAA_1_States.nUnknownAssertionID := nUnknownAssertionRootID;
    // Aperture 1
    fbMAA_4_States.stAprt1.fPosition :=  0;//-1;
    // Aperture 2
    fbMAA_4_States.stAprt2.fPosition := -14.5;//-16.6; re align data May 17,2024
    // Aperture 3
    fbMAA_4_States.stAprt3.fPosition := -30.9;
    // Aperture 4
    fbMAA_4_States.stAprt4.fPosition := -49.06;
    // X Cen
    fbMAA_4_States.stXCen.fPosition :=1.0;//0;//-0.9861;//0;//2.0345;

END_IF

//EBD
fbMAA_1_States(
     fbArbiter := GVL_PMPS.fbArbiter1,
     i_DevName:= 'AT1K0:GAS_MAA:01',
    fbFFHWO :=  GVL_PMPS.g_FastFaultOutput1,
    sPmpsDeviceName:='AT1K0:GAS_MAA:01',
    sTransitionKey:='AT1K0:GAS_MAA:01-TRANSITION',
    stYStage := Main.M2,
    stXStage := Main.M1);

fbMAA_2_States(
    fbArbiter := GVL_PMPS.fbArbiter1,
    i_DevName:= 'AT1K0:GAS_MAA:02',
    sPmpsDeviceName:='AT1K0:GAS_MAA:02',
    sTransitionKey:='AT1K0:GAS_MAA:02-TRANSITION',
    fbFFHWO := GVL_PMPS.g_FastFaultOutput1,
    stYStage := Main.M4,
    stXStage := Main.M3);
//FEE
fbMAA_3_States(
    fbArbiter := GVL_PMPS.fbArbiter1,
    i_DevName:= 'AT1K0:GAS_MAA:03',
    sPmpsDeviceName:='AT1K0:GAS_MAA:03',
    sTransitionKey:='AT1K0:GAS_MAA:03-TRANSITION',
    fbFFHWO := GVL_PMPS.g_FastFaultOutput1,
    stYStage := Main.M6,
    stXStage := Main.M5);

fbMAA_4_States(
    fbArbiter := GVL_PMPS.fbArbiter1,
    i_DevName:= 'AT1K0:GAS_MAA:04',
    sPmpsDeviceName:='AT1K0:GAS_MAA:04',
    sTransitionKey:='AT1K0:GAS_MAA:04-TRANSITION',
    fbFFHWO := GVL_PMPS.g_FastFaultOutput1,
    stYStage := Main.M8,
    stXStage := Main.M7);


(*Set global OK bit*)
US_MAA_OK := (fbMAA_1_States.fbStates.enumGet = fbMAA_2_States.fbStates.enumGet) AND (fbMAA_2_States.fbStates.enumGet = fbMAA_3_States.fbStates.enumGet)AND( fbMAA_3_States.fbStates.enumGet = fbMAA_4_States.fbStates.enumGet) AND NOT (fbMAA_1_States.fbStates.bError) AND NOT (fbMAA_2_States.fbStates.bError);
DS_MAA_OK := (fbMAA_3_States.fbStates.enumGet = fbMAA_4_States.fbStates.enumGet) AND NOT (fbMAA_3_States.fbStates.bError) AND NOT (fbMAA_4_States.fbStates.bError);

//change here line103 and 119
IF (US_MAA_OK AND DS_MAA_OK) THEN   eSelectedAprt:=fbMAA_4_States.fbStates.enumGet;//was fbMAA_1
ELSE  eSelectedAprt:= E_MAA_States.Unknown; END_IF;
////////////////////
//Set the right state i.e. apperture based on the current beam size/
/////
    IF( rPhotonEnergy >=0.9E3) THEN
        eSetAprt := E_MAA_States.Aprt1;
        ELSIF ( rPhotonEnergy >=0.6E3) THEN
            eSetAprt := E_MAA_States.Aprt2;
            ELSIF ( rPhotonEnergy >=0.5E3) THEN
                eSetAprt := E_MAA_States.Aprt3;
                ELSE
                    eSetAprt := E_MAA_States.Aprt4;
    END_IF
(*Aperture state selection*)
IF (xPMPSMode) AND (bChangeAperture)  AND (eSelectedAprt <> eSetAprt) THEN
    fbMAA_1_States.enumSet := eSetAprt;
    fbMAA_2_States.enumSet := eSetAprt;
    fbMAA_3_States.enumSet := eSetAprt;
    fbMAA_4_States.enumSet := eSetAprt;
    bChangeAperture:=False;
    fbLogger(sMsg:='AT1K0-MAA moving to correct apperture size', eSevr:=TcEventSeverity.Verbose);
    ELSE
    bChangeAperture:=False;
END_IF

IF NOT (xPMPSMode) AND bChangeAperture AND (eSelectedAprt <> eSetAprt)  THEN
    fbLogger(sMsg:='AT1K0-MAA is not set to correct apperture size', eSevr:=TcEventSeverity.Critical);
    bChangeAperture:=False;
END_IF

END_PROGRAM
Related:

PRG_Motors_Test

PROGRAM PRG_Motors_Test
VAR

    Y1_Power: MC_Power;
    Y2_Power: MC_Power;
    Y3_Power: MC_Power;
    Y4_Power: MC_Power;
    X1_Power: MC_Power;
    X2_Power: MC_Power;
    X3_Power: MC_Power;
    X4_Power: MC_Power;


    Y1_ENC AT%I* :INT;
    Y2_ENC AT%I* :INT;
    Y3_ENC AT%I* :INT;
    Y4_ENC AT%I* :INT;
    X1_ENC AT%I* :INT;
    X2_ENC AT%I* :INT;
    X3_ENC AT%I* :INT;
    X4_ENC AT%I* :INT;

END_VAR
X1_Power(//reverse motor direction?
    Axis:=  M1.Axis,
    Enable:= M1.bBrakeRelease,
    Enable_Positive:= M1.bLimitForwardEnable, // fix
    Enable_Negative:= M1.bLimitBackwardEnable,  // fix -- verify
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );

Y1_Power(
    Axis:=  M2.Axis,
    Enable:= M2.bBrakeRelease,
    Enable_Positive:= M2.bLimitForwardEnable,
    Enable_Negative:= M2.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );



X2_Power(
    Axis:=  M3.Axis,
    Enable:= M3.bBrakeRelease,
    Enable_Positive:= M3.bLimitForwardEnable, // fix
    Enable_Negative:= M3.bLimitBackwardEnable,  // fix -- verify
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );

Y2_Power(
    Axis:=  M4.Axis,
    Enable:= M4.bBrakeRelease,
    Enable_Positive:= M4.bLimitForwardEnable,
    Enable_Negative:= M4.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );

X3_Power(
    Axis:=  M5.Axis,
    Enable:= M5.bBrakeRelease,
    Enable_Positive:= M5.bLimitForwardEnable,
    Enable_Negative:= M5.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );
Y3_Power(
    Axis:=  M6.Axis,
    Enable:= M6.bBrakeRelease,
    Enable_Positive:= M6.bLimitForwardEnable,
    Enable_Negative:= M6.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );


X4_Power(
    Axis:=  M7.Axis,
    Enable:= M7.bBrakeRelease,
    Enable_Positive:= M7.bLimitForwardEnable,
    Enable_Negative:= M7.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );
Y4_Power(
    Axis:=  M8.Axis,
    Enable:= M8.bBrakeRelease,
    Enable_Positive:= M8.bLimitForwardEnable,
    Enable_Negative:= M8.bLimitBackwardEnable,
    Override:= ,
    BufferMode:= ,
    Options:= ,
    Status=> ,
    Busy=> ,
    Active=> ,
    Error=> ,
    ErrorID=> );

END_PROGRAM

PRG_PMPS

PROGRAM PRG_PMPS
VAR
 fbArbiterIO : FB_SubSysToArbiter_IO;
 ar1 : bool;
 ar2 : bool;
 nReqID:UDINT;
 nReqRM:UDINT;
 bRemove:bool;
 rtRemove: R_TRIG;

 //Testing
 ID1:DWORD:=43536;
 ID2:DWORD:=43552;;
 ID3:DWORD:=43568;
 ID4:DWORD:=43584;
 bTrans:BOOL;
 bAp11:BOOL;
 bAp12:BOOL;
 bAp13:BOOL;
 bAp14:BOOL;


 bTrans2:BOOL;
 bTrans3:BOOL;
 bTrans4:BOOL;
 bTrans1X:BOOL;
 bTrans2X:BOOL;
 bTrans3X:BOOL;
 bTrans4X:BOOL;
 bAp1XS:BOOL;
 bAp2XS:BOOL;
 bAp3XS:BOOL;
 bAp4XS:BOOL;

 bAp21:BOOL;
 bAp22:BOOL;
 bAp23:BOOL;
 bAp24:BOOL;
 bAp31:BOOL;
 bAp32:BOOL;
 bAp33:BOOL;
 bAp34:BOOL;
 bAp41:BOOL;
 bAp42:BOOL;
 bAp43:BOOL;
 bAp44:BOOL;

 iAp:INT;
END_VAR
(*Fast Fault instantiation*)
GVL_PMPS.g_FastFaultOutput1.bAutoReset :=TRUE;
GVL_PMPS.g_FastFaultOutput2.bAutoReset :=TRUE;
GVL_PMPS.g_FastFaultOutput1.Execute();
GVL_PMPS.g_FastFaultOutput2.Execute();

(* Arbiter Instantiation*)
(*Arbiter one responsible for the aperture valves*)
fbArbiterIO(Arbiter := GVL_PMPS.fbArbiter1, fbFFHWO := GVL_PMPS.g_FastFaultOutput1);
//GVL_ILK.fbArbiter2.ElevateRequest(GVL_ILK.fbArbiter1);

(* Photon Energy *)
rPhotonEnergy := PMPS_GVL.stCurrentBeamParameters.neV;

MOTION_GVL.fbStandardPMPSDB(
    io_fbFFHWO:=GVL_PMPS.g_FastFaultOutput1,
    bEnable:=TRUE,
    sPLCName:='plc-kfe-gatt',
);

(*remove*)
(*Debugging functions*)
bTrans:= fbArbiter1.CheckRequestInPool(ID1);//TransitionID
bAp11:= fbArbiter1.CheckRequestInPool(ID1+1);
bAp12:= fbArbiter1.CheckRequestInPool(ID1+2);
bAp13:= fbArbiter1.CheckRequestInPool(ID1+3);
bAp14:= fbArbiter1.CheckRequestInPool(ID1+4);
bTrans1X:= fbArbiter1.CheckRequestInPool(ID1+5);
bAp1XS:= fbArbiter1.CheckRequestInPool(ID1+6);

bTrans2:= fbArbiter1.CheckRequestInPool(ID2);//TransitionID
bAp21:= fbArbiter1.CheckRequestInPool(ID2+1);
bAp22:= fbArbiter1.CheckRequestInPool(ID2+2);
bAp23:= fbArbiter1.CheckRequestInPool(ID2+3);
bAp24:= fbArbiter1.CheckRequestInPool(ID2+4);
bTrans2X:= fbArbiter1.CheckRequestInPool(ID2+5);
bAp2XS:= fbArbiter1.CheckRequestInPool(ID2+6);

bTrans3:= fbArbiter1.CheckRequestInPool(ID3);//TransitionID
bAp31:= fbArbiter1.CheckRequestInPool(ID3+1);
bAp32:= fbArbiter1.CheckRequestInPool(ID3+2);
bAp33:= fbArbiter1.CheckRequestInPool(ID3+3);
bAp34:= fbArbiter1.CheckRequestInPool(ID3+4);
bTrans3X:= fbArbiter1.CheckRequestInPool(ID3+5);
bAp3XS:= fbArbiter1.CheckRequestInPool(ID3+6);

bTrans4:= fbArbiter1.CheckRequestInPool(ID4);//TransitionID
bAp41:= fbArbiter1.CheckRequestInPool(ID4+1);
bAp42:= fbArbiter1.CheckRequestInPool(ID4+2);
bAp43:= fbArbiter1.CheckRequestInPool(ID4+3);
bAp44:= fbArbiter1.CheckRequestInPool(ID4+4);
bTrans3X:= fbArbiter1.CheckRequestInPool(ID4+5);
bAp4XS:= fbArbiter1.CheckRequestInPool(ID4+6);


rtRemove(CLK:= bRemove);
if (rtRemove.Q) THEN
     GVL_PMPS.fbArbiter1.RemoveRequest(nReqRM);
    //GVL_ILK.fbArbiter2.RemoveRequest(nReqRM);
END_IF

END_PROGRAM
Related:

PRG_Transmission

PROGRAM PRG_Transmission
VAR
    arr_COEF_Table_Ar                       : ARRAY[1..50,1..2] OF FLOAT;
    arr_COEF_Table_N2                       : ARRAY[1..40,1..2] OF FLOAT;


    fbCTRL_LIN_INTERPOLATION_Ar                                     : FB_CTRL_LIN_INTERPOLATION;
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar      : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    fbCTRL_LIN_INTERPOLATION_N2                                     : FB_CTRL_LIN_INTERPOLATION;
    stCTRL_LIN_INTERPOLATION_PARAMS_N2      : ST_CTRL_LIN_INTERPOLATION_PARAMS;
    eMode                                                   : E_CTRL_MODE;
    bInit: BOOL :=TRUE;



    FFO    :    FB_FastFault :=(
    i_DevName := 'AT1K0-GAS',
    i_Desc := 'Fault occurs when the PMPS mode is switched off',
    i_TypeCode := 16#AAFF);
END_VAR
VAR CONSTANT
    rGasCellLength : REAL:= 1450.696;
    iTorr: INT :=750;
    rR_Ar:REAL := 1.66e-3;
    rR_N2:REAL := 1.16e-3;
END_VAR
A_INIT();

(*Calculate current transmission value*)
IF ( SelectedGas = E_GasType.Argon) THEN
        rCalculatedTransmissionValue := EXP(-fbCTRL_LIN_INTERPOLATION_Ar.fOut*(GCM_82.rPRESS/iTorr)*rR_Ar*rGasCellLength);
    ELSE
        rCalculatedTransmissionValue := EXP(-fbCTRL_LIN_INTERPOLATION_N2.fOut*(GCM_82.rPRESS/iTorr)*rR_N2*rGasCellLength);
END_IF
Cur_Trans.nTran:= TO_REAL(rCalculatedTransmissionValue*PMPS_GVL.TRANS_SCALING_FACTOR);

(*Calculate Pressure setpoint from requested transmission value*)
IF NOT (PMPS_GVL.TRANS_SCALING_FACTOR = 0) THEN
    rRequestedTransmission := (TO_REAL(Req_Trans.nTran)/PMPS_GVL.TRANS_SCALING_FACTOR);
END_IF

(*Transmission Request selection*)
IF (xPMPSMode) THEN
    xPressureControlMode := FALSE;
    IF NOT (PMPS_GVL.TRANS_SCALING_FACTOR = 0) THEN TransmissionValue := (TO_REAL(Req_Trans.nTran)/PMPS_GVL.TRANS_SCALING_FACTOR); END_IF
    rTransmissionSP :=  LIMIT(0.00000000001,TransmissionValue,1);
    ELSE TransmissionValue := LIMIT(0.00000000001,rTransmissionSP,1);
END_IF
// Set Status to the arbiter
stStatus.PMPSMode:= xPMPSMode;
stStatus.LocalMode := NOT(xPMPSMode);


IF ( SelectedGas = E_GasType.Argon) THEN
       if (fbCTRL_LIN_INTERPOLATION_Ar.fOut <>0) THEN
        rRequiredPressureSP := (-LN(TransmissionValue)/(fbCTRL_LIN_INTERPOLATION_Ar.fOut*rR_Ar*rGasCellLength))*iTorr;
        END_IF
    ELSE
        IF (fbCTRL_LIN_INTERPOLATION_N2.fOut <>0) THEN
            rRequiredPressureSP := (-LN(TransmissionValue)/(fbCTRL_LIN_INTERPOLATION_N2.fOut*rR_N2*rGasCellLength))*iTorr;
        END_IF

END_IF


(*FAST FAULT*)
FFO(i_xOK := xPMPSMode,
    i_xReset := ,
    i_xAutoReset := TRUE,
    io_fbFFHWO := GVL_PMPS.g_FastFaultOutput1);

END_PROGRAM

ACTION A_INIT:
IF bInit
THEN


    (* init array with the interpolation points  *)
    (*      fIn             (eV)                     |              fOut (mass coefficient)         *)

    (*X-Ray Mass Attenuation Coefficients for N2*)
    arr_COEF_Table_N2[1,1]:=201.37;    arr_COEF_Table_N2[1,2]:=7840.7;
    arr_COEF_Table_N2[2,1]:=215.2655;    arr_COEF_Table_N2[2,2]:=6694.2;
    arr_COEF_Table_N2[3,1]:=230.1188;    arr_COEF_Table_N2[3,2]:=5711.5;
    arr_COEF_Table_N2[4,1]:=245.997;    arr_COEF_Table_N2[4,2]:=4870.1;
    arr_COEF_Table_N2[5,1]:=262.9708;    arr_COEF_Table_N2[5,2]:=4150.6;
    arr_COEF_Table_N2[6,1]:=281.1158;    arr_COEF_Table_N2[6,2]:=3535.8;
    arr_COEF_Table_N2[7,1]:=300.5128;    arr_COEF_Table_N2[7,2]:=3011;
    arr_COEF_Table_N2[8,1]:=321.2482;    arr_COEF_Table_N2[8,2]:=2563.3;
    arr_COEF_Table_N2[9,1]:=343.4143;    arr_COEF_Table_N2[9,2]:=2181.6;
    arr_COEF_Table_N2[10,1]:=367.1099;    arr_COEF_Table_N2[10,2]:=1856.4;
    arr_COEF_Table_N2[11,1]:=392.4405;    arr_COEF_Table_N2[11,2]:=1579.5;
    arr_COEF_Table_N2[12,1]:=393.568;    arr_COEF_Table_N2[12,2]:=1568.6;
    arr_COEF_Table_N2[13,1]:=399.592;    arr_COEF_Table_N2[13,2]:=1511.9;
    arr_COEF_Table_N2[14,1]:=401.1984;    arr_COEF_Table_N2[14,2]:=1497.3;
    arr_COEF_Table_N2[15,1]:=403.608;    arr_COEF_Table_N2[15,2]:=30009;
    arr_COEF_Table_N2[16,1]:=409.632;    arr_COEF_Table_N2[16,2]:=29063;
    arr_COEF_Table_N2[17,1]:=419.5189;    arr_COEF_Table_N2[17,2]:=27603;
    arr_COEF_Table_N2[18,1]:=448.4657;    arr_COEF_Table_N2[18,2]:=23892;
    arr_COEF_Table_N2[19,1]:=479.4098;    arr_COEF_Table_N2[19,2]:=20593;
    arr_COEF_Table_N2[20,1]:=512.4891;    arr_COEF_Table_N2[20,2]:=17652;
    arr_COEF_Table_N2[21,1]:=547.8508;    arr_COEF_Table_N2[21,2]:=15059;
    arr_COEF_Table_N2[22,1]:=585.6525;    arr_COEF_Table_N2[22,2]:=12797;
    arr_COEF_Table_N2[23,1]:=626.0625;    arr_COEF_Table_N2[23,2]:=10838;
    arr_COEF_Table_N2[24,1]:=669.2609;    arr_COEF_Table_N2[24,2]:=9153.6;
    arr_COEF_Table_N2[25,1]:=715.4399;    arr_COEF_Table_N2[25,2]:=7711.4;
    arr_COEF_Table_N2[26,1]:=764.8052;    arr_COEF_Table_N2[26,2]:=6482.3;
    arr_COEF_Table_N2[27,1]:=817.5768;    arr_COEF_Table_N2[27,2]:=5438.6;
    arr_COEF_Table_N2[28,1]:=873.9896;    arr_COEF_Table_N2[28,2]:=4555.2;
    arr_COEF_Table_N2[29,1]:=934.2948;    arr_COEF_Table_N2[29,2]:=3809.4;
    arr_COEF_Table_N2[30,1]:=998.7612;    arr_COEF_Table_N2[30,2]:=3181.2;
    arr_COEF_Table_N2[31,1]:=1067.676;    arr_COEF_Table_N2[31,2]:=2651;
    arr_COEF_Table_N2[32,1]:=1141.345;    arr_COEF_Table_N2[32,2]:=2206.1;
    arr_COEF_Table_N2[33,1]:=1220.098;    arr_COEF_Table_N2[33,2]:=1833.6;
    arr_COEF_Table_N2[34,1]:=1304.285;    arr_COEF_Table_N2[34,2]:=1522.5;
    arr_COEF_Table_N2[35,1]:=1394.281;    arr_COEF_Table_N2[35,2]:=1263.2;
    arr_COEF_Table_N2[36,1]:=1490.486;    arr_COEF_Table_N2[36,2]:=1047.3;
    arr_COEF_Table_N2[37,1]:=1593.329;    arr_COEF_Table_N2[37,2]:=867.89;
    arr_COEF_Table_N2[38,1]:=1703.269;    arr_COEF_Table_N2[38,2]:=715.55;
    arr_COEF_Table_N2[39,1]:=1820.795;    arr_COEF_Table_N2[39,2]:=589.6;
    arr_COEF_Table_N2[40,1]:=1946.43;    arr_COEF_Table_N2[40,2]:=485.83;

    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS_N2.tCtrlCycleTime                                       := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_N2.tTaskCycleTime                                       := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_N2.nDataTable_NumberOfRows              := INT_TO_UINT(40);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS_N2.pDataTable_ADR                       := ADR(arr_COEF_Table_N2);
    stCTRL_LIN_INTERPOLATION_PARAMS_N2.nDataTable_SIZEOF            := SIZEOF(arr_COEF_Table_N2);

    (*X-Ray Mass Attenuation Coefficients for Ar*)
    arr_COEF_Table_Ar[1,1]:=201.3709;    arr_COEF_Table_Ar[1,2]:=6332.4;
    arr_COEF_Table_Ar[2,1]:=215.2655;    arr_COEF_Table_Ar[2,2]:=5911.6;
    arr_COEF_Table_Ar[3,1]:=230.1188;    arr_COEF_Table_Ar[3,2]:=5492.2;
    arr_COEF_Table_Ar[4,1]:=240.296;    arr_COEF_Table_Ar[4,2]:=5153.8;
    arr_COEF_Table_Ar[5,1]:=242.354;    arr_COEF_Table_Ar[5,2]:=5083;
    arr_COEF_Table_Ar[6,1]:=243.974;    arr_COEF_Table_Ar[6,2]:=5028;
    arr_COEF_Table_Ar[7,1]:=244.9548;    arr_COEF_Table_Ar[7,2]:=4995;
    arr_COEF_Table_Ar[8,1]:=245.997;    arr_COEF_Table_Ar[8,2]:=50587;
    arr_COEF_Table_Ar[9,1]:=246.0635;    arr_COEF_Table_Ar[9,2]:=50556;
    arr_COEF_Table_Ar[10,1]:=246.426;    arr_COEF_Table_Ar[10,2]:=50385;
    arr_COEF_Table_Ar[11,1]:=247.0527;    arr_COEF_Table_Ar[11,2]:=50090;
    arr_COEF_Table_Ar[12,1]:=248.5365;    arr_COEF_Table_Ar[12,2]:=71652;
    arr_COEF_Table_Ar[13,1]:=250.104;    arr_COEF_Table_Ar[13,2]:=70616;
    arr_COEF_Table_Ar[14,1]:=252.246;    arr_COEF_Table_Ar[14,2]:=69234;
    arr_COEF_Table_Ar[15,1]:=262.9708;    arr_COEF_Table_Ar[15,2]:=62861;
    arr_COEF_Table_Ar[16,1]:=281.1158;    arr_COEF_Table_Ar[16,2]:=53865;
    arr_COEF_Table_Ar[17,1]:=300.5128;    arr_COEF_Table_Ar[17,2]:=46248;
    arr_COEF_Table_Ar[18,1]:=313.6;    arr_COEF_Table_Ar[18,2]:=41979;
    arr_COEF_Table_Ar[19,1]:=318.4;    arr_COEF_Table_Ar[19,2]:=40556;
    arr_COEF_Table_Ar[20,1]:=319.68;    arr_COEF_Table_Ar[20,2]:=40189;
    arr_COEF_Table_Ar[21,1]:=321.2482;    arr_COEF_Table_Ar[21,2]:=44258;
    arr_COEF_Table_Ar[22,1]:=321.6;    arr_COEF_Table_Ar[22,2]:=44155;
    arr_COEF_Table_Ar[23,1]:=326.4;    arr_COEF_Table_Ar[23,2]:=42786;
    arr_COEF_Table_Ar[24,1]:=343.4143;    arr_COEF_Table_Ar[24,2]:=38407;
    arr_COEF_Table_Ar[25,1]:=367.1099;    arr_COEF_Table_Ar[25,2]:=33319;
    arr_COEF_Table_Ar[26,1]:=392.4405;    arr_COEF_Table_Ar[26,2]:=28856;
    arr_COEF_Table_Ar[27,1]:=419.5189;    arr_COEF_Table_Ar[27,2]:=24938;
    arr_COEF_Table_Ar[28,1]:=448.4657;    arr_COEF_Table_Ar[28,2]:=21501;
    arr_COEF_Table_Ar[29,1]:=479.4098;    arr_COEF_Table_Ar[29,2]:=18493;
    arr_COEF_Table_Ar[30,1]:=512.4891;    arr_COEF_Table_Ar[30,2]:=15863;
    arr_COEF_Table_Ar[31,1]:=547.8508;    arr_COEF_Table_Ar[31,2]:=13574;
    arr_COEF_Table_Ar[32,1]:=585.6525;    arr_COEF_Table_Ar[32,2]:=11589;
    arr_COEF_Table_Ar[33,1]:=626.0625;    arr_COEF_Table_Ar[33,2]:=9873.1;
    arr_COEF_Table_Ar[34,1]:=669.2609;    arr_COEF_Table_Ar[34,2]:=8394.2;
    arr_COEF_Table_Ar[35,1]:=715.4399;    arr_COEF_Table_Ar[35,2]:=7123.6;
    arr_COEF_Table_Ar[36,1]:=764.8052;    arr_COEF_Table_Ar[36,2]:=6035.4;
    arr_COEF_Table_Ar[37,1]:=817.5768;    arr_COEF_Table_Ar[37,2]:=5105.8;
    arr_COEF_Table_Ar[38,1]:=873.9896;    arr_COEF_Table_Ar[38,2]:=4313.6;
    arr_COEF_Table_Ar[39,1]:=934.2948;    arr_COEF_Table_Ar[39,2]:=3639.9;
    arr_COEF_Table_Ar[40,1]:=998.7612;    arr_COEF_Table_Ar[40,2]:=3068.4;
    arr_COEF_Table_Ar[41,1]:=1067.676;    arr_COEF_Table_Ar[41,2]:=2558;
    arr_COEF_Table_Ar[42,1]:=1141.345;    arr_COEF_Table_Ar[42,2]:=2133.7;
    arr_COEF_Table_Ar[43,1]:=1220.098;    arr_COEF_Table_Ar[43,2]:=1781.3;
    arr_COEF_Table_Ar[44,1]:=1304.285;    arr_COEF_Table_Ar[44,2]:=1486.6;
    arr_COEF_Table_Ar[45,1]:=1394.281;    arr_COEF_Table_Ar[45,2]:=1238;
    arr_COEF_Table_Ar[46,1]:=1490.486;    arr_COEF_Table_Ar[46,2]:=1031.9;
    arr_COEF_Table_Ar[47,1]:=1593.329;    arr_COEF_Table_Ar[47,2]:=861.03;
    arr_COEF_Table_Ar[48,1]:=1703.269;    arr_COEF_Table_Ar[48,2]:=719.19;
    arr_COEF_Table_Ar[49,1]:=1820.795;    arr_COEF_Table_Ar[49,2]:=601.34;
    arr_COEF_Table_Ar[50,1]:=1946.43;    arr_COEF_Table_Ar[50,2]:=503.35;

    (* init parameter struct *)
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar.tCtrlCycleTime                                       := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar.tTaskCycleTime                                       := T#10ms;
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar.nDataTable_NumberOfRows              := INT_TO_UINT(50);

    (* set the addresses *)
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar.pDataTable_ADR                       := ADR(arr_COEF_Table_Ar);
    stCTRL_LIN_INTERPOLATION_PARAMS_Ar.nDataTable_SIZEOF            := SIZEOF(arr_COEF_Table_Ar);

    (* set the mode to ACTIVE --> normal operation *)
    eMode                                                   := eCTRL_MODE_ACTIVE;

    (* reset the init flag *)
    bInit                                                   := FALSE;
END_IF




fbCTRL_LIN_INTERPOLATION_Ar(
    fIn:= rPhotonEnergy ,
    fManValue:= 1 ,
    bExtrapolate:= TRUE,
    eMode:= eMode,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS_Ar,
    fOut=> ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> );

fbCTRL_LIN_INTERPOLATION_N2(
    fIn:= rPhotonEnergy ,
    fManValue:= 1 ,
    bExtrapolate:= TRUE,
    eMode:= eMode,
    stParams:= stCTRL_LIN_INTERPOLATION_PARAMS_N2,
    fOut=> ,
    bInIsGreaterThanMaxElement=> ,
    bInIsLessThanMinElement=> ,
    eState=> ,
    eErrorId=> ,
    bError=> );
END_ACTION
Related:

PRG_VGP

PROGRAM PRG_VGP
VAR
    arrTable                                                                                        : ARRAY[1..14,1..2] OF FLOAT;
    arrTable_ENC                                                                            : ARRAY[1..14,1..2] OF FLOAT;

    bInit: BOOL:=true;

    VGP_REQ_POS: LREAL;
    VGP_OUT_POS:LREAL;
END_VAR
IF bInit
THEN


    (* init array with the interpolation points  *)
    (*      fIn                                      |              fOut            *)
    arrTable[1,1] := 0;                     arrTable[1,2] := 0;
    arrTable[2,1] := 5;                 arrTable[2,2] := 160;
    arrTable[3,1] := 10;            arrTable[3,2] := 270;
    arrTable[4,1] :=  20;       arrTable[4,2] := 435;
    arrTable[5,1] :=  30;       arrTable[5,2] := 570;
    arrTable[6,1] := 40;            arrTable[6,2] := 720;
    arrTable[7,1] := 50;            arrTable[7,2] := 854;
    arrTable[8,1] := 60;        arrTable[8,2] := 980;
    arrTable[9,1] := 70;        arrTable[9,2] := 1120;
    arrTable[10,1] := 80;           arrTable[10,2] := 1270;
    arrTable[11,1] := 90;           arrTable[11,2] := 1430;
    arrTable[12,1] := 95;           arrTable[12,2] := 1540;
    arrTable[13,1] := 98;           arrTable[13,2] := 1595;
    arrTable[14,1] := 100;          arrTable[14,2] := 1680;


    (* reset the init flag *)
    bInit                                                   := FALSE;
END_IF

VGP_80.i_xOpenIlkOK := (fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpRUNNING) ;

VGP_80(
    i_xExtIlkOK:=(fb_AT1K0_GAS_PTM_80.iq_stPtm.eState = pumpRUNNING),
    i_ReqPos:=  ,
    arrTable:= arrTable ,
    q_stVGP=> );

END_PROGRAM