LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Labview Design Tips

Hello all,

I have difficulites in designing bigger Labview applications. I have
got a huge program which is related to what I have to develop. But
this sample program uses *many* global variables, it is a mess for me.
Therefore, I decided not to use global variables in my application.
Now I realize that this is not so easy in Labview. These are my
problems:

I certainly want to modularize. Is it true that *all* the inputs and
the outputs of a sub-VI must be controls? As a consequence I have to
use a lot of dummy controls that shouldn't be visible in the front
panel.

Another problem is the number of terminals of a sub-VI. I have tried
to bundle the input and output wires into a cluster and vise vera. But
this seems to be too cumbersome: First I have
to create a dummy
cluster control (the shell). Then I have to include the controls
(dummy or not) into the cluster shell. I have no idea how to draw the
shell across the controls if they are scattered in the panel. The only
possiblity I can see is to create additional dummy controls in the
cluster shell and copy the values of the 'real' controls to them. Then
I have a cluster link between sub-VI. Inside the sub-VIs I have to
bundle/unbundle the clusters. This only makes sence if I use 'Bundle
By Name'. But then I first have to bundle the lines into a cluster and
then give all the lines a name.

Probably the most useful design is as follows: Create a (dummy) VI
which contains only controls. The wires of the controls are the
interface lines between all sub-VIs. Create and use global variables
of the controls.


I am expectant to hear expert design ticks.


Bye

Johannes
0 Kudos
Message 1 of 8
(4,509 Views)
Hi,

Most questions about making large programs are about the architecture. If
you want to make your program modular (you should...), the architecture is
the bigger concern. There are much possibilities; state machine, buffered
state machine, queued state machine.


"Johannes Eble" wrote in message
news:3e2e5ab0.168981606@news.online.de...
> Hello all,
>
> I have difficulites in designing bigger Labview applications. I have
> got a huge program which is related to what I have to develop. But
> this sample program uses *many* global variables, it is a mess for me.
> Therefore, I decided not to use global variables in my application.
> Now I realize that this is not so easy in Labview. These are my
> problems:

Not using globals is a wise choise.


> I certainly want to modularize. Is it true that *all* the inputs and
> the outputs of a sub-VI must be controls? As a consequence I have to
> use a lot of dummy controls that shouldn't be visible in the front
> panel.

Inputs must be controls, outputs must be indicators...

If you design modules, you should try to group them. Not every group will
need to have all inputs. Catagories to group by are: drivers for hardware,
window tools, MMI vi's, utilities, string manipulation, general file I/O,
app specific file I/O. E.g. an application specific file I/O function might
only need a 2d array and a file name. The module stores the file to the
path. No need for all the other inputs.

Mixing a hardware dirver with e.g. arithmetics is a mistake. This prevents
the reuse of the hardware driver, and the arithmetics. An exception to this
is the MMI. In LabVIEW the MMI window it often the window that controls the
process, and thus calls all the other subvi's that are needed in the
process.

If you need to pass data to other modules (e.g. tag values, or parameter
values, logged data), you can use a 'global data bus' (a.k.a. a buffer vi,
global vi, smart buffer, LV3 global), or an ini file reference. This still
has some backdraws, just like globals; it does not follow the flow
drivenness of LV, it's harder to make. It has advantages over a global; it's
easier to synchronise, clearer to read, easier to document, simpler to
use...

A module (e.g. a trending window) might even read all data it needs from a
file. This way it could suffice to have only one input, the file path.
Another module, e.g. the logging module, can write to the same file. This
way, the trending window can easily be reused to open stored files.

> Another problem is the number of terminals of a sub-VI. I have tried
> to bundle the input and output wires into a cluster and vise vera. But
> this seems to be too cumbersome: First I have to create a dummy
> cluster control (the shell). Then I have to include the controls
> (dummy or not) into the cluster shell. I have no idea how to draw the
> shell across the controls if they are scattered in the panel. The only
> possiblity I can see is to create additional dummy controls in the
> cluster shell and copy the values of the 'real' controls to them. Then
> I have a cluster link between sub-VI. Inside the sub-VIs I have to
> bundle/unbundle the clusters. This only makes sence if I use 'Bundle
> By Name'. But then I first have to bundle the lines into a cluster and
> then give all the lines a name.

