s7-SCL-scripts/s7-1500/cylinder_control/FB_cylinder_adv.md

2.3 KiB

FUNCTION_BLOCK "FB_Cylinder_Adv" { S7_Optimized_Access := 'TRUE' } VERSION : 0.2 VAR_INPUT i_xCmdFwd : Bool; // Output Command Forward i_xCmdBcw : Bool; // Output Command Backward i_xFwdSensor : Bool; // DI: Physical Forward i_xBcwSensor : Bool; // DI: Physical Backward i_xSimMode : Bool; // TRUE = Ignore sensors, use internal simulation i_iSensorConfig : Int; // 0:None, 1:Fwd Only, 2:Bcw Only, 3:Both i_tMoveTime : Time := T#1s; // Expected travel time i_tTimeout : Time := T#2s; // Alarm threshold i_xReset : Bool; END_VAR

VAR_OUTPUT q_xFwdOut : Bool; q_xBcwOut : Bool; q_xAtFwd : Bool; q_xAtBcw : Bool; q_xError : Bool; // Timeout Alarm END_VAR

VAR s_tonFwd {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; s_tonBcw {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; s_tonWatchdog {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; END_VAR

BEGIN // 1. Directional Interlock q_xFwdOut := i_xCmdFwd AND NOT i_xCmdBcw; q_xBcwOut := i_xCmdBcw AND NOT i_xCmdFwd;

// 2. Simulation vs. Real Logic
s_tonFwd(IN := q_xFwdOut, PT := i_tMoveTime);
s_tonBcw(IN := q_xBcwOut, PT := i_tMoveTime);

IF i_xSimMode THEN
    // In simulation, we only care about the internal timers
    q_xAtFwd := s_tonFwd.Q;
    q_xAtBcw := s_tonBcw.Q;
ELSE
    // Real World Logic based on Config
    CASE i_iSensorConfig OF
        0: // No Sensors
            q_xAtFwd := s_tonFwd.Q;
            q_xAtBcw := s_tonBcw.Q;
        1: // Fwd Only
            q_xAtFwd := i_xFwdSensor;
            q_xAtBcw := s_tonBcw.Q;
        2: // Bcw Only
            q_xAtFwd := s_tonFwd.Q;
            q_xAtBcw := i_xBcwSensor;
        3: // Both Sensors
            q_xAtFwd := i_xFwdSensor;
            q_xAtBcw := i_xBcwSensor;
    END_CASE;
END_IF;

// 3. Watchdog Alarm (Trip if moving but not arriving)
s_tonWatchdog(IN := (q_xFwdOut AND NOT q_xAtFwd) OR (q_xBcwOut AND NOT q_xAtBcw), 
              PT := i_tTimeout);

IF s_tonWatchdog.Q THEN q_xError := TRUE; END_IF;
IF i_xReset THEN q_xError := FALSE; END_IF;

END_FUNCTION_BLOCK