NIWeek 2011: “Beyond State Machines” Slides and Code Now Available

Thank you to everyone who packed the room for my NIWeek 2011 presentation last week, especially those of you who sat on the floor! The questions and discussion were great, and I’m sorry we only had an hour to kill together.

If you missed my talk, or if you just can’t get enough, don’t worry; the slides and sample code are now available for download below. If you’re interested in interprocess communication in LabVIEW, or if you just want to see a novel use for LabVIEW’s User Events, please give this framework a try! And as always, comments/questions/criticism are encouraged. Join the discussion below.

If this is your first exposure to the JKI State Machine, welcome! The JKI State Machine is a simple yet flexible and powerful template that forms the backbone of everything we do at JKI. You can use it for free in all your projects. Visit our JKI State Machine pages to get started.

 

Title: Beyond State Machines: Building Modular Applications in LabVIEW

Abstract: Nearly every significant LabVIEW application uses multiple loops and several pieces of hardware. Coordinating these moving pieces can create a recipe for unreadable code. Learn how to use a template for interprocess communication based on “public” and “private” events that is easy enough for intermediate developers but powerful enough for Certified LabVIEW Architects.

Download Slides & Code: niweek-2011-jki-beyond-state-machines.zip (4.5 MB)

Notes:
Example code requires LabVIEW 2009 or later.
Example code requires the JKI State Machine. Install the JKI State Machine using the free VIPM 2011 Community Edition if you don’t already have it.

This entry was posted in Events, JKI State Machine, NIWeek and tagged , , , , , , , , , , , , , . Bookmark the permalink.

