Sidling Up to Measurement Studio

Don’t look at Measurement Studio (MStudio) from National Instruments (NI) as a panacea: it won’t help your bunions. But, it does solve major problems plaguing test and measurement professionals. MStudio is a collection of preprogrammed controls that extend the range of visual programming languages to include data acquisition, measurement, and analysis functionality.

Meeting the requirements of test applications is complicated, especially if approached on an ad hoc basis. Instead, MStudio adds specialized test-related tools to consistent and well-accepted programming environments.

If you already know how to program in Visual Basic (VB), for example, MStudio allows you to write data acquisition programs without learning a completely new language. Visual languages really do increase programmer productivity, but they also have a steep learning curve. MStudio affords you the opportunity to shorten your learning curve while providing a comprehensive collection of new tools.

Evaluating MStudio is a job for an expert programmer with years of experience developing event-driven test applications in a variety of computer languages and targeting many types of data acquisition hardware. Accordingly, the title of this article reflects the limited encounter that actually occurred.

Forming an Impression

First, you need your own copy of VB or C++. Next, get an MStudio demo disk. You can request one by completing a form on the website or contacting your local NI office.

From, you can download MStudio news and evaluation software, sample programs, technical product tutorials, customer solutions, and Internet-based virtual instruments. The initial document you need is “Getting Started With Measurement Studio” for your selected language. Reading it now will help later.

However, don’t get carried away with the Web’s instant accessibility to the extent that good old snail mail is neglected. It still makes more sense to get a free demo disk than to attempt to download a 300-MB file, which is the approximate size of the MStudio demo package.

Loading only the MStudio file that corresponds to the language you will be using can considerably reduce the actual space taken on your hard disk. For example, I only loaded the VB version, skipping the C++ and LabWindows/CVI files.

The sample programs exercise particular controls or groups of controls. By examining these programs, you can familiarize yourself with the attributes of the various controls, and there are many. As you might hope, the example programs are well commented, so you can actually understand what is happening in the code.

On the other hand, because the controls are so flexible and comprehensive, a great deal of the programming required for an application may be hidden within the properties pages associated with the individual controls. This characteristic of VB helps make the limited amount of additional code easy to write, but it may not be obvious how the program works. You also have to look closely at how a control’s properties have been set.

The controls provided in the MStudio Full Development System are all included on the demo disk. However, the software only will remain operational for 30 days after installation, and some features have been disabled, depending on the language you are using. Generally, you cannot create a distribution version of your program, but all the controls will function correctly. See Table 1 for a list of the controls and the intended use.

Once VB has been launched together with MStudio, drag a control onto the form and right-click on it to access the MStudio Reference (help) section. This really is a comprehensive help facility, but even with the detail given here, you still may need to right-click on particular properties within the property pages of a given control. This action brings up a What’s This? box that offers further details about operation or perhaps a sample line of code.

By the way, in VB, all control names start with CW because, for the last few years, the functionality in MStudio has been sold under the ComponentWorks name. Similarly, MStudio for Visual C++ was called ComponentWorks++ or Tools for Visual C++. These names no longer are used, but help to explain the CW prefix. Of course, when you rename controls to suit your application, you don’t have to use the CW.

The present MStudio package retains the CW prefix for compatibility with legacy programs, but it is not simply ComponentWorks under a different name. The full development system is shipped with a 16-page booklet detailing the new components, classes, studio wizards, and data visualization features. In addition, the code has been enhanced to take advantage of multithreading and offers improved analysis and user-interface features.

An Example

Generating and Analyzing a Signal

Because I don’t have a lab or any lab equipment, I didn’t use those controls that interact with data acquisition hardware and real signals. These are given very detailed treatment in several NI application notes included with the demo disk and accessible from the Web. Instead, I was attracted by the CWDSP control and the signal generation, filtering, and analysis it can perform. You may want to simulate some part of a system, and this control can make that possible.

The CWDSP control is an invisible control. It appears just like any other control on the form you are developing, but it disappears when your program is running. Like other controls, it has a properties page, but this one contains only the control’s name, its position on the form, and an “about” property that leads you to copyright information.