'Bundle By Name' is much more fool proof. I always regret when I choose to
use a normal bundle because it's faster to code.


> Probably the most useful design is as follows: Create a (dummy) VI
> which contains only controls. The wires of the controls are the
> interface lines between all sub-VIs. Create and use global variables
> of the controls.

I still cannot see why you need all the controls on every subvi...

Regards,

Wiebe.


>
> I am expectant to hear expert design ticks.
>
>
> Bye
>
> Johannes
>
0 Kudos
Message 2 of 8
(4,508 Views)
Johannes Eble wrote:
> Hello all,
>
> I have difficulites in designing bigger Labview applications. I have
> got a huge program which is related to what I have to develop. But
> this sample program uses *many* global variables, it is a mess for me.
> Therefore, I decided not to use global variables in my application.
> Now I realize that this is not so easy in Labview. These are my
> problems:
>
> I certainly want to modularize. Is it true that *all* the inputs and
> the outputs of a sub-VI must be controls? As a consequence I have to
> use a lot of dummy controls that shouldn't be visible in the front
> panel.

The inputs and outputs of a sub-vi are controls _within_ the sub-vi.
When you put the sub-vi onto the higher level diagram, those controls
become wire connection points and the controls don't appear on the
front panel. Think of the in-built VIs, when you put a multiply VI
on a diagram, you don't get 'x', 'y' and 'x*y' controls appearing on the
front panel.


>
> Another problem is the number of terminals of a sub-VI. I have tried
> to bundle the input and output wires into a cluster and vise vera. But
> this seems to be too cumbersome: First I have to create a dummy
> cluster control (the shell). Then I have to include the controls
> (dummy or not) into the cluster shell. I have no idea how to draw the
> shell across the controls if they are scattered in the panel. The only
> possiblity I can see is to create additional dummy controls in the
> cluster shell and copy the values of the 'real' controls to them. Then
> I have a cluster link between sub-VI. Inside the sub-VIs I have to
> bundle/unbundle the clusters. This only makes sence if I use 'Bundle
> By Name'. But then I first have to bundle the lines into a cluster and
> then give all the lines a name.
>
Putting controls into a cluster is easy. Assuming that you've already
got a working vi and then want to 'clusterise' it try the following...

First put a cluster control on the front panel, then drag the controls
you want into the cluster control. You can select the cluster control
and right-click to bring up a sub-menu which has an option to let
the cluster autosize itself to fit the controls if you want.
Once you've done that, switch to the diagram and you'll find it has
broken as the controls are now disconnected from where they were connected.
Select the cluster control on the diagram and drag it to somewhere handy,
then right click and select 'Cluster Tools|Unbundle by name'. Add and select
elements to the unbundler and then wire these back to the appropriate places
in the diagram - your vi should now work the same as it did before, except
that the inputs are now in a cluster.

Converting a bunch of indicators to a cluster is a bit trickier, as the
'Bundle by Name' component wants an input cluster, however we can let
Labview create an input cluster for us...
Put an empty cluster control on the front panel as before.
Drag the indicators you want into the cluster, resizing it as needed or
using
the auto-resize option.
Switch to the diagram. This will now be broken as the wires that used to
lead to indicators will end in mid-air.
Select the new output cluster and from the right click menu select
'Cluster Tools|Bundle by name'.
Wire the output of the bundler to the output cluster.
Select the output cluster and from the right-click menu select
'Create|Constant'.
Wire the cluster constant to the input cluster terminal of the bundler.
Now add and select elements on the bundler until you have inputs
for each of the indicators in your cluster.
Wire the inputs of the bundler to the appropriate places in the diagram.
Your diagram should now work as before except that the outputs
are now in a cluster.

