09-08-2008 08:04 AM
I have a variable number of devices connected to the serial ports (actually USB virtual serial ports). The serial ports are polled to see if a device is present. Those with a device present are presented to the user. A reentrant subvi is dynamically loaded to provide a GUI for each device the user wants to use.
I have tried several methods but "RunVI" with "wait until done"=false provides the correct operation. But this is then messy since I have to also use FP.open and CtrlVal.Set to preload the com port and some title text to the rentrant vi. (serial port initialisation and closing is done inside the reentrant VI)
Qustion 1) is there a better way to do this?
Question 2) "terminal standalone.vi" runs correctly when launched as a vi but when run as above the read VISA vi stops working after the first newline character received - (there are no errors) it hasn't crashed the vi since there is still interaction with the front panel - just no serial coms after the first line!
Should I be able to initialise VISA / write VISA / Bytes at port / Read VISA in a reentrant vi?
09-08-2008 10:22 AM
09-08-2008 09:46 PM
09-09-2008 04:04 AM
Here is the terminal program . What I want to do is load the VISA, title and history length to the settings cluster then run and then return to the launch program without waiting for the terminal subVI to finish running. I would then launch several more terminals for the other devices (different ports).
If I want to "launch and leave running" the terminal I think that I'm forced to use the "RunVI" method but this means I don't have access to the connector pane. Therfore I open the VI reference using option "8" to prepare for reentrant operation then show the front panel ("FP.open" method) and then load the settings with the "Ctrl Val Set" method first.
Is there a better way to do this?
Any ideas why I get the unexpected behaviour mentioned in my original post?
09-09-2008 08:30 AM
It looks like you have a race condition going on. You are using several local variables for the Monitor indicator. You are using it in 3 places: as part of your write operation, with the results of your read operation, and stripping out a new line character, in addition to clearing it at the begininng of the VI. If monitor is intended to show the results of your read operation, why are you using it as a part of your write operation?
Where the race condition comes into play is with the local variables. There is no dataflow order between when the monitor indicator is read and written to in the VISA read case structure vs. when it is read and written to in the lower part of the loop. The read and writes could happen and any time relative to each other and cause the various parts of the code to step all over each other in trying to update the monitor string.
1. The use of the monitor string as a part of your VISA write operation makes no sense to me.
2. Use a shift register to store the monitor string between iterations and wire between the various case structures. Only use an indicator in the loop. The use of the local variable before the loop to clear the string is okay.
09-09-2008 09:20 AM
The write case takes the command surrounds it by "*" and appends to the monitor control at the same time writes the command to the serial. (so you know what you've typed - it actually makes it very easy to use and looks good!)
The read case reads any available characters from the serial and writes them to the monitor control.
The third case strips out excess lines from the monitor control i.e. only keeps the visible lines of the monitor plus "history" lines available using the scroll bars.
I've removed the locals and replaced with shift registers. Its now much more elegant code and the gremlins have gone.
I assume when the subVI is made reentrant what could work by luck before (the order of read / writes to locals) isn't necessarily compiled the same way.
Thanks for your help
09-09-2008 09:39 AM
That looks better. I'm glad it is working now.
I do believe that changing it to reentrant could have an effect. Since the reentrancy setting has a direct effect on execution, I do believe it can affect how LabVIEW will compile it for execution.
09-09-2008 10:04 AM
Oh no... unfortunately the main problem is still there. If you launch the terminal subVI with the RunVI method and WaitUntilDone=False then the serial dies without an error (VISA ref OK, no Error and subVI interaction still works)
if you change to WaitUntilDone=True or launch from pressing play then everything is OK.
The same happens if it is reentrant or not - so that was a red herring. AutoDisposeRef has no effect on this problem.
So is it possible to launch a subVI using VISA to access serial by using the RunVI method with WaitUntilDone=False?
09-09-2008 03:22 PM - edited 09-09-2008 03:25 PM
Your reentrant VIs all share the same path, so I'd use a "This VI" reference instead of a "This VI's Path" path constant, which will open a reference to a reentrant VI (which may or may not even do anything to your current instance). Also, I'd switch to an event driven structure for reentrancy, like the attached. The error indicator is just to see if anything happens before you get into your loop, because nothing will happen in it until you quit out of it (the errors will skip most of the important steps).
edit - there's also a race condition in my first Send Command event (and in your sequence) where the local variable could blank Command before it has a chance to be read, so I replaced it with a Value property node and wired it in after the Visa Write.
09-09-2008 05:20 PM
There was no race condition in my version since the "command" control is outside the first case statement.
You are correct the event structure makes for better code and the "This VI" reference is neater (I haven't seen that before do you need to "close reference" after use?)
Rather than have a "send command" button in previous designs I have looked for a "key down" event ="return key" to trigger the send command - more natural for the user.
I have used a modified version of your code called by some test code and it seems to work! but I don't see what is fundamentally different - any ideas?