From Saturday, Nov 23rd 7:00 PM CST - Sunday, Nov 24th 7:45 AM CST, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
From Saturday, Nov 23rd 7:00 PM CST - Sunday, Nov 24th 7:45 AM CST, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
In general, data acquisition programming with DAQmx involves the following steps:
Data acquisition in text based-programming environment is very similar to the LabVIEW NI-DAQmx programming as the functions calls are the same as the NI-DAQmx VI's.
DAQmx comes with APIs required for data acquisition programming. The DAQmx API is simply a set of libraries containing functions on how to perform all data acquisition operations. These APIs include support for LabWindows/CVI, C, C++, Visual Basic 6.0, VB.NET and C#.
The DAQmx APIs are installed along with the DAQmx driver and contain the following reference manuals:
Each of these APIs contains detailed information on how to use the library of functions and classes to communicate with and control an NI data acquisition (DAQ) device.
A virtual channel is a collection of settings such as a name, a physical channel, input terminal connections, the type of measurement or generation, and can include scaling information.
A task, an important concept for NI-DAQmx, is a collection of one or more virtual channels with timing, triggering, and other properties. Conceptually, a task represents a measurement or generation you want to perform. Tasks can be created for analog in and output, digital input and output and counter operations.
To create a task and an analog input channel in C, use the following function calls:
DAQmxCreateTask("", &taskHandle));
DAQmxCreateAIVoltageChan (taskHandle, "Dev1/ai0", "Voltage", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL);
To create a task and an analog input channel in .NET, instantiate the Task object and create a Channel as shown below:
analogInTask = new Task();
AIChannel myChannel;
myChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0", //The physical name of the channel
"myChannel", //The name to associate with this channel
AITerminalConfiguration.Differential, //Differential wiring
-10, //10v minimum
10, //10v maximum
AIVoltageUnits.Volts //Use volts
Most NI data acquisition devices use a sample clock to control the rate at which samples are acquired and generated. This sample clock sets the time interval between samples. Each tick of this clock initiates the acquisition or generation of one sample per channel.
In software, you can specify the interval (how fast the clock acquires or generates signals) by specifying the sample rate. You can also limit the sample rate by the signal conditioning you apply to the signals or the number of channels in your application.
To configure the timing parameters in C, call the DAQmxCfgSamp function as shown below:
DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising,
DAQmx_Val_FiniteSamps, 1000);
To configure the timing parameters in .NET, use the Task.Timing property as shown below:
analogInTask.Timing.ConfigureSampleClock(
"/Dev1/PFI0", // external clock source line or use "" for internal clock
10000, // expected rate of external clock or actual rate of internal clock
SampleClockActiveEdge.Rising, // acquire on rising or falling edge of ticks
SampleQuantityMode.ContinuousSamples, // continuous or finite samples
1000 // number of finite samples to acquire or used for buffer size if continuous
);
When a device controlled by NI-DAQmx does something, it performs an action. Two very common actions are producing a sample and starting a waveform acquisition. Every NI-DAQmx action needs a stimulus or cause. When the stimulus occurs, the action is performed. Causes for actions are called triggers. Triggers are named after the actions they cause, such as a start trigger to start an acquisition.
The NI-DAQmx Trigger function configures a trigger to perform a specific action. The most commonly used actions are a start trigger and a reference trigger. A start trigger initiates an acquisition or generation. A reference trigger establishes the location, in a set of acquired samples, where pretrigger data ends and posttrigger data begins. Both of these triggers can be configured to occur on a digital edge, an analog edge, or when an analog signal enters or leaves a window.
To configure a start trigger on a rising digital signal coming in on PFI line 0 of the device, use the DAQmxCfgDigEdgeStartTrig function in C:
DAQmxCfgDigEdgeStartTrig (taskHandle, "PFI0", DAQmx_Val_Rising);
To configure a start trigger in .NET, use ConfigureDigitalEdgeTrigger in the Task.Triggers.StartTrigger collection as shown below:
DigitalEdgeStartTriggerEdge triggerEdge = DigitalEdgeStartTriggerEdge.Rising;
analogInTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("PFI0, triggerEdge);
The NI-DAQmx Start Task function explicitly transitions a task to the running state. In the running state, the task performs the specified acquisition or generation. A task will implicitly transition to the running state, or automatically start, if the NI-DAQmx Start Task function is not used when the NI-DAQmx Read function executes. This implicit transition also occurs if the NI-DAQmx Start Task function is not used and the NI-DAQmx Write function executes with its auto start input specified accordingly.
To start a task in C, use the DAQmxStartTask function:
DAQmxStartTask(taskHandle);
To start a task in .NET, use the Task.Start function:
analogInTask.start();
NI-DAQmx provides multiple functions for reading and writing data. In many cases, you can use multiple options. The read and write functions have two major selection criteria: data format and data organization. Data format specifies the type of the data that is returned. Counter reads, for example, can return integers or floating-point formats. The second category, data organization, deals with the structure the data is returned in. Analog reads, for example, have a variety of array and scalar organizations.
Depending on the data operation, data may be acquired or generated. In acquisition mode, a read operation is required to read a specified number of samples from the buffer. In data generation mode, sample are been written out to the data acquisition board buffer.
To read data in C, use the DAQmxReadAnalog function call:
DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data, 1000, &read, NULL)'
To read data in .NET, create a ChannelReader object, bind it to Task.Stream and then call a read function as shown below:
//Create the reader and attach it to the stream
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
//Perform the read
double[] data = reader.ReadMultiSample(100);
For more information on reading and writing data in .NET, see the "Reading and Writing with the NI-DAQmx .NET Library" section of the NI-DAQmx .NET 2.0 Framework Help.
After completing a task, stop the task and de-allocate all reserved resources. The NI-DAQmx Clear Task function clears the specified task. If the task is currently running, the function first stops the task and then releases all of its resources. Once a task has been cleared, it cannot be used unless it is recreated. Thus, if a task will be used again, the NI-DAQmx Stop Task function should be used to stop the task, but not clear it.
To stop and clear a task in C use the following functions:
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
To stop and clear a task in .NET use the Task.Stop and Task.Dispose methods as shown below:
analogInTask.Stop();
analogInTask.Dispose();
For a clear example of how this works, please see the Example Code locations, further down in this document.
Here is an example of an analog input voltage operation to acquire a finite number of voltage samples from a transducer using an NI data acquisition board.
********************************************************************************
#include <stdio.h>
#include <NIDAQmx.h>
#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else
int main(void)
{
int32 error=0;
TaskHandle taskHandle=0;
int32 read;
float64 data[1000];
char errBuff[2048]={'\0'};
// DAQmx analog voltage channel and timing parameters
DAQmxErrChk (DAQmxCreateTask("", &taskHandle));
DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL));
DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandle, "", 10000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000));
// DAQmx Start Code
DAQmxErrChk(DAQmxStartTask(taskHandle));
// DAQmx Read Code
DAQmxErrChk(DAQmxReadAnalogF64(taskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data, 1000, &read, NULL));
// Stop and clear task
Error:
if( DAQmxFailed(error) )
DAQmxGetExtendedErrorInfo(errBuff,2048);
if( taskHandle!=0 ) {
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
}
if( DAQmxFailed(error) )
printf("DAQmx Error: %s\n",errBuff);
return 0;
}
********************************************************************************
Note: It is important to include the NIDAQmx.h header file in the main.c program in order to have access to the DAQmx library.
In this sample code, this function created a task:
int32 DAQmxCreateTask (const char taskName[], TaskHandle *taskHandle);
This assigned a name to the task with an output referencing the task created. This function then configured a virtual voltage channel:
int32 DAQmxCreateAIVoltageChan (TaskHandle taskHandle, const char physicalChannel[], const char nameToAssignToChannel[], int32 terminalConfig, float64 minVal, float64 maxVal, int32 units, const char customScaleName[]);
This function call specifies a reference to the task created, the physical channel names, the name to assign to the virtual channels, the input terminal configuration for the channel, the minimum and maximum value in unit that you expect to measure and the name of a custom scale to apply to the channel.
After configuring the virtual voltage channels, a sample clock setting function specified the sampling rate, sample mode, and number of samples to read:
int32 DAQmxCfgSampClkTiming (TaskHandle taskHandle, const char source[], float64 rate, int32 activeEdge, int32 sampleMode, uInt64 sampsPerChanToAcquire);
The sample mode can also be set to continuous using the DAQmx_Val_ContSamps constant. To actually start acquiring the voltage sample, the following function must be called with a reference to the task configured.
int32 DAQmxStartTask (TaskHandle taskHandle);
The DAQmxReadAnalogF64 reads multiple floating-point samples from a task that contains one or more analog input channels as shown in the function call.
int32 DAQmxReadAnalogF64 (TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved);
Here 1000 samples are read and written to an array of the same size as the number of samples acquired.
Finally the DAQmxStopTask and DAQmxClearTask, stops the task and returns it to the state it was in before you called DAQmxStartTask and releases any resources reserved by the task. You cannot use a task once you clear the task without recreating or reloading the task.
A similar pseudocode for the same operation can be written using the API for Microsoft .NET Framework DAQmx library for both Visual Basic and C#. The API contains classes, delegates, and enumerations that provide a .NET interface to NI-DAQmx. Example code for a very simple read operation is shown below:
********************************************************************************
// Create a channel
myTask.AIChannels.CreateVoltageChannel(physicalChannelComboBox.Text, "", (AITerminalConfiguration)(-1), rangeMinimum, rangeMaximum, AIVoltageUnits.Volts);
// Configure timing specs
myTask.Timing.ConfigureSampleClock("", sampleRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, samplesPerChannel);
// Verify the task
myTask.Control(TaskAction.Verify);
// Prepare the table for data
InitializeDataTable(myTask.AIChannels, ref dataTable);
acquisitionDataGrid.DataSource = dataTable;
// Read the data
reader = new AnalogMultiChannelReader(myTask.Stream);
// clear task
myTask.Dispose();
********************************************************************************
Note: That the NationalInstruments.DAQmx class library must be included to successfully run the program.
NI-DAQmx also comes with set of examples for each of the programming environment. You can find examples using the C API in one of the following directory locations:
<Program Files>\National Instruments\NI-DAQ\Examples\DAQmx ANSI C
or
<Documents and Settings>\All Users\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C
For the .NET API, you can find examples in one of the following directory locations:
C:\Program Files\National Instruments\MeasurementStudioVS2005\DotNET\Examples\DAQmx
or
<Documents and Settings>\All Users\Documents\National Instruments\NI-DAQ\Examples\DotNET2.0
Folders named VB contain Visual Basic .NET examples, and folders named CS contain C# examples.
Visual Basic 6.0 examples can be found in one of the following directory locations:
<Program Files>\National Instruments\NI-DAQ\Examples\Visual Basic 6.0
or
<Documents and Settings>\All Users\Documents\National Instruments\NI-DAQ\Examples\Visual Basic 6.0
After installing the NI-DAQmx driver and choosing support for C and/or .NET, shortcuts to the help will be located in the Start menu under Programs » National Instruments » NI-DAQ » Text-Based Code Support
Additional documentation covering NI-DAQmx concepts in-depth is found in the NI-DAQmx Help located under Programs » National Instruments » NI-DAQ