You can do all this with Bundle and Unbundle components but I prefer the
'Bundle by Name' version as its more obvious what connects to what.

If you want to create a second sub-vi whose input cluster connects to the
output cluster of a vi you already have, the easiest way is to copy the
output cluster from the first vi to the second vi and then use the
'Convert to Control' sub-menu option.



> I am expectant to hear expert design ticks.
>
No expert, just someone who has done it a couple of times.

HTH HAND
--
Remove "spamkill." when replying to this message
0 Kudos
Message 3 of 8
(4,508 Views)
Hello Wiebe,

thanks very much for your answer. Your advices are interesting.

I come from an object oriented background, mostly Java, but I have
also come across Python, C++, Smalltalk, and Eiffel. These languages
are mostly non-visual (well, except for GUI builders). On the other
hand, they support polymorphism which is only supported to some extend
in LabView. Also, I can't define new data types (classes) in LabView.
For instance, I have had the following difficulty in LabView:

At a certain point in a VI there is a cluster connecting the sequences
of a frame. The cluster contained only numeric lines, so I could have
used an array as well. Now, I wanted the following: One line of the
numeric lines should behave polymorphic at run time. Depending on an
option menu the line should sometimes be numeric, sometimes be an
array of numerics itsself. The cluster and the sub VIs connected to
the cluster shouldn't care about what is inside the cluster. But in
LabView, cluster is not cluster. Some sub VIs indeed behaved
polymorphic, but not all. After trying this and that I gave up. Now
the line (inside the cluster) which should have been polymorphic is
always of type array and most of the time the array contains one
'real' element and several dummy elements just to remain type-save.
Not a 'nice' solution in my mind. In an OO-language I whould have
defined an abstract class 'Parameters' and implemented (inherit) the
subclasses as needed and so on.

Another problem which was related to that above: The input was a
string control. It has to be checked if this control is empty or not
(Empty String/Path VI). Now I had an array of string controls as input
and it has to be checked if any of this string controls is empty. But
the 'Empty String/Path' VI doesn't (polymorphically) accept multiple
strings or string arrays and the 'logical and' VI doesn't accept
multipe inputs. I did the following to get the desired behavior: First
convert the array of string to a cluster (Array to Cluster VI). Then
unbundle the cluster to get the strings. Then check each single string
with 'Empty String/Path' respectively. Then build an array of booleans
with the boolean outputs of the 'Empty String/Path' VIs. Then, after
all, connect the output array of booleans to a 'And Array Elements'
VI. The output of this VI was *sweat* the output I wanted to have.

There are probably better ways to get the above behavior. I just have
to get used to another paradigm.


On Wed, 22 Jan 2003 11:44:09 +0100, "Wiebe@AIR" wrote:

....

>Inputs must be controls, outputs must be indicators...

I get to understand that 🙂

By the way: Is there an easy way to group MMI controls to get compount
controls? I often would like to group a decoration together with some
controls. If I want to move the whole group then I always have to draw
a line with the pointing device to include all the elements. Or I have
to select all elements with the shift key.

>
>If you design modules, you should try to group them. Not every group will
>need to have all inputs. Catagories to group by are: drivers for hardware,
>window tools, MMI vi's, utilities, string manipulation, general file I/O,
>app specific file I/O. E.g. an application specific file I/O function might
>only need a 2d array and a file name. The module stores the file to the
>path. No need for all the other inputs.
>
>Mixing a hardware dirver with e.g. arithmetics is a mistake. This prevents
>the reuse of the hardware driver, and the arithmetics.

Sounds interesting. I am used to the Model-View-Controller approach in
Smalltalk: The Model is the actual behavior of the application (the
data), the View is the representation on the screen (the look), and
the Controller is responsible for user interaction (the feel).
Sometimes the View and the Controller are together, but the main point
is that you should separate the representation and the user handling
from the data.
What do you mean by hardware driver? I have to use a DAQ-card and a
GPIB device in my application. I get several inputs from the DAQ-card,
an output of the application is sent to the GPIB device. Now, should
there be one (or several?) VI just reading from the DAQ card and
writing to the GPIB?

