While doing code for large and involved machine sequences, I normally use the Queued state machine. Just create a TypeDef for the states and keep shifting through them ... all well. Have created many such machine codes to date. But the catch here is ... in all these cases I used to do the code and I am also the designer of the hydraulic controls for the machine. So generally I can "think" out the whole sequence in mind and do it step by step converting mind ideas to LV code.
Now as part of a new project requirement I need to create a full sequence flow chart for someone else to do the LV coding. I am stuck !!
I tried doing it via a Flow chart but it was getting too large for comfort and the branches were too many. And indicating concurrent tasks ( outside of the QSM ) like temperature regulation, motor speed stabilization etc make it complex.
Tried to get sequences into a Excel spreadsheet but soon realized its futile.
So as of now I am advising the engineer small incremental steps to code and its happening.
But I am sure there is a better way to do this documentation in such a way that someone else can refer to it and start coding. Also is the fact that when we try to document, we are loosing a MAJOR advantage of the Graphic Coding like LV ..??
Any ideas as to how this is done ??
Solved! Go to Solution.
Firstly - I have no experience writing an architecture then having someone else execute it.
However, it would seem like the flow chart you mentioned is a good approach. Some simplifying steps might be:
If parallel processes aren't synchronised, write them as a completely separate diagram
If some sequence of steps occurs together, in a manner that would cause you to use a SubVI, refer to it as one step and then document the substeps separately.
If you have a complicated interprocess communication, look at the Actor Framework examples in the AF subforum. They show some ways to separate out different types of flow charts when separate components depend on one another.
You can draw such a diagram in e.g. WhiteStarUML.
In many cases a state machine is simply a way to organize code, you could have unbundled them and made each state as a sub vi and wired them together. Such a diagram can be added to a VI as documentation.
If you do this it should be easier to create and define the action blocks needed and create arrows for choices, as 'if OK continue, else repeat test'.
I'd say such a diagram shouldn't be too low level, stop at 'wait for temperature regulation and motor speed stab'.
Mostly ranting, maybe it helps?
For the past 3-4 years, I've also been using multiple QSM or QMH design patterns (although I'm now substituting Channel Wires for Queues, so I call them CSM and CMH). Like you, I have an Enum called <something>-State that holds the various States I need.
I've also been trying to do a better job of following the practice of "Write the Documentation First". In my case, it is often "Write the Documentation Co-Temporaneously", or "Write Some Documentation When You Get Stuck". Describing the States, what they do, the Transition Rules, why they are there, etc. often clarifies problems and confusions.
One other "design principle" that works for me is more of a LabVIEW Style thing, Fit the Entire Block Diagram on a Single Screen. In some cases, this has led me to "split" a State to keep it from getting too big, which (as often as not) highlights inefficiencies in my design or in my code. Another principle is "Don't be Afraid to Add a State" -- adding a State in an Enum-based State Machine is much easier than Removing a State, as you (almost never) get the State Cases "mis-assigned".
While doing code for large and involved machine sequences, I normally use the Queued state machine....
Any ideas as to how this is done ??
Please note I am speaking of a QSM and not a QMH.
In this thread from ten years ago I shared two different designs that I put together for the design phase of two projects which could have been developed by others.
I used a "top-down" approach to the design where I approached from the high-level and included the details as I got to the specifics.
Abandon the QSM, stick with dedicated components and your job will be do-able.
I've just been watching Norm Kirchner's presentation from Alliance Day (I couldn't get in but fortunately the video is pretty clear) and in the middle he discusses documenting a Queue Driven State Machine or Queue Driven Message Handler.
Actually, he's talking about why you should decouple state from actions (which seems like a sensible idea, although I try to avoid state as much as possible) and how to go about implementing a more robust solution. It looks like a great presentation but I've only seen around the first half so far.
OK ... we have been discussing about QSM and QSH.
For a new project i was just creating the basic data flow between VIs.
This is the set up :
I guess its pretty elementary and though i am using Globals the data flow is only one direction ... what is written in the Main is ONLY read in Sub and similarly what is written in Sub is ONLY read in MAIN. I don't think there will be any issue in this ? And till date i have been using Function Globals for this but understood that simple Globals are much faster in comparison.
Maybe the Subs can use a simple While Loop but then i am not sure about their firing order as they are independent VIs. So used Timed Loops.
Any comments on traps or pitfalls to watch out ?
Without knowing more about the particular problem, hardware, and organization of data, this is definitely not how I would structure this task (and not how I've structured essentially all of my DAQ tasks to date). Note that I have almost no experience with LabVIEW FPGA, so the following points are meant to apply to non-FPGA systems.
Note that this "assigns priority" to the DAQ Loops, as the other Processing (or Control-watching) loops sit idle until there is work for them to do. Usually timing doesn't need to be "tight" between Controls and "code being controlled" (does it matter if the VI responds in 1 micro-second vs 10 milliseconds after you push a button?), nor between Acquisition and Processing (do you care if you see data points 1 vs 10 milliseconds after it is acquired?).
Bob "My $0.02" Schor
Understood the point in Timed Loop.
But still I would like to retain it in Main as I can then get deterministic timing by creating a Timing Source and controlling the Timed loop with it. This has worked well for me in many instances.
Of course the Sub VIs need not have Timed Loops and can just run in Synch with the Main based on the data arrival in a Queue. Did a small project to explain this concept.
Still in this case I need to figure out how to send data from the Sub back to Main ( for writing to DAQMx DO and AO ). I tried to open a new Queue inside of the Sub and read it in Main.... the code just froze.
For me, the simplest way to use a queue between a calling VI and its subVI is to create the queue in the caller and pass the queue into the SubVI as an input.
Then in your case you can enqueue in the callee and dequeue in the caller, and release the queue after the SubVI finishes (preferably in the main VI that creates the queue to make it simpler to visualise).