using a string in a command line

Hi folks.

Quick question:

I have this script in a CALC block. I have two identical productions lines, with the same equipement name, except for the line number: 2211 and 2212.

Now, I have the operator select which line he's configuring.

Here's the sigle line example:

   '//2211-YV03/DC1/SP_D.CV' := 1; 
   '//2211-YV04/DC1/SP_D.CV' := 1;
   '//2211-YV06/DC1/SP_D.CV' := 1;

I would like to modify it for something like that:

if LINE_SEL = 1 then
 LINE := "2211";
else
 LINE := "2212";
endif;

   '//LINE-YV03/DC1/SP_D.CV' := 1; 
   '//LINE-YV04/DC1/SP_D.CV' := 1;
   '//LINE-YV06/DC1/SP_D.CV' := 1;

OF course, this doesn't work, as well as the two dozen other possibilities I've tried.

Any idea how to achieve this? Rather new to DeltaV, going to my training next week.

Regards,

Pierre.

  • Pierre,
    A slightly alternate way:
    Have three sets of parameters
    Set 1:
    Module-level parameters that point to the Line 1 parameters as external references (say, for example, LINE1_YV03_SP that points to //2211-YV03/DC1/SP_D)
    Set 2:
    Module-level parameters that point to the Line 2 parameters as external references (say, for example, LINE2_YV03_SP that points to //2212-YV03/DC1/SP_D)
    Set 3:
    Line-neutral parameters that are dynamic references (say, for example, YV03_SP)

    Have an ACT block (sequenced before the calc block) that activates on CHANGE of Line that assigns the dynamic references to point to either set 1 or set 2
    In the calc block, check the connection status (.CST) of the dynamic reference variables and, if 0, perform the actions.
    E.g.,        If '/YV03_SP.CST' = 0 Then '/YV03_SP' := 1;

    Benefits:
    The longest connection-establishing time (external reference) is already done at download.
    The 1-scan connection-establishing time (dynamic reference to in-module parameter) is only performed when needed, not every scan
    Variable names can be chosen that start with an alpha character
    No run-time errors occur trying to write to a variable whose connection has not been fully established. Note that it should only take 1 scan to establish the connection, even for sub-second modules.

    Cons:
    Using dynamic references in any way means that you cannot take an action on the same scan that the Line changes
    Processing time is going to be higher than using the multi-Line (multi-process lines, not multi-coding lines) calc with big IFs
            Need to establish dynamic references on Line Change
            Need to check for good connection in calc (can be omitted if willing the take the 1-scan errors)
    Uses a lot of variables. No impact on processing time, but uses memory


    Jack,
    If there is a limit of setting 5 dynamic references in an expression, it must be a new thing. From DeltaV 6.x through 10.x we have used expressions setting 11 dynamic references with no problems.
    Although, ours are dynamic references to internal parameters, so there may be a limit on how many dynamic external references you can make.

    Side note:
    Our local convention is to avoid having a module drill down into the innards of another module if at all possible. If MODULE_A needs to reference the PV of MODULE_B's DC1 block, we have a module-level parameter (say, PV) in MODULE_B that points to DC1/PV_D. MODULE_A would just reference MODULE_B/PV. If we ever need to change the internal structure of MODULE_B, we won't need to change MODULE_A.



    From:        "Jack_France" <bounce-Jack_France@community.emerson.com>
    To:        <DeltaV@community.emerson.com>
    Date:        03/13/2013 11:19 AM
    Subject:        RE: [EE365 DeltaV Track] using a string in a command line




    Hi Pierre

     

    Just for information because this way to proceed may be to heavy :

     

    To concatenate strings to provide a module path, you need to use Dynamic Reference.

    - Declare 3 input labels (ie named TARGET1 2 and 3) witch type will be "Dynamic Reference"

    - In your programm, prepare the modules path string like you do with the LINE parameter + add the rest of complete syntax (1)

    - Wait for the connection of the 3 TARGET dynamic reference to be operational (2)

    - Then, you can use the TARGET label the same way you use a module path attribute :

        '^/TARGET1.CV' := 1;

        '^/TARGET2.CV' := 1;

        '^/TARGET3.CV' := 1;

    I think I remember that you cannot manipulate more than 5 dynamic reference labels at a time (in the same expression).

    Regards, Jack

     


    (1) String manupilation in a CALC expression is a little bit amazing sometimes because the compiler often preform an implicit conversion to numeric value.

    Your parameter contents must ALWAYS begin with an alphabetic sign (A/a to Z/z, space)

    If the first char is a numeric char, it will return 0 instead of the string.

    If you have this kind of problem, declare a new input label typed String and use it instead of the internal parameter. The rule about the fist char remains valid!

    Example of code :

        If LINE_SEL = 1 then

         LINE := "//2211";

        Else

         LINE := "//2212";

        EndIf;

        Rem I hope the heading double / will be read as a string ...

        '^/TARGET1.$REF' := LINE + "-YV03/DC1/SP_D.CV";

        '^/TARGET2.$REF' := LINE + "-YV04/DC1/SP_D.CV";

        '^/TARGET3.$REF' := LINE + "-YV06/DC1/SP_D.CV";


    (2) Waiting for dynamic reference connection :

    That's a problem in a CALC expression because you have to wait the next module scan to test it.

    You have to test that the .CST value to become = 0 on each TARGET 1, 2 and 3.

    So, you have to imagine a way to hold an OUT1 to 1 and connect it to an IN1 of the same CALC to know if you have to prepare le .$REF string values (when IN1 is 0), or if you have to test the .CST attributes to know if the connections succeed before assigning a value.

  • In reply to SBPosey:

    SBposey puts a twist on this with the external references.  It's actually a good idea if the modules are in remote controllers.  Here's why.  When a controller is downloaded, it knows about all the modules it is hosting, but nothing about all the other modules.   When a module needs a parameter from any of these local modules, the reference link is direct into the controller memory and the CST will resolve to good (0) instantly.  When the module is in a remote controller, the calling controller needs to find out where this module is.  This requires a broadcast to the "directory services" computer, typically the Pro Plus, to find what controller is hosting the remote module.  Once this is known, a Proxy Client/SErver connection is created.  This proxy client holds the module location information for any future parameter requests from this remote module to this controller.

    So when the Dynamic Reference is made for the first time, the connection is made to the Proxy Client, which has already been established.  If the Dynamic reference is to a different parameter, the CST will take up to 200 ms to clear as the parameter is requested and added to the Proxy server in the remote controller.

    External References and Dynamic references are basically pointers to the data, the value is not actually held in the module, unless you wire the external ref to a physical parameter.  Since you aren't moving the value, you don't expend CPU or additional memory.  The value will be updated by exception from the hosting module.

    If you only use the dynamic reference, the parameter becomes unused when teh $ref is changed.  The parameter may "prune" or its update rate slowed when there is noone using the value.  Therefore it is always good practice to check the CST on a parameter before using it in an expression, especially if it comes from a remote location, even if it is via a Dynamic Reference to an External Reference.  The CST will reflect the availability of the remote value.

    Andre Dicaire

  • Hi Pierre,

    The solution provided by Phill L. is correct.

    The only reason it may not work is due to the use of internal variable for 'LINE'. CALC or ACT block does not perform the parameter/variable type conversion, & all internal variables used in the code are default considered as "Float" unless they are directly written from a different type of parameter (e.g.: LINE := '^/LINE.CVS'). If you are trying to write the string directly in the code to the variable, then it is better to use a actual parameter, than the internal variable. E.g.:

    IF LINE_SEL = 1 THEN
       '^/LINE.CVS' := "2211";
    ELSE
       '^/LINE.CVS' := "2222";
    ENDIF;

    '^/D_YV03_SP.$REF' := "//" + '^/LINE.CVS'+ "-YV03/DC1/SP_D.CV';
    '^/D_YV04_SP.$REF' := "//" + '^/LINE.CVS'+ "-YV04/DC1/SP_D.CV';
    '^/D_YV06_SP.$REF' := "//" + '^/LINE.CVS'+ "-YV06/DC1/SP_D.CV';

    (* It is always better to use the check for dynamic reference resolution, before writting the value, as otherwise it generates output transfer error in the module diagnostics. *)

    (IF '^/D_YV03_SP.CST' = 0 AND '^/D_YV03_SP.$REF' <> "") THEN '^/D_YV03_SP' := 1; ENDIF;
    (IF '^/D_YV04_SP.CST' = 0 AND '^/D_YV04_SP.$REF' <> "") THEN '^/D_YV04_SP' := 1; ENDIF;
    (IF '^/D_YV06_SP.CST' = 0 AND '^/D_YV06_SP.$REF' <> "") THEN '^/D_YV06_SP' := 1; ENDIF;

    You can use the ACT block to write this code & disable it with IF loop / use of code (ACT1/IN_D = 0), when the dynamic reference is resolved. This will reduce the loading and also will reduce the efforts taken by controller to continuously resolve the dynamic reference.

    Additional Benefit: You can use the "LINE" parameter to display the selected line on HMI if you want, which you could not do with the internal variable... :-)

    Best Regards,
    Amod.

  • In reply to amodbobade:

    Why not use a state driven EM?  First create a name set with two states "Line 2211" and "Line 2212" for example and add the appropriate valve modules to the newly created EM.  While we "can" do all this using a calc block, it really isn't a good practice for troubleshooting reasons.