Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Looping through methods/fbs

somlioy
2018-03-16
2018-04-15
  • somlioy - 2018-03-16

    Hello

    I have initiated a function block several times and want to loop through to check for a variable.

    VAR CONSTANT
       numOfGensets      : BYTE := 2;
    END_VAR
    VAR
       gen1, gen2      : fbGenset;
       gensets         : ARRAY[1..numOfGensets] OF fbGenset := [gen1, gen2];
    END_VAR;
    .... Main prog....
    gen1();
    gen2();
    // Loop through all initiated gensets
    FOR i := 1 TO numOfGensets DO
       IF gensets[i].breakerStatus() = BREAKER_STATUS.TRIPPED THEN
          tripped := TRUE;
       END_IF
    END_FOR
    
    METHOD breakerStatus : BREAKER_STATUS
    // Check status of circuit breaker/generator breaker
    IF closed THEN
       breakerStatus := BREAKER_STATUS.CLOSED; // Closed
    ELSIF NOT closed THEN
       breakerStatus := BREAKER_STATUS.OPEN; // Open
    ELSIF tripped THEN
       breakerStatus := BREAKER_STATUS.TRIPPED; // Tripped
    END_IF
    

    This dosent work as desired as gen1 and gen2 isnt updated cyclically in the array.
    How should this be done the proper way without having to update the array every scan?

     
  • Anonymous - 2018-03-16

    Originally created by: Viacheslav Mezentsev

    program PLC_PRG
    var constant    
        numOfGensets: byte := 2;
    end_var
    var
        i: byte;
        gen1, gen2: ton; 
        gensets: array [ 1 .. numOfGensets ] of pointer to ton := [ adr( gen1 ), adr( gen2 ) ];   
    end_var
    // ------------------
    gen1( pt := t#10s );
    gen2( pt := t#20s );
    // Loop through all initiated gensets
    for i := 1 TO numOfGensets do
        
       if gensets[i]^.pt = t#10s then gensets[i]^.pt := t#55s; end_if
       
    end_for
    
     
  • somlioy - 2018-03-16

    Brilliant, thanks!

     
  • somlioy - 2018-03-28

    New but similar question.

    Assume two FBs where FB_B extends FB_A.

    Lets say I have declared some instances of FB_B and a few of FB_A.

    How can I loop through all of the declared instances of both FB_B and FB_A to do something thats declared in FB_A?


    Question 2:
    Is it possible to have a variable shared between declared instances, not beeing in a GVL?

     
  • Anonymous - 2018-03-29

    Originally created by: Viacheslav Mezentsev

    Zitat:
    How can I loop through all of the declared instances of both FB_B and FB_A to do something thats declared in FB_A?

    Online help.

    METHOD FB_Init : BOOL
    VAR_INPUT
      bInitRetains : BOOL; // TRUE: the Retain-variables are initialized (reset warm / reset cold)
      bInCopyCode : BOOL;  // TRUE  the instance will be copied to the copy-code afterward (online change)
    END_VAR
    

    Zitat:
    Is it possible to have a variable shared between declared instances, not beeing in a GVL?

    It is possible, but why you need this? (you can use var_stat... end_var in FB_A)

    function_block FB_A
    var_input
        value: int := 0;    
    end_var
    var_stat
        m_index: int := 0;
        m_instances: array [ 0 .. 1000 ] of pointer to FB_A;
    end_var
    -----------------------
    method public FB_Init : bool
    var_input
        bInitRetains : bool; // initializing of retain-variable
        bInCopyCode : bool; // instance is copied to copy-code
    end_var
    m_instances[ m_index ] := this;
    m_index := m_index + 1;
    -----------------------
    method GetInstAt : pointer to FB_A
    var_input
        index: int;
    end_var
    GetInstAt := m_instances[ index ];
    -----------------------
    function_block FB_B extends FB_A
    -----------------------
    program PLC_PRG
    var
        bFirstCycle: bool := true;
        f1: FB_A;
        f2, f3, f4: FB_B;
        p: pointer to FB_A;
    end_var
    if bFirstCycle then
        f1.value := 1;
        f2.value := 2;
        f3.value := 3;
        p := f1.GetInstAt(3);
        if p <> 0 then p^.value := 4; end_if // Check f4.value online
        bFirstCycle := false;
        
    end_if
    
     
  • somlioy - 2018-04-02

    Hmm. Ok. Not sure how to do that.

    Reason behind the looping is to monitor the state of a variable in FB_A (aswell as FB_B which extends FB_A). Normally I'd do this as proposed by you in a earlier post, but this dosent work when I also need to include both FB_B and FB_A.

    Reasons behind shared variable is because I want a interlock between declared instances. Say FB_A has a method for controlling something external (relay for example) and if any of FB_A (aswell as FB_B which extends FB_A) has this output active none of the others shouldnt be able to actuate the external output.

    Maybe you have a better solution to this?

     
  • Anonymous - 2018-04-04

    Originally created by: Viacheslav Mezentsev

    There is a library with synchronization elements: with BOLT and SEMA. To use them you need to know more precisely what you want.

    Interlocking - what does this mean in your opinion? How should this work? Other fbs must wait or do nothing or return error state?

     
  • somlioy - 2018-04-04

    Each FB has a variable to start a sequence (action), if any of the FBs has say "BREAKER_STATUS.CLOSED" active (from first post), then the others should not be able to activate the closing sequence.

     
  • somlioy - 2018-04-15

    Any more tips?

     

Log in to post a comment.