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.
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.