03-31-2015 09:18 AM - edited 03-31-2015 09:21 AM
I am sure this has been discussed before, but I cant seem to find the correct search terms.
I have two Classes (Class A and Class B) that handle communication to a UUT in a test nest.
This particular test system has 4 cells in the nest (4 UUTs at a time).
Obviously each UUT requires a different COM port. I current have 4 independent loops that run the tests, but all use Class A and Class B.
The private data for each class contains a VISA control, which is access by specific read and write vis in the class.
Is there a way to make sure that the COM port will be different for each instance of the class in each loop?
I attached a picture of the vi, exposes the VISA, configures the port, then puts it back using the Write
.
03-31-2015 09:34 AM
Are you running into any issues with the code you have? It shouldn't be a problem, assuming you have four copies of Class A / B each configured with a different VISA resource. LabVIEW classes are by value, so each class wire will hold its own private data, independent of other instances of the class.
03-31-2015 11:12 AM
It should be the responsibility of the code that instantiates classes A and B to make sure that it assigns a different COM port to each one.
The code you show looks odd to me. I would NOT make accessors for the VISA resource in the class. Instead, make a class method for initializing the class that takes a VISA resource (or a COM port number), and then handle the initialization inside the class (if you want to reuse the initialization between the classes, make a new VI that isn't part of either class, but is called from within the class). You might also have a boolean as part of the class data, which is set to true in that initialization VI, and if the initialization VI is called when that boolean is already true, it returns an error (or, don't provide a class input to that VI). That way you can guarantee that the serial port is assigned only once and doesn't change throughout the life of the class instance.
04-02-2015 06:35 AM - edited 04-02-2015 06:49 AM
Sorry for the delay, I was trying to confirm some things.
Looking at the code, it seems like each cell loop is having to wait for a class vi to be unused before that loop can use it, ie, if cell A is using Class A\Get Counts from UUT.vi, when Cell B tries to call that same ClassA\Get Counts from UUT.vi, it has to wait until Cell A is finished with it before Cell B can use it.
Do I have to make all the vis in my class re-entrant as well?
I have placed a Class constant on the block diagram to choose which child of the IR class I am using. I know I could change this to Dynamically load the class, but I didnt go there yet.
The innards of the Set COM.vi
nathand: What you are saying is I should change the Set COM Port to something like this and just unbundle in each of the vi's instead of the accessor:
But when accessing the VISA name when in the Child (In my case IR.lvclass is the Parent, HRE and Orion are child classes), I still have to use a accessor to get the VISA name.
04-02-2015 06:51 AM
You could use a class static variable (a privatly scoped FGV, for example) that maintains a list of all currently used VISA resources. Whenever you construct a new instance of the class (within the constructor / initialize VI), add the instance's VISA resource to the list.
@Kenny_K wrote:
Sorry for the delay, I was trying to confirm some things.
Looking at the code, it seems like each cell loop is having to wait for a class vi to be unused before that loop can use it, ie, if cell A is using Class A\Get Counts from UUT.vi, when Cell B tries to call that same ClassA\Get Counts from UUT.vi, it has to wait until Cell A is finished with it before Cell B can use it.
Do I have to make all the vis in my class re-entrant as well?
Yes. Not all of them, but those that you want to be able to call from multiple locations at the same time.
...nathand: What you are saying is I should change the Set COM Port to something like this and just unbundle in each of the vi's instead of the accessor:
nathand was suggesting that you have a constructor / initialization VI that you use to instantiate an object of your class. Instead of placing an object constant on your caller block diagram, always call this VI to get an object. This VI would handle all initialization tasks and take in required inputs - i.e. take a VISA resource as an input, configure it, check the static list that I suggested, and then return the fully-initialized-and-ready-to-use object.
04-02-2015 07:09 AM
Here's an example of what a caller block diagram might look like:
Inside the constructor VI:
04-02-2015 12:39 PM - edited 04-02-2015 12:40 PM
@Kenny_K wrote:
But when accessing the VISA name when in the Child (In my case IR.lvclass is the Parent, HRE and Orion are child classes), I still have to use a accessor to get the VISA name.
Well, in that case, I'd use only a Read accessor (no Write), to make sure that the COM port cannot be changed after the object is initialized. If you have an initialize VI that doesn't accept a class input, but does output a class, and that's the only place where the COM port is set, then you guarantee that only objects that have been properly initialized will have a COM port, and that COM port cannot be changed after initialization. This does, however, mean that the initialization method cannot be dynamic dispatch, so if you do need that ability, you might instead use a boolean as part of the class data that indicates whether the class has already been initialized. Also look into the Factory pattern.
There's no need to repackage the VISA resource into the class after each use, since VISA resources are references to real hardware.