LabVIEW Channel Wires

cancel
Showing results for 
Search instead for 
Did you mean: 

Channel Bus

I've just discovered channel wires, and have quickly found several applications for them as I frequently am communicating between parallel sections of code. I like how it provides an elegant and visual method of asynchronous communication (as I believe was their intent). I have a suggestion to further improve on the idea of channels, though I'm not sure how widely used it would be, or whether it is even possible with the way they are implemented.

One of the first things I attempted to do was place several channels into an array...and quickly received a broken wire telling me I could not do so. In my application, I launch several asynchronous instances of a class, each of which has a command processing loop and a message handling loop running in parallel. The command processing loop occasionally modifies the private data of the class, and updates the message handler through a tag channel. The command processor is the ONLY process which will update the current value of the object private data.

Above the classes there is a management VI which sends commands to each class, and updates a front panel with information pertaining to the current state of the class (most of which is handled through references and thus does not require the current value of the object to update). Occasionally however, a value update must be shared with the manager, which I currently accomplish by sending a message to it with the current object value flattened to a string. This works well enough, however, I think it could be improved by the use of a "Channel Bus".

Essentially my thought is that in the VI which launches the asynchronous instances of each class, the object channel each command processor updates could be exported and combined with the channels of each of the other instances, and exported as one channel bus. I could do it by exporting each channel as an individual output, but when you start to get a lot of channels out, this can really clutter the block diagram. My guess is that for the most part, channels are meant to be reserved for very specific tasks, and I've probably gone "channel crazy" in my code.

I'm curious to hear what people's thoughts are regarding this, or if there are "better practice" methods that are currently supported.

Thanks!

Ben Barrett

0 Kudos
Message 1 of 15
(12,537 Views)

If you see\hear JeffK, myself, or anyone else in R&D brainstorming about the possibilities of "zip ties", that's exactly what we're brainstorming about. We're using a term that has absolutely no chance of being the final name both because it keeps us open to possibilities and avoids confusion with other terms of art.

We cannot build them into an array -- arrays are data values. Channels are not data.

We cannot build them into a cluster -- clusters are data values. Channels are not data.

The act of bundling/unbundling a cluster feels similar to what we could/should/might do with channels -- certainly the analogy is there -- but the implications thereof are very different... for example, there could be no "center terminal" for the bundle node except perhaps to supply a name.

> My guess is that for the most part, channels are meant to be reserved for very specific

> tasks, and I've probably gone "channel crazy" in my code.

When one person alone does a thing, they call it an oddity. When multiple people do it, they call it a tool. When the majority does it, they call it a standard. When everyone does it, they do not mention it at all but instead only note its absence.

We have yet to discover where channels fall on this spectrum, but given that most dataflow languages *only* have asynch wires and build incredibly sophisticated programs out of nothing but those, I'm betting that their role in LV will eventually approach ubiquitous.

0 Kudos
Message 2 of 15
(11,888 Views)

