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.
I ran into a similar problem a couple years back. I wanted to display the string name of the person currently on call given a set of conditions. My solution (probably one of many) was to store the strings in input parameters and reference the parameter names in my logig instead of the strings. This also allowed me to make online changes without having to download (should 2 people switch weeks).
Here's my code:
if 'IN1.CV' = 0 then '^CURRENT_ON_CALL.CV' := '^ONCALL_0.CV'
else if 'IN1.CV' = 1 then '^CURRENT_ON_CALL.CV' := '^ONCALL_1.CV'
else if 'IN1.CV' = 2 then '^CURRENT_ON_CALL.CV' := '^ONCALL_2.CV'
endif;
James Suisse
if LINE_SEL = 1 then LINE := "2211"; else LINE := "2212"; endif;
I've often used strings in command lines - the key is to use dynamic references and a parameter to store the string. Then you build your reference using the string as a portion of the .$REF field.
IF LINE_SEL = 1 THEN
LINE := "2211";
ELSE
LINE := "2222";
ENDIF;
'^/D_YV03_SP.$REF' := "//" + LINE + "-YV03/DC1/SP_D.CV';
'^/D_YV04_SP.$REF' := "//" + LINE + "-YV04/DC1/SP_D.CV';
'^/D_YV06_SP.$REF' := "//" + LINE + "-YV06/DC1/SP_D.CV';
'^/D_YV03_SP' := 1
'^/D_YV04_SP' := 1
'^/D_YV06_SP' := 1
That should take care of it - it might take a couple block scans before the dynamic reference connects, but if your block is continuously writing it should resolve itself.
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 Steve Elves:
Thanks to all.
The way to go seems to be with the dynamic reference. However, whatever I do, either with LINE := "2211" or "//2211" or even "A//221" ( to put a real alpha character in front), the result for the LINE variable is always 0 in the concatenated string. (endup with: '//0-YV03/DC1/SP_D.CV' in my dynamic reference.)
Any idea of what I'm doing wrong?
Pierre
In reply to Pierre_Dion:
Replace your internal LINE variable with a module-level variable that is explicitly defined as a string. That should force the interpreter to handle it as such. What does your binding expression look like?
In reply to Maarten van der Waal:
Yes.
Maarteen confirms what I suggest : Using a String label instead of this internal string parameter and it works (just test it)
You might also want to look at creating an SFC or State Driven module instead of burying all of this in a calc block with dynamic referencing.Either case will be much easier to troubleshoot in the future. (Especially if you need to do this for 70 pieces of equipment for each line.)
In reply to Tyler Anderson:
I'm going with Tyler's suggestion. I'm getting way over my head here with a lots of dynamic references, strings parameters, and the likes. I'm gonna endup with a calc bloc surrounded by input pararameters...
Thanks a million for all your help guys. Really appreciated. I'll try the SFC.
Piere.
Pierre,
I totally agree with Tyler. The CALC block is a powerful block, but as you've found out, it can get you into a complicated problem, and difficult to troubleshoot. Use the right tool. I often see "solutions" implemented in the controller that have nothing to do with the process control functions. Text manipulation is not what the controller was built for, so the text management is rudimentary. I avoid string manipulation in the controller where possible. CALC blocks should be focused on executing an algorithm that can't be done with native function blocks, such as an iterative convergence calculation, complex equation, or a conditional expression that makes sense as an IF-THEN-ELSE. Just because you can put it all in a CALC block, doesn't mean you should.
In some cases, a CALC block solution could be more CPU load than a group of FB's, but even more important the CPU efficiency is visibility of the code for troubleshooting. The SFC structure has powerful delay and confirmation statements, timers and execution flow that make the logic easier to work with. That is often woth a view CPU cycles.
Anyway, I was glad to see Tyler bring some sanity to the discussion :-)
Andre Dicaire