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

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...