Monday, July 30, 2007

Pop Quiz Answer

Nobody answered my pop quiz!


Pop Quiz: Default data on a front panel control is useful, for example, when the control is on the connector pane, but isn't wired in the caller's diagram. The subVI runs with the default value in that case. When is default data on an indicator useful?

Read more for the answer...



We pass data out of subVIs through its indicators that are on the connector pane. But what if an indicator doesn't receive any data while the subVI runs? In that case, we use the indicator's default data and pass that out to the caller.


A picture helps. Here are the two frames of a case structure...



This is an example of a conditional indicator. The indicator is only updated in one frame. If the VI never executes that frame, no data ever reaches the terminal for the indicator. When the indicator's data is passed out of the connector pane, the default data for the indicator is used in that case.


So in the example above, I made the default data for "My Conditional Indicator" the value 456. I put the "Case?" Boolean and the "My Conditional Indicator" on the connector pane and saved the VI. In the calling VI, if I pass True, I get the result "123". If I pass False, I get "456". Make sense?


Why did I bring this up in a posting about performance? Because it affects memory usage. LabVIEW has to account for two different ways that a conditional indicator can be updated (through a wire or by copying the default data). This interferes with the in-place algorithm and means that LabVIEW can't be as efficient with memory usage.


Conditional indicators aren't typically needed. I could have achieved the same effect with the following diagram...



(Or, for simple things like this, I could have used the Select function.


So, you might want to look at your own code for places you are using conditional indicators to see if you can improve your memory usage. I wouldn't worry much about scalars and other small data, but if you have large arrays or strings, this can make a difference.


Read more of this article...

Thursday, July 26, 2007

NIWeek 2007

NIWeek 2007 is fast approaching on August 7-9. If you use NI products (or are thinking of using them), this is an awesome event. Dozens of technical sessions, amazing keynotes, and scores of exhibitors. In addition, we have special summits for Graphical System Design, RF and Wireless Communications, Sound and Vibration, and Vision applications. Register now at niweek.com.


Staying informed during NIWeek



  • Whether or not you are attending NIWeek, watch the NIWeek Blog by Michael Aivaliotis. Videos and stories throughout NIWeek.

  • The official NIWeek Twitter link can keep you informed of late-breaking NIWeek news. Or maybe you can just twitter each other during my presentation about how great it is. ;-)

Speaking of my presentations, I have three this year...



  • Software Engineering - The NI Way

  • Using LabVIEW in an LXI-Based Test System

  • Head-to-Head High-Speed Bus Comparison: GPIB, PCI, PCI Express, USB, and Ethernet/LAN


I'll post more information on these as we get closer.

Read more of this article...

Thursday, June 21, 2007

Yet another kind of data

Note... I'll be in Vancouver, B.C., for next week's LabVIEW Developer Education Days on June 26. I hope to see some of you there.

As I mentioned last time, there's a fourth kind of data that can show up in the profile window...Default Data.



I'll go back to the simple VI I used in the last posting. It's an array of int8's wired to an array of int8's. The default value of each array is empty. This means that when I load the VI into memory, the front panel doesn't have the arrays allocated. (And the VI only takes up about 8 kilobytes of disk space.) For my earlier profiling tests, I was typing a new value into the millionth element of the array control, which allocates the million bytes for it. When I ran this VI, it consumed five megabytes of data.


Now let's see what happens when I go ahead and "Make Current Value Default" for the million-byte array...