I consider myself an "early adopter" (I played with the, shall we say, primitive form hidden inside of LabVIEW 2015, and the "Version 2" form present in the LabVIEW 2016 beta (and in LabVIEW 2016).  One of the LabVIEW techniques I use, particularly in my Real-Time code, are "detached Parallel Loops" that I create using Start Asynchronous Call (I say I "spawned" a VI).

One of my LabVIEW RT Projects utilizes about a dozen spawned loops, both on the Host and Remote part of the Project.  I used Queues and Notifiers to communicate with these detached (and "invisible", hence connecting wires) through one of three techniques -- use of a "Wireless Queue" (an Action Engine that held the Queue Reference and implemented the Queue functions, except for Dequeue), passing the Queue reference in as part of the Start Asynchronous Call, and using Named Queues that can be created inside the Spawned routine, obviating the need for a physical Queue "wire".  Unfortunately, none of these techniques are possible with Channels.

OK, so I have to put all of my parallel loops on the Block Diagram of the main VI, just as illustrated on the Example Projects.  But that means that I have to start them at the same time as my "main" -- a virtue of Spawning them is I could obtain, say, Configuration data, then Spawn the DAQ loop, passing in the Configuration.  So I had to figure out how to do this with Channels.

Well, I've just finished a small Project that uses Channels exclusively.  There are four parallel loops in this Project -- an Event Loop, a Control Loop (configured as a "Channel Message Handler"), a Producer Loop, and a Consumer Loop.  I use a Messenger to connect the Event Loop and the Control Loop, a second Messenger to connect the Control Loop to the Producer (which also runs as a Channel Message Handler, sending messages to itself once it gets into its DAQ mode), and a Stream to connect Producer to Consumer.

I solved the issue of having the Producer "wait" until the Control Loop was ready to start by simply not sending it an Initialize Messenger until the Control Loop had the data it needed to start the Producer.  To stop the four loops, there was an Exit button in the Event loop which sent an Exit Messenger to the Control Loop (as well as stopping the Event Loop).  The Exit Control case sent an Exit Messenger to the Producer, and stopped itself.  The Producer sent a "Last Data, Not Valid" Stream to the Consumer, and stopped itself.  The Consumer stopped itself when it got "Last Data".  So the loops stop sequentially and all is well.

Unless, of course, there's an Error.  That gets trapped in the Control Loop and generates an Error case, recording and clearing the Error, and sending the Exit Messenger to the Control loop, which stops the Producer, which stops the Consumer.  But how about the Event Loop?  I confess, I "cheated".  I made the Exit Button a Push Button, and generate a Value (signalling) property for this button in the Exit Case.  I could have used a Tag, but this seemed unnecessary for this "end-of-program" special case.

I remain enthusiastic about Channel Wires.  However, I have to confess that they are still definitely "a work in progress".  Working with Channels using multiple Projects having VIs and Channels with identical names can be (to put it kindly) "challenging".  I have also had a situation where I made a simplification to my Project (basically I incorporated the code in a sub-VI into its parent, removing the need for the sub-VI.  Everything worked fine in Development Mode.  The original worked fine when I built it as an Executable.  But when I built the "improved" version and ran one particular option, I got the "We Apologize for the Inconvenience" NI Crash Message.  Working with an NI Applications Engineer, I realized it was (probably) a "Channel Issue".  Once I knew that, I cleared out the Channels, rebuilt it, and it ran just fine.

I then spent about three days trying to reproduce the circumstances leading to the Crash (including resurrecting the Before code from Subversion, making the Edit changes again, and then running Before and After code).  No more crashes.  So the Bug is still Out There, but hiding from me ...

Bob "Long-Winded" Schor

0 Kudos
Message 3 of 15
(11,888 Views)

Bob: The fix for the multiple-project-same-name-different-typedef issue that you found will be in LV 2017.

(Note: There isn't going to be a 2016 SP1 becuase of the the accelerated timetable of LV 2017.)

(It *may* get into a patch, but my fix bumps up against the limits of what we are comfortable patching... patches don't get the full test exposure of a beta.)

0 Kudos
Message 4 of 15
(11,888 Views)

Thank you, AQ.  I've been successful (so far) in dealing with this, but it is an annoyance ...

Bob "Always Complaining" Schor

0 Kudos
Message 5 of 15
(11,888 Views)

I tried something similar.  But quickly ran into issues with LV 2015.

I was trying to make a network server that could stream data to multiple clients.  Thus I wanted to asynchrounously launch VIs and give them each a channel as input.  Each could read the data from the channel and stream it to the clients.  But the 2015 version had some bugs in multiple readers.  I believe these have been fixed in LV 16.

I can see why channels cannot be put in an array or a cluster but they can be passed to a subVI.

Is this a good architecture for a multi client server.  At the moment I have an array of network references but cycling through them would cause any one to block all the others.  I would rather just pass the data to independent VIs which act like run time created independent loops.

LabVIEW ChampionLabVIEW Channel Wires

0 Kudos
Message 6 of 15
(11,888 Views)

To me, the advantage of Channels is simplifying and clarifying the definition of static communication between loops that are designed to live and die together.  If one is talking about dynamically "launching" or "spawning" things, or waiting for one loop to do something before another loop starts, then I'm not sure I see Channels as being any advantage. 

0 Kudos
Message 7 of 15
(11,888 Views)

I agree that channels simplify and clarify communication between concurrently running code.  Everything they do can be done with FGV or queues but they are certainly a syntax that makes the code functionality clear and thus helps writing and debugging robust code.  Channels are not a feature but a syntax to make code robust, standard and simple.

But why the limitation to static rather than dynamic concurrently running code.  Since channels can have one writer and multiple readers then it would seem to me to be an obvious design to have a writer and multiply spawned dynamic readers for example.  I just don't quite get the limitation to static connections.

All the channels have an implicit wait for data to be available on the reading side of the loop.  If they have a finite buffering limit then they may also have an implicit wait on the writing side as well.  Tags do not since they are a single overwritten value, but streams etc. do.

LabVIEW ChampionLabVIEW Channel Wires

0 Kudos
Message 8 of 15
(11,888 Views)

I agree with sth here, and from what AQ said about how most dataflow languages work, channels could be utilized for much more. Though for now, I think it is more about clarifying what data is going where since everything channels do can already be implemented through other means. The dominant use by far will be static communication between parallel loops, and many channels will never leave their spawning sub-VI.

I see several of the problems that could arise when trying to tie channels together, what do you mean when you say there can be no "center terminal", is this the term used for the part of the wire which carries data?

I'm curious about the other dataflow languages you mentioned AQ, as LabVIEW is really the only one I have significant experience with, Simulink with Matlab being the other. Are they graphical as well? When you say they *only* have async wires, does that mean they use async wires as the standard and must choose to use wires which force order of execution, or is it not even an option for anything but async? I would like to read up on some of these languages so if you could name one or two of the ones you were referring to I would appreciate it.

0 Kudos
Message 9 of 15
(11,888 Views)

I think the "no center terminal" is the section of the wire that stores data temporarily.  The actual queue memory or shift register.  There is no access to that part.  I think that in an early version that part could be highlighted on the BD in a distinctive color to give the programmer some feedback on how to think about the underlying implementation to avoid misuse.

The history of dataflow languages is extensive.  The first I came across was a company called "Thinking Machines" which built massively parallel hardware to run data flow programs.  They had one when I was a postdoc at BU.  It never really fully lived up to its promise but it is an interesting system and LV could benefit from hardware where threads were limited by number of CPUs.  Christian Altenbech has pushed some of this on 24 core systems trying to optimize performance.

http://www.cs.cmu.edu/~seth/papers/CullerGSvE93.pdf

http://surface.syr.edu/cgi/viewcontent.cgi?article=1027&context=npac

Introduction to Concurrency in Programming Languages

By Matthew J. Sottile, Timothy G. Mattson, Craig E

LabVIEW ChampionLabVIEW Channel Wires

0 Kudos
Message 10 of 15
(11,888 Views)