05-06-2014 12:28 PM
I have a temperature control process which has an array of process variables for which I wish to implement parallel PID control loops. The size of this array is set according to a configurable number of temperature control zones, so while it is variable in the application, it is known and constant at the level of the SubVI which will handle the PID processing. While the PID and Fuzzy Logic toolkit contains PID VIs which accomodate DBL Array instances for parallel processing (and thus would handle whatever size array of process variables is thrown at it), the specific VI that I wish to use (PID Autotuning (Temperature).vi) does not. What I want to do is: in response to a configuration change which changes the number of heater control zones, preallocate as many clones of the PID Autotuning (Temperature).vi as there are process variables in the array (determined by user configuration), and then within my SubVI, run the array of process variables into a FOR loop in which each iteration uses a different clone, thus duplicating the behaviour of those PID VIs which do accept array inputs for running parallel control loops.
I am unfortunately unfamiliar with the use of the VIs on the Application Control palette. Any help would be appreciated.
Sean
05-06-2014 12:51 PM
Dig into the shipping examples. The ones that will be the most helpful would be:
"Asynchronous Call and Collect (Using Option 0x40).vi"
"Populating the Asynchronous Call Pool.vi"
05-07-2014 08:59 AM
Okay, I have managed to preallocate the data spaces, and if I pass the resultant reference into a FOR loop (N= minimum # of data spaces) containing a property node outputing the "Is Clone VI" property, all output Booleans are TRUE. Interestingly, the CloneName property is the same string regardless of iteration, which I gather was done on purpose by NI in a recent revision of LabVIEW to prevent programmatic access to specific clones, but unfortunately, that is precisely what I am trying to do. The asynchronous start / wait functions, or call by reference node, will operate on the reference passing through the FOR loop, but how can I be sure that the correct instance is being used if I can't address them directly? I also notice that for minimum space values less than six, the preallocation node coerces the value to six. I am unsure how this would be handled when it gets to my PID FOR loop - I want to iterate through the clones starting at the first one, but the next time the loop is encountered, it needs to start at the beginning again. If there are more allocated data spaces than process variables, wouldn't it iterate through all of the available preallocated clones before starting again?
05-07-2014 09:07 AM - edited 05-07-2014 09:08 AM
Now you are going to have to show us some code.
There are a few "Ideosynchracies" that you need to be aware of. If you are getting the same clone name you are reading the same refnum. you should be opening a refnum to each clone.
The likely cause here is you put the ref on a SR in the loop with the ACBR. you don't want to do that.
Populating the clone pool with preallocate lets you create more than the minimun (default) number of dataspaces. you cannot create less than the minimum (1 per core I believe?) so index into your array and only use the first x number of clones if you do not need them all.
05-07-2014 09:33 AM
Okay, so posted below is the portion of my code in which I am performing the preallocation, as per the shipping example. The "Current Size" ouput of the Invoke Node appears to be coerced to at least 6, regardless of the "Minimum Size" input. As you can see, the Invoke Node following the Open VI Reference outputs a single reference, when what I really want to get out of this is an array of references, each referring to their specific clone. This array is what I want to keep in the shift register you see, where it would subsequently be acted upon by a FOR loop which indexes the references and contains a Call by Reference node to run the PID. I don't know how to get the reference array though - everything I try results in an array of identical references.
05-07-2014 09:58 AM - edited 05-07-2014 10:01 AM
You need to open the clone references in a loop then pre allocate the clone pool to the number of references you opened.
I know the help gets failrly convoluted on clone pools ACBRS and the open ref flags.
I would use sandbox code to get a feel for the concepts before plugging it into my main project.
Look over here and dig through the search online to
05-07-2014 10:10 AM
I tried as you suggested (see below), but the resultant array consists of identical references.
05-07-2014 10:26 AM
My mistake - comparing the references directly with an equals comparator results in a Boolean TRUE, but if you Type Cast each reference to U32, the resultant numbers are different. I presume then, that the resultant array of references can be used exactly the way I intend?
05-07-2014 11:12 AM
I think I have this figured out. The allocation code is here:
My only remaining question is whether I must use the "Start Asynchronous Call" and "Wait on Asynchronous Call" VIs in my processing FOR loop to effect the proper reentrant behaviour, or if it is sufficient to use a "Call by Reference" node, given that I don't need to read or write the data in different locations?
Sean
05-07-2014 11:52 AM
Here is the code on the processing end. Note that I have enabled iteration parallelism on the FOR loop.