When I run the VI (and I've run it more than once, so you can see the final values in the profile window), you see that the five megabytes has turned into six megabytes. The profile window is now showing you that there's an extra megabyte of memory being consumed by this VI, because of the default data.


To take it a step further, if I also made the indicator array's data the default, I'd be growing the memory consumption to seven megabytes.


Default data is often a good thing, but we sometimes find VIs where we've saved a large amount of data as default accidentally. This is easy to do if you select the "Make All Current Values Default" menu item from the Edit menu. I try to stay away from this menu item, and instead only set the default value for the controls I know that need it.


Pop Quiz: Default data on a front panel control is useful, for example, when the control is on the connector pane, but isn't wired in the caller's diagram. The subVI runs with the default value in that case. When is default data on an indicator useful?

Note that the VI Analyzer reports non-empty default values for arrays so that you can take a closer look at them. (The VI Analyzer is a separate add-on for LabVIEW that can check your VIs for common programming errors, style conformance, and in this case, performance issues.)


Interesting side note... When I save my new test VI to disk, how much disk space do you think it consumes? Seven megabytes? Two megabytes?


It turns out that it takes up about 8 kilobytes, which is about what it took when I hadn't saved any default data. Why is that? It's because my default data was entirely made up of zeros. The VI's data gets compressed when it's saved, and a million zeros compresses very well.


Just for fun, I created an identical VI with a million bytes of random data saved as default data for each front panel array. That VI took about 1.2 megabytes on disk—still, that's a 40% savings over the uncompressed data, which is pretty good, I think. (Your mileage may vary.)


Read more of this article...

Tuesday, June 19, 2007

LabVIEW Performance and Memory Management

When I talk about performance optimization in LabVIEW, I pretty quickly focus on memory management issues. Memory isn't the only concern. It's just that memory issues are sometimes the hardest to understand. Plus, since LabVIEW is a dataflow language, we have a lot of emphasis on the data.


One way to monitor memory usage in LabVIEW is to use the profiler.




Select Profile Memory Usage to see how much memory each of your VIs is consuming.



Here's a simple VI I wrote that contains an array control wired to an array indicator. I changed the data type of the array element to be a 1-byte integer. This makes it easy to see how much memory the array is taking--one million array elements equals one million bytes. (If we had an array of doubles, one million array elements equals eight million bytes.)


I've initialized the control to have one million elements. (Actually, 1,000,001, but who's counting. ;-) Before I run the VI, it is using 1 million bytes for its data--the indicator is an empty array. The profiler won't show you this; it doesn't do its thing until you run the VI.


Okay, once I run the VI, how much memory do you think it takes? Let's see what the profiler says...



Approximately 4 million bytes! What's going on?


In my last blog entry, I said I'd tell you about the three kinds of data in LabVIEW, and they're all showing up in this profile result. The three types of data are...



  • Operate Data—Every front panel control and indicator keeps data that we call the "operate data".

  • Execute Data—Every wire on the diagram represents a buffer of data. The data for the diagram is called "execute data" or "execution data".

  • Transfer Data—Buffer used to isolate execution threads (which work with execution data) from the user interface thread (which works with operate data).


So why do we need these three kinds of data? As we'll see in later postings, the diagram likes to share execution data buffers among parts of the diagram, so the data that originally came from a control can get overwritten with intermediate and final results as the VI executes. You don't want front panel control's data to be changing while the VI runs, though! This means that we have to have a separation between the diagram and the panel.


The transfer buffer is used as an optimization in LabVIEW's multithreaded execution system. When the diagram wants to send data to an indicator, it has to work with LabVIEW's user interface thread to draw the data. There can be many execution threads, but there's only one user interface (UI) thread. Thus, the UI thread can potentially be a big bottleneck if all those execution threads had to sit and wait for it. That's where the transfer buffer comes in. It's a buffer that both the UI thread and execution threads can quickly access without (usually) blocking.


So when a block diagram updates an indicator, the execution data is copied to the transfer buffer by an execution thread, and some time later, the UI thread reads the transfer buffer and copies the data to the operate data.


So back to our example. We have a million bytes in the control (operate data), a million bytes in the control's transfer buffer, a million bytes on the wire (execute data), a million bytes in the indicator's transfer buffer, and a million bytes in the indicator (operate data). That adds up to five million bytes, right?


But the profile window said four million. What's the deal? Recall that I said that the profiler does its thing while the VI is running. It turns out that in this simple diagram, the VI stops running before the UI thread has had a chance to make the last copy of the data (from the transfer buffer to the indicator's operate data).


When profiling, I tell people to run their VIs a few times to make sure that buffers are allocated. If I run the VI again, I'll now see five million bytes...



If this were a more realistically complicated VI, there's a good chance that the profiler would have counted all the data the first time.


Next up... I lied. There's a fourth kind of data that can show up in the profile window. What is it?


