Search code examples
plccodesys

R_TRIG, F_TRIG and TOF not working correctly


I have VARs declared

trigger_pos_sensor_left                 : BOOL;

trigger_ticks                           :   INT := 0;
trigger_sensor_rtrig                    :   R_TRIG;
trigger_sensor_ftrig                    :   F_TRIG;
delay_timer                             :   TOF;

Program is :

IF (re = FALSE )THEN
    trigger_sensor_rtrig(CLK := trigger_pos_sensor_left);
    trigger_sensor_ftrig(CLK := trigger_pos_sensor_left);
    delay_timer(IN := trigger_sensor_ftrig.Q, PT := T#10s);
    trigger_ticks := 5;

    re := TRUE;
END_IF

IF (trigger_sensor_rtrig.Q = TRUE) AND (delay_timer.Q = OFF) THEN
    trigger_ticks := trigger_ticks - 1;
END_IF

If I understand it correctly r_trig, f_trig and tof are set and "activated" in the first IF and then everytime trigger_pos_sensor_left is activated it should activate set trigger_sensor_rtrig.Q to true and then decrement trigger_ticks by one. It actually does nothing. Why?


Solution

  • If by "activated" you mean that they will execute the preset logic without you touching, then NO, you must execute the Function Block on every cycle for it to update the state.

    Let's check the example in the documentation for R_TRIG:

    (* Example declaration *)
    RTRIGInst : R_TRIG ;
    
    (* Example in ST *)
    RTRIGInst(CLK := VarBOOL1);
    VarBOOL2 := RTRIGInst.Q;
    

    Notice that the RTRIGInst(CLK := VarBOOL1); line is NOT enclosed in an if statement, it is executed on every cycle.

    Perhaps it would help you understand if we created our own R_TRIG block to show how it probably works under the hood:

    FUNCTION_BLOCK R_TRIG
      VAR_IN
        CLK: BOOL;
      VAR_END
      VAR_OUT
        Q: BOOL;
      VAT_END
      VAR
        _first_run: BOOL := TRUE;
        _last_clk: BOOL;
      VAR_END
    
    // implementation:
      IF _first_run THEN
        _first_run := FALSE;
        _last_clk := CLK; // this is so Q isn't set if the initial CLK value was TRUE
      END_IF
      
      Q := FALSE;
      
      IF _last_clk <> CLK THEN
        _last_clk := CLK;
        Q := CLK;
      END_IF
    
    FUNCTION_BLOCK_END
    

    As you can see in my reference implementation, the edge detection happens inside the Function Block, which is only executed when the Function Block is run. Hope this clarifies things.