Jump to content

Re-Designing Multi-Instrument, Multi-UI Executable


Recommended Posts

I have searched extensively and cannot find the example anywhere in the 2012 Beta. Could you point me to it please?

It's right on the Getting Started Window (new project from template, or so). See the beta forum for an update to the sample project, though. Arg, this doesn't count as talking about the beta, does it?

Link to comment

It's right on the Getting Started Window (new project from template, or so). See the beta forum for an update to the sample project, though. Arg, this doesn't count as talking about the beta, does it?

Yeah, it kind of does, but I won't tell the Powers That Be if you don't...

jbjorlie: Read the beta forum for comments from me about this.

Link to comment
I actually don't like calling it MVC because I don't think it's an accurate description. It's closer to a Model-View-Mediator architecture, but that's not exactly right either. Depends on your messaging topology. Applications using the observer pattern lean towards a lot of direct point-to-point communication. In these the message source usually sends a copy of the message to each receiver. I prefer a hierarchical messaging topology. In that system the thermocouple sends out a single Temp message to it's owning mediator, which then forwards it to the next mediator, and so on down the line. Copies are only made if a mediator has to forward the message to multiple destinations. Or you could always do a hybrid of the two...

This is somewhat tangential, but the Gang of Four folks (pp. 5-6) consider M-V-C a composite design pattern, where the individual design patterns are Observer, Composite, and Strategy.

Link to comment

In our components the Model publishes its state.

My preference is more along the lines of Paul's "other flavor" MVC implementation. There is no direct communication between the model and view at all; it all goes through the controller. (Instead of a triangle my three components are in a line with the controller in the middle.) The controller is where I put the glue code that translates output messages from one into input messages for the other. I actually don't like calling it MVC because I don't think it's an accurate description. It's closer to a Model-View-Mediator architecture, but that's not exactly right either.

I prefer a hierarchical messaging topology. In that system the thermocouple sends out a single Temp message to it's owning mediator, which then forwards it to the next mediator, and so on down the line. Copies are only made if a mediator has to forward the message to multiple destinations.

Excusing my horrible flowchart design, are we talking about something like this?

post-15786-0-76975100-1328907695_thumb.j

Edited by jbjorlie
Link to comment

Excusing my horrible flowchart design, are we talking about something like this?

Well, Dave and I are advocating different things.

In practice, our project uses a hybrid approach. This is from our presentation last August:

post-6989-0-47233900-1328914000_thumb.pn

Description:

A user clicks a button on the view. The view code handles the button event and publishes a value (a demand). (Note that another view or controller in the application can publish this same demand, if we so design it. This is great for designing a hierarchical system.)

The "Data Listener" for the component subscribes to all relevant demands (really any input data) for that component, and upon receipt of a new demand creates a corresponding Command object (see Command Pattern), which it publishes. Hence the Data Listener is a sort of mediator, I suppose.

The Controller subscribes to Command, and responds accordingly. When there is something to do it invokes methods on the Model.

The Model changes state as appropriate, and publishes updated aspects of its state to appropriately named topics.

The View subscribes to these state topics. When a value change event occurs, it updates the appropriate indicator. (Binding the indicator to the shared variable is another way to accomplish the same thing in the very simplest cases.)

Note that multiple Views can subscribe to the same information.

We have implemented a number of systems now and I think this is really quite elegant.

[some details: We actually use programmatic access to SVs. Also we right justify and fix the digits for numeric indicators and use proper units. For this and other reasons we use events rather than shared variable binding in most instances.]

Link to comment

In practice, our project uses a hybrid approach.

I assume your "Model" is self sufficient and processes internal events through its own "mediator(s)" thingys? If not, what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

With that in mind, this updated flowchart may be inaccurate but I would appreciate more feedback on this:

post-15786-0-62909100-1328919194_thumb.j

Link to comment

Excusing my horrible flowchart design, are we talking about something like this?