Read more of this article...

Wednesday, June 13, 2007

LabVIEW Performance, The Early Years

I started working at NI in 1988, when LabVIEW 1 was shipping. LabVIEW 1 was so cool. But once you got past the awesome (for the 1980's) graphics and graphical programming paradigm and started to use it for real work, you noticed that it was a tad slow.


We learned a lot doing LabVIEW 1. So much so that we decided to throw away the source code and start over with LabVIEW 2. While LabVIEW 1 was an interpreted language, LabVIEW 2 was built from the ground up to be compiled. And when it came out in 1990, LabVIEW 2.0 demonstrated much better performance. For some applications, it was an order of magnitude or more faster. (So fast, in fact, that we ran into problems talking to many GPIB instruments that couldn't keep up with commands we were sending.)


LabVIEW 3 released in late 1993, and was the first version of LabVIEW that unified our original Macintosh codebase with our PC and Sun versions. Soon after, I created the first presentation to customers about LabVIEW performance...



In May 1994, I was invited to Sweden to present "Tips & Techniques for Improving LabVIEW Performance". It discussed how to take advantage of the many performance optimizations available in LabVIEW, and also discussed patterns to avoid, such as local variables. (Don't worry, I'll cover these in subsequent postings.)


My presentation was based on some earlier technical notes, as well as an article by Monnie Anderson in the now defunct LabVIEW Technical Resource. (LabVIEW Memory Secrets, Volume 2, Number 1, Winter 1994)


Before I left for Stockholm, I practiced the presentation in front of the LabVIEW team. This turned out to be a great experience—I presented to the toughest audience first. It did yield one unexpected result: the LabVIEW development team did not agree on how LabVIEW worked!


More precisely, I had found a common situation where LabVIEW made an extra copy of data that unexpected and unnecessary. Within a few days, our compiler expert had a fix that later came out in LabVIEW 3.1.


Why am I telling you these stories? Even though the latest LabVIEW is many orders of magnitude faster than LabVIEW 1, and even though we can handle much more complicated applications than we could a couple of decades ago, we're not resting. We're still working on performance issues today.


For example, we've seen much growth in the use of multi-core processors in affordable PCs. While LabVIEW has been ahead of this curve and able to take advantages of multiple processors and cores since our 1998 release of LabVIEW 5.0, we're continuing to look at new ways to leverage all this computing power.


Another reason for these stories is to make it clear that performance issues are sometimes difficult to understand. And I'm hoping that my future blog posts will help clarify these for you.


Next up... The three kinds of data in LabVIEW.


Read more of this article...

Tuesday, June 12, 2007

Expanding Scope

I returned recently from a couple of trips lamenting that I haven't been keeping this blog current. I was visiting customers in Massachusetts, Connecticut, and Colorado, discussing topics ranging from "performance optimization" to "software engineering". It occurred to me that my blog's current focus isn't keeping up with my everyday work life.


I spend a lot of my day at NI working on "next year's LabVIEW". It's cool stuff. You'll like it. But it doesn't produce much fodder for my blog, because I can't talk about specifics yet. Also, my current project is pretty far-reaching, and doesn't fit neatly into just "data acquisition and instrument control".


So, I'm going to start expanding the scope of my blog a little to cover a few more topics that I care about—and that many of you have told me that you care about, too.


Coming soon... The first of several postings about performance issues. If you have other LabVIEW-related topics you'd like me to cover, please post a comment or send an email.




Read more of this article...

Friday, April 20, 2007

A Good Cause

Today's the day I leave for the MS-150, a two-day, 180-mile bike ride from Houston to Austin, Texas. I'll be riding along with 12,000 other friends and strangers to raise money for the National Multiple Sclerosis Society. This is my third year to do the ride.


Am I ready? Hmm. I'm not sure I can ever be "ready" for a 180-mile bike ride. It is definitely hard. It's also fun to be doing this with nearly a hundred of my co-workers. And I take pride in my own personal accomplishment, as well as being able to help the National MS Society.


My goal is to raise $1500 for the society. The National MS Society is a 501(c)(3) organization, so your donation may be tax deductible. Your donation benefits thousands of people affected by multiple sclerosis. You can donate online here...
http://ms150.org/edon.cfm?id=190138


You can learn more about the society, about multiple sclerosis, and about the bike ride here...
http://ms150.org/ms150/about_ms_society.cfm

Read more of this article...

Monday, February 19, 2007

La Mort du Serpdrv

A series of "interesting" events have conspired to keep me away from my blog lately, so I decided to write about something "juicy" to start things back up. (Where "juicy" means "controversial for people who have been using LabVIEW for more than five or so years". ;-)


Today's topic is about an entity named "serpdrv", mentioned in an earlier post. This entity provided serial (RS-232) support for LabVIEW 2.5 through LabVIEW 6.x. In LabVIEW 7, I arranged for its demise. This posting will talk a little about how it came into existence, and how it made its exit. You'll hopefully gain some insight into how we reach the decision to phase out aging features.



In January of 2002, I posted a message to the Info-LabVIEW mailing list to help a LabVIEW user solve a problem with his serial I/O. Near the end of my posting, I inserted the following text...


I will again encourage people to use VISA for all future serial port development. At some point, I would like to see the "serpdrv" VIs go away. (And since I'm the decision-maker on this, it'll probably happen. :-)

And thus began an outpouring of support for this little thing we call "serpdrv".


It's also the day that I started an internal document called "La Mort du Serpdrv", to start my plan to remove "serpdrv" from LabVIEW. You can construe the existence of this document a couple of ways. Some might consider it our battle plan to kill off the feature. I personally considered it a place to gather user feedback, document shortcomings and features of serpdrv, and come up with a plan to strengthen our other options for serial I/O so that removing serpdrv would be easier.


The Birth of Serpdrv


LabVIEW 1 and 2, as many of you recall, were only available on the Apple Macintosh. Macs had RS-422 serial ports, disguised as the "modem" and "printer" ports. They were quirky not only from a hardware perspective, but also from software. On the old Macs, you used the "Device Manager" to talk to the serial drivers named ".Ain", ".Aout", ".Bin", and ".Bout". Inside Macintosh described the data structures for the driver and how to get the serial port to do all the right things.


In LabVIEW, we created some low-level primitives for this Macintosh Device Manager. We then built the serial VIs on top of the Device Manager primitives. (And as I recall, we built GPIB and DAQ VIs on top of those same Device Manager primitives to get to our own devices.)


When we ported LabVIEW to Windows and SunOS, we needed to invent a cross-platform approach to serial I/O. Every platform did something completely different, so we made a decision not unlike many other decisions of the day: Let's make everything look like a Mac.


So, we invented a Device Manager for LabVIEW for Windows and Sun that looked like the Apple Device Manager. Then we intented Macintosh-like "drivers" that plugged into our new proprietary device manager. Constrained by the Windows 8.3 filenaming conventions of the day, we used the names "serpdrv", "gpibdrv", and "daqdrv" for those low-level drivers.


And that's how things stayed for the next several years. Our GPIB and DAQ support eventually switched to more modern technology. Serpdrv, however, remained. We'd fix the occasional bug, but the overall structure of serpdrv stayed the same.


And Then There Was VISA...


Around the time of LabVIEW 4.1 and 5.0, NI-VISA came into existence. Among other things, VISA could read and write to serial ports and the GPIB. At first, it wasn't as good at serial I/O as "serpdrv", and it wasn't as good at GPIB as our NI-488.2 driver. What VISA had going for it is that it was a combined API layer that made serial and GPIB devices look nearly the same. Since many hardware devices had both GPIB and RS-232 options, we could write a single instrument driver with VISA, and it would work regardless of the I/O option in the device. (And the benefit continues to this day with USB- and LAN-based instruments.)


Around the LabVIEW 5 and 6 timeframe, I became the manager of the part of LabVIEW that was responsible for all the forms of I/O. Among many other things, I was responsible for "serpdrv", and I was responsible for ensuring that VISA worked well in LabVIEW.


Even then, "serpdrv" was legacy code that only one person (not me) really understood. I remember investigating a problem where hardware flow control didn't work. The code to handle flow control clearly didn't match what Microsoft said it should. So I changed it. But that broke something else. This is where I start to question whether we need two ways to do serial I/O in LabVIEW.


Making VISA better


So I put out a challenge to the VISA group... "Remove the barriers that keep VISA from replacing serpdrv."


VISA already had a lot of things going for it. It was a better API for LabVIEW. It had more features, such as control over individual hardware lines. It also had fewer bugs—for example, hardware flow control worked. On the other hand, it was slower and bigger.


The NI-VISA group responded to the challenge. The speed problems were caused by extra threading overhead in the driver. It didn't take long for VISA to be faster than "serpdrv" for serial I/O. They also created a small VISA serial runtime that the LabVIEW Application Builder could use for deployment. It wasn't as tiny as "serpdrv", but it was a big improvement over the tens-of-megabytes for the full VISA driver. And then we had to work through some VISA licensing issues so that LabVIEW users could freely distribute applications that used the VISA serial runtime.


What our customers didn't see was a lot of internal discussion and angst. Besides feedback from external customers, we also had feedback from our own FieldPoint group. They had industrial controllers with very limited processing and memory capability. Switching to VISA was a bigger deal for them than for most of our external customers.


And "serpdrv" disappears...


By LabVIEW 7, VISA had improved and I decided that we could proclaim that it was good enough that we could deprecate "serpdrv". We created a set of compatibility VIs that presented the old API, but it was built on top of the VISA functions. Many people did not notice. Some did, leading to another round of commentary on Info-LabVIEW.


It didn't take long for somebody to figure out that the old "serpdrv" VIs would still work in LabVIEW 7. This gives our customers an "out" if they absolutely don't want to use VISA for serial I/O. While not supported (or even tested), they should still work in LabVIEW 8.x, too. That's because the mysterious Device Manager primitives are still in LabVIEW. But that won't always be the case, and I can announce to you today that we'll remove the Device Manager interface in a future version of LabVIEW. I don't know when, but it's going to happen.


Moving on...


So I want you to realize that we do agonize over changes like this. Before we started, VISA was in many ways superior to the old serial VIs. Not satisfied, we put in a substantial amount of additional effort to make it better still. I still look back over my shoulder to see if I've missed something, but I'm confident that "serpdrv" won't be coming back.


Read more of this article...

Friday, December 29, 2006

Using IVI-C and VXIpnp Drivers in LabVIEW

Happy end of 2006 to everybody out there.


In earlier posts, I've talked about the various kinds of instrument drivers. All of the modern types of instrument drivers work reasonably well in LabVIEW, but some work better than others. Specifically, LabVIEW Plug and Play instrument drivers (written in native LabVIEW source code) give LabVIEW users the best experience.


But not all instrument drivers are written in LabVIEW. This post talks about instrument drivers written in C, and how to bring them into the LabVIEW environment. C is considered a kind of "universal language"; C compilers are available for a huge number of platforms. So, vendors whose mission is to write a single driver that is usable on many platforms in many different environments often write a driver in C. (Though a reminder from an earlier post, the one-size-fits-all instrument driver isn't a particularly good idea.)



The first step in using a C-based driver in LabVIEW is to turn the C code into a DLL or Shared Library. Often, the person who wrote the driver does this for you, at least for Microsoft Windows. How to compile the driver is left as an exercise for the reader. My focus is on making the resulting shared library usable in LabVIEW.


To use a shared library (DLL) in LabVIEW, you use the Call Library Node (CLN) function on the diagram. You configure a CLN for every function you want to call. Typically, you create a single VI for each C function, and then use these VIs in higher-level diagrams. (Click to enlarge)



As you can imagine, if you have a shared library with dozens or hundreds of entry points, it can be tedious to make these VI wrappers. Fortunately, we have tools to make this easier.


Kinds of C-based Instrument Drivers


Broadly speaking, there are three different kinds of C-based instrument drivers...



  • Drivers that do not conform to VXIpnp standards

  • Drivers that conform only to VXIpnp standards

  • Drivers that conform to both VXIpnp and IVI-C standards


The more standards a C-based driver conforms to, the more we know about how it is structured. The more we know about it, the better job we can do pulling the driver into the LabVIEW environment.


For drivers that don't conform to VXIpnp, we can't make any assumptions at all. We see this more often with somewhat esoteric instruments, or instruments from industries other than traditional test & measurement.


For VXIpnp drivers, we know they have an Initialize, a Close, a certain form of error checking, and a few other details. We don't know anything about instrument-specific functionality, such as whether a device is a DMM, a Scope, or something else.


IVI-C drivers go a step further, and define more of the API, at least for certain classes of instruments (such as DMMs, Scopes, Switches, etc.). This lets us more intelligently bring these drivers into the LabVIEW environment.


Tools for Importing


There are two separate LabVIEW tools you can use to help import these drivers. The first is the DLL Import Wizard, for importing generic (not VXIpnp or IVI-C) DLLs. The NI web site has a tutorial about this tool, so I won't go into much detail about it here.


If you have a VXIpnp or IVI-C driver, you want to use a different tool—the LabVIEW Instrument Driver Import Wizard, found on Instrument Driver Development Tools and Resources page on ni.com.


Unlike the generic DLL Import Wizard, the Instrument Driver Import Wizard is able to use its knowledge of the VXIpnp and IVI-C standards to create better wrapper VIs. It even makes an attempt to translate the C terminology in the help to LabVIEW terminology. Here's an example, showing the original C help and the translation into LabVIEW terminology...(Click to enlarge)



The Instrument Driver Import Wizard understands VISA and IVI refnum data types, it knows how the driver does error checking, and it creates better icons. It isn't perfect—there's a very good chance that you will want to tweak some of the resulting VIs to improve front panel layout, connector panes, and help. You may also want to clean up parameters to make them easier to use in LabVIEW—for example, integers that represent bitfields that you are supposed to "OR" together. But, the Instrument Driver Import Wizard handles a lot of the conversion for you.


If it isn't obvious... If you have a VXIpnp or IVI-C driver, you use the Import Instrument Driver Wizard, not the Generic DLL Import Wizard.


Final Caveats


The Instrument Driver Import Wizard used to be called the "CVI Function Panel Converter" and we shipped it with LabVIEW. Beginning with LabVIEW 8, we made it a web download. Some instrument vendors complained about this. They were claiming good LabVIEW support for their C-based drivers, but telling end users to go run the tool themselves to create the LabVIEW VIs.


My philosophy is that most end users don't need to run this tool. In an ideal world, the developer of the C instrument driver should be the one to run the LabVIEW Instrument Driver Import Wizard. Since the output of the tool often needs some tweaking (or even fixes to the C code), I'd prefer that only one person (the driver developer) create the wrapper. If every end user has to create the wrapper VIs, and then go hand-tweak them, it isn't very efficient. Many end users aren't going to understand the C driver well enough to make these changes easily.


Another caveat is that these tools only run on Windows. Fortunately, the resulting VIs can run on any LabVIEW platform (assuming you can recompile the DLL on the other platforms). Many VXIpnp drivers can run on multiple platforms. Interestingly, members of the IVI Foundation have told me that conformant IVI drivers can only run on Microsoft Windows. So even though we have instructions for porting IVI-C drivers to Linux, the Linux driver may not officially be an IVI driver. Regardless, the wrappers you create for LabVIEW should work with such a driver.


Read more of this article...

Tuesday, December 05, 2006

LabVIEW API Design

Sorry it's been a while since my last post. I've been traveling, most recently to New Mexico and Colorado for National Instruments Technical Symposia, and a little bit of photography at the Bosque del Apache National Wildlife Refuge.

In my role at National Instruments, I work with many of the driver and toolkit groups that provide LabVIEW APIs for their products. We make decisions about how to best represent our products in easy to learn and easy to use ways.


We're often faced with difficult tradeoffs, and some decisions come down to a "gut feel" by those of us involved. I thought I'd share some of the thought process that goes into making a good API for LabVIEW.



First, a little history. Many of you have attended, or at least heard of, NIWeek—Thousands of users, dozens of presentations, dozens of exhibitors. Did you know that we have a similar NI-only event called "NITech"? This is where NI R&D sets aside three days to have NI engineers present to other other NI engineers. We learn about the latest hardware and software technologies, ongoing research ideas, and good development practices. (And just as at NIWeek, we have fun, too.)


At NITech 2001, I co-presented a session on "Why Good Hardware APIs are Different in LabVIEW, CVI, VB, and VC". Each development environment is different. Some differences are radical, such as LabVIEW's data flow approach vs. text languages that are control flow. Some are as simple as the differences in the online help systems, or the fact that LabVIEW APIs have icons in addition to function names. One conclusion of the presentation is that it's worth it to fine-tune an API for the development environment your users are going to use.


For NITech 2002, I expanded the presentation and called it "Good LabVIEW API Design". I moved it out into the open at NIWeek 2003, where I updated it and called it "Developing High Quality LabVIEW Add-ons". For NIWeek 2004, I updated it once again, and put some spin on the name—"Advanced LabVIEW Design—Usability, Reusability, and Maintainability".


Some of the ideas from those presentations have been incorporated into either the LabVIEW Development Guidelines (available in the LabVIEW help), or the Instrument Driver Development Guidelines. I don't plan to rehash every guideline here, but there are a few ideas from the presentations I'd like to cover from time to time.


At a recent LXI meeting, I was asked whether it made sense for IVI-COM drivers to have LabVIEW VI wrappers around them. That is, instead of having users use the IVI-COM drivers as COM objects directly in LabVIEW, should he create a VI for every property and method in the driver? As with so many things, the answer is, "it depends".


When someone asks, "should I do it this way?", you have to step back and consider the alternatives. There's not necesssarily one perfect way.


A few years ago, one of the well-known instrument vendors developed LabVIEW instrument drivers that consisted of hundreds of VIs. Basically, they had one VI per SCPI command. In a scope API, you called one VI to set coupling, and another to set vertical range, and another for vertical offset. In my book, this was pretty low-level tedious programming. It was also error-prone—some instruments, for example, have a particular order in which you need to send the commands.


I've argued that users really want a higher-level instrument driver—"configure channel" or "configure vertical", not the lower-level components. Let the author of the instrument driver figure out the programming details once, instead of pushing that onto each user. Still, some vendors really like the low-level approach, since it's so powerful and so granular. I think users who want such a low-level approach can use VISA Write to send their own SCPI commands.


Let me restate this to make the tradeoffs clearer. Approach 1 is to have hundreds of simple VIs that consist mostly of VISA Write calls. The driver covers every command the instrument can handle. Approach 2 is to have only a few more complex, higher-level VIs that are commonly used. If you want something more granular, you either modify one of the existing VIs, or you create your own new VI with a VISA Write in it.


I generally lean towards approach 2. The first approach is often overwhelming, and users don't know where to start and how to put the pieces together.


The IVI APIs presented some new challenges. They're more complex, and it's not as simple to insert a VISA Write in your code to tweak a specific setting. So the IVI-C APIs have a few high-level methods, and hundreds of low-level properties. When we designed the first IVI-C APIs for the various instrument classes, we tried to make it so that 80% of typical user applications could be accomplished with only the higher-level methods.


The palette menus for an IVI-C driver in LabVIEW expose the high-level functions. We often also include a single property node to make it easy to get to the rest of the API. Thus, the palettes lead you to the right starting place for the API.


The same idea could map to IVI-COM. Unfortunately, IVI-COM drivers do not always expose a high-level approach in the specific driver interface. Recall from my earlier post about IVI-C and IVI-COM, that the specific interface to an IVI-COM driver doesn't conform to any standard.


So, since I don't know anything about the structure of the API, I can't recommend creating LabVIEW wrappers around it. And because I know that most IVI-COM specific interfaces use a low-level, property-centric approach, I usually actively discourage creating wrapper VIs. The end user is going to have to explore the entire API to figure out how to put it together in an application. Fortunately, the LabVIEW Class Browser (under the View menu, and new in 8.0, I think), makes it somewhat easier to explore IVI-COM drivers.


On the other hand, if you have a well-designed API that has easy-to-use high-level functions, it makes sense to highlight those in the palette menus and lead users to them.


More on API design in future posts.


Read more of this article...