10-20-2009 10:32 AM - edited 10-20-2009 10:36 AM
Hi, I've got a situation where I have several numeric controls where you can change different values. I also have several subVIs with control references (as described in this article: http://labviewwiki.org/Control_References) that takes in references to these numeric controls on the mainVI. These subVIs continously read the values in their own threads.
So whenever I change a value on any of the controls, the values does of course change in the subVIs, since they reference to the value of the control. How would I make the actual value only change only after I clicked the ok button?
To illustrate this I made a VI with an event structure and a separate while loop that continoulsy reads a reference to the control and updats an indicator. I can think of a few cumbersome solutions, whereas I have two controls for every value. The second control would then be hidden and only written to in case of the Ok button press. But having two controls to do something simple as this seems superfluous.
Solved! Go to Solution.
10-20-2009 10:44 AM
10-20-2009 11:06 AM
There are several reason as to why I used references. The first was that that LabVIEW article recommended it to make subVIs generic and resuable. I will also be able to change more than just the value, for example properties of the controls (i.e. disabled/enabled). I only write to values in one location, but read in several, so I will not run into any race conditionings here. I also felt that using controls and references makes it much more readable. Let us say I have 40 control values to be read when I press ok. That would mean 40 queues, 40 wires all over the place (unless I use named queues, which I think removes the generic portion of the subVI). So I just said to myself that I will go the easy route.
So if there was some option to not change the value displayed until ok is pressed, that would be great.
10-20-2009 11:17 AM
If you use a notifier you can have multiple listeners on the single notifier. They will all receive the update message. However, if you are using 40 individual controls I imagine you can organize things better using clusters and eliminate the need to treat them individually. Also, do you have forty tasks that are all monitoring for the data to be changed. If so, perhaps there is a better architecture to use to accomplish what you want. Using references isn't a terrible thing to do. However I generally look at the purpose the reference is being used. If I am specifically controlliing the UI then references are the way to go. If however I want to pass the data to sub-tasks, then I prefer to use queues or notifiers. I like to decouple the UI from the processing taskings. By using references you do not decouple the items. You also get performance benefits when you separate the processing from the UI. When you use references the subVIs will be running in the UI thread. There is only one UI thread per application. By using queues or notifiers you allow the system to run your sub-tasks in different threads.
It would help to have a better explaination of exactly what you are trying to accomplish.
10-20-2009 11:42 AM
I have several subVIs with their own state machines (per suggestion from a very humble guy I talked to before ;)). Let's say I have 40 front panel objects, in this case Kp, Ki, Kd values for a controller. I want to pass these values to the different subVIs and, as explained, only pass these values when I press an ok button. From that link I posted above I figured the good way would be to use references. I also knew that in other programming languages the value change was easily only triggered when I pressed a button, so I thought it would be possible to do it here too.
I have tried different options and different ways for reading data, and to me notifiers/queues make the code less readable. I only want to write the data in one place, but read in several so I knew I would never get race conditions. That is why I choose the reference.Do I really, really have to use notifiers to do this? It adds another level of complexity I think, since I have to handle errors/releasing them etc. When I in reality only want to do something very simple.
10-20-2009 12:32 PM - edited 10-20-2009 12:33 PM
Given what you want to do then I would suggest that you use an Action Engine to contain your data. This has the advantage of decoupling the UI from the subtasks. I would recommend that your action engine consist of an array of clusters. Each cluster would contain the data values, in your case Ki, Kd and Kp for each controller. This has the advantage of reducing the individual values you are dealing with and treats the data for a given controller as a whole. The subtasks could either poll the data looking for a value change. You could even keep track of that in your Action Engine so you would only need to poll to see if the data changed. If it did, then read the data. You would need an index or ID to specify which controller's data you would want to access. The action engine allows you to grow your application if more controllers are added. You should use a typedef to define the cluster. If you wanted to make this more event driven you could use a single notifier shared by your subtasks that would simply indicate a data change event. Part of the data for the notifier could specify which data. That way only interested subtasks would take action. This type of architecture wouldn't add lots of wires to your diagram especially if you used a named notifier.
Regardless of the way you choose to pass the data to the subtasks I would take a look at your UI. I haven't seen it so I can't comment on it specifically. However is you have 40 controls on the front panel at the same time it most likely is a confusing interface. There are ways to reduce the complexity and still provide the same functionality. If you haven't already looked at I would recommend getting the book The LabVIEW Style Book by Peter Blume. If you did reduce your UI to only work with a single controller or a couple of related controllers at a time the Action Engine approach would work nicely since you take your data from the FP and only update the data that has changed. From a UI perspective you have less controls to worry about on your UI and it will probably be easier for the user to understand. From the application's perspective you have decoupled the subtasks from the UI in a very clean way. Another approach would be to use LVOOP for your controller data and processing. Then you simply instantiate a new instance of the class (an object) for each controller that your system is using. This has an added benefit of allowing you to use different controllers and load them at runtime using dynamic dispatching.
PS You are good for the overall Kudo count. Thanks.
10-21-2009 01:36 PM
10-21-2009 01:48 PM - edited 10-21-2009 01:48 PM
10-21-2009 03:36 PM
Ben wrote a nugget on action engines aka LV2 globals.
http://forums.ni.com/ni/board/message?board.id=170&thread.id=240328
Hope this helps
10-21-2009 04:52 PM