1. What You Need
Hardware
- NI multifunction DAQ device (this tutorial uses a USB-6001)
- Voltage supply
- LED
- Wires
Software
- ANSI C compiler (this tutorial uses Microsoft Visual Studio)
- NI-DAQmx driver version that supports your device (the USB-6001 requires NI-DAQmx 9.9 or later)
2. Hardware Instructions
Setting Up the Device
First, make sure you have installed the supporting NI-DAQmx driver software version. If you are using a USB DAQ device, a green or blue LED light should turn on when the device is recognized by your host PC. Open Measurement & Automation Explorer and confirm that the device appears under Devices and Interfaces. Select the Self-Test button and confirm that the device passes.
Connecting the Voltage Supply
To measure voltage with a referenced single-ended configuration, connect the signal wires according to the diagram below:
- Connect the positive lead of your voltage supply to AI0.
- Connect the negative lead of your voltage supply to AI GND.
Connecting the LED
On a standard LED, there are two leads of different lengths. The longer lead is positive and the shorter is negative. We configure the digital output as an open collector digital output driving an LED. Connect signals according to configuration 1 on the diagram below. We do not use a resistor in this tutorial; however, many LEDs could be damaged if a resistor is not used to limit the current to the LED. Use your LED specifications to calculate the value of the resistor.
- Connect the positive lead to the +5 V power supply.
- Connect the negative lead to P0.0.
3. Software Instructions
Map Your Program Flow and Start With an Example
For our application, we want to power an LED when the voltage exceeds 5 V. To do this, we want to set up a program that creates and configures a physical analog input and digital output channel, acquires a voltage sample, and determines if the voltage is greater than 5 V. If the voltage is greater than 5 V, we want to write to the digital output and if it’s not greater, then we want to take another reading. After we have acquired all the readings we want, we can clear the tasks and release the resources.
Instead of building this entire application, we’re going to use one of the example programs included with your DAQ device. You can find the location of these example programs for your specific OS by visiting ni.com/info and typing in daqmxexp. We’re working with an ANSI C example. Specifically, we are going to modify a voltage measurement example called VC_Acq_IntClk, which acquires a finite amount of data.
Copying the Example Program Into Your Personal Folder
Copy the example program from its original location to your personal folder, so that modifications to your program do not overwrite the original example.
Opening the Program
The first thing that you should notice in your program is the extensive comments in the code that provides instructions on how to run the program, how to connect your I/O, and where certain functions are executed in your code. In this example, there are four sections in the code: DAQmx Configure Code, DAQmx Start Code, DAQmx Read Code, and DAQmx Stop Code.
Modifying Your Code
To achieve the functionality that we want from our program, we must modify the existing example to add a digital output task and to change the analog input from finite acquisition to continuous. Follow these steps to modify the program. Changes made to the program are in bold.
- Declare a digital output task and rename your analog input task.
A task is a collection of virtual channels, timing and triggering information, and other properties regarding acquisition or generation. In NI-DAQmx, you must have a unique task dedicated to different functions such as analog input and digital output. In code, we want to declare these tasks with unique identifiers so we can reference them throughout the code. Rename your analog input task by using Find and Replace to find all references to your task and replace the reference with the unique identifier. In the following code, we replaced the generic taskHandle with AItaskHandle to differentiate between the analog input task and digital output task.
int32 error = 0;
TaskHandle AItaskHandle = 0;
TaskHandle DOtaskHandle = 0;
float64 data = 0.0;
int32 i = 0;
char errBuff[2048] = { '\0' }; - Configure your analog input and digital output tasks.
To interact with the device, you first have to create tasks and reserve the channels you want to measure data from or write data to. Leave the default values for the analog input task. For the digital output task, add the following code to create the task and reference the physical device and channel that the task applies to. In the following code, the USB-6001 we are using is named Dev1. Also important, is commenting your code as you make edits. In the following code, we have specified that we are configuring both our AI and DO tasks in this section of code.
Be aware that for this example, we are eliminating configuration of sample clock timing, which specifies finite samples to be read for the program. Instead, we check each sample value for a value over 5 V.
/*********************************************/
// DAQmx Configure AI and DO Code
/*********************************************/
DAQmxErrChk(DAQmxCreateTask("", &AItaskHandle));
DAQmxErrChk(DAQmxCreateAIVoltageChan(AItaskHandle, "Dev1/ai0", "", DAQmx_Val_Cfg_Default, -10.0, 10.0, DAQmx_Val_Volts, NULL));
DAQmxErrChk(DAQmxCreateTask("", &DOtaskHandle));
DAQmxErrChk(DAQmxCreateDOChan(DOtaskHandle, "Dev1/port2/line0", "", DAQmx_Val_ChanForAllLines)); - Add digital output to Start Code.
When your program executes, you want the analog and digital tasks to start at the same time. This allows your digital write to occur as soon as a read greater than 5 V is detected, instead of having to start the task each time you want to write a digital value. Starting a task each time is resource intensive and does not allow your program to run efficiently
/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk(DAQmxStartTask(AItaskHandle));
DAQmxErrChk(DAQmxStartTask(DOtaskHandle)); - Configure a For Loop to read and check the voltage values with each read.
For this section of code, we completely replace the existing code in the example, which reads a finite number of samples and prints the number of samples read. For this application, we implement a For Loop that acquires 100 samples and prints the voltage value of each of those samples and then a Case structure checks the value of the voltage. If the value exceeds 5 V, we will write to the digital line and power the LED.
Note the sleep function in the code. This function delays the interim of data acquisition for 100 milliseconds, giving us time to adjust the voltage and see our program respond.
*********************************************/
// DAQmx Read Code and Write if Value Exceeds 5 V
/*********************************************/
for (i = 0; i < 100; i++) {
DAQmxErrChk(DAQmxReadAnalogScalarF64(AItaskHandle, 10, &data, NULL));
printf("Voltage value: %0.2f\r", data);
if (data > 5.0)
{
DAQmxErrChk(DAQmxWriteDigitalScalarU32(DOtaskHandle, TRUE, 10, FALSE, NULL));
}
else
{
DAQmxErrChk(DAQmxWriteDigitalScalarU32(DOtaskHandle, TRUE, 10, TRUE, NULL));
}
_sleep(100);
} - Add error handling for the digital output task.
Best programming practice dictates that the program is built to handle an error. In this case, we have determined to Stop and Clear the task when an error is experienced. Stopping the task stops the executing in code and clearing the task releases the resources that were reserved for the task, such as device and channel.
Additionally, we want to notify the user of the program that an error has occurred so that the program doesn’t stop unexpectedly without explanation. After the tasks have been cleared a message is displayed to the user that an error has occurred and the error identifier is displayed so the user can begin troubleshooting.
Error:
if (DAQmxFailed(error))
DAQmxGetExtendedErrorInfo(errBuff, 2048);
if (DOtaskHandle != 0) {
DAQmxStopTask(DOtaskHandle);
DAQmxClearTask(DOtaskHandle);
}
if (AItaskHandle != 0) {
DAQmxStopTask(AItaskHandle);
DAQmxClearTask(AItaskHandle);
}
if (DAQmxFailed(error))
printf("DAQmx Error: %s\n", errBuff)
Running Your Program
In the video, we used Microsoft Visual Studio as the compiler. To run the program, select the green run arrow and run as a Local Windows Debugger. When the program starts to acquire the voltage, turn the knob on the power supply to adjust the voltage to above 5 V and watch as the LED turns on. Reduce the voltage to below 5 V and watch as the LED turns off.
4. Related Links
- Low-Cost Landing Page
- USB-6001 Model Page
- Learn 10 Functions in NI-DAQmx and Handle 80 Percent of Your Data Acquisition Applications
- How to Power an LED That Corresponds to Encoder Measurement
- How to Emit an Audio Frequency on Command
The mark LabWindows is used under a license from Microsoft Corporation. Windows is a registered trademark of Microsoft Corporation in the United States and other countries.