LabView - coltonlab

advertisement
LabView Tutorial
By Lee Wienkes and David Meyer
This work has been support by Dr. John Colton
Table of Contents:
0. Introduction
1. Starter Tutorials
1.1. Without Instruments
1.1.1. The Basics: The Screens, Types of Variables, etc
1.1.2. Case and Sequence Structures
1.1.3. Loops
1.1.4. SubVI’s
1.1.5. Arrays & Clusters
1.1.6. Global Variables: Interrupt Buttons and Constants
1.1.7. Graphing, Property Nodes, Text Rings/Enums and Formulas
1.1.8. Decorations – Making it Look Nice (Interlude)
1.1.9. Event Handling: Efficient User Input and Variants
1.1.10. Time and Dialogue
1.1.11. Debugging and Error Handling
1.1.12. File Operations
1.1.13. Misc. Topics
1.2. With Instruments
1.2.1. Communicating with Instruments: Back to Basics (GPIB, RS232, and ActiveX)
1.2.1.1. GPIB
1.2.1.2. RS232
1.2.1.3. ActiveX
1.2.2. Serial Polling
2. The Equipment
2.1. The Spectrometer
2.2. The Pulse Generator
2.3. The Photon Counter
2.4. The Synapse CCD
2.5. The Magnet
2.5.1. Power Supply
2.5.2. Temperature Control
2.5.3. Level Meters
2.5.4. Putting it all together
2.6. Scans: Example with the Spectrometer
3. Helpful Coding Suggestions
4. References and Further Reading
5. Appendix
5.1. Numerical String Formatting
0.0 Introduction
Back to Top
Welcome to LabView! This is probably your first look at things, so we will try to start
from the beginning. I am assuming you have had some kind of computer program experience;
that is you at least understand the basic concepts of variable, loops, etc and just need to learn the
syntax and format of the LabView program. This is (or will be soon) an entire series of tutorials
covering a variety of subjects in LabView – the usual format will be a brief outline of what is
contained, an exercise(s) to be done at the end of the tutorial (solution is included in this folder
as well) and then all the pertinent information. As concepts do build on each other, these
tutorials should be done in approximately the order intended, though that is not to say that you
couldn’t figure stuff out if you skipped one, but if you don’t know a word or concept, chances
are you missed it in one of the previous tutorials. The tutorials begin with a basic exploration of
LabView and its abilities and functions (both with and without instruments attached) and then
proceeds to programming issues specific to the equipment we have in the laboratory.
1.1.1 The Basics
Back to Top
LabView is graphical programming language in contrast to text based languages like Java
or C++. You program by placing icons on a screen and then linking them up with wires, with
various operators that represent functions. In the end, it looks like a cross between a flow chart
and a schematic diagram.
To start off with, in LabView you have two screens – the Front Panel and the Block
Diagram – both of them together compose the VI (Virtual Instrument), which is your program.
The front panel is your graphical interface; that is what you will see when the program is actually
running. This is where you will put your buttons, text boxes, numerical indicators and so on.
Right-clicking on the background of the front panel will bring a palette, which has all the
different types of objects that you can use1. They are grouped by variable type (e.g. Boolean,
numerical, etc). Each item you place on the front panel (with only minor exceptions) will have a
counter part on the block diagram called the terminal. Once they have been placed, both items
may be moved separately; that is if you move an object on the front panel, it’s counterpart on the
block diagram does not move, but if you delete one, the other will also disappear. The block
diagram is essentially the code of the program, though it is a graphical kind of code. You must
link up the various terminals with wires to transfer data between them. In addition to the
terminals there are numerous functions that LabView provides – such as add, subtract, Boolean
operations, etc. Later on, we will learn how to make our own functions, which will be called
subVI’s.
There are two main types of front panel objects – controls and indicators. As one might
suspect, indicators can only be used to display something during run time – the user cannot alter
these values while the program is running, only the code (block diagram) can. Controls let you
alter a value from the front panel during run time, but can also be changed by the code by using
local variables (we’ll get to what that means later).
There is another important way to divide the objects in LabView; by data type. The
common ones are numeric (which can be further defined as integers, floating, etc), strings,
Note: I would recommend changing your palette options. Go to “Tools:Options…” and find “Controls/Functions
Palettes” in the pull down menu. From there, choose “Palette View” to be “Advanced” and “Format” to be “All
Icons”.
1
Boolean, arrays (which can be string arrays, Boolean arrays, numeric arrays, etc), clusters and
finally the code (which is also represented visually).
As mentioned before, the code is very similar to a flow chart. There are the
representations of your data (i.e. your variables), “nodes”, which carry out operations or call
functions, and wires that transmit your variables to the nodes or data between nodes. All of the
abstract operations from text-based coding now become physical realities; wires you can follow,
nodes you can see, etc. As an example, let us examine Figure 1.1. We can see all the different
parts of LabVIEW, as we can see both the block diagram and the front panel. The wires,
variables and function nodes are pointed out. Additionally, the front panel object is linked to the
object on the block diagram to indicate the dual nature of the objects. Notice that there is no
front panel representation for the function node; this exists only in the code.
Figure 1.1: Some of the many things you will find in LabVIEW; wires for connecting data,
controls and indicators for user interaction and function nodes to perform operations.
Introduction of Variables in LabVIEW
Variables are an important part of LabVIEW. There are three kinds of variables: your
“terminal” (which is the actual object on the block diagram), local and global. The first two
types will be discussed here and global variables will be saved for a later chapter. The first two
types of variables are the same in almost every way; the only difference is that the terminal
reflects the input/output nature of the front panel object. That is, if the front panel object is a
control, you can only take data from the terminal. Local variables are used when you need to
reference a front panel object more than once in your code (a highly likely situation). There are
two ways to create a local variable; the first is to right-click on the terminal or front panel object
and select “Create:Local Variable” from the list of options. This will automatically create a
write-only local variable. The second way is to go to the structures palette in the block panel and
select local variable. This will allow you to place a blank local variable, which you can then link
to any object already in existence by click on the “?” in the center of the local variable. You can
link multiple local variables to the same object.
Once you have a local variable, you can right-click on it to change its read/write status.
Note, this does not affect the control/indicator status of the front panel object; it only affects the
particular local variable selected. This is how you can change the value of a control during the
program without user input. You can have essentially an infinitely number of local variables for
a particular object and they are all linked, so that when the value for one instance of a variable
changes, all of them change.
Below is a list of variable types. Each variable type corresponds to a certain color that
makes it easy to distinguish variable types. Black is reserved for “undefined” – usually your
program will not run if you have any black variables floating around. All wires, variables and
constants are color coded. Notice that, with the exception of Boolean buttons, all variables types
behave the same on the block diagram, even if they have different visual representations on the
front panel.
List of Variable Types:
1. Boolean (green)
A true/false variable. This variable type is used in logic operations (AND, OR, XOR,
etc), if/then statements, cases, comparisons, etc. The main complication of this variable
type comes with mechanical action property that is found by right clicking on the front
panel object. Booleans with non-latching mechanical action settings cannot be used as
local variables as their value is not steady. You can convert an array of Boolean
statements into an integer (and vice versa). This is often useful in reading the status of
instruments.
2. String (pink)
Strings consist of characters, which have numerical ASCII values. There are a wide
variety of built in functions for strings, such as concatenate, search, replace, etc.
Additionally, you can convert many types of variables into strings, which is sometimes
done to display coherent messages (e.g. “The wavelength was measured to be 801 nm”,
where 801 was probably a number at some point). These conversions are all found in the
string palette on the block diagram.
3. Numerical (blue = integer, orange = fractional - floating point, scientific, etc)
A number that can be in many formats: integer, floating, single/double precision,
complex, time stamps, etc. LabVIEW is usually good about being able to convert
between the different formats if it needed. For example, you can add a time stamp and an
integer; it simply takes the integer to be seconds and adds accordingly. There are also
many numerical operations and functions that can be found on the numerical palette on
the block panel (but not on the front panel palette because function nodes have no front
panel representation). NOTE: You can make any integer a floating by adding a decimal
and zero. LabVIEW will get rid of your decimal point but the number will change from
blue to orange.
4. Array (thick/double line – matches variable type color)
An array is an indexed list of elements. You can have an array of almost any data type;
an array of Booleans, numbers, strings, etc. The only stipulation is that they are all of the
same data type – this goes even for different types of integers! For example, if you have
an array of integers and put 6.3 into it and then look that value up later, you will find that
it has become 6. Furthermore, arrays can have more than one index (i.e. a 2D or 3D
array). Commonly used built in functions are: search, sort, index (picks an element of the
array) and insert.
5. Cluster (brown)
A cluster is similar to an array in that it is a collection of elements. However, clusters
have no index and can contain multiple data types. Thus you can have a cluster that
contains a string, a number and a Boolean. You can create arrays of clusters.
6. Path (blue-green)
Related closely to string. Can convert to a single string or an array of strings.
7. Ring/Enum (blue, because it is really an integer index)
This variable type allows you to choose from a list of options. The main difference
between these two variables is that in an enum you can reference a string (the label of
that option) while in a ring you must reference its index number.
8. Graphs (brown or pink)
Graphs are not really a different data type, they are really a different way of displaying a
specific data type. A graph is an array of clusters, where the cluster contains the
coordinates for a point on that graph (two points if it is a 2D graph). Furthermore, these
arrays can be clustered again, then put into another array to form a muli-plot graph. This
is outlined below:
Cluster of Points  Array  Single Plot Graph
Cluster of Points  Array  Cluster of Arrays  Array  Multi-plot graph
Constants
Besides variables, there are constants as well in LabVIEW. These follow all the variable
types, but are simply fixed values that you can use. For instance, if you wanted to divide a
number by two, you can wire the input number to the “divide” function node, along with the
constant two, and the output will be x/2. Thus, you don’t need a variable for every number in
your program; just the ones that might change!
Comments
Comments are a very important aspect of any programming language; it lets others (or
you if it is has been a while) know what is going in a program. Simple phrases like “Button
Checking Loop” can tell a user what a piece of code does without them having to trace the whole
thing. It can also be helpful for marking bugs that you have found and do not know how to fix or
simply do not have time to fix right now. To place a comment in the block diagram, simply
double click on the white background and start typing. This will place a text box that has no
effect on the program itself.
Default Values
Default values are the values that a variable/object have when LabVIEW first starts up.
The built-in default values are: numeric = 0, string = “” and Boolean = false. However, by right-
clicking on an object, you can change its default value by selecting set current value to default
(under the data operations menu). Please note that the variables only revert to their default
values after you exit out of LabVIEW completely! If you just stop and start your program, the
variables will maintain their last value from the previous running of your program. Thus, it is
often important to create an initialization step in your program that resets all the variables where
the initial value matters.
Labels, Captions, Boolean Texts and Good Variable Naming
Right-clicking on an object will bring up a menu with the option Properties. By selecting
this and then going to the Appearance tab on the new screen gives you two options: label and
caption. While the two words may have similar meanings, in LabVIEW they are very different
things. A label is the name of your variable; it is what LabVIEW will use to refer to that
variable. A caption is just a text box attached to the variable; it has no bearing on anything else.
Generally, you want to make your variable names, the label, as short and concise as possible. For
example, if you had a numeric that was a random integer, rndint or RndInt might be a good
variable name, depending on your feelings towards capitalization in variable names. However,
this would not be good as the descriptive text attached to the numeric on the front panel. By
changing the variables caption to Random Integer, hiding your labeling and displaying only your
caption, you can have the best of both worlds; a short and concise variable name and a
descriptive text attached to it.
Object Order and Grouping on the Front Panel
As with any graphical user interface (GUI), there is an order to the objects on the front
panel that helps the computer decide what to do should two objects occupy the same visual space
on the front panel. LabVIEW is no different. At the end of the tool bar there is a box that looks
like two arrows going in a circle; this is the order and group button. By clicking on an
object/group of objects you can move them forward, so that they will be displayed on top of
other objects or move them back so other objects will have preference. Furthermore, by selecting
a group of objects, you can group them together, which means they will move as if they were one
object on the front panel. All of the functions are merely for ease of layout; they have no effect
on the code of the program.
Good Housekeeping: A Quick Note on Clean Code
With a graphical program like LabVIEW, clean code becomes not just an item on a check
list that earns you 5 points on an assignment; it is a necessity. Without clean code, in any
decent-sized program, you will quickly become lost and fixing bugs/tracing code can be a
hopeless task. Here are a few tips to keep your code readable.
1. Space considerations: Make your code as compact as possible, but not so compact that
you cannot clearly see all the labels and where the wires are connected.
2. Use Small Icons on the Block Diagram: Rather than using the default icons on the block
diagram, use the smaller ones, it will conserve space. To switch your icons, go to
Tools:Options, select Block Diagram from the menu and uncheck Place Front Panel
Terminals as Icons.
3. Periodically Clean up Your Code: Keep your code clean, do not wait until the very end
to try to clean everything up; it may be too late by then! Ctrl+u will automatically clean
up either the selected code or default to the entire block panel is nothing is selected. Note
that large, complex programs tend to respond poorly to a complete Ctrl+u. You will end
up with a lot of wasted space and loose items will tend to be placed in illogical locations.
Good preventative measures to avoid this include:
a. Clean up structures individually: Select the border of the given structure and then
use Ctrl+u. If there is no structure, click and drag to select the code that needs to
be cleaned up.
b. Use labels to document code: Right click the object on the block diagram, then
navigate to Visible-->Label. You can then replace the object name with a
description of what you are trying to do. This forces your comment to stay with
the given object even under clean-up.
c. If you have a number of loose variables on the block panel (common in control
panel programs with lots of local variables), group them together with a flat
sequence. The prevents the clean-up from scattering them around the block panel.
4. Use subVIs Often: Once again saves space and allows you to get the “gist” of the code
without seeing the cuts of everything. SubVIs will be discussed in section 1.4.
Exercise 1.1: In the Labview Tutorial folder, copy the file Exercise Solutions/1.1/Palettes.llb to
a location of your choosing where you can work on it (i.e. not in a SubVersion-ed folder) then
open it. This library contains brief primers for the various data types and a few of the most
common palettes. The goal is to familiarize yourself with LabVIEW’s data types and structures.
You should explore the VI’s in the same order they are covered in this tutorial (Boolean, String,
Numbers and Structures, then Arrays and Clusters). All of the palettes and functions covered in
these VI’s (except one) can be found by right clicking the block diagram and navigating to the
Programming subheading.
Begin by running the program working with the front panel (the run button is the small
arrow in the upper left). Complete any tasks listed on the front panel. Finally, switch to the block
diagram, see how things work and complete any tasks listed there as well (Ctrl+e switches
between the front panel and block diagram).
Avoid getting too hung up on how exactly everything works. It is quite alright if you
don’t get everything, some of the examples are rather complex. Because LabVIEW is a graphical
programming language, it is important you get your feet wet early so you can see what this
tutorial is talking about. These VI’s can also be used as examples of how to use some of the more
common functions and programming techniques when you start your own LabVIEW coding.
Exercise 1.2: Adding Machine: create a simple calculator. It should add two numbers together
and then display the result. Add another output that displays the difference (absolute). One
display should be a numerical and one should be a string display. HINT: The numberstring
function can be found under the string palette. Hints on formatting can found in the appendix.
Experiment with the properties of the inputs and outputs. What is the difference between a label
and caption? Find out how to adjust the size, style, etc of the font. Explore also the different
button mechanisms (i.e. latching vs non-latching) and the other properties that you can change
for each type of object on the front panel.
1.1.2 Case and Sequence Structures
Back to Top
A case structure is a box with different layers corresponding to the different possible
inputs of the variable type being used. The easiest case structure to imagine is for a Boolean
expression; you have just true or false, but you can also have numerical cases (0, 1, 2…) or
string cases. You can find the case structure in the structures palette in the block diagram. You
place it by clicking on the diagram and then expanding the rectangle to enclose all the code you
want to be run for a particular case. Every time the condition is met, you will run the code that is
inside of the structure. The condition is defined by the small green question mark on the left
hand side of the case structure (you wire the variable being checked to that box). You can cycle
through the possible cases by clicking on the arrows at the top of the case structure (the “case
toggle” if you will). Right-clicking on the top of the case structure allows one to add cases,
delete cases or rearrange the cases. Additionally, you can rename the cases (e.g. you can change
true to false). Nested statements are possible by simply placing a case within a case.
Figure 2.1: Various structures in LabVIEW (left). On the right hand side of the figure is the
palette, where you will find all your objects and functions. There is a different palette for the
block diagram (shown) and the front panel.
A sequence structure is a structure that allows the user to create an explicit order of
execution for instructions. On the block diagram, LabVIEW will of course execute instructions
that produce data that is needed for another structure in the correct order, but outside of this,
there is no particular order. By placing different code inside different frames (think of making a
movie) of the sequence structure, you are telling LabVIEW to follow the order you defined.
You can create stacked or flat sequence structures, the only difference being that in a flat
sequence structure, you can see all of the frames at once. The stacked version has the advantage
of saving space on the block diagram. Right-clicking on the sequence brings up similar options
as with the case structure: add a frame, delete a frame, rearrange the frames and others options.
Figure 2.1 below depicts a case and a sequence structure, along with the palette used to create
them.
Passing Data in/out of Case and Sequence Structures
Passing data into a case or sequence is straight forward. Simply wire your data (i.e.
variable) to the wall of your structure. This will create a small rectangular tunnel, whose color
matches that of the variable type being used. The tunnel will have an output, which is on the
inside of the structure; you can wire this to anything inside the structure. Conversely, you can
usually use the data directly to whatever is on the inside of you structure and LabVIEW will
create this tunnel automatically. One important thing to notice is that once the data is passed into
the case structure via that tunnel, the value does not change, even if the value of variable to
which it is attached does. For example, if I wire num1 into a sequence structure to num2 and
sometime after the data has been passed to the tunnel, but before it is passed to num2, num1
changes, the value that will be passed num2 will be the older value of num1, because that is what
is stored at the tunnel.
Passing data between frames of a flat sequence structure works the same as passing data
into a sequence to begin with. However, if you are using a stacked structure, you will need to
create a sequence local, which a variable that is local to that particular sequence. This is done by
right-clicking on any of the walls of the sequence and choosing the option “Add Sequence
Local”. You can wire it to some variable and it will maintain that value for the rest of sequence
(i.e. you can set its value once). Each subsequent frame will have an output where the sequence
local is and each previous frame will have simply a small grayed out box. Passing data out of
sequence works the same as passing data in, except in reverse. That is, wire an output from
inside the sequence to an input that is outside of the sequence.
Figure 2.2: Getting data into and out of structures using nodes.
Getting data out of a case structure is a bit more complicated, but you need to define the
output for each case. You start out by wiring your case structure the same as if you were
bringing in data (except in reverse) and should notice that your small tunnel is now white, with a
color outline. This means that not all the cases have a defined value for that output. You must
now go through your cases and wire a value to that tunnel for each case. This is illustrated in
Figure 2.2.
Exercise 2.1: Calculator: expand the functionality of your simple calculator from before. Add
the option to add, subtract, multiply or divide. You should have two displays still, but now they
should display the same number based on your selection. Add a light that turns on when the
result is positive.
Exercise 2.2: Rube Goldberg Machine: create a program that does a series of tasks in order. It
should:
1. Turn on a light.
2. Add two numbers.
3. Check if that sum is non-negative and take the square root if it is.
4. Pick out the 4th and 5th character of a string and concatenate it to the end of the string.
5. Light a red light to signal it is done.
There should be a second between each stage. HINT: The wait timer is found under the “Time
& Dialogue” menu of the block palette. We’ll talk more about this in a later section – all you
need to do is wire a numerical constant to the input, which is the desired wait time in
milliseconds.
1.1.3 Loops
Back to Top
Loops are some of the most important coding tools that one can have, because it takes
advantage of the main strength of a computer; its ability to do repetitive tasks quickly and
efficiently. A loop consists of two main parts; the body of the loop (i.e. the instructions it will
carry out each iteration) and a condition that determines whether the loop will be run again. For
some loops (specifically ones using shift registers, which will be discussed shortly) there is the
optional initialization portion, where you define an initial value for some variable.
– mention auto-indexing – finishes instructions after stop condition reached – shift register – if
just tunnel and no auto-indexing?
Run-Continuous Loops and User Input Buttons
Checking for a Change (i.e. User Input)
Button Checking Loops
Exercise 3.1: Advanced Calculator: expand your previous calculator by adding a factorial button
(not the built in function!). Also, add an overall while loop with an exit button to let the
calculator run continuously. Add a square root (that handles both real and imaginary roots), a
raise to power and a log button. You may use the built in functions (under the Numeric palette).
Extra Credit: Write your own square root function. If you have taken any Computational
Mathematics course, you should know how to do this (for the curious use keyword: Babylonian
Method). You can do away with the positive indicator as well.
Exercise 3.2: Guessing Game: create an integer guessing game, where the computer will
randomly pick an integer between 0 and 100 (inclusive). The user should be given a high/low
indication. Add a “guess” button, a guess counter (displays the number of the guesses), a give up
button and an exit button.
1.1.4 SubVI’s
Back to Top
This next section will introduce you to the concept of subVI’s – a glorious way of writing
code that will make your code much easier to read and, even better, will save you lots of time!
You may not realize it, but have been using subVI’s this whole time – any time you use the
logarithmic function or concatenate string function, these are really subVI’s. The only difference
is that these are subVI’s written by LabVIEW, whereas we will learn how to write our own
custom subVI’s.
In the traditional language of computer programming, subVI’s would be called
subroutines, procedures or functions2. They serve three main purposes: they allow you to reuse
sections of code (imagine if you had to write the code for the concatenate function every time
you wanted to use it!), they make your code easier to follow and read and easier to debug. The
second purpose is of particular importance in LabVIEW because of the graphical nature of the
code; if you were to look at the entirety of your code all the time, it would quickly become
gibberish. Using subVI’s allow you to replace a large area of code with a small rectangular box,
whose name can give you the gist of what that code does without having to worry about the
actual mechanisms involved. They save time, because instead of rewriting lots of code or even
cutting and copying code, you can simply place on object on the screen. As for debugging, with
subVI’s you can effectively compartmentalize your code, so you can test each subVI separately
to find the source of your problem.
Before we can use a subVI, we must
learn how to create one. You start by creating
a VI as you normally would. For example,
you could write a factorial VI, where you
would input the number and have the factorial
of it as the output. At this point, you could
save the VI and simply place it in another VI
to make your factorial VI a subVI. This is
done by going to your palette in the block
diagram and clicking on the button in the
bottom left corner called Select a VI. This will
open up a file dialogue, where you must find
your VI and place it within another VI.
However, this does not do us much good here,
since we want to be able to pass, or input,
values into our subVI and receive an output.
Otherwise, we will always calculate the same
Figure 4.1: Getting subVI’s on the block
factorial, or default value, and will never be
diagram palette.
able to check the value of that factorial. To
add inputs and outputs for our VI, we go to the
upper right corner of LabVIEW, where our icon currently is. By right-clicking on it, we see the
option to Show Connector, which we should choose. A box with several compartments should
2
Some computer languages distinguish between functions, which return a value, and procedures/subroutines, which
simply do something, but do not output anything.
appear. Each compartment is called a terminal and we can link a variable to it. Simply click on
the terminal and then on the object on the front panel. Notice how the terminal took on the color
of the variable type. Now if we save the VI and place it in another VI, we see that where the
terminal was (in relation to the subVI icon), there is now an input/output terminal, which we can
wire to some variable.
Figure 4.2 – Left - where to click to get the connector menu, right - shows the placement of a
subVI on a block diagram.
Figure 4.3 – Shows the linked terminals.
Editing the Terminals and Terminal Names
You should have noticed that when you first looked at the connector, there were as many
terminals as there were variables. However, the connector does not grow automatically after you
first look at it. Therefore, if later on you decide to add an input (perhaps an option for display
the number in scientific notation or floating point), you will have to add another terminal. You
can just right-click on the connector and select Add Terminal, but this will sometimes rearrange
your existing terminals and/or place the new terminal in an odd location. Another way of doing
this is to click on Patterns which allows you to choose the layout of your terminals.
Furthermore, you can define each terminal as optional, recommended or required (by rightclicking on it). If a terminal is required, LabVIEW will not let a program containing the subVI
run unless some value is wired to it. Note that if you do not wire anything to the terminal, the
variable associated with that terminal will take on its default value.
Editing the Icon
Now that we are using subVI’s within our program, it would be helpful if we could
change the icon so they do not all look the same. By right-clicking on the terminal, we can select
Show Icon and then by right-clicking on the icon, we can choose Edit Icon. This brings up a
screen reminiscent of Paint, which allows you design a custom icon. Remember that this icon
will be small, so do not try to put a lot of words on it – easily recognizable symbols work much
better.
Recursion and Order of Operations
Even though it is tempting to try to create a recursive formula using subVI’s, this is
forbidden by LabVIEW. If you want recursion, you must make it using feedback loops or shift
registers. One should also note that there is a hierarchy to subVI’s within a program; indeed this
applies to other nested structures as well, such as loops and case structures. If we imagine the
large VI or loop as the top of hierarchy, we can create a pyramid style diagram. Once a subVI is
executed within a branch of the hierarchy, everything above it in that branch must wait for it to
finish running before they can return to action. For example, if you have a button checking loop,
and a button is pressed, causing a subVI to be run, the loop will stop checking the buttons until
the subVI is finished running. This can become problematic for things like interrupt buttons, a
topic we will examine in a later chapter. It is not always a problem, just something to keep in
mind if your program is not behaving as you would like it to.
VI Properties
Scroll bars, abort, run, menu, etc
Pop up vi’s
Special Topic: Random Number Generator
Exercise 4.1: Advanced Calculator with SubVI’s: create subVI’s for your factorial button,
custom square root function (if you did that) and an additional subVI that computes the value of
the sine function using the series expansion. HINT: You will need to add a piece of code that
will adjust the input for the periodic nature of sine (e.g. Sin[5 Pi/2] = Sin[Pi/2]. Put these
subVI’s into your calculator program, replacing your code that was there previously. Notice how
nice it looks now! Also remember to create neat icons for your subroutines.
Exercise 4.2: Random Integer Generator: create a random integer generator subVI, where you
can generate a random integer within a user defined range.
1.1.5 Arrays and Clusters
Back to Top
Arrays and loops go hand-in-hand; without loops, it would be almost impossible (at least
impractical) to handle arrays. Therefore, this next chapter may seem like a review of loops, but
you will also practice many of functions associated with arrays. After a look at arrays, we will
examine a similar structure in LabVIEW, the cluster.
An array is an index list of elements. Those elements could be numbers, Booleans or
strings, but they must all be of the same type. Arrays can be 1-dimensional lists or they can be
multi-dimensional objects. The index of an element gives its position within the array. An
element in an n-dimensional array will have n indices. In LabVIEW, all indices start with zero
and go to k - 1 for an array of length k. LabVIEW has many built in functions to deal with
arrays; some of these we will rewrite ourselves in the exercises to gain experience using arrays
and loops. Some of the most common functions are found below:
1. Index Array – gets the element at the given position. You input the array and the
required indices and it fetches the element.
2. Array Size – gets the length of the array in each dimension. If the array has n dimensions
and n > 1, the output will be an array of length n.
3. Build Array – build an array by adding on elements to the end. You must append an
entire row at a time; if you have a 1-dimensional array, this is just a single element. If
your array has 2 dimensions, then you must append a 1D array to it (i.e. a row).
4. Initialize Array – creates an n x m array filled with one element, which is user defined.
5. Sort Array – sorts an array in ascending order (or alphabetical order). To get a sort in the
other direction, combine this with Reverse Array.
6. Search Array – searches an array for a given element and returns the index. The value -1
is returned if the element does not exist within the array.
7. Insert, Replace and Delete from Array – three different functions that are related. Insert
inserts an element into an array, pushing down all the elements below it. Replace will
delete an element and put another in its place. Delete simply removes the element,
sliding all the elements below it up one.
8. Transpose Array – Rotates the array, so that length becomes width.
Creating Arrays
To create an array, open up the front panel palette and go to Array & Cluster and select
Array. You now have a blank array; it should be black (on the block diagram). To finish
creating your array, you have to create an object of the data type that you want your array to be
of (recall arrays can only contain one type of data) and place it in the array. You now have an
array! There are two ways to change the size of an array; you can click and drag on the
individual cells to make all of the cells larger or you can click and drag on overall array to show
more elements. Determining which one you are actually clicking can be somewhat difficult so
be careful. Note that the number of elements you are displaying is independent of how many
elements are actually in the array. Right-clicking on the array allows you hide or show the radix,
which allows the user to scroll through all of the elements of the array if they are not all visible,
as well as to add dimensions to the array.
Figure 5.1: Creating an array. Figure 5.1a – 5.1c show the steps involved in the creation of a
Boolean array.
Auto-indexing
Auto-indexing is another function that is useful when combining arrays and loops. If you are
generating a series of data elements (whether they are random numbers or data points from your
machine), instead of building the array yourself, you can have LabVIEW do it for you. Simply
wire the output to the wall of the loop; you should see a solid tunnel as usual. If you right-click
on it, you can select Enable Indexing, which will automatically index your elements and build an
array. In For loops, this is the default action as you wire elements out of your loop.
Finally, I would like to give a quick tip on default settings for arrays. There are two kinds of
default settings for an array: a default for the entire array and a default for new cells. To set the
default for the entire array, you need to be sure you have the entire array highlighted when you
click on Set Current Value to Default. This will causes an array to be come up as the same value
very time you start up LabVIEW; for example, you could set an array of numbers called fib to
come up as (1, 1, 2, 3, 5, 8, 13). If you are clicking on a single cell of an array when you set the
default value, you will set the value that each new element becomes (if left undefined) every
time you extend an array. For example, if you set this default value to 0 for a particular array,
every time you create a new element without directly defining it, it will be 0.
Cluster
A cluster is very similar to the array, in that it is collection of elements. However, a
cluster is an un-indexed collection of elements, which may or may not be of the same type. This
means that I have a cluster that contains a string, two numbers and a Boolean; it does not matter.
You can have an array of clusters, which is helpful if you want to attach a string or label to some
number, rather than relying solely on the index for identification of the number. The elements of
a cluster also maintain some of their individuality; they all keep their individual name (i.e. label).
To create a cluster, you use the Bundle command, where you input as many different elements as
you want and you get back a cluster containing all of those elements. Unbundle works the same,
except in reverse; it displays the data type along with the terminal for the element. A more
elegant way of examining a cluster is to use Unbundle by Name. As the name suggests, when
you use this function, the names of the elements in the array are displayed rather than just their
data type. Of course there is a Bundle by Name command, but to use this you have to input the
cluster, meaning it already exists.
Creating Clusters
Creating clusters is a fairly straight forward task; you open up the front panel palette and
go to Array & Cluster and choose the Cluster option. After placing this on the front panel, you
can name it and then begin adding items to it. Simply create any kind of front panel object you
want (string, numeric, etc) and place it inside of the cluster. Doing so will add it to the cluster.
Once inside the cluster, the object retains its prior name and does not acquire an index number.
The only stipulation is that they all have to be controls or they all have to be indicators. If you
attempt to place a control inside of an indicator cluster, the control will be automatically
switched to an indicator of the same variable type.
Figure 5.2: Creating a Cluster. Figure 5.2a – 5.2d show the steps to create a cluster.
Because clusters are un-indexed, it is less helpful to use loops with them. However, if
you have a cluster that contains elements of the same type, you can use the clusterarray and
arraycluster subroutine to convert the cluster into an array to use in a loop and then back
again. However, you will lose some properties of your cluster in the mean time, such as the
individual names of the elements; you will end up with something like nameofarray[i] for your
element names.
Exercise 5.1: Check the Random Integer Generator: check that your random integer is really
random by making sure all your values have an equal probability of being selected. HINT: One
way to check this is to create an array of zeroes of length n + 1, where your random integer range
is 0 to n. Then randomly pick x values, where x is very large (say a million). Every time you
select a number y, add 1/x to the array value at index y and write over this value in the array. If
you have an equal probability, you should get approximately the same value for each cell.
Exercise 5.2: Search/Sort Program: create a program that will search and sort data without using
the built-in LabVIEW functions. You should have four buttons: a generate array button, a sort
ascending, sort descending and search button. The generate array button should generate a 1D
array with n random number elements, where n is user defined. The two sort buttons should sort
the array in the desired direction. Finally, the search button should be able to find a user defined
number and be able to return the index or let the user know that there exists no such number
within the array. HINT: It is faster to search a sorted array (lookup binary search if you are
unsure why), so create two buttons; one for sorted arrays and one for non-sorted arrays. Also
write a method to search a 2D array (and a button to generate a 2D array).
Exercise 5.3: Dr. Colton’s Grading Program: create an array of clusters; the cluster should have
two strings and a number. Make your array at least 15 elements long. Enter a series of names
(one box for first, one for last) for the strings and a test score (0-100) for the number. Write a
program that searches the array for the right name and reports the proper score (capitalization
and white spaces should not alter the search). Create a button that sorts the array by either last
name (alphabetically) or by score. HINT: Comparing strings with > and < gives a true or false
based on ASCI character values, which are in alphabetical order (though you will have problems
with capitals versus lower case). Also create a buttons that creates a “score report”, which lists
all the student’s names and their respective scores, as well as mean and standard deviation. The
output for score report should be a single string. HINT: There is a built-in standard deviation
node under the Analyze:Mathematics:Probability and Statistics palette.
1.1.6 Global Variables: Interrupt Buttons and Constants
Back to Top
Global variables are an important part of LabVIEW; it is one of two ways to have two
VI’s interact in real time (the other will be discussed in chapter 9). A global variable is a
variable which can be accessed by any VI currently loaded for you LabVIEW session. Global
variables are nice in that they do not have to be passed to subVI and thus can be continuously
monitored and updated. The downside is that you have to a bit more careful in how you alter
global variables, as any changes made to the global variable in a subVI are saved even if you do
not want them to be. As such, global variables should only be used in a situation where the value
is not expected to change very often, but is needed across multiple VIs. Ideally, any global
variable you make should only be editable by hand (using Make Current Value Default) or with a
single sub-VI in order to control access to it.
In LabVIEW, global variables exist separate from any VI in their own .vi file. Global
variables look just like the front panel to any other VI, however, there is no block diagram.
Thus, you can store only values in a global variable. By placing different objects in a global
variable, one global variable in LabVIEW can store a wide range of values. You can have a
global variable that contains a number, a string and a Boolean all at the same time. You simply
have to tell LabVIEW what value you want each time you access that global variable. Thus the
term global variable is perhaps a bit of a misnomer; the objects within the global variable are the
global variables, while the file itself is best called a global file.
To create a global variable, go to the structures palette on your block diagram and select
Global Variable. Once you place this on your block diagram, double click on it to bring up the
global variable itself. Here you can add numerical indicators or strings indicators just as you
would on any other front panel. You must first save your global variable to the hard disk before
you can access it elsewhere. If you go back to your original block diagram and click on the
global variable, it will bring a short menu of all the variables stored in that global variable.
Select the one you want to read/write and you are on your way! You can switch the read/write
status of you variable in the same manner as for a local variable. You can add another instance
of the same global variable the same way you would add a subVI to your program. Simply go to
Select a VI… on your palette and search for your global variable file. Once you have placed this
on your block diagram, you can click on it to select which object in your global variable you
want to reference.
Global variables hold the same value for any VI currently running in LabVIEW. This
allows us to have real time interaction between VI’s. If a subVI is monitoring a global variable
and the global variable’s value is changed elsewhere in the program, this change is reflected
instantly in the subVI that is monitoring that global variable. Therefore global variables work
well for stop conditions on loops, where the stop condition happens elsewhere in your program.
It is also important to note that the global variable only stores the value it does not save it! That
means, it will store the value for the current LabVIEW session, but once you exit of out of
LabVIEW completely and come back in, the global variables goes back to its default value
(which of course you can set to be whatever you want).
Interrupt Buttons
One of the most useful applications of global variables of global variables is for interrupt
buttons. For example, if you were continuously polling an instrument using a subVI, you might
want to able to stop this with a button in case it took to long. We will look at the broader case of
a loop with in a subVI that you want to stop. First, create your global variable and add a Boolean
to it called interrupt. Put this in whatever loop you want to stop as the stop condition (or one of
the stop conditions). The loop will now continuously monitor that global variable and when it
comes up as true, the loop will stop. If you go back to your main or driver program, you
probably have an overall while loop that checks your front panel for user interaction. If you
recall, this loop freezes when it goes into the subVI and does not advance until the subVI is
done; thus we cannot put our interrupt button in this loop. However, a second loop next to your
overall while loop will still run even if the overall while loop stops to run a subVI. LabVIEW
will run loops and sequences in parallel if they are on the same “level” or have the same
importance, where importance is defined by how all of your loop/sequence structures are nested
within each other. This is how we can keep checking our interrupt button even we are running a
subVI in the overall while loop. Simply put a condition in your second loop that flags your
global interrupt as true whenever you push your interrupt button. You will have to think about
your stop conditions for both loops to make the interrupt button work more than once.
Figure 6.1: Loop structure for creating an interrupt button. The two loops will run in parallel
because they have the same importance.
Global Variables as Constants
Another important use of global variables is for constants, such as equipment
communication parameters, settings that do not change and other information (for example, if
true/false button that you want to use to toggle change the caption on a box, you could store
those strings in a global variable). You could, of course, simply use the built-in constants of
LabVIEW to do all this, but using global variables has the advantage, that if you ever need to
change that constant value, you can change it in one place and that changes all of its occurrences.
If you had used constants, you would have track down all of them and change them one by one.
As I mentioned before, global variables do not save their value once you leave LabVIEW; they
go back to their default value. So the trick is to create your global variable, create your objects
and put in all your information. Then right-click on the objects and select Set Current Value to
Default. Now that variable will revert to those settings every time LabVIEW starts up and if you
are using it as a constant, you never write to it, just read, so it should be that value all the time.
A handy way of doing this is to use an array of clusters. You could create a cluster which
includes some kind of designation or identification tag (a string or number) and then all the
information that goes along with it (such as communication settings or settings for a particular
activity). Put this cluster in the array and create a subVI that searches through the identification
tags and then extracts the appropriate information. The figure below shows a global variable
being used to store communication parameters for a various instruments. This tag identifies the
setting as belonging to the spectrometer (see section 2.1 for more information on the
spectrometer). There is a toggle that determines if the instrument uses GPIB or RS-232 (serial)
communication standards. This one uses GPIB, so the GPIB address is provided. Global
variables are good for communication parameters, because many such parameters, such as GPIB
addresses, are not fixed, but rather can be altered by changing a setting on the instrument. Thus,
if for some reason you need to one of these parameters, you can do so with minimum hassle.
Figure 6.2: A global variable being used to store instrument communication settings.
Exercise 6.1: Create an interrupt button for a counting loop. Make two counting loops; one that
does not use a subVI so that you can use a local interrupt and one that uses a subVI so that you
must use a global interrupt. The subVI should be a “pop-up” subVI, meaning it displays itself
when called and should have no scroll bars. The interrupt should stop the counting, not the
overall program (i.e. I can hit the count button and then interrupt it without getting kicked out of
the program). HINT: It may make your life easier to change the mechanical action of one or
more of your button on the front panel so that you can create local variables for them. You
should also add a separate counter that displays where the subVI counter should be and a “busy
bar” or “wait bar” that cycles through an array of 10 LEDs, turning each one on (and then back
off) in order. This should have the effect of making one light appear to run along the array of 10
lights. A good speed would be to change one light every 100 ms. HINT: Recall loops and
sequences will run in parallel if they have the same importance to get all three processes (the
subVI, counter and lights) to run at the same time.
Exercise 6.2: Global Variables as Constants: create a program with one button and a set of radio
buttons, so that the button does a different, but similar task depending on the radio button. One
of the radio buttons should be called “+10” and add 10 to a number. One should be called “-5”
and should subtract 5 from a number. The third button should be called “*2” and should
multiply the number by two. Finally, the last button should divide by 4 and be called “/4”. You
should create a global variable as described above, each which has an identification tag, a toggle
to switch between addition and multiplication and the number with which the operation is being
carried out. For example, +1 might have a string tag “increment” or simply “+1”, the toggle set
to addition and 1 stored in the numeric. You must input the tag and then extract the other
information. HINT: a subVI with a searching loop will work nicely for this. Exit out of
LabVIEW and come back in to ensure that your settings are preserved. There are, of course,
easier ways to do this simple example, but once you begin to write larger and more complicated
programs, you will begin to see the value of this approach.
(description is confusing per Andrew)
1.1.7 Graphing, Property Nodes, Text Rings/Enums and Formulas
Back to Top
Graphs are an important part of any scientific program, however, they are not truly
unique. A graph (in LabVIEW) is just another way of viewing an array of points. Thus a graph
is an array of points, where the points are represented by clusters of numbers. You would cluster
two points together for a 2D graph and three points together for a 3D graph. The graph object is
found in your front panel palette under Graph; the most common one that we will use is called
the XY Graph, though you can experiment with the other types if you want.
XY Graph
An XY Graph consists of an array of clusters of two numbers, which appears brown in
LabVIEW. To create a multi-plot graph, you need create a separate cluster from each plot and
then make an array of all of the clusters; this appears pink. The process of building a graph is
depicted in the figure below. It usually works best to build your arrays using loops, like in
chapter 5. You can change all of the different properties of your graph, such as the range, color
or point style, using property nodes, which are discussed below. This is useful for run-time
changes, but for non-run-time changes, you can simply click on the properties that are visible
and edit them. For example, you can just click on the axes labels and it will let you type
something in to change it. Or you can right-click on the graph to bring up the property menu like
before.
Figure 7.1: For single plot graphs: numbers  cluster  array, for multi-plot: numbers 
cluster  array  cluster (single plot)  array.
Property Nodes
A property node is a node that can read or alter the properties of an object in LabVIEW.
To create a property node, you can right-click on an object or a terminal (object in the block
diagram) and select Create:Property Node.
Alternatively, you could open up the palette
on the block diagram and select Application
Control:Property Node. After creating the
property node, you can right-click on it and
select Link To…, which opens up a menu
containing all of the objects in your current
VI. Simply select one to link that property
node to that object. Examples of object
properties are: value (signaling), caption,
height and width, placement on the front
panel, min or max values (for the x-scale of
a graph for example) and visible. The value
signaling property will become very
Figure 7.2: Property Nodes
important once we begin event-driven
programming. There are many properties
you can alter, some of which are object specific, far too many to list. The best way to learn how
to use some of the properties work is to create some property nodes for different objects and
examine your options. Clicking on the property node allows you to change the property being
displayed. You can also drag the bottom of the property node, which expands it, so that you can
display more than one property at a time for a given object. Right-click on the property also
brings up option to change the read/write status of that property or all properties currently being
displayed for that node.
Text Ring and Enums
Text rings and enums (short for enumerated) are very similar objects; they both allow you
to create a pull-down menu of options. To create a text ring or enum, on your front panel palette,
go to Ring & Enum and select one. By right-clicking on it, you can go to Edit Items, where you
can add different options. You will notice each option gets an index number; this is how you can
set your object to a certain number (you should also notice on the block panel, that text rings and
enums are blue; the same color as integers). If you wanted to manually set your ring to option 2,
simply wire a 2 to the text ring. The difference between the two comes in how you read what
option has been selected. For both objects, it is best to use a case structure. Wire the output of
your text ring or enum to a case structure and it will automatically change the cases to the first
two by index number. However, text rings display the case by index number and enum by the
title of your option. Each works well for a certain situations. If you right-click on the case
structure, you can select Create Case for Every Value, which does exactly what the name
suggests so you do not have to do it manually.
Formula Nodes and Expression Nodes
As you have seen, doing math in LabVIEW can be a bit cumbersome. However,
complex math can be made much easier using formula nodes and expression nodes. To place an
expression node, open up the block diagram palette and go to Numeric; there you will find the
expression node. Formula nodes are found under the Structures menu in the block diagram’s
palette. An expression node is essentially a simplified version of a formula node. With an
expression node, you have only one input, which is always denoted by x, and one output. You
do not need to use a y = or anything, just type in your expression and your output is the result of
that expression. With a formula node, you can have more than one input and output. You do
this by right-clicking on the node’s walls and selecting Add Input or Add Output. By typing in
the box that appears, you can give the variable a name (can be a multi-character name). You
then wire values to it the same as any other input/output scheme. Finally, in formula nodes you
can write multi-line expressions. Each line is separated by a semicolon.
Syntax
Here is a quick note on syntax, which is the same for both formula and expression
nodes. To multiply, you must use a *, you cannot simply leave a space between the two
variables as in Mathematica. To raise a number to a power, you use ** rather than ^ (e.g.
x**y = xy). To use functions, like sine and cosine, you type the function code followed
by parentheses, which surround the value you want to input to the function. Some
common functions are below; a more extensive list can be found in the LabVIEW help
file.
exp(x) (ex), cos(x), sin(x), log(x) (base 10), ln(x) (natural log), abs(x) (absolute
value), sqrt(x) (square root), ++ -- (increment, decrement)
Furthermore, you can use logical operators in both the expression nodes and formula
nodes. Some logical operators are shown below; once again, refer to the LabVIEW help
for more. An output of 1 and 0 will be used to denote true and false respectively.
|| (or), && (and), == (equals), != (inequality), > < (greater than, less than)
Exercise 7.1: Graphing Calculator: add a graphing function to your calculator. You should be
able to enter a polynomial function in a text box and have the program graph it. HINT: If you do
not want to try to figure out how to extract a polynomial from a text box, you can just create an
array, which contains a cluster of two numbers; the coefficient and the x power. Furthermore, it
should be able to do a “stat plot” – plot a list of points. It should just graph a line for the
function, but show each point for the stat plot, with the option of connecting the points (you may
want to add an order by x value button for the list). Make an input for the x and y max and min.
Make a switch to make it auto-scale or manual. HINT: The name of the property that does this is
XScale.ScaleFit and the values are 2 for auto and 0 for manual.
Exercise 7.2: Numerical Solution to a Differential Equation: create a program that graphs the
solution to the three differential equations (DEs) below. You should be able to choose which of
the three DEs you are graphing using an enum. You should graph two solutions: the analytical
solutions (given) and the numerical solution using Euler’s Method (also described below).
(HINT: Even for the analytical solution, you are still just plotting points; that is, just feed in the
x’s to the solution function and plot those points. You will have to determine how many points
to feed in.) It should plot them simultaneously. Furthermore, create a slide to adjust the plotting
speed so that you can watch it plot if you so desire. Also, you should be able to adjust the color
of each plot. The color property for the graph takes the input in the following fashion:
RRGGBB, where it is a hexadecimal number. The odd thing is, even though that the format to
determine the color is hexadecimal, the property node takes decimal numbers. So it will work
best to have three numerical inputs, convert these to a hexadecimal string, concatenate them
together and then convert that into a decimal number to send to the property node. To select the
plot whose color you are altering, use a text ring. You should also set the range on the plot
accordingly.
Differential Equations
Initial Conditions
Analytical Solution
2
y ( 0)  1
1. y   xy
y( x)  e x / 2
y
0.997
 9x
y ( x )  3x 2 
y (0.1)  10
2. y  
x
x
3e
y ( x )  cos( x )  3
y ( 0)  0
3. y   y sin( x )  3 sin( x )
e
Euler’s Method: To approximate the solution to a differential equation, we use a tangent
line to approximate the next y value. Since our differential equation represents the slope of the
line, our tangent line looks as such:
y( x )  y0  ( x  x0 ) y ( x0 , y0 ) (since y’ may be a function of both x and y)
So the next y value can be predicted based on the old y value and x value. This method is an
iterative method, where each step we increment our x value by some step value h. So if we have
our kth approximation, we can generate the (k+1)st approximation using the following:
y k 1  y k  h * y ( x k , y k )
Some pseudo-code for Euler’s Method:
x = x0, y = y0, h = (step size), stop = (stop value for x);
f(x_,y_) = (your differential equation);
Do While (x <= stop)
y = y + h*f(x,y);
x = x + h;
Print[x,y];
“initialization”
“input diff. eq”
“loop to generate our values”
“generate the new y”
“step our x value”
“Prints the new x and y values –
could also store them in an array”
End;
Figure 7.3 Graphical Representation of Euler’s Method, the blue is the analytical solution while
the red represents each iteration of the approximation.
1.1.8 Decorations – Making it Look Nice (Interlude)
Back to Top
In addition to functional front panel objects, you can add front panel objects that merely
enhance the appearance or make the front panel easier to read and decipher. All of the
decorations can be found in the front panel palette under Decorations; there are many to choose
from in a variety of shapes and sizes. One of my personal favorites is the Recessed Box, which is
helpful for grouping objects on the front panel together. Other handy ones are the label, the
arrows and the other shapes for grouping items together. Note that when I mention grouping
here, it is nothing more than visually grouping your items together; it has no consequence on the
how anything behaves. Explore this area of the palette and see what each one looks like on the
screen. Refer to chapter 1 if you do not remember how to change the order on the front panel;
this will be help as many of the decorations are opaque.
Figure 8.1: Examples of some decorations during development (left) and runtime (right).
Exercise 8.1: Pretty Calculator: Add some decorations to your calculator to make it easier to
read. Group all your buttons together in some sort of decoration, as well as your input and
outputs. Furthermore, add a snazzy title area to your calculator, which proudly proclaims your
calculator program to be the best in the land.
1.1.9 Event Handling: Efficient User Input and Variants
what are and why use?
Basic components
Notify vs filter
Static and dynamic, registration
Programmatically generating events
Dynamically loading VI
Controlling front panel objects
Passing references
Back to Top
Exercise 9.1: Analyzing the Efficiency of the Event Handling Structure: write two programs that
do a very simple task; they check a button repeatedly and add one to a counter if it is pushed.
Write one program using the previous loop techniques and one using event handlers. Also add a
loop iteration counter for both programs (for the overall while loop that checks the buttons).
Now open up your task manager and loop at the CPU usage. Run both programs and note any
interesting observations.
Exercise 9.2: Interrupt Button Revisited: create a program that has two buttons; one to counts
and one that stops it. The counter should be activated by a start button and after the second
button has been pressed output the time elapsed (a non-updating stop watch if you will). Make
the counting routine a subVI. Use event handling to stop the counter without creating a separate
event structure to continuously check your interrupt button. HINT: You can pass a reference to a
front panel object. Details are on page 5-22 and 5-23 of the LabVIEW manual.
Exercise 9.3: Calculator v2.0: try to rebuild your old calculator using event handling; you should
have lots of work done already because you created some subVI’s from chapter 6. The catch this
time is to try to make it behave like a real calculator. That is, have one input area where you
would input a number, hit add, then another number, hit equals and get an answer in a display.
Check it out on your computer calculator to see how it works and see if you can duplicate that.
1.1.10 Time and Dialogue
Back to Top
Exercise 10.1: Simple Dialogue Boxes
Exercise 10.2: Stop Watch Program: create a program that has two buttons; one to start a stop
watch (accurate to hundredths of a second) and one to stop it. HINT: Think what would work
better, wait or wait until next multiple. Add functionality to store laps and make sure to have a
clear/reset button. Also format the display to look like a stop watch (i.e. in 00:00:00.00 format).
1.1.11 Debugging
Back to Top
Suggestions – no Exercise
1.1.12 File Operation
Back to Top
Exercise 12.1: Clock In/Out Machine
1.1.13 Misc. Topics
Back to Top
1.2.1 Communicating with Instruments: Back to Basics
Back to Top
In the lab, there are a number of interfaces in use for communicating with the
instruments. To control this equipment using LabVIEW, we need to understand a few basics for
communication using GPIB, RS232, and ActiveX.
1.2.1.1 GPIB
In our lab, the GPIB (General Purpose Interface Bus) is by far the most common method
for instrument communication. Originally conceived in the late 60s for test automation by HP,
the first universal standard approved by IEEE was 488.1 in 1975. This standard specified the
mechanical parameters for manufacturers to use when incorporating GPIB into their equipment,
but did not specify command syntax. Later, in 1987, the IEEE 488.2 standard was approved that
created a basic syntax for commands, data format, and even some device independent
commands. IEEE 488.2 was also made to be completely compatible with the 488.1 standard to
allow complete interoperability.
Unfortunately for us, about half of our equipment uses the older 488.1 standard, requiring
heavy customization in both command syntax as well as general operation. One of the many
unfortunate features of GPIB (which I will hereby refer to as "safety features" since there are
quite a few and it gets depressing listing off defects) is that for optimal speed and reliability,
there can be no more than 15 devices connected to a single bus with no more than 2 meters of
average distance between the devices and no more than 20 meters of overall cable length. All in
spite of having 30 available primary addresses (not to mention the 30 secondary addresses). But
this does limit the required programs and computing power needed, which is good for the
programmer (you). Another "safety feature" is the result of the age of this bus. Since its creation,
computers have far exceeded the speed of the bus and instruments on it. To accommodate for the
difference in speed, one has to force programs to evaluate more slowly, as if the bus wanted to be
sure we had time to reconsider our grating choice, just to be on the safe side.
With that said, we can write our first program that uses the GPIB. There are three sets of
LabVIEW VIs for interfacing with the GPIB, and we will start with the oldest and most archaic.
The general concept for interfacing with a GPIB instrument is that you write a command to the
instrument's input buffer, which stores the command in queue until it is executed. If the
command produces a response, the instrument will then send data to its output buffer, which will
store the data until it is read by you. To test your VI, use the Stanford Research Systems SR830
Lockin Amplifier.
Exercise 1
Create a basic driver that writes a command to the instrument then reads back a response.
For this exercise, only use the VIs found in the Instrument I/O-->GPIB Function
directory.
Hints: The primary address of the Lockin is 9, there is no secondary address (anywhere in
the lab actually). A safety feature provided by LabVIEW itself is that each set of VIs has
a unique method for addressing the instruments, so you won't accidentally mix and
match. This variety uses strings with "primary address + secondary address" (no quotes).
If there is no secondary address, only input the primary address. Some good commands to
try are "*IDN?" or "SNAP? 1,2,3,4", without quotes. Finally, don't spend too much time
on this. Just get it working and move on.
Solution: VISA Tutorial Answers.llb-->GPIB w-r basic.vi
Now, it is possible that you ran into some issues writing the last program. If you didn't, I
can assure you it is only a matter of time. Common pitfalls when using GPIB are short timeouts,
insufficient delays, and reading too few bytes. The last can be a serious problem and difficult to
debug if it occurs. Since the output buffer only clears when read, forced by a flush command, or
becomes full and is automatically flushed (which is instrument specific), it is possible to read the
output from previous commands (a "safety feature" so you don't lose data, obviously).
Fortunately, this is easily avoidable thanks to an actual safety feature of GPIB. Namely, when the
output buffer is empty, the instrument will send a termination character that will tell LabVIEW
the read is done. So telling LabVIEW to read 1024 bytes (recommended) is really just a
maximum number that ensures the whole buffer gets read. Note that this technique only works if
you send one command at a time. If you send multiple commands that result in output data
(which is perfectly legal), you then need to know the exact format of the reply so you can parse
the individual responses properly. This “safety feature” can be particularly troublesome when
debugging programs since aborted programs tend to leave data on the output buffer. To avoid
this, clearing the buffers at the beginning of the program is usually a good idea while debugging.
Each set of VIs has a clear function for this express purpose.
Timeout errors and bad delays are closely related and stem from the speed of the
computer and the lack of speed in the instrument. The delays are just a way to slow down the
program to better match the instrument speed and should not be excessively long (>200ms).
Another way to address the speed difference problem is to set longer timeouts. A timeout works
much like the bytes to read; it is a maximum amount of time allowed for the operation to
complete. If you set a timeout of 2 min, a GPIB read function will wait up to 2 minutes for data
to become available. If the operation does not complete, you will get the dreaded -1073807339
"safety feature." If you get a lot of these, increase the timeout, but don't exceed a minute except
in special circumstances. If problems persist, add in delays. If they continue to persist, the
problem is elsewhere.
Exercise 2
Rewrite the driver from Exercise 1, but use functions found in Instrument I/0-->GPIB->488.2. This time, include controls and indicators for the Command string byte count,
GPIB timeout, delay time, bytes to read, and bytes read. Alter bytes to read, the timeout,
and the delay time to see where the limitations are for each. Be sure to under-read the
output buffer at least once followed by sending the same command again with a larger
bytes-to-read value and observe the result. When testing the timeout and delay, run the VI
multiple times in a row.
Hints: By default, the first GPIB bus on a computer is 0. Since our computers only have
one bus, they are all bus 0. The timeout is set by a separate function and applies globally
to all 488.2 functions. Be sure to use a sequence structure to force execution in the proper
order (Set Timeout, Write, Delay, Read). Also, for the delay, DO NOT USE THE
EXPRESS VI VERSION. Express stuff doesn't play nicely with the other low level VIs
we need to use. Also, John hates them.
Solution: VISA Tutorial Answers.llb -->488.2 w-r basic.vi
As you hopefully found out, the Lockin is very agreeable. Delays are not needed and the timeout
can be very short. Let's try something that isn't as nice.
Exercise 3
Use the driver from Exercise 2 with the Newport 1830-C Optical Power Meter and redo
the timeout and bytes read tests.
Hints: Make sure to turn it on and that it initialized correctly (it should display “SN
1376”). Its address is 4. Good commands to use are "D?" and "W?", without quotations.
There are a few differences between these two instruments. First, the Power Meter is IEEE 488.1
(note that the general 488.2 drivers still work). Second, the power meter buffers are only ~10
bytes whereas the lockin buffers are 256 bytes. Third, the power meter is a lot cheaper and a lot
slower in operation. The take-home message here is that old instruments are harder to work with
and must be coerced. Also note that the Power meter's behavior is more typical than the lockin's
in our lab. So remember, each instrument is going to behave a little different and some trial and
error will be needed to get programs working smoothly.
Finally, we come to the batch of Function VIs you will use the most, VISA. Virtual Instrument
Software Architecture (VISA) is the current industry standard for interfacing with test and
measurement equipment. Its power comes in that it can work over all of the interfaces commonly
used. All that is required is a VISA resource name that specifies the address and interface, VISA
will then handle the rest. This ease does come at a price of extra programming. Before using the
VISA functions, a VISA session should be opened (found in the advanced VISA functions) and
when finished, the session should be closed. So the proper order becomes Open Session,
Timeout, Write, Delay, Read, Close Session.
Exercise 4
Rewrite the driver from Exercise 2, but with functions found in Instrument I/O-->VISA
and its subdirectories.
Hints: Though it will probably still work without opening or closing the VISA session,
get in the habit of doing it. With VISA, the timeout is set using a property node and only
applies to the current session. Also note that the VISA resource name control contains a
pull down menu that shows all active addresses that can be used. The general form for
GPIB VISA addressing is: GPIB[bus number]::[primary address]::[secondary
address]::INSTR (don't include the brackets). If there is no secondary address, omit it.
Solution: VISA Tutorial Answers.llb -->VISA w-r basic.vi
It should be noted that the opening and closing of a VISA Session is only required at the
beginning and end of the entire session respectively. This means that a session could be opened
and closed that handles any number of operations, instead of one command sequence at a time.
Excessive Opening and Closing of VISA Sessions isn’t necessarily bad, but it is a lot of extra
programming. So despite the example driver VI doing so, you certainly don’t need to have a
separate VISA Session for each command sequence in a real program.
1.2.1.2 RS232
RS232 is a legacy communication standard that makes use of common serial ports. Only
once device can be connected to a serial port at a time, meaning that a typical computer can only
have one RS232 device connected at a time. Because of this limitation, our lab currently has only
three RS232 connected devices: the Oxford Magnet and the Black & Blue Digikröm
spectrometers. For our tutorial, we will use the spectrometers since they are less expensive and
have the added benefit of using the exact same commands.
Luckily for us, the only option for RS232 communication in LabVIEW is through the
VISA function set, making programming at least familiar if not easy. The primary complications
are command formatting and performing reads properly.
1.) Command formatting: Oddly, this is not a problem that inherently stems from RS232
itself. Though physical structure is outlined by the RS232 standard, command syntax is not. So
we have the recurring problem of having to consult the manual in detail in order to do anything.
A bigger problem results from the age of the instruments. Since we only use RS232 when forced,
they are typically from around the time when instrument automation programs were written in
compiled programming languages. As a result, commands are just numbers representing specific
byte sequences. To send such a command in LabVIEW through VISA functions (which we have
to use), you first need to input the number as an unsigned byte integer (U8) data type. This is
done my placing an integer control/constant, right clicking it in the block diagram, selecting
Data Representation then U8. Once you do this, you then need to turn your number into an array
of one (or more, if available) elements using the build array function. You can then go to the
conversion palette and select Byte Array to String which will give output that the VISA Write
can interpret. This process is then completely reversed by the VISA Write function when sending
the command, thereby undoing all our hard work.
2.) Proper Reading in RS232: This subject gets special treatment despite the fact that we
are using the simplistic VISA functions because it can be a very, very big pain with RS232. This
is because RS232 lacks a universal end of line character and instead has four different options
that can be used: [<lf>, \n, 0xA], the line feed; [<cr>, \r, 0xD], the carriage return; any custom
end of line character; or nothing at all.3 In any case, VISA does not handle these options terribly
well and will NOT always automatically stop trying to read once the output buffer is empty.
There are two ways to correct for this. One is using a property node found in the Instrument
I/OSerial palette titled VISA Bytes at Serial Port. This function queries the instrument and
determines how many bytes are available for reading. You can take the output of this command
and feed it directly to a VISA Read which then reads exactly what is available and stops. The
pitfall to this method is that it can return 0, which will happen on slower instruments since when
it checks, there really will be no bytes at the port. This then causes problems because those bytes
3
Formats are [pseudo-code, string, hexadecimal], respectively
will remain in the output buffer until read by another command that is almost certainly expecting
a different result. The other (and preferred) solution is to know exactly how many bytes to expect
and hard-wire in that amount. In order for this method to work, longer timeouts than GPIB
operations will almost certainly be necessary. The instrument’s manual should indicate the exact
size of all responses.
There is one final consideration for using RS232; the serial port has to be configured
before it can be used. This configuration takes the place of a VISA Open Session and is found in
the Serial palette as VISA Configure Serial Port. Important features of this configuration include
the baud rate, data bits, parity, and the stop bits. These parameters are specific to each instrument
and must be set before read/write operations. This function also configures the termination
character and global timeout for VISA functions using the serial port. Its default value of 10
seconds will usually be sufficient.
Exercise 1
Write a driver VI for a Digikröm spectrometer that will adjust the opening of the entrance
slit.
Hints: The specific procedure for the Digikröm spectrometer is to first write the
command, then read the echo of the command (1 byte). You can then send the desired slit
width in high bit/low bit format. That is done by taking an unsigned 16 bit integer (U16)
and passing it to a Split Number Function found in the Data Manipulation palette. Then
turn the two bytes into a byte array that can then be converted to a string. With the
command and parameter written, the spectrometer will move the slits and then write a
status byte and a cancel byte. The status byte gives the state of the spectrometer and bit
definitions can be found in the manual. The cancel byte (value of 24) is how the
spectrometer signals that the operation is complete and is ready for a command. These
two bytes can be read at the same time.
Don’t forget to put in a VISA CLR function at the beginning of the program while
debugging and to convert responses from the spectrometer back into byte array format.
Solution: VISA Tutorial Answers.llbRS232 basic.vi
1.2.1.3 ActiveX
Unlike GPIB and RS232, ActiveX is not an interface standard. Instead, ActiveX is used
to define software components in a way that is independent of any specific programming
language. This independence allows for software operations to be written and then easily ported
between programs and even operating systems. First created in 1996 by Microsoft, ActiveX has
now permeated the Windows operating system and found its way into many of the constituent
programs. Because of its flexibility, LabVIEW has also seen fit to include ActiveX support.
The general concept of ActiveX actually follows a form of Object-Oriented programming
and therefore has many distinct similarities to the LabVIEW programs we use and write in this
lab. ActiveX controls are organized into different libraries which contain classes that are
explicitly tied to specific hardware or software references. When one of these classes is
instantiated it is tied to the hardware or software either implicitly or manually which turns the
class instance into an object reference. Each of these classes also has multiple methods
associated with them that perform specific actions on the object referenced.
In Windows, the installation of the ActiveX classes is buried deep within the system files
and is usually bundled with a specific program that makes use of them. Using LabVIEW, we can
access these classes using either property nodes or invoke nodes. A property node accesses the
details of the class, providing attributes of the object referenced. An invoke node is used to
access the methods of the class. To access a specific object, an Automation RefNum is tied to
each object reference, which is then passed to the nodes. These nodes can be found in multiple
palettes in LabVIEW, with the most general location being found in Programming Application
Control and more specifically in Communication ActiveX. You can then select the ActiveX
class by right-clicking the node, going to Select Class Browse…. LabVIEW then loads every
installed class, which is a lot, and you can select the library class you need. Nodes will also autoconfigure to the appropriate class if you wire up a reference. A significant downfall to using
ActiveX is that the classes do not always come bundled with documentation, meaning that you
have to guess what the class references and what the methods do based off of their names. We
still use ActiveX despite this failing due to its portability as well as its ease of use when
interfacing with the instruments (or we have no choice—see Synapse CCD). To see this, we will
use ActiveX to adjust the wavelength the TRIAX 550 Monochromator (the big tan spectrometer)
in Exercise 1.
The simplest way to create an ActiveX RefNum is to place a node, use it to select the
class, and create the control for it. You can then wire this control to an Automation Open
function that assigns a RefNum to the ActiveX class in question. In terms of our previous VISA
programming, the Automation Open function takes the place of the VISA Open Session and the
Close Reference function takes the place of the VISA Close Session. Finally, our Writes and
Write/Read combos are replaced by single nodes. Let’s see this simplification in practice.
Exercise 1
Write a driver VI that adjusts the wavelength of the TRIAX 550 Monochromator and
returns the new wavelength as read directly from the spectrometer (you do this because
the spectrometer does not always make it to the exact wavelength specified).
Hints: Though opening and closing the ActiveX class is just as simple as a VISA Session,
initialization of the spectrometer is quite complicated, so feel free to use the ActiveX-Init
and ActiveX-UnInit VIs found in the VISA Tutorial Answers.llb (look through them to
see what they do, of course). Using these VIs, the procedure becomes: Initialize, Write,
Wait until the move is done, Read, Uninitialize. The Waiting can be accomplished using
a while loop connected to an invoke node with the IsBusy method. Because the
spectrometer uses GPIB, small waits are needed before and after the loop to keep things
smooth.
Solution: VISA Tutorial Answers.llbActiveX-SetWave.vi
Though the overhead for getting this to work is somewhat more substantial than using
VISA functions (and to be fair, most of the complexity is inherent to the spectrometer itself),
actually communicating with the instrument is much easier. Syntax is completely taken care of,
complicated functions are reduced to a single node, and addressing is much simpler. This is
accomplished inside the ActiveX class itself. Before using these specific drivers, the
spectrometer must first be set up using another ActiveX class that ties the instrument and details
for communicating with it (i.e. bus and pertinent parameters) to a Unique ID. When this ID
string is associated with a reference, the reference then points to that instrument and
automatically configures the methods to use the appropriate bus and syntax. You should also
note that, much like in VISA, the opening and closing of the RefNum does not need to be
excessive, and the initialization and un-initialization procedures should only be applied once per
program (i.e. don’t initialize in each driver VI of an instrument control program).
It is important to note that the details of this procedure are specific to this particular
ActiveX class that interfaces with Horiba Jobin-Yvon Monochromators. Luckily, two of the
three ActiveX-enabled instruments in our lab are Horiba Monochomators (eventually Haeyeon is
going to take his back, making an eventual total of two). The only other thing is the Horiba CCD
attached to the spectrometer. As mentioned before, to use ActiveX to control something else, the
details will be different and knowledge of what the methods specifically do will be necessary
either through reference material or by trial and error. A wonderful example of this is the
advanced Excel Exporter the CCD program uses for saving data. Not only is it wildly different
from the JY ActiveX classes, but even different versions of Excel have different implementations
of the same ActiveX class.
1.2.2 Serial Polling
Back to Top
Serial Polling has a long and storied tradition in instrument automation. The concept
behind serial polling is to be able to know the state an instrument is without having to use a
traditional command to read it. This is accomplished by every instrument having a Status Byte
Register that can be read querying the value of a specific line in the GPIB bus. Typical
information contained in a Status Byte is: instrument error states (i.e. command errors or
physical limitations exceeded), command completion, message available (MAV), and Service
Requests (SRQ). The last two are universal to all GPIB instruments and always correspond to
bits 4 and 6 respectively. In more complicated instruments, there can be multiple Byte Registers
(the Lockin has four) that contain more information about the instrument. An important note on
these bytes is that they will not clear unless read by a serial poll or forced to clear by a command.
An unfortunate “safety feature” LabVIEW has included in its all-knowing design is that the
VISA:STB function does not count as a serial poll despite fulfilling that exact function and will
not clear the Status Byte, just in case you wanted to read the same error multiple times. To
accommodate for this, either conditional byte clearing after the fact or forced clearing before any
commands are sent is required.
For our purposes, there are only two uses for serial polling. First, it can be used to prevent
timeout errors by checking that information is available before trying to read it. Second, it can
also be used as a way to case select. For example, if the instrument’s status byte contains a bit
reporting parameter errors, you could use a serial poll after commands to ensure the command
was properly formatted or the given parameters were within range. In the case of an error, the
program could then report the error and abort before more harm is done.
Before we get into the nitty-gritty, special attention should be paid to the Service
Request. The SRQ is one of the standard features of GPIB and can be quite useful. A SRQ is
signaled by an instrument when any number of conditions is met and is a way for the instrument
to signal the GPIB Controller that attention is needed. The conditions for a SRQ are specific to
each instrument and will be outlined in detail in the instrument’s manual. In some special cases,
the conditions for a SRQ can even be customizable. This allows the programmer to set specific
conditions then serial poll for a single bit or even use special VIs that wait for a SRQ before
proceeding.
Exercise 1
To begin, we will use serial polling to identify errors in the Newport 1830-C Power
Meter. Write a VI that will write a “Rn” command to power meter, where n is any
integer, then read the Status Byte Register. Your VI should then interpret the Status Byte
and display a dialog box describing it. For this exercise, use the VISA set of VIs.
Hints: Remember, serial polling with VISA uses the STB function. The output will be an
integer. To convert to the Boolean representation for each bit, use the Number to Boolean
Array function under the conversions menu. Don’t forget the proper procedure for VISA
sessions [Open, Write, Delay, Read, Close]. Also remember to clear the buffers while
debugging and to clear the byte register when errors occur.
Solution: VISA Tutorial Answers.llbSPOLL.vi
Error handling using serial polls is a great tool for the LabVIEW programmer, and
hopefully it was not overly complicated. This ease may cause you to think that serial polls are a
wonderful thing and should grace every step of your programs. DO NOT DO IT! Excessive
serial polling is a very, very fast way to crash LabVIEW and can even lead to crashing the GPIB
bus itself in extreme cases (which will happen when you first try it; a computer reboot is the only
way to fix it). To illustrate the problem, exercise 2 will have you implement the first reason to
use serial polls—preventing timeout errors.
Exercise 2
Again using the Power Meter, apply the procedure for reading only new measurements
found in the power meter’s manual on page 26. Use any set of LabVIEW GPIB
functions.
Hints: This can be an extremely painful exercise, so don’t get too hung up on it. A longer
timeout and delays before any reading operation (including polls) will almost certainly be
required. Examples using each set of GPIB functions are provided, but they are buggy at
best, especially under repeated use. Use them as a guide when you get stuck.
Solutions: VISA Tutorial Answers.llbApplied SPOLL ***.vi
If you haven’t looked at Applied SPOLL.vi already, you should now. Its disabled
diagrams contain the standard VISA serial poll commands while the enabled diagrams show two
alternative methods to accomplish the same thing. Oddly, these methods are probably the most
reliable in this application. The one using SRQ even more so than the other (Look up the M
command in the manual to see how that works).
The reason this application is so troublesome is because of the limitations of the GPIB
bus and the instrument. The primary cause of timeout and other errors is sending too many
commands in too short a time. Therefore, using serial polling to eliminate these problems makes
little sense since it only adds to the traffic. The only way to get it to work is to use delays
everywhere to slow down the execution, which begs the question: “Why not just use delays in
the first place?” Why not indeed…
2.1 The Spectrometer
Back to Top
In this tutorial we will learn to control the spectrometer4 using LabView. What is nice
about this instrument is that it comes with most of the functions we will need already written, so
there is no need to rewrite them or use the programming manual that came with it. This contains
all the commands that the subVI’s use to actually control the instrument. All the subVI’s that
came with the spectrometer can be found in the library iba_user.llb in …\Spectrometer\Libraries.
The two that I wrote can be found in the main Spectrometer folder. Places in matrices are
defined as (row,col)
There are a few basic functions we are going to want to be able to do:
1. Learn to initialize the spectrometer.
2. Control the grating, which affects the wavelength that the spectrometer is currently
reading. We will want to control not only spinning the grating, but which grating (turret
is the place which holds the grating) we are actually using. There are 3 turrets, though
only 2 gratings, which means one spot is empty. We will primarily use turret #1. We will
want to read and write the spinning but can only write the turret setting.
3. Control the slits, which, by altering their widths, adjust how much light is entering the
spectrometer and the photomultiplier tube. There are four slits, but we only use two – the
axial entrance, which controls how much light enters the spectrometer, and the lateral
exit, which controls how much light enters the photomultiplier tube. It is recommended
by the manual that we keep the entrance and the exit the same for best results. We will
want to read and write this.
Your task at the end of this will be to write a short program that controls the spectrometer and
has the following features/does the following tasks:
1.
2.
3.
4.
5.
6.
7.
8.
9.
Initializes the spectrometer on start up and through a button – both time reading the
instrument settings.
Can set the turret and read the blaze wavelength and groove density
Can read the wavelength (preferably continuously, at least every half second)
Can change the wavelength to a user defined one, checking the allowable limits of the
spectrometer. You should also be able to watch the wavelength progress on an
indicator as it steps forward.
Can read the slit widths.
Can set the slit widths, checking the allowable limits before hand.
Have a button that just closes the slits (that is sets them to zero).
An error and spectrometer ready (that is already initialized) indicator.
A mechanism to ensure that one cannot change anything on the spectrometer until it is
initialized.
A solution can be found at Spectrometer Tutorial.vi. Please note this is not the only possible
solution (or necessarily the best) just the route that I took.
4
For more information on what a spectrometer is, see the manual that came with it or
http://en.wikipedia.org/wiki/Spectrometer
1. Initializing the spectrometer
It is important to initialize the spectrometer at the beginning of every program you
write (or every part of the program where you might try to access the spectrometer for the
first time in that program). It is actually only necessary the first time you use the
spectrometer after you turn it on, but since the spectrometer is rarely off, this is seldom.
However, it could happen and rather than having to run a separate program before you
can use your main program, it is good to put it the main code. It only takes a few
milliseconds to complete if the spectrometer is already initialized, so there is no harm in
doing it more than necessary.
The actual initialization of the spectrometer is carried out by a subVI that came
with spectrometer entitled Start up.vi. This does the dirty work – all you have to define is
the number of contact attempts, which I generally set to 2, which seems to work well.
This will attempt to contact the spectrometer and three possible things can happen:
I.
The spectrometer has already been initialized, which is the most likely case.
It will simply return the boot version and the main version, which contain no
important information, though I like to have it pop up just to be sure that has
made contact and things are running smoothly. The boot version and the
main version are stored in positions (0,0) and (1,0) respectively of the array
Controller Program Versions. Start up.vi will also output an error, which will
be true if an error has occurred.
II.
The spectrometer has not been initialized but is able to be initialized. This
process takes several seconds, as the spectrometer spends some time spinning
the gratings to find the correct one. After it is done, it will return the boot
version, main version and error as in the case beforehand.
III.
The spectrometer has not been initialized and cannot be for whatever reason
(most likely = power unplugged). This time, the program will not return the
boot version or the main version, simply “Error = T”. The program Start
Up.vi will attempt the contact the spectrometer until it times out, so generally
I set the timeout to 1000 ms before I run Start Up.vi.
It is also a good idea once you have made contact with the spectrometer to read all
the variables (wavelength, slit width, etc) to see what the spectrometer is set to.
I have put this entire process into a subVI called Initialize Spec.vi, which you can
use in test program if you want, or you can try and write one from scratch. You will
need to read the next two sections to find out how to control the grating and the slits so
you can read them in your initialization program.
2. Controlling the grating
The grating is the main part of the spectrometer – it controls what wavelength you
are on and what range of wavelengths you have (by changing which grating you are
using). The first step in communicating with the grating will be set the turret, so that
you have the correct information to know which wavelength you are on.
a. Setting the turret
Unfortunately there is no way to simply read which turret you are using (at
least that I have found yet). You must simply set the turret at the beginning of
your program, which I do in the initialization subVI (Initialize Spec.vi). Knowing
what turret, and therefore grating, you are using is important, because gratings can
have a potentially different groove density, which the program thatcontrols the
wavelength position uses to determine which wavelength it is on. However, both
gratings used now have the same groove density of 1200 groves/mm, but if
another grating were added with a different groove density, this would be
important.
To set the turret, you use the program Port & Grating.vi, which was
supplied by the manufacturer. You input the spectrometer number, desired turret
number and the mirror positions and you receive as output the error, blaze
wavelength and groove density of the grating.
I.
The spectrometer number is zero and is only meaningful if you
have more than spectrometer you are trying to control with the
same program.
II.
The desired turret number is either 0, 1, or 2, but only two of
them actually have gratings (0 and 1 – on the back of the
spectrometer that corresponds to grating 1 and 2, respectively. I
will always refer to them by either 0 or 1 because that
corresponds to the coding). Turret position #1 is what we have
used for almost all of our experiments to date, therefore, when I
initialize the spectrometer, I tell it to go to turret #1, which it is
usually already at.
III.
There are two mirror positions, entrance and exit and can be
set to either T or F, which correspond to “in position” and “out
of the way” approximately. The mirror settings are always the
same, entrance = F and exit = T. Entrance is set to F because
there is no mirror here and exit is set to T because the exit mirror
is needed to direct the light into the proper exit slit.
IV.
The error returns as T if something has gone wrong with Port &
Grating.vi.
V.
The groove density is used by the wavelength program to
determine which wavelength it is at, however, it retrieves this
data automatically from a global variable used by Port &
Grating.vi, so there is no need to save the variable yourself. I
usually display it, because it often more important to know that
than the turret number.
VI.
The blaze wavelength is not as important for the program as the
groove density. Basically the blaze wavelength (or blazing
wavelength) refers to the wavelength where the particular grating
is most efficient.
b. Reading the wavelength
Reading the wavelength is accomplished with a subVI provided by the
manufacturer called Spectral Position.vi. You have to just input the spectrometer
number and it will output the current wavelength, the spectral unit and the error.
To my knowledge, the spectral unit will never change from nm. I believe it is
primarily there to make programming with other models easier, which may have
ranges crossing the nm limit. Once again, the error will be T if there was a
problem.
c. Setting the wavelength
One sets the wavelength using a manufacturer-supplied program called
Spectral GOTO.vi, found in the usual library file. To set the wavelength you need
only input the spectrometer number and the desired wavelength and it will output
error, limit hit and invalid wavelength. So that we don’t have to worry about
these indicators (and as a matter of good form), it is probably a good idea to set up
a check for the wavelength being passed to Spectral GOTO.vi to ensure it is
within the limits, which are 0 nm and 1400 nm for both gratings.
One thing that I usually do is to run the Spectral GOTO.vi and Spectral
Position.vi simultaneously (Spectral Position.vi will have to be in a loop – the
other won’t), so that the program displays the wavelength as it is moving – not
only is it a cool effect but it also lets us know that it is still moving. To achieve
this effect, set up two frame structures in the area of the code where you are going
to want to move the grating – one to tell it to move the grating and one to track
the changes, using a variable to signal from “move to section” to tell the “tracking
section” that you are at the required wavelength. A possible solution is in
Spectrometer Tutorial.vi.
3. Controlling the slits
The slits control much light enters the spectrometer – therefore the width of your slits
will be proportional to the number of counts you get. Letting in too much light can
damage the photon counter, so it is always good to have safe guards in place, but that will
be covered in the photon counter tutorial.
a. Reading the slits
Unfortunately there was no “read slits” subVI when we received the
library files from the manufacturer; however I was able to modify the “set slits”
subVI, called Slits.vi, to only read the slits and not set them. The read only subVI
is called Read Slits.vi and can be found in the main spectrometer folder. The only
input is the spectrometer number and you receive as an output the four slits and
error. The first and last slit (axial entrance and lateral exit respectively) are the
only two that you need to concern yourself with when writing a program.
b. Setting the slits
To set the slits, you can use the built in subVI Slits.vi, where you specify
the slit widths in mm and the spectrometer number and you receive as an output
the adjusted slit widths and error. Once again, only the first and last slits concern
us, the other two can be left blank (the default is zero, which is fine). It should
also be noted that the smallest possible step size is 0.002 mm – the computer will
automatically round it for you to the closest one (though curiously, 0.001 mm is
rounded to 0.000 mm, even though 0.003 mm is correctly rounded to 0.004 mm)
Useful Information:
 Gratings
o Grating 0
 Groove Density – 1200 g/mm
 Blaze Wavelength – 500 nm
o Grating 1
 Groove Density – 1200 g/mm



Blaze Wavelength – 750 nm
Slits
o Ones in use – Axial Entrance and Lateral Exit
o Min – 0 mm
o Max – 2.24 mm
o Step – 0.002 mm
Spectrometer Files:
o Manufacturer supplied – C:\LabView
Programs\Spectrometer\Libraries\iba_user.llb
 Start Up.vi
 Port & Grating.vi
 Spectral Position.vi
 Spectral GOTO.vi
 Slits.vi
o Other – C:\LabView Programs\Spectrometer
 Initialize Spec.vi
 Read Slits.vi
 Tutorial – Spectrometer Tutorial.vi in folder Spectrometer
2.2 The Pulse Generator
Back to Top
The Agilent 81110A Pulse/Pattern Generator, as its name suggests, can do two major
things; put out a pulse that repeats itself or put out a certain pattern. The pulse is simple – just up
and down, what you control is the frequency, amplitude, duty cycle, etc. The pattern generation
is more complicated but ultimately more useful – it is this feature that we will use more often
than not.
In this tutorial, you will learn to do the following things:
1. Learn some basic commands and also which preexisting subVI’s can be used in place
of those commands.
2. Learn to use the pulse mode of the pulse generator by adjusting the frequency,
amplitude, etc.
3. Learn to use the pattern mode to create different shaped patterns (this will also require
the basic pulse concepts such as frequency and amplitude learned above).
4. Write a small program to use both modes as well as initialize the pulse generator.
Communicating with the Pulse Generator
Communicating with the pulse generator is straight forward – it uses GPIB and works
well with LabVIEW. For the most part, you shouldn’t have to worry about talking to the
pulse generator directly as there exists a system of subVI’s to do all a number of tasks,
though we will still cover the basics of GPIB communication in the first section5. The
subVI’s are located at C:\LabVIEW\Instruments\Pulse Gen\... to see all these subVI’s. There
are subVI’s to do the following tasks:
a. Check to see if the pulse generator is on.
b. Set/Read the voltage levels.
c. Set/Read the period or frequency.
d. Set/Read the pulse width or duty cycle.
e. Set/Read the output status (output 1, not-output 1, output 2, not-output 2).
f. Set/Read the various digital parameters associated with using the pattern mode
(pattern mode on/off, NRZ/RZ).
g. Turn on and off the display on the front of the spectrometer.
h. Set the arming source of the pulse generator.
1. Basic Commands
The pulse generator uses GPIB to communicate, so use the appropriate GPIB communication
subVI’s supplied by LabVIEW. The commands are always preceded by a semicolon and
there is a semicolon between each section of the command. After the command is fully
specified there is a space and then the value(s). If a unit is needed it follows the value
directly (no space) and is also in all caps. Queries are simply the command followed by a
question mark (no space). There is often a channel number associated with the command,
since there are two channels and this comes directly after the command, before the question
5
For a complete set of the commands used to communicate directly with the pulse generator, see the Agilent
81110A Reference Guide, beginning on pg. 43.
mark or space. Also note that if you look in the manual at the commands they usually appear
longer – anything in brackets is optional. I will always give the shortest possible command.
If a channel number is specified, channel 1 is assumed.
a. Asking for the Pulse Generator’s System Version
A query that returns the current system version – usefully for checking to see if
the pulse generator is on/connected.
:SYST:VERS?
b. Default Settings
Resets pulse generator to the default settings. Exception to the usual syntax
because this is a general GPIB command that works on any GPIB compatible
piece of equipment. Default settings can be found on page 33 of the Agilent
Reference Guide.
*RST
c. Frequency-Period
These two settings are linked – that is if you change one, you necessarily change
the other and it doesn’t matter which one you specify. Telling the pulse generator
a frequency of 1 Hz or a 1 sec period is the same thing.
:FREQ (value)(unit choice – S MS µS NS)
***responses from the pulse generator always use S
:PULS:PER (value)(unit choice – HZ KHZ MHZ GHZ)
***responses always use HZ
d. Duty Cycle-Width
As with the previous set of commands, these two are linked. Duty cycle refers to
the percentage of time that the pulse is “on” or at the high voltage level. This is
specified using a percentage, from 0 to 100. Width specifies the same thing,
except you do it with a time, 50NS for example. Width must be between zero and
the period currently in use.
:PULS:DCYC(1|2) (value)%
PULS:WIDT(1|2) (value)(unit choice - S MS µS NS)
e. Voltage Levels
Sets the voltage levels – there are several ways to do this, but the easiest is to
specify a high voltage and a low voltage. The other ways to set the voltage can be
found in the reference book. Note that these commands are all linked as well.
:VOLT(1|2):HIGH (value)(unit choice – V MV)
:VOLT(1|2):LOW (value)(unit choice – V MV)
***responses always in V
f. Outputs
There are four total outputs – output1, not-output1, output2, and not-output2.
Output1 is for channel 1 and output2 is for channel 2. All four can be turned on
and off separately.
:OUTP(1|2) (ON|OFF)
:OUTP(1|2) (1|0)
:OUTP(1|2):COMP (ON|OFF)
:OUTP(1|2):COMP (1|0)
***responses will be given in terms of 1 (on) or 0 (off)
g. Pattern Mode On/Off
This command simply sets the machine in either pattern or pulse mode.
:DIG:PATT (ON|OFF)
*responses are given as ON or OFF
h. Loading Pattern Data
This command is used to load the pattern into the pulse generator. The pattern
itself is just a string of 1’s and 0’s, which correspond to high and low voltage
respectively. This command is slightly more complicated than most of the others.
:DIG:PATT:DATA(1|2) #(length of header)(header, which tells the length
of the data)(data)
***there are no spaces after the # - length of the header is just a
number (1 – 9). The header consists also of 1 – 9 and can be as
long as you specified earlier. . The data must be only 1’s and 0’s.
(I think 2’s are possible if you are using the output adding
function, but I am not sure about this) The header can only be 9
bits long!! This means the max length of pattern is 999999999.
Example:
:DIG:PATT:DATA1 #1510101
The pattern goes to channel 1 – the header is 1 bit long, the
pattern is 5 bits long and the pattern is 10101
i. “Return to Zero” Status
This is a setting for pattern mode. If it is set to return to zero (RZ) then after each
bit in the pattern, whether it is a one or zero, the pulse generator goes to zero.
Conversely, if you are in not return to zero status (NRZ), then the pulse generator
stays at whatever voltage level the bit from the pattern tells it to.
:DIG:SIGN(1|2):FORM (RZ|NRZ)
***responses are given as RZ and NRZ
j. Pattern Updating
When uploading a pattern, the pulse generator can either switch to the new pattern
right away (pattern update = auto) or it can keep the old one running and hold the
new one in its memory until you manually tell it to switch. So we have three
commands – to set it to auto, set it to manual and to tell it to update.
:DIG:PATT:UPD ONCE
k. Triggering and Arming
There are two commands here that are related, but not quite the same. Arm refers
to when you are ready to start a new period/pattern. Trigger refers to when you
actually start your next period/pattern. By setting the trigger source to the internal
osc. (INT) we can sync these two up, so that every time it is armed, it triggers
right away. This will be our most common mode of operation. For most of our
experiments, we will arm using the external input (EXT1) and hook up the PEM
out to the external input. This way our pulse generator will stay synced with the
PEM, keeping our laser pulse synced with changes in retardance of the PEM. If
you simply want to output a 30 MHz continuous wave, set your arm source to
IMM.
:TRIG:SOUR (INT|INT2|EXT2)
:ARM:SOUR (EXT1|INT2|IMM|MAN)
INT = Internal osc.
INT2 = Internal PLL
EXT1 = External Input on the front of the pulse generator.
EXT2 = Clock-In on the back of the pulse generator
IMM = Signifies continuous mode where the next period/pattern starts
right after the previous
MAN = Manual key (on the front of the pulse generator).
Additionally there is trigger count (:TRIG:COUN) which can allow you to do tw
periods/patterns for each arm. Each new period/pattern is triggered by your
trigger source. We will usually keep this at one.
Note: The PLL (INT2) cannot be used as both a triggering and arming source)
l. Turn on/off display
This command simply turns on or off the display – the pulse generator programs
faster when the display isn’t on, so when speed counts turn it off!
:DISP ON
:DISP OFF
2. Pulse Mode
All pulse mode means is that you are creating a periodic wave, which may be
continuous or triggered based on your preferences. In its most basic form, pulse mode
simply puts a TTL of a certain frequency. You already have all of the commands you
will need to run the pulse generator. Pulse mode is the easiest mode to run it in; all you
need to do is specify your freq/period, width/duty cycle and voltage levels. You may
have to adjust the triggering and arming sources if you are starting off with the default
settings.
(include examples and Exercises)
3. Pattern Mode
Pattern mode is a bit more complicated than pulse mode – in pattern mode you are
defining a pattern using 1’s and 0’s (high and low voltage respectively). The sending of
the pattern is only slight complicated, once you figure out where your header is and such.
The most complicated part is probably generator the pattern using an interface that people
can easily understand. You can see one way of doing this in a the subVI Build Pattern
into String.vi. Basically you input your desired periods of on and off, along with your
actual period and it fits a string of 1’s and 0’s to it. It should also be noted that most of
the programs will do the opposite of what you want (in terms of 1’s and 0’s) because for
the laser is actually on for 0’s and off for 1’s. This seemed a more like a more logical
approach to things when the programs were first written because the user only had to
think in terms of the traditional 1 and 0, rather than having to switch it all in ones mind.
(include examples and Exercises)
4. Exercise
Create a program with the following features/abilities:
1.
2.
3.
4.
5.
6.
Initialize on start up and through a button (i.e. create a subVI for initialization).
Can create either patterns or pulses and a toggle between.
Adjustable amplitude.
Adjustable frequency or period and can toggle between the two.
Adjustable duty cycle.
Pattern as follows:
a. User defined number of sections (areas that alternate between up and down)
b. User can adjust the length of each section separately.
c. Your program must process this information and turn it into a pattern that the
pulse generator can use (a string) – make this into a subVI.
7. A button to send all the new information to the pulse generator (i.e. it doesn’t update realtime, rather only when you tell it to).
8. A text box that displays the current settings of the pulse generator (at least all the items
that are supposed to be adjustable) – updated every 0.5 seconds.
9. Can select with output you want to use.
5. Useful Information
a.
b.
c.
d.
e.
Minimum Period: 3.03 ns (330 MHz)
Maximum Period: 999.5 s (0.001 Hz)
GPIB Address: 10
Bus: 0
2.3 The Photon Counter
Back to Top
A photon counter is a device that does exactly what its name suggest; it counts photons. It
does this by examining current spikes from the photomultiplier tube (PMT). Each time a photon
strikes the detection surface of the PMT, an electron is released via the photoelectric effect. This
electron then strikes a series of dynodes, which release additional electrons. For example if one
dynode releases 5 electrons for each electron it receives and there are 6 dynodes, then one photon
generates 56 = 15,625 electrons. Thus one photon generates thousands or even millions of
electrons6.
The photon counter has nothing to do with this detection process – it merely counts the
current spikes to determine how many photons have been detected, but it does have special
capabilities. A photon counter must be able to detect these current spikes, set a level (called a
discriminator level) to determine how the high the spikes must be and, of course, count fast.
Additionally, many photon counters are gated, which means that over different intervals, the
photons are counted by different channels. For example, if you are counting over 1 second, you
can define the first half second to be counted by channel A and the second half second to be
counted by channel B. Of course, this arrangement can be more complicated. All of these are
settings that can be adjusted via LabVIEW.
In this tutorial, you will learn to do the following things:
1. Learn some basic commands and also which preexisting subVI’s can be used in place
of those commands.
2. Learn to count photons both with and without gates.
3. Write a small program to use both modes as well as initialize the photon counter.
1. Basics
2. Gating
3. Exercise
Create a program that does the following things:
1. Initializes with the basic settings that are almost never changed.
2. Counts photons for a set time period and displays both total counts and normalized counts
per second (CPS). This will involve creating a subVI that acquires the data from the
photon counter (using a serial poll). It should be able to count for one cycle or
continuously.
3. Create a stop counting button. This will probably require use of global variables.
4. Can count in gated or un-gated mode, with one or two channels.
5. Can adjust the gate width and delay.
6. The program should be able to take the count time input as seconds and adjust them in
terms of the number of cycles for whatever counter you are using.
6
There is a problem with this; thermal energy can lead to the spontaneous emission of electrons, which will be
registered as a false photon. The sum of the spikes generated from thermal emissions is known as the dark current
and it obviously dependent on temperature. Our PMT is cooled to approximately -40 C, where the dark current is in
the single digits of counts per second. Further PMT information: http://en.wikipedia.org/wiki/Photomultiplier.
4. Commands
Cmd List
0
CM {j}
1
CI i {,j}
2
NP {m}
3
NN {j}
4
NE {j}
5
DT {x}
6
SD {j}
7
TS {j}
8
TL {v}
9
DS i {,j}
10
DM i {,j}
11
DL i {,v}
12
GM i {,j}
13
GD i {,t}
14
GW i {,t}
15
CS
16
CH
17
CR
18
CL
19
SS {j}
20
ST m
21
RC m
22
QA
23
QB
24
CP i {,m}
Counting Mode
Counting Inputs
Number of Periods
Scan Position
Scan End Mode
Dwell Time
Count Disp Mode
Trigger Slope
Trigger Level
Disc Slope
Disc Mode
Disc Level
Gate Mode
Gate Delay
Gate Width
START Key
STOP Key
Reset Counters
Default State
Read Status Byte
Store
Recall
Read A
Read B
Counter Presets
2.4 Synapse CCD
Back to Top
This section is a bit different from the rest. Most of the nitty-gritty details are actually in
the ActiveX section and the SynerJY SDK. Instead, this section contains guidelines and a list of
known issues to keep you on the straight and narrow.
The Synapse CCD is the only instrument in the lab that requires us to use ActiveX classes
for the drivers (the spectrometer borrowed from Haeyeon aside). As such, its programming is
significantly different from that of other instruments in the lab and should be approached with
some caution. We did manage to obtain an SDK for their ActiveX classes to give us some
documentation in the summer of 2011 in order to aid our programming efforts. Unfortunately,
some further caution is still warranted when using it since our software is from 2007, resulting in
differences between what the SDK claims and what actually happens. Finally, the source of the
ActiveX classes is Horiba Jobin-Yvon’s SynerJY program. This alone warrants extreme caution
on our part. I do not trust their programmers any farther than could punt their computers. Not
only does their own program have catastrophic bugs, but they are even so bold as to release the
development version of their ActiveX classes to customers (the SDK mentions some internal
“test” methods we shouldn’t use). In order to protect yourself from hours of frustration and an
intense, burning hatred of one particular company, follow these simple rules before and while
working with the CCD programming:
1.) Read the Tutorial You must read the ActiveX section of this tutorial before doing
anything else. If you haven’t read it yet, do it RIGHT NOW. Actually work through the example
too.
2.) Unit Tests New methods should always be tested in a controlled environment before
being using in another program. These tests are simple, single pass VIs that initialize, do the
operation to be tested, then finish up. Make sure that the method is behaving properly under
every possible condition. Be thorough. This one step will save a lot of trouble later on.
3.) Test Functionality with Other Programs If you have code that either should or did
work and is now not functioning properly, start by making sure the other CCD and spectrometer
programs we have are still functioning. These include SynerJY, Horiba’s spectrometer contol,
and the spectrometer control panel in LabVIEW. Different programs allow you to test different
things. SynerJY uses the same ActiveX classes that LabVIEW does, so errors with the classes
can be identified with it. Horiba’s spectrometer control is designed to work independently of
everything, and is a good for making sure the spectrometer itself isn’t broken. Our spectrometer
control uses direct GPIB commands and is a good test for connectivity, communication, and
functionality of the spectrometer.
4.) Have You Tried Turning It Off and On Again? This trick has never actually
helped with the spectrometer (disconnecting all other GPIB devices has though). The CCD,
however, responds very well to this. Unplug the USB cable from the computer when you do it
for good measure.
5.) Re-use Code The code we have now is fairly robust. If nothing else, you should at
least use it as a template for your own code. Just don’t use the driver VIs from Jobin-Yvon as a
template. You don’t need the ability to initialize in every VI. You also shouldn’t make VIs with
non-uniform connector patterns. And don’t write your comments in French either.
2.4.1 Known Bugs
There are a few known issues with the CCD’s and Monochromator’s ActiveX classes that
are not listed in the SDK.
1.) Ideally, we should be able to pass a RefNum for the attached monochromator to the
CCD class. This would allow the CCD to control the monochromator directly, ensuring a high
level of coordination. Unfortunately, the JY programmers type-casted the monochromator class
improperly so we can’t do it. Too bad.
2.) There is an interesting quirk with the monochromator methods. Namely, the methods
tend to lock down communication with the instrument even when unnecessary. For example, it
should be possible to query the center wavelength while it is moving. Using direct GPIB
commands this is possible, but not with the ActiveX classes. Doing something like this therefore
requires use of the more direct commands.
3.) The three built-in spectrum processing methods for the CCD (Average, Dark
Subtract, and Cosmic-Ray Removal) only work if the spectra were taken using the
‘DoAcquisition’ method. Unfortunately, this method doesn’t really work. Not only does the
documentation leave something to be desired, but the spectra it acquires are usually incorrect.
The current workaround is to simply do the post-processing after the fact by hand. This is a
somewhat complex process, but appears work for our needs.
4.) It is possible to outright break the ActiveX classes, we just aren’t sure how. The
former main lab computer suffered from this. One day, the ‘SetCenterWavelength’ method
decided it would set to the desired value divided by 10. The slit setting methods also stopped
working properly; requiring multiple sets to achieve the desired value. Ultimately, we had to
switch computers to another system that did not suffer the same problems. Strangely, the new
system is identical to the old one. Hope that you don’t run into this one again.
Of course, you may be wondering if you could find another way to do this, to avoid
ActiveX entirely. It is technically possible. Not only do we have SynerJY, but it should be
possible to use the USB VISA command to communicate. Each approach has its problems. First,
the poor quality of SynerJY is the reason we wrote our own LabVIEW program in the first place.
Second, Jobin-Yvon does not provide the command set for the CCD, which you would need to
use direct communications.
Now, an astute observer may notice that even the attached spectrometer is controlled with
ActiveX in the CCD program, which it doesn’t need to be. We already have a functioning set of
drivers for the spectrometer that use direct GPIB, so why not use them? This is more a matter of
preference really. Assuming bugs 2 and 4 are not a problem, using the ActiveX classes makes the
software much more general. We would be able to simply attach the CCD to any compatible JY
spectrometer, change a few lines of code, then be up and running again. All thanks to an extra
layer of abstraction that boils down details for communication into a single UniqueID string. The
ActiveX classes also tend to be a bit more stable on the GPIB bus than our own code, which I
appreciate.
2.5 Magnet
Back to Top
3.0 Helpful Coding Suggestions
Back to Top
Some very helpful information can be found on the wiki for our Google Code page. It can
be found at code.google.com/p/coltonlab.
4.0 References and Further Reading
Back to Top
1.
2.
3.
4.
5.
6.
LabView7 Express: User Manual.
LabView7 Express: Getting Started.
LabView7 Express: Development Guidelines.
LabView for Dummies. < http://www.iit.edu/~labview/Dummies.html>
Info-LabView. <http://www.info-labview.org/>
LAVA: LabView FAQ. <http://forums.lavag.org/index.php?showforum=30>
a. LabView forums where you can read posts and ask questions.
7. National Instruments: LabView. <http://www.ni.com/labview/>
a. LabView homepage.
8. LabView Developers Zone. <http://zone.ni.com/devzone/labviewzone.nsf/
OpenPage?openagent&lvsection=labviewzone>
a. LabView developers site supported by National Instruments.
5.0 Appendix
5.1 Numerical String Formatting
The format is:
%.(digits past decimal)(display type)
Back to Top
Back to Top
Example:
%.3f = floating point with 3 digits of precision (3 digits past the decimal).
10.4533  10.453
%.2e = engineering (scientific) format with 2 digits past the decimal.
10.4533  1.05E+1
The allowed formats include:
 f = floating point
 e = scientific or engineering format
 p = floating point in SI format
 g = LabVIEW uses floating point if the value of the exponent in scientific
notation is > -4 or less than the precision specified; otherwise it uses
engineering format
 x = hex
 o = octal
 b = binary
 u = unsigned
**Certain members of the scientific community, especially those in computationally
heavy areas, will recognize this as FORTRAN formatting.
Download