The CWDSP control operates upon and returns data—it doesn’t have visual properties like buttons or labels. Its important aspects are its methods. You need to go to the help pages and examine the many examples given there to understand the control’s capabilities.

I used three methods of the CWDSP control to create a square wave, filter it, and generate the complex FFT of the original signal. I also plotted the signal, the filtered signal, and the FFT magnitude and phase. The code to accomplish this and the form I created are shown in Figure 1 and Figure 2, respectively.

For the CWDSP.SquareWave generation function and the very similar CWDSP.SineWave, the speed of the generated waveforms is normalized with units of cycles per sample. It generally will be a fractional value, but cycles-per-sample is not a misprint. It gives you the capability to control resolution and, consequently, the number of cycles within an array of a certain size.

The filtering routines are not so clearly defined. For a low-pass Butterworth filter, the parameters comprise the number of samples in the waveform array, the sampling frequency, the cutoff frequency, and the filter order.

There appear to be no details, at least not in the filter or CWDSP help sections, which relate the sample rate for the CWDSP.BwLPF() filter and the sample rate for the signal-generation routines. Of course, if you actually were using data that had been acquired at a 1-kS/s sampling rate, for example, then sample frequency would make more sense.

In the example I developed, I set the filter’s sample frequency to 50 Hz, the inverse of the 0.02 cycles/sample value associated with the generated waveform. It follows that the actual signal frequency is 1 Hz. To confirm this, I generated a sinewave and filtered it with a Butterworth filter with a 1-Hz cutoff. Sure enough, the output amplitude was down 3 dB. From a 10-unit amplitude input, I generated a 7.07-unit amplitude output.

As you can see from Figure 1, the filtered value of a 10-unit square wave is greater than 7.07 units. So, to make certain of my facts, I simply changed the function to CWDSP.SineWave and then changed it back again to CWDSP.SquareWave after confirming the 1-Hz frequency.

It’s worth noting that filters have separate transient and steady-state responses. Initial conditions do make a difference because the digital filter output depends on previous input values, the present input, and the present output. It’s only after a few cycles of the input signal that the transient response will have decayed, to be replaced by the textbook steady-state response. In my example, I’ve used a third-order filter with a 1-Hz cutoff frequency so the transient performance isn’t too pronounced when the 1-Hz square wave starts.

Some of the CWDSP methods generate a sequence of values, so you need to provide an array for their storage. For example, in the expression

x = CWDSP1.SquareWave(n, Amp, Freq, DutyCycle, Phase)

x is a one-dimensional array that accepts a succession of waveform sample values from the square-wave generation method. Although listed as a method in the MStudio Reference help section, this routine behaves like a function with a list of arguments and requires them to be placed within parentheses.

On the other hand, some methods generate outputs that directly fill arrays within the list of parameters. An example of this type of operation is

CWDSP1.AmpPhaseSpectrum x, Unwrap, dt, AmpSpectrum, PhaseSpectrum, df

Notice that no parentheses are used, nor are they accepted. In this case, the expression is simply stated, and the AmpSpectrum and PhaseSpectrum arrays are filled when it executes.

The MStudio Reference information correctly lists each method with or without parentheses as appropriate. A clue to operation is the correspondence of parentheses to a paragraph headed Return within each method’s definition. This section describes the values returned by the method, but is only present if the method acts like a function.

Plotting the Results

The CWGraph control requires 13 property pages to give you access to 31 properties, 13 methods, and 22 events associated with plotting data. Virtually everything to do with a graph’s appearance is handled by these property pages.

The CWGraph.PlotY method is called as

CWGraph.PlotY z, 0, 0.2, True

where z is the array holding the data to be plotted, 0 denotes the start of the X values, 0.2 is the X-axis increment, and True relates to a variable that controls plotting from each row of a multirow array. If False instead, then data for each plot is assumed to be in separate columns.

Why 0.2 instead of the default value 1? The frequency increment df output by the CWDSP1.AmpPhaseSpectrum routine is 0.2 Hz, so inserting 0.2 as a parameter in the CWGraph.PlotY method will correctly change the X-axis scaling.

