01-29-2013 08:40 AM
Dear LabView users,
I would like to ask your opinion about my project (see attached files). For beginning, I only made the "backbone" of my project, this is what you can see in my VI. My project will need to have the following functionalities:
-Start and possibly abort measurements (and also plot data to graph and record measurement data to file) --> there is a while loop to record data from DAQmx (USB6009), and another while loop with different loop rate to ramp up voltage output to a magnet's amplifier.
-During measurement, or when the system is Idle, the user is able to read in measured data files, and evaluate measured data, etc...(so there will be more functionalities...)
I decided to use Producer consumer structure with events and notifiers, and I also use dynamic user event to be able to communicate from the consumer back to the producer (where I have my state machine also in a shift register).
So please comment on my VI, what do you think? Maybe I should use the state machine (the shift register with the state cluster) in the lower loop? I could also use queue instead of the notifier, but since I only send commands, and parameter values, (no high speed data streaming) I guess the notifier is just fine?
Thanks for advice!
Solved! Go to Solution.
01-29-2013 08:57 AM - edited 01-29-2013 09:07 AM
I just thought it over again, and I think I just unnecessarily overcomplicated the design: I try to use the top while loop with Events only for capturing user events, and the state machine and everything else will be in the bottom while loop. In this way I do not need Dynamic event either...
EDIT: But, it is also not really good, if I have my state machine "on" the bottom while loop, since it should only execute when it gets a command from the top loop. Therefore I cannot iterate through the STATES of my state machine...maybe I stay with this original version so far.... still any comments are welcomed 🙂 thanks!
01-29-2013 09:38 AM
please have a look on this VI. In my command cluster, I have commands what should be read by the measurement loop, or only by the "file read and data eval" loop. Therefore, I use in both places a "Default" case where I do nothing.
I think this structure will fulfill my needs....still any advice welcomed..
01-29-2013 09:50 AM
The code you posted looks like a solid start. The architecture is very similar to the Continuous Measurement Sample Project which shipped with LabVIEW 2012.
A few things I noticed:
Good luck with the rest of your application.
~Simon
01-29-2013 10:28 AM
Thanks very much for the very useful comments!
I am happy only with the latest command, and I also disable those buttons which I do not want the user to click on it (I like disable property node for buttons, it can save enormous amount of programming and logic)
You mean I do not need the shift register for the notifier ref wire? Or also I do not need it for the cluster wire?
I will do it as you say.
You are right, I can initialize my hardware just before the measurement, inside the start_measurement case. So, I do not need the init case at all...
I will program error handling, beside when I make the DAQmx codes for this part, you are right.
Well, this "dirty trick" comes from one official NI template. But you are right, I will do proper shutdown event.
01-29-2013 03:20 PM
- In general, using the error status as the primary way of stopping a consumer loop is a bad practice. I'd rather see a "Shutdown" command that causes the consumer loop to stop. It's more scalable and less likely to be triggered by accident.
Well, this "dirty trick" comes from one official NI template. But you are right, I will do proper shutdown event.
I use this "trick" all the time. I've not had any issues.
01-29-2013 04:20 PM
@drjdpowell wrote:
- In general, using the error status as the primary way of stopping a consumer loop is a bad practice. I'd rather see a "Shutdown" command that causes the consumer loop to stop. It's more scalable and less likely to be triggered by accident.
Well, this "dirty trick" comes from one official NI template. But you are right, I will do proper shutdown event.
I use this "trick" all the time. I've not had any issues.
Christian is correct. The proper way is to use an explicit shutdown message. Relying on the error status can cause problems. Just because it hasn't happened doesn't mean it can't.
01-30-2013 03:41 AM
@Mark_Yedinak wrote:
Christian is correct. The proper way is to use an explicit shutdown message. Relying on the error status can cause problems. Just because it hasn't happened doesn't mean it can't.
Can a communication reference throw an error and then go back to working properly? I've never encountered it. Your consumer is useless and needs to shut down anyway if the communication reference becomes invalid, so you are going to have to write shutdown-on-error code anyway. Also, not every consumer loop naturally requires the extra overhead of a command-message system; kill-the-comm-to-kill-the-loop works on loops that don't use a command enum/string. Finally, if the consumer is in a dynamically-launched VI separate from the producer, then shutdown of the producer for any reason (including aborting) will invalidate the comm reference and trigger automatic shutdown naturally. Which, if nothing else, avoids the annoyance of having to close the project to kill off the orphaned daemons.
01-30-2013 05:16 AM
01-30-2013 09:19 AM
@drjdpowell wrote:
@Mark_Yedinak wrote:
Christian is correct. The proper way is to use an explicit shutdown message. Relying on the error status can cause problems. Just because it hasn't happened doesn't mean it can't.
Can a communication reference throw an error and then go back to working properly? I've never encountered it. Your consumer is useless and needs to shut down anyway if the communication reference becomes invalid, so you are going to have to write shutdown-on-error code anyway. Also, not every consumer loop naturally requires the extra overhead of a command-message system; kill-the-comm-to-kill-the-loop works on loops that don't use a command enum/string. Finally, if the consumer is in a dynamically-launched VI separate from the producer, then shutdown of the producer for any reason (including aborting) will invalidate the comm reference and trigger automatic shutdown naturally. Which, if nothing else, avoids the annoyance of having to close the project to kill off the orphaned daemons.
All valid points.
I advise against exclusively using the error to stop the loop whenever there is an aspect of state or session in the consumer loop. For me, more often than not, there eventually is a difference between a normal intended stop and an unexpected system failure that needs to stop (i.e. you may wish to preserve the state, put hardware into a different mode, give something time to finish before closing etc.). If the messaging infrastructure is there then I think you should use it. Both the error and the stop command may trigger a move into the same stop state before stopping the loop but it's normally worth the investment to provide both entry points.
It's also feasible that a consumer may need to attempt to regain communication rather than stop (more common in networked applications).
The NI supplied Sample Projects only use the error to stop a loop that has a notifier read and a graph update in it. Since there is no state, no logic, and no hardware or file resources being used we determined it was appropriate. For every rule, an exception. The message loops all have an explicit Exit message.
Good discussion. As with many things in programming, well informed reasoning often trumps the "rules" but following the "rules" will generally prevent headaches down the road (which you may never run into).
~Simon