Using function block outputs to select global variables

2012-05-10
2012-06-21
  • AusEngineer - 2012-05-10

    Hi guys,
    This is a similar problem to the one found here:
    http://forum-en.3s-software.com/viewtopic.php?t=1544
    However I can't get the pointer solution to work for me. The only requirement for this project is that the main program be coded using FBD.
    A small sample of the code used in my function block is as follows:

    FUNCTION_BLOCK Var_Select
    VAR_INPUT
    Local_Input1:BOOL;
    Local_Input2: BOOL;
    END_VAR
    VAR_OUTPUT
    Local_Output1:BOOL;
    Local_Output2:BOOL;
    END_VAR
    VAR
    END_VAR
    IF Local_Input1=TRUE THEN
    Local_Output1:=Global_Var1; (*just want it to take the address of Global_Var1*)
    ELSIF Local_Input2:= TRUE THEN
    Local_Output2:=Global_Var2;
    END_IF
    

    Then I try to implement in FBD as shown in the image "CodeSys Problem1" attached.
    BUT when I simulate I get unknown values as shown in attached image "CodeSys Problem 2".

    I want/expect the following to happen:
    - Set Global_Var3 high
    - Local_Input1 goes high and in turn assigns Local_Output1 to Global_Var1
    - Global_Var1 passes its value to program variable Local_Var1
    - I can then use Local_Var1 throughout my program and it will have the value of Global_Var1

    Can I even pass different variables across the inputs and outputs of my FB??
    Is there some other way I can do this? Blank canvas for this project just need to use FBD language.

    Thanks in advance for your help. Need to overcome this 'variable selection' hurdle because the rest of my program becomes relatively simple with it.

    Regards,
    N

    IMG: Codesys problem2.png

    IMG: Codesys problem1.png

     
  • shooter - 2012-05-10

    you are mixing types of variables.

    you can use the FB SEL from standard.lib
    or the CASE also standard

     
  • AusEngineer - 2012-05-17

    Hi Shooter,

    Thanks for your response. I tried using the FB SEL which is good except in my actual program I need to be able to assign a local variable one of 4 global variables based on the input, and SEL only allows me to choose one of 2. Is there another FB I can use? or is there some way to modify SEL to allow me to select from more than two inputs?

    Also I'm not sure how to use CASE or WHILE in FBD.. All the 3S documentation I can find only explains it in ST. When I put a box in my program and call it CASE or WHILE it will only let me assign outputs. Could you please explain how to use these instructions in FBD?

    Here is some of the actual code I was trying to use in my FUNCTION_BLOCK.
    To begin the application one of four inputs is activated. Based on which input goes high I want to deal with a specific set of global variables.

    IF MOTOR1_START=TRUE THEN
       START_READY:=START1_READY;
       START_OPEN:=START1_OPEN;
       START_CLOSED:=START1_CLOSED;
       OPEN_START:=OPEN_START1;
       CLOSE_START:=CLOSE_START1;
    ELSIF MOTOR2_START=TRUE THEN
       START_READY:=START2_READY;
       START_OPEN:=START2_OPEN;
       START_CLOSED:=START2_CLOSED;
       OPEN_START:=OPEN_START2;
       CLOSE_START:=CLOSE_START2;
    ELSIF MOTOR3_START=TRUE THEN
       START_READY:=START3_READY;
       START_OPEN:=START3_OPEN;
       START_CLOSED:=START3_CLOSED;
       OPEN_START:=OPEN_START3;
       CLOSE_START:=CLOSE_START3;
    ELSIF MOTOR4_START=TRUE THEN
       START_READY:=START4_READY;
       START_OPEN:=START4_OPEN;
       START_CLOSED:=START4_CLOSED;
       OPEN_START:=OPEN_START4;
       CLOSE_START:=CLOSE_START4;
    END_IF   
    

    Thankyou.

    -AusEngineer

     
  • shooter - 2012-05-17

    as there is not an easy way to make it with if then i made a function block containing your ST code.
    It is possible to make it with SEL too but it is more lines

    20120517 motor.pro [28.77 KiB]

     
  • spfeif - 2012-06-11

    Create a structure: This is not good programming practice as you noticed you copied the same data over and over but just added a 1 or 4 to the data. It should be rolled into a reusable class.

    I assumed they are boolean since there is no indication of variable type. This was very fat off the top of my head since I do not know the cirmumstances of the data.
    TYPE MOTOR_STATE :
    STRUCT
       START_READY :BOOL;
       START_OPEN  :BOOL;
       START_CLOSED:BOOL;
       OPEN_START  :BOOL;
       CLOSE_START :BOOL;
       xStart      :BOOL;
    END_STRUCT
    END_TYPE
    Use this FUNCTION to set the data of the structure for each motor.
    FUNCTION MOTOR : MOTOR_STATE
    VAR_INPUT
       i_xSTART_READY:BOOL;
       i_xSTART_OPEN:BOOL;
       i_xSTART_CLOSED:BOOL;
       i_xOPEN_START:BOOL;
       i_xCLOSE_START:BOOL;
       i_xStart      :BOOL;
    END_VAR
    VAR
    END_VAR
    MOTOR.xStart      :=i_xStart;
    MOTOR.CLOSE_START :=i_xCLOSE_START;
    MOTOR.OPEN_START  := i_xOPEN_START;
    MOTOR.START_CLOSED := i_xSTART_CLOSED;
    MOTOR.START_OPEN   := i_xSTART_OPEN;
    MOTOR.START_READY  := i_xSTART_READY;
    Then select the motor with this block:
    FUNCTION MOTOR_SELECT : MOTOR_STATE
    VAR_INPUT
        atMotorState :ARRAY [1..4] OF MOTOR_STATE;
    END_VAR
    VAR
     i :INT;
    END_VAR
    FOR i:= 1 TO 4 DO
       IF (atMotorState[i].xStart = TRUE) THEN
           MOTOR_SELECT := atMotorState[i];
           EXIT;
       ELSE
           MOTOR_SELECT := atMotorState[i]
       END_IF
    END_FOR
    

    Just create a MOTOR class and select which class to use.

    FYI I am guessing and did this in like 2 minutes so it is very sloppy.

     
  • AusEngineer - 2012-06-21

    Hi Guys!

    Just wanted to post to say that I have figured out what I was doing wrong and it was very, very simple This is my first time using CodeSys so I am unfamiliar with the software.

    The problem was the way in which I was trying to simulate the program, not the coding itself. In fact my original code works perfectly when the software is operated correctly. My mistake when simulating was because I was activating simulation mode, loggining in, but not running the simulation (F5). THEN when simulating the program and trying to look inside the FB to monitor the data flow, I was looking inside the function block itself by double clicking it in the POU tree and not the instance inside my main program
    Working program is attached.

    To simualte correctly and see the FB work:
    Online -> Simulation
    Online -> Login
    Online -> Run
    POU tree -> double click PLC_PRG
    Resource tree -> Open global variables
    Global variables -> set MOTOR1_START
    PLC_PRG -> Double click MOTOR_SELECT_FB block
    Global variables -> set START1_READY (and any other variable associated with motor 1, i.e. CLOSE_RUN1)
    PLC_PRG -> START_READY and CLOSE_RUN are now set

    (to test with a second motor)
    Global variables -> set all to false.
    PLC_PRG -> START_READY and CLOSE_RUN are now reset to false
    Global variables -> set MOTOR4_START
    Global variables -> set START4_READY and CLOSE_RUN4
    PLC_PRG -> START_READY and CLOSE_RUN are now set again.

    In this way once a MOTORx_START signal is recieved its associated physical I/O will be assigned to the local variables within PLC_PRG, meaning whichever one of the four motors is selected the logic required to operate a motor only needs to run once.

    Hopefully this can help some other n00b who comes across a similar problem!

    Cheers,
    -N

    Motor_sel_FB_working.pro [49.48 KiB]

     
  • shooter - 2012-06-21

    to avoid all this selection i make a visualisation to check and to set vars.

    But yes this doubleclick system works for all instances, divide the screen in the global var list and your PLC_PRG doubleclick then you can see all different actions.
    It is even possible to have all instances at the screen.

     

Log in to post a comment.