>An exception to this
>is the MMI. In LabVIEW the MMI window it often the window that controls the
>process, and thus calls all the other subvi's that are needed in the
>process.

I have a start screen the user have to input all data necessary for
the measurements. Then another screen showing the measuring process
appears. Probably there should be a splash screen before the start
screen and a status screen at the end (but this is cosmetics). So I
have at least two MMI VIs.

....

>> Probably the most useful design is as follows: Create a (dummy) VI
>> which contains only controls. The wires of the controls are the
>> interface lines between all sub-VIs. Create and use global variables
>> of the controls.
>
>I still cannot see why you need all the controls on every subvi...

You are right, I don't need all of them on every subvi. But if I use
globals (I do not now) it is probably better to centralize all of them
in one subvi. If a certain VI uses a certain global reference it is
probably better to know that it is always defined in one 'globals' VI.


Johannes
0 Kudos
Message 4 of 8
(4,508 Views)
> I come from an object oriented background, mostly Java, but I have
> also come across Python, C++, Smalltalk, and Eiffel. These languages
> are mostly non-visual (well, except for GUI builders). On the other
> hand, they support polymorphism which is only supported to some extend
> in LabView. Also, I can't define new data types (classes) in LabView.
> For instance, I have had the following difficulty in LabView:
>

LV does have polymorphism support in its built-in nodes, and if you have
a modern version of it, in subVIs. The major difference is that some of
these languages are late binding where others, including LV are early
binding. The tradeoffs are of course that early binding allows for
compilation, typically leading to quicker execution, and with stricter
syntax is able to point out some bugs before execution begins. The
advantages of late binding are that the language has looser syntax
allowing for more flexible code, and with good JIT compilation and a
good debugging environment, their performance can be quite good.

Anyway, here are a couple things that may help. To define custom types,
you have two primary mechanisms -- clusters and arrays. The type is
strict, but you can arbitrarily combine them into a large number of
types. Again, the built-in nodes will adapt to the types, and you will
be able to build operators/methods on these types as subVIs. If you
have a modern version of LV, then these subVIs can be combined to
present a smaller interface by making polyVIs. You make several
datatype signatures and combine them into a polyVI to make what is
essentially a base class.

If you would like to have late binding behavior, then you probably want
to look at using the variant datatype. Putting a variant on a connector
pane, you have a subVI that will accept all datatypes. You will then
need to handle the types on the diagram, typically by casting them to
the accepted types and operating on them as fixed types.

Another approach to look at is GOOP. These libraries are built on top
of LV and allow for instanciation. One approach would be for an element
of your cluster to be a reference to an object. That object would
sometimes contain a single element, other times mutiple elements.
Search for GOOP and you should find lots of info.

Greg McKaskle
0 Kudos
Message 5 of 8
(4,508 Views)
Hello Dave,

thanks very much for your answer. I have rarely got such a detailed
explanation.



On Wed, 22 Jan 2003 12:23:38 -0000, "Dave Langstaff"
wrote:

....

>Wire the output of the bundler to the output cluster.
>Select the output cluster and from the right-click menu select
>'Create|Constant'.
>Wire the cluster constant to the input cluster terminal of the bundler.
>Now add and select elements on the bundler until you have inputs
>for each of the indicators in your cluster.
>Wire the inputs of the bundler to the appropriate places in the diagram.
>Your diagram should now work as before except that the outputs
>are now in a cluster.

....

I didn't know the trick with the constant. Works great!

On the other hand, ther
e should be a module 'bundle/unbundle by name'
without requiring the intermediate cluster IMHO. The diagrams of the
super VIs get cluttered up by the cluster constants. The constants
look like important petrol stations, but they are only there for
formal / syntactical reasons.


Johannes
0 Kudos
Message 6 of 8
(4,508 Views)
Hi Greg,

On Fri, 24 Jan 2003 16:03:09 GMT, Greg McKaskle
wrote:

