CALC block

Hi,

Is it possible to change the out(n) of a CALC block with 16 outputs based on an Input?

‘OUT(‘IN1.CV’).CV’ := ‘IN2.CV’;

Thanks

  • Best I can tell is with IF statements:

    IF IN1 = 1 THEN

    OUT1 := IN2;

    ENDIF;

    IF IN1 = 2 THEN

    OUT2 := IN2;

    ENDIF;

    etc.

  • Not as you have indicated. The out parameters are not an array, but are individual parameters.

    You cannot use the syntax indicated above. You'll have to have an explicit assign statement. Use IF THEN logic to conditionally execute the statement needed: IF IN1 = 1 then OUT1 := IN2 end if.

    Andre Dicaire

  • In reply to Andre Dicaire:

    Andre,
    I was hoping for another way to turn multiple lines into one but it doesn’t sound like it.
    Thanks for confirming.
  • Hi
    You can send the modified (*) number to one Calc:Output, connect it to a BFI module input and then getting equivalent 16 bits output.
    (*) BFI use 2^ numbers. So, you only have to send 2^n to the output (where 'n' is your number).
  • In reply to Jack_France:

    Hi Jack,
    I was hoping to do this using a single CALC block with IN1 as the output selector. It doesn’t sound like it can be done without using a bunch of if statements.
  • You can use dynamical reference or floating point aray (in special items) using pointers you can something write and next read.
  • Hi

    For the fun, here is one solution using Dynamic Reference input parameter named "OUT_NUMBER" (place this parameter at the same level as the CALC block, in your Module)

    Calc expression :

    Rem Init all OUT
    'OUT1.CV' := 0;
    'OUT2.CV' := 0;
    'OUT3.CV' := 0;
    'OUT4.CV' := 0;
    'OUT5.CV' := 0;
    'OUT6.CV' := 0;
    'OUT7.CV' := 0;
    'OUT8.CV' := 0;
    'OUT9.CV' := 0;
    'OUT10.CV' := 0;
    'OUT11.CV' := 0;
    'OUT12.CV' := 0;
    'OUT13.CV' := 0;
    'OUT14.CV' := 0;
    'OUT15.CV' := 0;
    'OUT16.CV' := 0;

    Rem Prepare dynamicreference
    '^/OUT_NUMBER.$REF' := "^/CALC1/OUT" + 'IN1.CV' + ".CV";

    Rem If Dynamic Reference link is established
    If '^/OUT_NUMBER.ST' = 128 Then
     Rem Active the designed OUT
      '^/OUT_NUMBER.CV' := 1;
    EndIf;

  • In reply to Jack_France:

    Hi Jack,

    Once I changed '^/OUT_NUMBER.CV' := 1; To '^/OUT_NUMBER.CV' := 'IN2.CV'; It did what I was looking for.

    Thank you.
  • In reply to RJA:

    Remember that you can create a complex module using CALC, BFI and so on, and save it as a new custom block that you can insert in your real modules.
    So, the use of a single CALC is not a ultimate target.
  • In reply to RJA:

    I'm curious to know exactly what you were trying to accomplish. From what I can tell, you have a single input that based on some logic, you would like to assign this value to one of 16 Outputs? What is to happen to the Outputs that are not currently selected? Should there status change to Constant? How should the block initialize after download or a power fail?

    When setting the $ref of a dynamic reference, the parameter takes time to bind, and as such, I'm thinking you have to build logic to confirm the parameter is bound before you write to it. If you don't, you might see a write error reported when changing the reference, depending on how you configured error reporting in the MStatus, MError masks.

    There may be other ways to do what you need. Also, be sure to handle status properly.

    I tried a couple of approaches for fun. :-)

    It is quite easy to do with a FP Array, however, what do you do with the array after? Here is the code to both initialize the array, which is a 16 row by 2 column array. I store the Input and its status in each location during initialization and then update the selected pair during normal operation. Status propagates. If we don't care for status, we can cut the array to one column and delete the Status commands.

    rem Set all OUT values equal to INPUT if Initialize bit is true.

    IF '^/INITIALIZE'THEN

    i:= 0;
    while i <= 16 do
    '^/FP_ARRAY'[i][1] := '^/INPUT.CV';
    '^/FP_ARRAY'[i][2] := '^/INPUT.ST';
    i := i +1;
    end_while;
    LAST_SELECT := 0;

    '^/INITIALIZE' := FALSE;

    ELSE;
    rem Set Array value equal to INPUT value and status, based on SELECT number

    If '^/SELECT' >16 THEN
    '^/SELECT' := LAST_SELECT;
    ENDIF;
    IF '^/SELECT' > 0 THEN
    '^/FP_ARRAY' ['^/SELECT'][1] := '^/INPUT.CV';
    '^/FP_ARRAY' ['^/SELECT'][2] := '^/INPUT.ST';
    ENDIF;
    LAST_SELECT := '^/SELECT.CV';
    ENDIF;

    However, I cannot use parameter reference paths to read individual cells of the array to connect to another function block. I can read the array from expressions or displays. So, to have the data available in a parameter, I have to create 16 Float with status parameters and write the values from the Array to these parameters.

    REM Update OUT parameters from Array values

    '^/OUT1.CV' := '^/FP_ARRAY' [1][1];
    '^/OUT1.ST' := '^/FP_ARRAY' [1][2];
    '^/OUT2.CV' := '^/FP_ARRAY' [2][1];
    '^/OUT2.ST' := '^/FP_ARRAY' [2][2];
    '^/OUT3.CV' := '^/FP_ARRAY' [3][1];
    '^/OUT3.ST' := '^/FP_ARRAY' [3][2];
    '^/OUT4.CV' := '^/FP_ARRAY' [4][1];
    '^/OUT4.ST' := '^/FP_ARRAY' [4][2];
    '^/OUT5.CV' := '^/FP_ARRAY' [5][1];
    '^/OUT5.ST' := '^/FP_ARRAY' [5][2];
    '^/OUT6.CV' := '^/FP_ARRAY' [6][1];
    :
    :
    and so on.

    This is a more efficient expression in terms of memory, but I execute 18 parameter writes per scan. So it takes a bit more CPU.

    I built an expression with IF statements which is much bigger in memory, but executes a pair of writes, and 16 If statements. slightly less CPU.

    They are approximately 150 to 200 usec of execution time.

    But since there are no dynamic references, I save on checking for parameter binding.

    Interesting exercise. Noticed two fun facts about arrays in BOL.
    - An array bigger than 200 cells will not update to the redundant controller.
    - Arrays update every 10 seconds to workstations.

    happy new year....

    Andre Dicaire

  • In reply to Andre Dicaire:

    Good morning all and Happy New Year!

    Andre, I don’t have any immediate plans for this CALC block. It is more of a learning thing and first time use of the website. Thank you all for your ideas and advice!