jcz Posted March 25, 2009 Report Share Posted March 25, 2009 cross-post with http://decibel.ni.com/content/thread/2532 : NI Home > Communities > Groups > Large LabVIEW Application Development > Discussions Dear All, I am developing a medium-sized application. I've got a camera that detects a laser beam on a wall, a system that controls this beam and a switch to change between various beams. I used a modular architecture such that a separate program controls the camera (image acquisition and analysis), separate program to control the mentioned system, and a separate small program to control the switch. Each program can be run independently and can be build as a standalone application (used a consumer-producer architecture). Once I had those three small applications (let's call them sub-programs), I've written another application to control other apps. I implemented a common queue for all sub-programs and the main one to send 'telegrams' between all of them (cluster with two enums FROM,TO and two variants SUBJECT,MESSAGE). Each sub-program continuously checks the status of the 'telegram' queue and once the message is addressed to it, the queue element is dequeued and analyzed. The sub-program then does what it was asked to do and sends back an acknowledge telegram back to where it came from (the main application waits for this acknowledge). Then the main app access the data from the subprograms (functional global or reference to controls).. but it's a different story. Basically it all works quite nicely, but it's not perfect, and I want to change it. I've got some ideas, but I was wondering if you have any suggestions, links to a good resources or ideas on how to develop such modular (is that a good word for it?) applications. Ideally with examples, and screenshots (or LabVIEW 7.1 compatible code). BTW. I know about http://zone.ni.com/devzone/cda/tut/p/id/7198 - Large Application Development in LabVIEW http://zone.ni.com/wv/app/doc/p/id/wv-160 - Software Design Architectures in NI LabVIEW http://zone.ni.com/devzone/cda/tut/p/id/3252 - Developing a Modular Software Architecture but it's not really what I am looking for. regards, Jakub Quote Link to comment
Mark Yedinak Posted March 26, 2009 Report Share Posted March 26, 2009 What are you dissatisfied with? From what you describe you have a pretty decent architecture. About the only thing I would consider changing would be to make your queues network based which would give you more flexibility in deploying your individual control programs. This would require you to actually pass program data between applications as opposed to directly referencing them via functional globals or references. Beyond that I don't see where your design is necessarily falling short. Quote Link to comment
jdunham Posted March 26, 2009 Report Share Posted March 26, 2009 One thing I programmed recently was my own version of a model-view-controller architecture. It uses an action engine/producer consumer system which is certainly nothing new. Commands are sent to the model (the engine) with queues, and if the command wants a response it can supply a notifier. So what is new (to me, at least) is that the model is in an lvclass, and the queue is private, so no other modules can access the action engine without using a method from the class. Similarly the event structure in the same VI as the model also uses those methods so the front panel button presses exercise the exact same code available to other modules. The VIs inside the action engine are mostly private scope, so no other routines can invoke them outside of the engine. Once it's deployed, the front panel can remain hidden forever or else it can be shown if you want to give the end-user manual control of that system. The lvclass just contains the message queue (which is basically the controller), and the status notifier (the view), which is different from the per-action response notifier which is optional for each control message. The status notifier is updated whenever the model changes, or it can be put in a timeout case to update constantly. Other modules can call a public method which gets the latest data out of the private status notifier. Quote Link to comment
Neville D Posted March 26, 2009 Report Share Posted March 26, 2009 Your lung icons are pretty cool! N. Quote Link to comment
jcz Posted April 8, 2009 Author Report Share Posted April 8, 2009 QUOTE (Mark Yedinak @ Mar 25 2009, 03:59 PM) What are you dissatisfied with? From what you describe you have a pretty decent architecture. About the only thing I would consider changing would be to make your queues network based which would give you more flexibility in deploying your individual control programs. This would require you to actually pass program data between applications as opposed to directly referencing them via functional globals or references. Beyond that I don't see where your design is necessarily falling short. Hi Mark, Thanks for reply and sorry for my delay in response. I foolishly believed that the forum will automatically notify me about reply, and simply forgot to check it Firstly I should say that I am still working on this architecture, as I develop the main application, so all those things I am writing about might be solved within say weeks. What I'm dissatisfied with is mainly the fact that all sub-programs are waiting for the telegram by querying the "inter-process" queue status in a while loop. This lows down the message handling, and even it's just a tiny delay, sending hundreds/thousands of commands may delay the whole program. I still haven't worked out how to lock a subprogram from receiving any new telegrams (e.g. during initialisation). And finally at the moment the telegrams are one-directional only - the only response from any subprogram is the acknowledgement that it finished what it was asked to do. So that for me the telegram is only a message related to some sort of action (e.g. grab image from camera), and the result of this action (i.e. image) is then stored in a functional global which is accessible from main program. The main idea I had was to create a bunch of main programs that would pretend to be a real-hardware-devices. So then I could simply implement some sort of protocol, define commands and talk to each sub-program as it was a real device. For instance to grab an image from a camera, I could then add a command to a queue (in exterme version SCPI-like command) :camera:image:snap, and only camera interface would run this command returning ACK. I am curious if there is anyone who came up with similar approach. At the moment I am trying to work out in details LabVIEW Queued State Machine Architecture by expressionflow.com : http://expressionflow.com/2007/10/01/labvi...e-architecture/ Below some screenshots of my implementation: Telegram queue (from,to,subject,message) : Telegram send & wait for ack Receive mechanism in a subprogram: Jakub Quote Link to comment
Mark Yedinak Posted April 8, 2009 Report Share Posted April 8, 2009 Are you using a single queue to communicate with all of your spawned tasks? If so, I would recommend that you use a separate queue to send commands to each subtask and then a single queue which all subtasks use to send information back to the main controller. If you do this you will eliminate the need to poll your queues since any message received will be for that task. Using this approach will mean that everything will be event driven and you will not require polling. When a task waits on a queue nothing happens until a message gets posted. If you need to communicate directly between two tasks you can have a message that the subtasks use to request the queue name for the desired task and your main application could then return this information to the subtask. Also, queued state machines are very powerful and we use them quite extensively in all of our applications. They are well worth your time to learn. Quote Link to comment
jdunham Posted April 8, 2009 Report Share Posted April 8, 2009 QUOTE (jcz @ Apr 7 2009, 07:41 AM) What I'm dissatisfied with is mainly the fact that all sub-programs are waiting for the telegram by querying the "inter-process" queue status in a while loop. This lows down the message handling, and even it's just a tiny delay, sending hundreds/thousands of commands may delay the whole program. If you use a separate queue for each object, then you don't need to poll the queue status. QUOTE (jcz @ Apr 7 2009, 07:41 AM) I still haven't worked out how to lock a subprogram from receiving any new telegrams (e.g. during initialisation). If you use a separate queue for each object, each subprogram (object) will not process subsequent queue messages while any other message is being processed. This includes the initialization message. By using separate queues, each subprogram can be initializing itself in parallel. QUOTE (jcz @ Apr 7 2009, 07:41 AM) And finally at the moment the telegrams are one-directional only - the only response from any subprogram is the acknowledgement that it finished what it was asked to do. So that for me the telegram is only a message related to some sort of action (e.g. grab image from camera), and the result of this action (i.e. image) is then stored in a functional global which is accessible from main program. If you include a notifier in your message cluster, that gives a mechanism by which the subprogram can return an acknowledgment, along with any data. The caller creates a new unnamed notifier, bundles it into the message, send the message, and waits for the notifier. The subprogram checks the notifier refnum and if it's valid, sends the response, and if invalid, just ignores it (not all queued commands need a response). QUOTE (jcz @ Apr 7 2009, 07:41 AM) The main idea I had was to create a bunch of main programs that would pretend to be a real-hardware-devices. So then I could simply implement some sort of protocol, define commands and talk to each sub-program as it was a real device. For instance to grab an image from a camera, I could then add a command to a queue (in exterme version SCPI-like command) :camera:image:snap, and only camera interface would run this command returning ACK. If you use a separate queue for each object, and a separate enum of commands specific to that object (subprogram), then your subprograms are all totally reusable. In fact I would wrap each bit of queue-sending code into a VI and then those VIs are the public methods of your subprogram. In case I was too subtle, I think it's a mistake to use the same queue for all of your hardware components. Each object should be its own independent queued state machine which can accept commands and do stuff. Otherwise I think you are on the right track. Jason Quote Link to comment
jcz Posted April 9, 2009 Author Report Share Posted April 9, 2009 Thanks guys for all suggestions. They are very useful for me. As soon as I get to the coding again I will implement your suggestions. Jakub Quote Link to comment
ssingh1 Posted April 19, 2010 Report Share Posted April 19, 2010 (edited) Thanks guys for all suggestions. They are very useful for me. As soon as I get to the coding again I will implement your suggestions. Jakub Dear Jakub, Did you ultimate came out with some better solution? I too was finding myself in similar type of situation :-) Dear jdunham, Can you please provide a small working example of your suggested MVC model? Shourya Edited April 19, 2010 by ssingh1 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.