>> I come from an object oriented background, mostly Java, but I have
>> also come across Python, C++, Smalltalk, and Eiffel. These languages
>> are mostly non-visual (well, except for GUI builders). On the other
>> hand, they support polymorphism which is only supported to some extend
>> in LabView. Also, I can't define new data types (classes) in LabView.
>> For instance, I have had the following difficulty in LabView:
>>
>
>LV does have polymorphism support in its built-in nodes, and if you have
>a modern version of it, in subVIs.

I use version 5.1. Modern enough?

>The major difference is that some of
>these languages are late binding where others, including LV are early
>binding.

What you call 'late binding'/'early binding' I would call 'implicit
typing'/'explicit typing'.

In C++, Java, (and Eiffel with other syntax) you have to write int
i=0, long count, float value and so on. This is explicit typing. The
types can be checked at compile time. But you can perform 'late
binding' with these languages. In C++, early binding is the default
(for performance reasons I guess), but you get late binding if you
declare the methods in your base class 'virtual'. Then you can
overwrite these virtual methods by the methods with the same name in
your sub classes. In Java, Eiffel, and Smalltalk, late binding is the
default. In Java and Smalltalk there is even no possibility to get
early binding.
On the other hand, you don't have to explicitely type in Smalltalk and
in Python. The types are checked at run time.

I think that late binding (my definition) is a fundamental and
important feature. I wouldn't call a language object oriented without
it. I am not so clear with explicit/implicit typing. Personally I
prefer implicit typing since it reduces the developing time. On the
other hand, in larger projects (>1000 classes) and if speed is an
issue then explicit typing could be an advantage.




Johannes
0 Kudos
Message 7 of 8
(4,508 Views)
> I use version 5.1. Modern enough?
>

Well, I think 5.1 was released in '99. So, not quite modern enough. I
believe that polymorphic VIs were introduced in 6.0, or LV 6i as it was
officially named.


> What you call 'late binding'/'early binding' I would call 'implicit
> typing'/'explicit typing'.
>
> In C++, Java, (and Eiffel with other syntax) you have to write int
> i=0, long count, float value and so on. This is explicit typing. The
> types can be checked at compile time. But you can perform 'late
> binding' with these languages. In C++, early binding is the default
> (for performance reasons I guess), but you get late binding if you
> declare the methods in your base class 'virtual'. Then you can
> overwrite these virtual methods by the methods with the same name in
> your sub classes. In Java, Eiffel, and Smalltalk, late binding is the
> default. In Java and Smalltalk there is even no possibility to get
> early binding.

You are right, early and late don't really describe the whole picture,
just one aspect of it. In C++, however, even though the exact datatype
isn't known until late, because of the explicit typing, you do know its
base class early so that the compiler can prevent illegal usage based
upon the base class.

> I think that late binding (my definition) is a fundamental and
> important feature. I wouldn't call a language object oriented without
> it. I am not so clear with explicit/implicit typing. Personally I
> prefer implicit typing since it reduces the developing time. On the
> other hand, in larger projects (>1000 classes) and if speed is an
> issue then explicit typing could be an advantage.

The tradeoff between them is the same point I was making. Implicit is a
more expressive syntax. Though more prone to error, if used correctly,
the programs are smaller and more elegant. Explicit typing typically
catches errors in the program earlier and generates more efficient code
so that adding two integers together doesn't involve more than one
machine instruction.

In its current state, I agree that the LV language is not object
oriented. It is strictly early binding, and the array and cluster are
its data construction tools. The GOOP toolkit is built on top of LV and
it should be compatible with 5.1. Similar to how C-Front added object
oriented classes and virtual dispatching to C. GOOP adds object
oriented tools to LV. GOOP isn't part of the language, but a
library/framework that allows for OO programming in a non-OO language.
You may find it useful.

The other tools I described, variants and poly-VIs would also be useful
for solving your other problem, but in a non-OO or less-OO way.

Greg McKaskle
0 Kudos
Message 8 of 8
(4,507 Views)