Close. What you show is more of a mixed model. A strict hierarchical messaging topology looks more like this. (I don't know what those symbols mean in a flowcharts, but here it just represents one "thing" and multiple "things.")

post-7603-0-36901200-1328915889_thumb.pn

A couple things to note:

1. The "things" on the diagram do not represent individual vis or even classes; they are loops. IMO loops are the fundamental unit of execution.

2. The hierarchy represents "is responsible for," not "is dependent on." A vi containing a sub loop may or may not be on the block diagram of the mediator vi. I think it's easier to start with the responsibility tree matching the dependency tree, but it is not a requirement.

3. The purpose of a mediator loop is strictly message routing. They don't do any file IO, VISA commands, etc. This helps prevent message queues from getting clogged.

4. The messages the mediator loop accepts from and sends to "higher" loops define the public api for all the functionality below it. Mediator loops also handle message routing between its immediate sub loops. (i.e. Messages always go up or down; they don't go sideways.)

5. The diagram shows the controller being responsible for the UI and Model components. In truth any of them can be responsible for the other two--it just depends on your goals. It's probably most common to use the UI as the root.

There's a lot of other little bits of information rattling around in my head... I'd better stop there lest I get too long winded.

...what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

This is just my opinion, but the model should be self sufficient except where user interaction is required. I'd definitely put temperature monitoring and automatic shutdowns in the model.

Link to comment

I assume your "Model" is self sufficient and processes internal events through its own "mediator(s)" thingys? If not, what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

OK, the Controller executes Commands, which simply invoke methods on a Context (see Command Pattern). The Context methods (also trivial) delegate their instructions to State methods (see State Pattern) that implement a state machine.

The State methods invoke Model methods directly (OK, via an interface).

The State methods determine which Model methods to call based on:

1) A new external trigger (user interaction, message from another system)

2) An internal trigger (overheatingIsTrue). The Model has a method that calculates that overheatingIsTrue (and will create an error or warning as appropriate) but it does not determine what to do in that circumstance. The state method does. This is actually quite important.

To reiterate, the State methods know what to do but not how to do it. The Model methods just now how to do what they are told.

By the way, we treat an interrupt or other start loop trigger as just another instance of an external trigger (external to the controller thread, but running on the the same hardware in the same application). This simplifies things dramatically.

Within our State methods we have exactly two methods where we wire an error cluster input to a case structure!

[by the way, I view the state machine as part of the controller, not the model. I think the definition of the two is sufficiently ambigous in the literature I have read that you could alternatively define the "model" to encompass what I am calling Context, State, and Model here.]

Link to comment

Great information fellas, I hope I can return the favor somehow someday. Thank you, I had the model looking more like the set of instrument drivers and not the loops that control them. Now it is much more clear how I should be approaching this AND how to name what.

There are many more questions coming but I need to take what I've learned and put it into action first. Also, I'm leaving the Actor Framework to a smaller project in LV2012 and walking the LapDog through this one :yes: It sure is tempting to try and use them all though! Why is it so painful and expensive to be an early adopter? :throwpc:

Link to comment

It's not so much early adoption as it is hours spent up front instead of 10-fold on fixes and more fixes. A well designed application is more or less hitting the ground running, and you can focus on adding functionality or the next application instead of perpetually fixing the old ones.

So the pain you feel is just because you do all the work up front, and the sum of it is much less than if you look back at the work put into a poorly designed application :).

Cheers,

Steen

PS: I hope the "holiday dinner" feeling has faded - for the record I believe the debate about using Shared Variables or not is very much in synch with the topic (if that was the topic you felt sidetracked your thread a bit here). My experience with SVs, which I described here, was a direct response to your "I now see no reason to avoid shared variables for sharing data between vis when only one vi is ever going to write to them" statement. And that experience didn't come cheap. Just for the record. Didn't want to swamp your voice :P.

Edited by Steen Schmidt
Link to comment

A well designed application is more or less hitting the ground running, and you can focus on adding functionality or the next application instead of perpetually fixing the old ones.

Very good quote! If I ever throw that into a presentation I'll give you credit.