17 Responses to NIWeek 2011: “Beyond State Machines” Slides and Code Now Available

  1. Shaun says:

    Great presentation – wish I could have seen it in person!

    What was the most annoying bug ever that was fixed in LabVIEW 2011?

  2. Hi Shaun,
    — What was the most annoying bug ever that was fixed in LabVIEW 2011?
    Everyone keeps asking me that :). The bug, and I want to stress that as far as I know this is fixed in LV2011, was a little complicated but I’ll try to explain.

    Basically, if you had a cluster of User Event refnums for which your Event Structure was registered, and you deleted one of those refnums from the cluster (even if the cluster was typedef’d), LabVIEW would remap the frames of your Event Structure to different Events even if those events weren’t related to what you deleted. The worst part was that it would do this in a weird semi-intelligent way where it would remap frames to events whose datatype matched the original ones. The net effect of this was your code would be horribly wrong but syntactically correct so your Run arrow wouldn’t break. You’d find out at runtime that all your API VIs now activated the wrong methods. The only real workaround I ever found was just excessively good documentation and a keen sense of when something bad was about to happen :).

    Anyway, it’s fixed now!

  3. Raúl Rodríguez Pearson says:

    Justin, it isn’t possible to view the video of the presentation from Spain, can you make it available here too? Thanks!

  4. Raúl,
    I’m sorry you can’t view the presentation in Spain. I’m not sure why that’s the case.

    The ZIP file linked in the post (niweek-2011-jki-beyond-state-machines.zip) includes the presentation slides in a PDF, so I’d recommend you just download that.

    Thanks!
    Justin

  5. Yair says:

    Justin, Raúl is talking about the video, which I can’t see either. Based on the text, I’m guessing the video is simply Depeche Mode’s “Just can’t get enough”, which has simply been restricted to US addresses.

  6. Ah, I get it.

    Yes, the linked video is just a Depeche Mode song on YouTube. Perhaps count yourself lucky that you can’t see it, as it’s the kind of thing that will stick in your head for a week ;).

    Justin

  7. Raúl Rodríguez Pearson says:

    I see :D.

    Anyway, thanks for the slides and code!

  8. Jim Kring Jim Kring says:

    @Shaun: Here’s a link to the most annoying bug ever :)

  9. Amiri McCain says:

    Justin, Great job on your presentation! I really enjoyed the detailed explanation of how you guys use dynamic user events for inter process communication. I’m reviewing my notes and going over your slides now…

    Question. We use a single loop queued state machine and launch VI’s dynamically (from MAIN) that need to run in parallel with each other and MAIN knows the queue names of all of parallel processes and in that way from MAIN we can enqueue any state we need to and through an FG share data.

    I see our method as similar to what you do with dynamic user events, (okay, here’s the question) but could you explain in just a sentence or two the major pros/cons of doing it (inter process communication) the way you detailed in your presentation versus the way that I am doing it with ques and que names?

    Thanks,
    Amiri

  10. could you explain in just a sentence or two the major pros/cons of doing it (inter process communication) the way you detailed in your presentation versus the way that I am doing it with ques and que names?

    Hi Amiri,

    Sorry for the delay in getting around to answering this.

    That’s a great question. To boil it down into just a few points:
    Pros
    * Events preserve the native datatype of the event data — you never have to deal with Variant to Data and the associated uncertainties of that.
    * Events (at least in this template) are a one-to-many pattern. Multiple modules can register for any other module’s events. Queues, by contrast, are many-to-one pattern because only one piece of code can receive the queue data.
    * Events allow you to receive data from multiple sources in the same Event Structure. With queues, if you want to receive data from two different sources you have to do it with two separate Dequeue operations. This simplifies things pretty dramatically in large applications, where a module might be receiving events from 5 or 6 or 10 other modules.

    Cons
    * Events don’t allow for inspection or manipulation of the event queue. You can’t check to see how many events are pending, and you can’t force the queue to flush. There are some rumors that NI may improve this eventually, but for now it is what it is.
    * Events don’t allow for “Insert at Front” behavior – i.e. you can’t interrupt the queue to handle high-priority messages.
    * The event queue has some odd behaviors that can be confusing if you’re not expecting them.

  11. James Powell says:

    One can get some of those “Pros” with queues too. Have each receiver make one queue and pass it to multiple senders, and have the senders deal in arrays of queues, and you have a many to many architecture with only one queue per module.

    One can also get datatyping advantage by using LVOOP objects as messages instead of variants, and using dynamic dispatch and the “command pattern”. Doing this with User Events is perhaps a lot easier to grasp (for me at least), so this is still a strong advantage of your User Event design over Queues.

    Nice design, BTW. My only questions about possible “Cons” are:

    1) What if I want two of a module? Or N clones, with N specified at runtime?

    2) What if I have Module A all working and interaction with Module Main, and I learn that I need Module A to run on a different computer (i.e., over the network from Main). Can I make that work? An advantage of the basic enqueue/dequeue functions is that they map well to TCP write/read (or various other network communication APIs) so one can think if making a “network queue” more easily than a “network User Event”.

    — James

  12. Hi James,

    You’re correct – there are lots of ways to build many-to-many patterns. The main advantage of this User Event-based pattern in that regard is that the “guts” of it are a lot easier to understand because it relies heavily on the event handling system that’s built into the backend of LabVIEW. Other approaches (like the queue-based thing you mentioned) typically involve creating that backend from scratch. That’s a double edged sword: you get to make it however you want :), but you also get to spend time creating/debugging/maintaining it :(. You’re completely right, though, that it’s an alternative option.

    You also make a great point about the Command Pattern. It’s something I’d like to learn a lot more about. Personally I’ve found every implementation of it I’ve seen pretty hard to follow, but I see a ton of potential in it and I think for someone immersed in it, it might be a really natural way to do things.

    | 1) What if I want two of a module? Or N clones, with N specified at runtime?

    That’s a great question, and that use case is just beyond the scope of this presentation. We have an extension of this template at JKI that covers this, and maybe (no promises) I’ll get to talk about it someday. Basically, it kind of boils down to “Make the Process and Get Public/Private Events VIs re-entrant; Turn the LVLIB into an LVOOP object whose private data is references to those re-entrant VIs; use that LVOOP object like a by-reference handle to the module.” In practice there are some real gotchas to this, which is why it’s not something we’ve tried to boil into a one-hour NIWeek talk :).

    | 2) What if I have Module A all working and interaction with Module Main, and I learn that I need Module A to run on a different computer?

    Another great question, and one that I don’t have a pat answer for because I haven’t had to do it with this particular template yet (although again, we have another extension at JKI that natively supports remote communication).

    My first recommendation would be to just create a new module on each end of the TCP/IP connection, whose sole job is passing messages over TCP/IP. These TCP/IP modules would register for all the necessary Public Events and use the Public API of the modules they’re connected to. The details of how the events/API calls get serialized & unserialized is something you’d have to work out, but there are a few benefits of this approach:
    * The modules actually doing the real work on either end would have no idea their APIs are being mapped over the network – as far as they’d know, that DMM or motor or other instrument is still just “there.”
    * The TCP/IP modules would be very simple and lightweight.
    * Because the TCP/IP modules are constrained to use the Public Events and Public API of whatever they’re connected to, the design naturally enforces weak coupling. Other options (like making the TCP/IP comms part of each module itself) run the risk of becoming leaky abstractions.

  13. James Powell says:

    That’s a double edged sword: you get to make it however you want, but you also get to spend time creating/debugging/maintaining it.
    I can certainly vouch for that. From experience.

    “Make the Process and Get Public/Private Events VIs re-entrant; Turn the LVLIB into an LVOOP object whose private data is references to those re-entrant VIs; use that LVOOP object like a by-reference handle to the module.”
    Yes, on thinking about, I thought that it should be relatively easy to do something like this. Personally, I’m not a big fan of “wireless” sets of subVIs, so I would prefer a “handle” even if I was pretty sure I would never need more than one of something.

    My first recommendation would be to just create a new module on each end of the TCP/IP connection, whose sole job is passing messages over TCP/IP…
    Unless I’m mistaken, you would need a new custom module for each connection. With no way to treat User Events generically (is this statement true?) you cannot write a generic TCP-module that can couple arbitrary other modules together across a network (sudden side thought: can you use Shared Variable Events in your framework to allow network communication?).

    An advantage of using LVOOP message objects (or the old text/variant messages) is that, though one has to create the “backend”, the backend only deals with the generic message objects, and is independent of the actual types of the messages transmitted. Thus you don’t have to customize anything for a specific pair of modules communicating. You can also write your Modules to use semi-generic “Messengers” rather than explicit queues. Normally one can plug-in a Queue-based child Messenger for local communication, but can plug in a TCP-based child Messenger for network communication, without making any changes to the Module itself (not that I’ve gotten around to actually writing a TCP-based Messenger yet).

    — James

  14. Amiri McCain says:

    Justin,

    Great, thanks for the explanation and interesting discussion between you and James…. “Leaky Abstractions” first time I have ever heard that expression, if i ever open an art store, this will be the name. 😉

    I hope that you keep presenting and building on this theme at NI Week 2012. I would like to hear more details and explanations of how to use this template with a plugin architecture.

    Amiri

  15. Pingback: NI QMH Template

  16. Pingback: Something happened: Events in LabVIEW

  17. Pingback: Ours is not better than yours (YAF)

Leave a Reply

Your email address will not be published. Required fields are marked *