08-29-2009 02:19 AM - edited 08-29-2009 02:21 AM
DFGray wrote:To keep things simple and scalable for future expansion, I like to have single point sources for my data and user interaction, and single sinks for data handling. In your case, this would mean one loop for events and one for datasocket monitoring.
Exactly, that's what I am trying to do.
Data handling should be done with a third loop. If UI events need special handling, they can be a fourth loop or handled in a case structure in the main UI loop (asynchronous or synchronous - your choice). This is a common architecture that is easily expandable (for a full blown example, see this post). One key to making it work is separating action handling from events. This allows you to essentially intermingle a state machine into a producer consumer architecture.
Yes. I have tried to do so in the posted designs.
Short answer, you want both a state machine and a producer consumer architecture. See the example above (all the posts) for an example. It does essentially what you want to do, but using input from a sound card instead of datasockets.
Yes, you've posted a well documented example. I opened the XylophoneTunerXIII, but then I saw Core Architecture thread, and I guess that's what you wanted me to see in particular, yes?
If yes, I see there is UI event handling. But I don't see the data event handling (from sound card, as I want to do from datasocket). Can you tell me please the file where I should look? Or may be I am missing to understand something.
08-31-2009 07:36 AM
Sound card data acquisition is being handled in a subVI - ASQ.lvlib:AcquireSound.lvclass:ExecutionLoop.vi (on disk, this is simply ExecutionLoop.vi). It is the first subVI in the bottom fork of the error wire during the initialization. It implements a task handler, to handle GUI events, and a simple two-state state machine (running, not running). It also feeds the pulse analysis loop on the main diagram through the use of a queue. This loop contains:
09-01-2009 11:16 AM
Hi Dr Damien,
I studied the file. the coding is very good. You have tried to accomodate everything in one single loop, which is good, but I would say this is what I am explaining, that I cannot have everything in one single loop (technically I can have, but I don't want) because I want the User Events and Events based on the Datasocket data to be executed in parallel.
If I talk about my application from your template, then, if the user clicks some button on the front panel, several actions can occur, like sending somed data to datasocket, calculations, change of attributes and so on... and this would take some time... Meanwhile, if there is already some data on datasocket, then it would be processed (or the event related to that data would be processed) ONLY after this user event has finished. Yes?
Thanks ahead!
09-03-2009 04:43 AM
09-03-2009 08:42 AM
Actually, no. Your datasocket handling loop should be separate from your UI handling loop and should run independently from it (short of responding to commands, when needed). The Xylophone Tuner has such a three-loop structure. The top loop in the main VI is the UI handling loop. It is a synchronous UI handler which contains both the event structure and the event command cases. Some people prefer to separate the event structure and event handling into two loops (see discussion on architecture post of Xylophone Tuner). The bottom loop in the main VI is the data processing loop. In the Xylophone Tuner, this searches the sound data for events and posts the analysis to the GUI if found. In your case, this would be a loop to do whatever processing is necessary for the datasocket data. Finally, there is the data collection loop. In the Xylophone Tuner, this is in the VI discussed earlier. In your case, this would be the datasocket acquisition loop.
In a properly designed application, UI events should not prevent data processing from happening.
09-04-2009 09:40 AM - edited 09-04-2009 09:42 AM
Yes, sounds like what I'm trying to build.
But in the previous message, I couldn't find out which is your Main VI? I thought of Initialize.vi, but it has no subvi calling in the bottom fork of the error node (as you wrote earlier) calling the ASQ.lvlib:AcquireSound.lvclass:ExecutionLoop.vi.
Or is it XylophoneTuner.vi ?
In the XylophoneTuner.vi I found this case in the "Initialize" state (which sounds like ur sentence "It is the first subVI in the bottom fork of the error wire during the initialization") But still not sure if you're talking about the one in the "Run" node in the image below (from ur code, I hope you didn't mind).
Is it possible to have some brief documentation of this, which explains about the nodes etc?
In a properly designed application, UI events should not prevent data processing from happening.
How true!
Thanks for your support!
09-08-2009 07:47 AM
The main VI is Xyl.lvlib:XylophoneTuner.vi. Make sure you get the latest code from the last post (the one about documentation). Earlier code will not have the data acquisition loop, since it was not implemented yet. You may want to walk through the development process so you see how the application was created and why. Most of the reasoning applies to your application, as well. This will also present the various parts of the program one at a time instead of all at once, as in the final code. The location in the main VI is as follows:
09-08-2009 03:03 PM
Thanks Dr Damien,
Appreciated your informative answer. The latest version I have is XIII. Please give me link to the latest if this is not the latest.
Yes, I DO like to see the entire process and not just the end product, as I myself believe in a well designed product with proper documentation. But I am at the very high point of the implementation of my application. Still need to write (or rather Draw) a lot of stuff in my application. And you know that vhooshing sound of the deadlines, as they fly by, well, I am just listening to it everyday. So right now I won't study everything, but with my selfishness powered by my curiousity, I just want to know how have u implemented the Events capture and execution loops, Data aquisition loop, and data events loop, to see how it fits with mine.
I have half developed one of the modules (other 2 will follow the same path) and I am using a big state machine loop, which, in more than one states, has event structures (I can see those raising eyebrows, and hear those Dooohhhhhs!!!) and I would have to implement the Datasocket reading (and corresponding actions) loop in more than one states too.
I have a previously developed, and well working, application developed by one of my professors, who also agrees that it was developed a long time ago but would like to put it with state machines.
If not anything else, I would just use that model (running several loops in parallel) into my state machine's state.
But would like to understand your method.
also, from the discussion so far, I can understand you have these loops in different VIs. Right? So are they running in parallel? I mean, if you call a subVI, it would need to finish the execution before the control returns back to the calling VI, no?
09-08-2009 08:21 PM
Will it be too much if I ask you to make a template which shows the program flow clearly?
I know I am being demanding, but it would explain me easily how you are talking about the loops to interact. Because, alongwith the above queries, I need to understand many other nodes in your program, and a simple block diagram with just loops etc. would explain me exactly what you're talking about.
Thanks ahead!
09-09-2009 08:25 AM
LabVIEW has a concept of "clumps". Each clump can be executed in an independent thread once its inputs are valid. Loops are typically clump boundaries, so each loop on a block diagram can operate in an independent thread. The Xylophone Tuner has three loops (one of which is in a subVI). These are for UI event handling, data acquisition, and data analysis. Data and commands are passed between the loops using queues. States are implemented as case statements in all loops (e.g. in the Run state, a configuration command on the data acquisition loop stops the data acquisition, reconfigures, and restarts it. In the idle state, nothing happens, since configuration is done at startup). Different states can result in different behavior in all the loops.
So, if control is passed to a subVI in one loop, the other loops continue processing normally (assuming your processor has sufficient threads to do this). The exception to this is if a subVI is used in two loops and the subVI is not reentrant. In this case, the subVI in one loop would block its use in the other loop. The subVI should probably be reentrant for this use case so both loops can freely and independently execute.
I would strong recommend you eliminate all but one of your event structures and implement states in the single event structure with one case statement per event. While there are advanced use cases which are more easily handled with multiple event structures (and, hopefully, dynamic event registration), your use case is not one of them.
Unfortunately, I do not have the time to write the example you wish. I, too, have deadlines...