As for the holiday dinner, it wasn't so much of getting sidetracked than of many related but distinct conversations going on at once. Not bad, just hard to follow for my experience level. Thanks for all your input, I am glad you came back with some pitfalls of SV's and I am now thinking of messaging all my process values, LED's and whatnot. The result will depend on my skill, I suppose, and if it is too slow or creates too much complexity in message handling I may give your vi registers a try for those needs. The registers are completely self-sufficient, yes? If I remember right, they just drop onto the block diagram without the need for any database or administration type vi's? Do you think they will be highly portable to future LV versions?

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By drjdpowell
      View File Messenger Library
      An extensive library for passing messages between parallel processes. Generalizes the communication method, allowing the message sender to use the method provided by the receiver. Supported communication methods include wrappings of simple queues, user events, and notifiers, as well a more complex channels such as a TCP server and client. In addition, one can configure simple forwarding addresses (“Observers"), which can send messages to multiple destinations, optionally with modifications such as adding a prefix to the message label, relabelling, or substituting a different message.
      Communication patterns supported include request-reply (asynchronous or synchronous), where the reply is sent to a "reply address" attached to the request, and register-notify, where one process sends a registration message to another in order to subscribe to a series of updates.  Also supports scatter-gather, the gathering of replies from multiple senders into an array of messages.
      An option framework for dynamically-launched VI "actors" is also provided, including example templates, which can be accessed via the Tools menu (from an open Project, select Tools>>Messenger Library>>Create Actor from Template..).  An "Actor Manager" debug tool is also installed under the Tools menu.  Please note that this package has nothing directly to do with the NI Actor Framework (other than both packages are influenced by the Actor Model).
      ***Introductory Videos are on a YouTube channel.***
      ***A great summary of many Messenger Library sources, provided by Bob W Edwards***
      JDP Science Tools group on NI.com.
      Original conversation on this work is here.

      Now hosted on the LabVIEW Tools Network (but note that the latest version will often be on LAVA)
      ***NOTE: latest versions require VIPM 2017 or later to install.***
      Submitter drjdpowell Submitted 11/27/2012 Category LabVIEW Tools Network Certified LabVIEW Version 2013 License Type BSD (Most common)  
    • By drjdpowell
      An extensive library for passing messages between parallel processes. Generalizes the communication method, allowing the message sender to use the method provided by the receiver. Supported communication methods include wrappings of simple queues, user events, and notifiers, as well a more complex channels such as a TCP server and client. In addition, one can configure simple forwarding addresses (“Observers"), which can send messages to multiple destinations, optionally with modifications such as adding a prefix to the message label, relabelling, or substituting a different message.
      Communication patterns supported include request-reply (asynchronous or synchronous), where the reply is sent to a "reply address" attached to the request, and register-notify, where one process sends a registration message to another in order to subscribe to a series of updates.  Also supports scatter-gather, the gathering of replies from multiple senders into an array of messages.
      An option framework for dynamically-launched VI "actors" is also provided, including example templates, which can be accessed via the Tools menu (from an open Project, select Tools>>Messenger Library>>Create Actor from Template..).  An "Actor Manager" debug tool is also installed under the Tools menu.  Please note that this package has nothing directly to do with the NI Actor Framework (other than both packages are influenced by the Actor Model).
      ***Introductory Videos are on a YouTube channel.***
      ***A great summary of many Messenger Library sources, provided by Bob W Edwards***
      JDP Science Tools group on NI.com.
      Original conversation on this work is here.

      Now hosted on the LabVIEW Tools Network (but note that the latest version will often be on LAVA)
      ***NOTE: latest versions require VIPM 2017 or later to install.***
    • By Ryan Vallieu
      I have seemingly found an issue with the shipping example code for Nested Malleable VIs.  Another user has verified that he saw the same behavior in 2019.
       
      I am working through the examples and the presentation from NIWeek 2019.  In running the Lesson 2b code (C:\Program Files (x86)\National Instruments\LabVIEW 2019\examples\Malleable VIs\Nested Malleable VIs) I found the Equals.vi in the class was not being leveraged and the search failed.  When I went to my LabVIEW 2018 machine and ran the Lesson 2b.vi the code worked to find the element by correctly leveraging the in-class Equals.vi.
      One difference I see is that in the 2018 example the Equal.vi is in the example folder with the code, and in 2019 the Equal.vi has been moved to VI.lib - otherwise the code looks to be the same.  The Equals.vi code looks identical, and the calling VIM look identical.  I posted on the LabVIEW NI.com forum here: 
      https://forums.ni.com/t5/LabVIEW/LabVIEW-2019-Malleable-VIs-Shipping-Examples-Lesson-2b-Nested/m-p/3966044/highlight/false#M1129678
       
      I am trying to determine what may have broken or changed between the implementation in 2018 and 2019, visually the code looks the same.
    • By Benoit
      Manufacturing a satellite or a simple pen require to test the quality of the product before delivery to the customer.
      LabVIEW is widely used for that purpose. Since 20 years of LabVIEW development I saw numerous test framework. I was wondering if people where interested to work in a collective and open source test framework.
      Per example the following feature can be included:
      HAL (hardware abstraction layer)
      Database to record test results with the data viewer (PostgreSQL)
      single/asynchronous/batch/debug mode
      multi-language support
      Image analysis (open CV) + bar code reader
      User access level
      Remote monitoring
      Jig identification to prevent user error (testing the wrong product with the wrong jig/test sequence)
      HTML/xml/txt report
      and so on....
      Benoit
    • By Voklaif
      Hello all,
      I am programming with LabVIEW for around 2 years and was recently stumbled upon LVOOP.
      I am required to write a communication protocol to work with a micro-controller, which later will be also used for ATP and debug purposes.
      I want to build the program "correctly" from the beginning so it will be maintainable and flexible to additions and changes.
      My natural way of building a program would have been a queued state machine, with several loops, each loop is in charge of a different module (one for GUI obviously), but as I stated in the beginning, I want to use LVOOP.
      Does anyone have a LVOOP project I can use as reference? I've searched online and found some nice examples, but they are small and teach you the basic stuff.
      For me it's important to see the how to use the project tree wisely, where to place the classes, see the managing loop and to learn as much as possible before I create one of my own.
      Thanks in advance,
      Voklaif
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.