Alternatively, you could have determined max/min scale values and inserted them on the CWGraph.axes properties page in place of autoscaling. The example square wave filled an array with 250 locations. The FFT produces half as many points in the frequency domain as are presented to it in the time domain, so the AmpSpectrum and PhaseSpectrum arrays each have 125 locations. With 125 samples in the frequency domain and a 0.2-Hz spacing, the X axis would run from 0 to 25 Hz.

Note that FFT-related functions in MStudio have been improved so that they no longer require the data set size to be a power of two: 256, 512.

Because the CWGraph control requires the data for multiple plots to be provided as separate rows or columns of a single array, I copied AmpSpectrum and PhaseSpectrum into the two rows of a 2 × 125 array. The m/2-1 upper index on the For loop correctly aligns the 125 columns of the array z with the 0 to 124 numbered locations in the AmpSpectrum and PhaseSpectrum arrays.

Also, the second graph’s values have to be explicitly associated with the second Y axis. I found the relevant code in a What’s This? box after right-clicking on the Plot-Y2 box on the CWGraph.plot property page.

Set CWGraph.Plots(2).YAxis = CWGraph.Axes(3)

This line associates the third axis property with the second plot. The first axis is the X axis, so two Y plots plus X make three.

From Figure 1, it’s easy to see that only odd harmonics are present, as expected. It’s not so easy to tell what’s happening with the phase. Phase is in radians, so the left axis needs to be scaled by 360/2p to become degrees. This could be done in the statement that copies PhaseSpectrum values to the z array. Then, you would have to set new fixed-range limits for the Y1 axis or choose autoscale.

I selected Unwrap = 1, which leads to the more or less continuously increasing negative phase angle. If Unwrap = 0, the phase plot will remain within the 0° to -360° range and appear like a noisy triangle wave.

With a bit more effort, menus could be created that managed waveform generation and allowed changes to be made as the program ran. Cursor values could be read from the plots and values tested against user-defined criteria.


I’m not a VB expert, but I managed to get some meaningful results in a couple of days of working with MStudio. How long would it take to write a program like my example without the MStudio controls? Would a programmer be tempted to implement less professional-looking graphs? How long could such a program be maintained if it was periodically changed to address new test demands?

True, there are some syntax and operational points that could be made more clear, and some problems are just things that a more experienced programmer might already know to look for. Nevertheless, there’s no question that MStudio is a valuable engineering tool.


Thanks to Charles Lecklider of Invisible Software Ltd. for VB programming help.

Figure 1. Example Program Code

Option Explicit

Private Sub cmdStart_Click( )
Const m = 250
Dim x As Variant, Amp As Variant, Phase As Variant
Dim DutyCycle As Variant, Freq As Variant
Dim n As Variant, I As Integer, z(2, m / 2) As Variant
Dim fs As Variant, fc As Variant, order As Variant
Dim y As Variant, Unwrap As Variant, dt As Variant
Dim AmpSpectrum As Variant, df As Variant, PhaseSpectrum As Variant

‘generate 1-Hz square wave and plot it

n = m: Phase = 0: DutyCycle = 50: Freq = 0.02: Amp = 10

x = CWDSP1.SquareWave(n, Amp, Freq, DutyCycle, Phase)
grphInput.PlotY x

‘filter the square wave to check its frequency. Plot the output

fs = 50: fc = 1: order = 3

y = CWDSP1.BwLPF(x, fs, fc, order)
grphOutput.PlotY y

‘generate the complex FFT of the square wave and plot it

Unwrap = 1: dt = 1 / fs

CWDSP1.AmpPhaseSpectrum x, Unwrap, dt, AmpSpectrum,_ PhaseSpectrum, df

For I = 0 To (m / 2 – 1)
z(1, I) = AmpSpectrum(I): z(2, I) = PhaseSpectrum(I)

Next I
grphFFT.PlotY z, 0, 0.2, True
Set grphFFT.Plots(2).YAxis = grphFFT.Axes(3)

End Sub

Return to EE Home Page

Published by EE-Evaluation Engineering
All contents © 2002 Nelson Publishing Inc.
No reprint, distribution, or reuse in any medium is permitted
without the express written consent of the publisher.

May 2002


To join the conversation, and become an exclusive member of Electronic Design, create an account today!