06-29-2016 09:26 AM
Hello all,
I'm having some trouble with a VI I'm putting together for some lab research. I'm trying to use two SubVI's: one writes nine analog voltage outputs through a PCI 6723, the other sends M Code commands to a linear positioner through COM 4. Both work individually, but when I place them in another VI, it seems the outside loop only runs once. If I preset a track position and hit run, the track moves to that position but does not respond to further inputs. The voltage control does absolutely nothing, preset or not. The goal is that both SubVI's run in real time. That is, changing the enum for the track will automatically update the position, and moving the voltage sliders with update voltage and indicators in real time. I've tried a couple of configurations without luck. Is it perhaps because I'm trying to use both a serial port and a DAQ?
I've attached the main VI and SubVI's for review. Any advice is appreciated.
Solved! Go to Solution.
06-29-2016 11:02 AM
Dataflow 101: A loop cannot iterate until all of the code inside has completed. But your subVIs are not completing since their "stop" condition is set to a constant of FALSE.
You need to break apart your state machines and make one larger state machine that runs at the top level. State Machine inside of another State Machine is a clear indicator of a bad design.
06-29-2016 11:06 AM
@crossrulz wrote:... State Machine inside of another State Machine is a clear indicator of a bad design.
Could you talk to me abou that last point a bit more?
I have some "learnin" to do if that is true.
Ben
06-29-2016 11:11 AM
"Is it perhaps because I'm trying to use both a serial port and a DAQ?"
No, that would be a silly restriction of the language 🙂
There are many problems with your application (by the way, you should use a LabVIEW project for your main and subVIs), like the insane structures in the DAQmx subVI.
The actual bug you see is the reason of you do not understand how a shift register stores data: you use initialized shift registers for both subVIs, therefore you overwrite the stored values at every iteration. You should learn about Functional Global Variables and Action Engines, so you will understand the problem. So you need to work (also) on your subVIs, you have to change how they work. In their recent form they are not capable to do what you want...Do not have an internal state machine for the subVIs, use actions: Init, Check, Change, Close. So it is very important that your subVIs only perform one action at a time. Finally, when you stop your main While loop in your main VI, you call the two subVIs with action command "Close" to close and delete the tasks properly.
Here is some more reading: http://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/td-p/503801
06-29-2016 11:16 AM
Thanks for your help everyone, it sounds like I'm expecting my SubVI's to do too much relative to the overall sceme of things. The 1/2 credit labview course I took last semester clearly didn't offer very much education. I'll redesign the SubVI's.
06-29-2016 01:17 PM
@Ben wrote:
@crossrulz wrote:... State Machine inside of another State Machine is a clear indicator of a bad design.
Could you talk to me abou that last point a bit more?
Disclaimer: This is a general rule based on my personal observations.
In the applications I have done, I find it best to keep your states "fast". This often means repeating states. But this needs to be done in order to 1) do timing checks and/or 2) check for user inputs (or other input states). But if you put a loop that is a state machine inside of a state, then you are violating that "fast" principal. Plus you are just making things more complicated and break the opportunity to reuse those states. Whatever states you had in your tiny little state machine should really be states in your larger state machine.
In my mind, I find it very similar to putting a large wait inside of an event case so that your GUI is bascially locked up until that very long task is complete. In general, that is a very bad idea.
06-29-2016 01:50 PM
@crossrulz wrote:
@Ben wrote:
@crossrulz wrote:... State Machine inside of another State Machine is a clear indicator of a bad design.
Could you talk to me abou that last point a bit more?
Disclaimer: This is a general rule based on my personal observations.
In the applications I have done, I find it best to keep your states "fast". This often means repeating states. But this needs to be done in order to 1) do timing checks and/or 2) check for user inputs (or other input states). But if you put a loop that is a state machine inside of a state, then you are violating that "fast" principal. Plus you are just making things more complicated and break the opportunity to reuse those states. Whatever states you had in your tiny little state machine should really be states in your larger state machine.
In my mind, I find it very similar to putting a large wait inside of an event case so that your GUI is bascially locked up until that very long task is complete. In general, that is a very bad idea.
Fair enough and thank you.
And for anther way of looking at things...
I DO have state machines inside of state machines when warrented. I find it simplifies complex functionality.
Example: Curve tracer control.
Will generally transition between an "Idle State" and a "Running State.
The "Running State" can be a state machine that starts out with an "Autoscaling State" and then enters a "Collection state".
The "Autoscaling State" can also be a state machine that determines the proper range for the DUT.
So that would be a state machine inside a state machine inside a state machine.
My general rule of thumb is;
"If I can not illustrate the states and the transitions on a sinlge sheet of paper, it is too complicated." ( "The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise" Dijkstra see here )
Re:"Re-using a state"
I never re-use a "state" of a state machine. If there is something done in a a state that has to be done in more than one part of the application I hear the words coming from the nether world saying "Create a subVI Ben".
But this is just another way to approach developing an application.
Thakn you for you explanation.