Difference between revisions of "NI-DAQ Cards on Linux"

From Mech
Jump to navigationJump to search
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==Overview==
==Overview==
Project by: James Yeung, Master in Electrical and Computer Engineering, 2010.<br>
Project by: James Yeung, Master in Electrical and Computer Engineering, 2010.<br>
Last updated: April 23, 2010
Last updated: June 11, 2010


The goal of this project was to get the National Instruments Data Acquisition Cards to work on Linux. More specifically, the two cards that will be documented here are:
The goal of this project was to get the National Instruments Data Acquisition Cards to work on Linux. More specifically, the two cards that will be documented here are:
Line 7: Line 7:
* [http://sine.ni.com/nips/cds/view/p/lang/en/nid/10702 NI PCI-6713] 12-Bit, 1 MS/s per Channel Analog Output Board
* [http://sine.ni.com/nips/cds/view/p/lang/en/nid/10702 NI PCI-6713] 12-Bit, 1 MS/s per Channel Analog Output Board


This wiki document assumes that you have real-time patched SUSE 11.0 operating system installed. You can follow the guide [http://hades.mech.northwestern.edu/index.php/Real-Time_Linux_for_TrackCam here].
This wiki document assumes that you have real-time patched SUSE 11.0 operating system installed. You can follow the guide [[Real-Time Linux for TrackCam|here]].


==Installing Drivers and C-API==
==Installing Drivers and C-API==
Line 54: Line 54:
</ul>
</ul>
</li>
</li>

<li>Restart the computer.</li>


<li>Restart the computer.
<li>Restart the computer.
<ul>
<ul>
<li>Open terminal and type<li>
<li>Open terminal and type</li>
>> nilsdev
>> nilsdev
<li>You should be able to see information about the NI-DAQ cards.
<li>You should be able to see information about the NI-DAQ cards.
Line 65: Line 63:
</li>
</li>
</ol>
</ol>

===Configuration Guide===
There is a configuration guide (ConfigurationGuide.html) included in the drivers that you downloaded from step 1. For example, you can configure the name of the card from dev0 to something more descriptive like AnalogIn. This name will also affect how you program later on.


==Datasheets==
==Datasheets==
[http://hades.mech.northwestern.edu/images/1/1f/Nipci-6220_datasheet.pdf NIPCI-6220 Datasheet]
[http://hades.mech.northwestern.edu/images/1/1f/Nipci-6220_datasheet.pdf NIPCI-6220 Datasheet]

[http://hades.mech.northwestern.edu/images/8/87/Nipci-6220_manual.pdf NIPCI-6220 Manual]
[http://hades.mech.northwestern.edu/images/8/87/Nipci-6220_manual.pdf NIPCI-6220 Manual]

[http://hades.mech.northwestern.edu/images/9/95/Nipci-6713_datasheet.pdf NIPCI-6713 Datasheet]
[http://hades.mech.northwestern.edu/images/9/95/Nipci-6713_datasheet.pdf NIPCI-6713 Datasheet]

[http://hades.mech.northwestern.edu/images/5/5d/Nipci-6713_manual.pdf NIPCI-6713 Manual]
[http://hades.mech.northwestern.edu/images/5/5d/Nipci-6713_manual.pdf NIPCI-6713 Manual]

==Timing Data==
Here are some experimental timing data.

===Analog===
Time it takes to read x analog inputs.<br>
2 = 27.6-42.5us (typically 28.8us)<br>
3 = 41.9-55.3us (typically 43.6us)<br>
4 = 55.9-72.9us (typically 57.8us)<br>
5 = 69.8-86.3us (typically 72.6us)<br>
6 = 84.3-100.5us (typically 87.1us)<br>
7 = 98.0-124.0us (typically ~101us)<br>
8 = 112.0-130.4us (typically ~115us)<br>
<br>
Time it takes to write x analog outputs.<br>
2 = 12.8-23.2us (typically 13.1us)<br>
3 = 13.1-23.2us (typically 13.1us)<br>
4 = 13.4-23.8us (typically 13.7us)<br>
5 = 15.1-26.0us (typically 15.4us)<br>
6 = 15.9-27.9us (typically 16.2us)<br>
7 = 17.6-29.9us (typically 17.9us)<br>
8 = 19.0-32.1us (typically 19.5us)<br>
===Digital===
Time it takes to read x digital inputs.<br>
1 = 12.0us-22.3us (typically 12.0us)<br>
8 = 12.6us-24.9us (typically 12.6us)<br>
<br>
Time it takes to write x digital outputs.<br>
1 = 12.3us-21.5us (typically 12.6us)<br>
8 = 13.1us-24.0us (typically 13.1us)<br>
<br>
===Encoder===
Time it takes to read x encoder inputs.<br>
1 = 14.2us-27.6us (typically 14.5us)<br>
<br>


==Example Code==
==Example Code==
Line 274: Line 313:
/*********************************************/
/*********************************************/
for(ii = 0; ii < 2000; ii++){
for(ii = 0; ii < 2000; ii++){
data = ii % 2;
DAQmxErrChk(DAQmxWriteDigitalLines(taskHandle,1,TRUE,10.0,DAQmx_Val_GroupByScanNumber,&data,&written,NULL));
DAQmxErrChk(DAQmxWriteDigitalLines(taskHandle,1,TRUE,10.0,DAQmx_Val_GroupByScanNumber,&data,&written,NULL));
printf("%4d\t%d\n", ii, data);
printf("%4d\t%d\n", ii, data);
}

Error:
if( DAQmxFailed(error) )
DAQmxGetExtendedErrorInfo(errBuff,2048);
if( taskHandle!=0 ) {
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
}
if( DAQmxFailed(error) )
printf("DAQmx Error: %s\n",errBuff);
printf("End of program, press Enter key to quit\n");
getchar();
return 0;
}
</pre>

===How to Read Encoder Counts===
See page 136-137 of the [http://hades.mech.northwestern.edu/images/8/87/Nipci-6220_manual.pdf NIPCI-6220 Manual] for the ChA and ChB pins.
<pre>
#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
int32 error=0;
TaskHandle taskHandle=0;
int32 read;
float64 motorAngle;
char errBuff[2048]={'\0'};
int ii;

/*********************************************/
// DAQmx Configure Code
/*********************************************/
DAQmxErrChk(DAQmxCreateTask("EncoderTask",&taskHandle));
DAQmxErrChk(DAQmxCreateCIAngEncoderChan(taskHandle,"AnalogIn/ctr0","Counter",DAQmx_Val_X4,0,0.0,DAQmx_Val_AHighBHigh,DAQmx_Val_Degrees,600,36000.0,""));

/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk(DAQmxStartTask(taskHandle));

/*********************************************/
// DAQmx Read Code
/*********************************************/
for(ii = 0; ii < 2000; ii++){
DAQmxErrChk(DAQmxReadCounterF64(taskHandle,1,10.0,&motorAngle,1,&read,NULL));
printf("%4d\t%f\n", ii, motorAngle);
}
}


Line 298: Line 392:
===Others===
===Others===
More example code can be found in the directory "/usr/local/natinst/nidaqmx/examples/".
More example code can be found in the directory "/usr/local/natinst/nidaqmx/examples/".

Full documentation on the nidaqmx API can be found at "/usr/local/natinst/nidaqmx/docs/daqmxcfunc.chm/_main.html"
Full documentation on the nidaqmx API can be found at "/usr/local/natinst/nidaqmx/docs/daqmxcfunc.chm/_main.html"


==Useful Links==
==Useful Links==
<ul>
<ul>
<li>http://decibel.ni.com/content/docs/DOC-2808</li>
<li>[http://decibel.ni.com/content/docs/DOC-2808 NI forum on installing drivers on openSUSE]</li>
<li>[http://sine.ni.com/ds/app/doc/p/id/ds-15/lang/en Datasheet for 6220]</li>
<li>[http://zone.ni.com/devzone/cda/tut/p/id/6999 List of sample code provided by NI]</li>
</ul>
</ul>



Latest revision as of 14:27, 15 June 2010

Overview

Project by: James Yeung, Master in Electrical and Computer Engineering, 2010.
Last updated: June 11, 2010

The goal of this project was to get the National Instruments Data Acquisition Cards to work on Linux. More specifically, the two cards that will be documented here are:

This wiki document assumes that you have real-time patched SUSE 11.0 operating system installed. You can follow the guide here.

Installing Drivers and C-API

The supporting software is all available on the National Instruments website. The specific package that we will need is NI-DAQmx 8.0.1. This package contains the drivers, C-API library, documentation on the library functions and example code.

Instructions

  1. Download the NI-DAQmx 8.0.1 here
    • The file that you download is an ISO, or an image of a disk. You could burn it on a CD and run it from a physical disk, but we will be mounting the ISO virtually.
  2. Install necessary supporting packages.
    • Open a terminal window. GNOME Terminal would do.
    • Use zypper to install the packages.
    • >> zypper in kernel-source-rt kernel-syms-rt
  3. Configure SUSE to startup in 4G memory mode.
    • This is not necessary if your system is 32-bit.
    • Go to the grub folder.
    • >> cd /boot/grub
    • Add "set mem=4096" to the entry.
    • >> vi menu.lst
    • Find the entry that you normally boot into and add "mem=4096M" to the end of the line that starts with "kernel".
  4. Restart the computer with 4G memory mode.
  5. Install NI-DAQmx
  6. >> cd ~/Downloads/ >> tar >> cd nidaqmx801 >> mkdir /mnt/daqmx >> mount -t iso9660 -o loop nidaqmx801.iso /mnt/daqmx >> cp /mnt/daqmx/disk . >> cd disk >> sudo ./INSTALL
    • Follow the prompts to install.
  7. Restart the computer.
    • Open terminal and type
    • >> nilsdev
    • You should be able to see information about the NI-DAQ cards.

Configuration Guide

There is a configuration guide (ConfigurationGuide.html) included in the drivers that you downloaded from step 1. For example, you can configure the name of the card from dev0 to something more descriptive like AnalogIn. This name will also affect how you program later on.

Datasheets

NIPCI-6220 Datasheet

NIPCI-6220 Manual

NIPCI-6713 Datasheet

NIPCI-6713 Manual

Timing Data

Here are some experimental timing data.

Analog

Time it takes to read x analog inputs.
2 = 27.6-42.5us (typically 28.8us)
3 = 41.9-55.3us (typically 43.6us)
4 = 55.9-72.9us (typically 57.8us)
5 = 69.8-86.3us (typically 72.6us)
6 = 84.3-100.5us (typically 87.1us)
7 = 98.0-124.0us (typically ~101us)
8 = 112.0-130.4us (typically ~115us)

Time it takes to write x analog outputs.
2 = 12.8-23.2us (typically 13.1us)
3 = 13.1-23.2us (typically 13.1us)
4 = 13.4-23.8us (typically 13.7us)
5 = 15.1-26.0us (typically 15.4us)
6 = 15.9-27.9us (typically 16.2us)
7 = 17.6-29.9us (typically 17.9us)
8 = 19.0-32.1us (typically 19.5us)

Digital

Time it takes to read x digital inputs.
1 = 12.0us-22.3us (typically 12.0us)
8 = 12.6us-24.9us (typically 12.6us)

Time it takes to write x digital outputs.
1 = 12.3us-21.5us (typically 12.6us)
8 = 13.1us-24.0us (typically 13.1us)

Encoder

Time it takes to read x encoder inputs.
1 = 14.2us-27.6us (typically 14.5us)

Example Code

To compile: gcc main.c -o main -lnidaqmx

How to Read Analog Inputs

#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
	int32		error=0;
	TaskHandle	taskHandle=0;
	int32		read;
	float64		data;
	char		errBuff[2048]={'\0'};
	int		ii;

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk(DAQmxCreateTask("Task",&taskHandle));
	DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandle,"AnalogIn/ai0","ChannelName",DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NULL));
	// To read more analog inputs, simply add more channels to the task.

	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk(DAQmxStartTask(taskHandle));

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	for(ii = 0; ii < 2000; ii++){
		DAQmxErrChk(DAQmxReadAnalogF64(taskHandle,1,10.0,DAQmx_Val_GroupByChannel,&data,1,&read,NULL));
		printf("%4d\t%f\n", ii, data);
	}

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	if( taskHandle!=0 )  {
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("End of program, press Enter key to quit\n");
	getchar();
	return 0;
}

How to Read Digital Inputs

#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
	int32		error=0;
	TaskHandle	taskHandle=0;
	int32		read;
	int32		readBytePerSamp;
	int8		data;
	char		errBuff[2048]={'\0'};
	int		ii;

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk(DAQmxCreateTask("Task",&taskHandle));
	DAQmxErrChk(DAQmxCreateDIChan(taskHandle,"AnalogIn/port0/line0","",DAQmx_Val_ChanPerLine));
	// Use the line below to add multiple lines from the same port
	// DAQmxErrChk(DAQmxCreateDIChan(taskHandle,"AnalogIn/port0/line0:7","",DAQmx_Val_ChanPerLine));

	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk(DAQmxStartTask(taskHandle));

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	for(ii = 0; ii < 2000; ii++){
		DAQmxErrChk(DAQmxReadDigitalLines(taskHandle,1,10.0,DAQmx_Val_GroupByScanNumber,&data,1,&read,&readBytePerSamp,NULL));
		printf("%4d\t%d\n", ii, data);
	}

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	if( taskHandle!=0 )  {
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("End of program, press Enter key to quit\n");
	getchar();
	return 0;
}

How to Write Analog Outputs

#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
	int32		error=0;
	TaskHandle	taskHandle=0;
	int32		written;
	float64		data;
	char		errBuff[2048]={'\0'};
	int		ii;

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk(DAQmxCreateTask("Task",&taskHandle));
	DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandle,"AnalogOut/ai0","ChannelName",DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NULL));
	// To write more analog outputs, simply add more channels to the task.

	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk(DAQmxStartTask(taskHandle));

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	for(ii = 0; ii < 2000; ii++){
		data = ii % 10;
		DAQmxErrChk(DAQmxWriteAnalogF64(taskHandle,1,TRUE,10.0,DAQmx_Val_GroupByChannel,&data,&written,NULL));
		printf("%4d\t%f\n", ii, data);
	}

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	if( taskHandle!=0 )  {
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("End of program, press Enter key to quit\n");
	getchar();
	return 0;
}

How to Write Digital Outputs

#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
	int32		error=0;
	TaskHandle	taskHandle=0;
	int32		written;
	int8		data;
	char		errBuff[2048]={'\0'};
	int		ii;

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk(DAQmxCreateTask("Task",&taskHandle));
	DAQmxErrChk(DAQmxCreateDOChan(taskHandle,"AnalogIn/port0/line0","",DAQmx_Val_ChanPerLine));
	// Use the line below to add multiple lines from the same port
	// DAQmxErrChk(DAQmxCreateDOChan(taskHandle,"AnalogIn/port0/line0:7","",DAQmx_Val_ChanPerLine));

	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk(DAQmxStartTask(taskHandle));

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	for(ii = 0; ii < 2000; ii++){
		data = ii % 2;
		DAQmxErrChk(DAQmxWriteDigitalLines(taskHandle,1,TRUE,10.0,DAQmx_Val_GroupByScanNumber,&data,&written,NULL));
		printf("%4d\t%d\n", ii, data);
	}

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	if( taskHandle!=0 )  {
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("End of program, press Enter key to quit\n");
	getchar();
	return 0;
}

How to Read Encoder Counts

See page 136-137 of the NIPCI-6220 Manual for the ChA and ChB pins.

#include <stdio.h>
#include <NIDAQmx.h>
#include <time.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void){
	int32		error=0;
	TaskHandle	taskHandle=0;
	int32		read;
	float64		motorAngle;
	char		errBuff[2048]={'\0'};
	int		ii;

	/*********************************************/
	// DAQmx Configure Code
	/*********************************************/
	DAQmxErrChk(DAQmxCreateTask("EncoderTask",&taskHandle));
	DAQmxErrChk(DAQmxCreateCIAngEncoderChan(taskHandle,"AnalogIn/ctr0","Counter",DAQmx_Val_X4,0,0.0,DAQmx_Val_AHighBHigh,DAQmx_Val_Degrees,600,36000.0,""));

	/*********************************************/
	// DAQmx Start Code
	/*********************************************/
	DAQmxErrChk(DAQmxStartTask(taskHandle));

	/*********************************************/
	// DAQmx Read Code
	/*********************************************/
	for(ii = 0; ii < 2000; ii++){
		DAQmxErrChk(DAQmxReadCounterF64(taskHandle,1,10.0,&motorAngle,1,&read,NULL));
		printf("%4d\t%f\n", ii, motorAngle);
	}

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);
	if( taskHandle!=0 )  {
		/*********************************************/
		// DAQmx Stop Code
		/*********************************************/
		DAQmxStopTask(taskHandle);
		DAQmxClearTask(taskHandle);
	}
	if( DAQmxFailed(error) )
		printf("DAQmx Error: %s\n",errBuff);
	printf("End of program, press Enter key to quit\n");
	getchar();
	return 0;
}

Others

More example code can be found in the directory "/usr/local/natinst/nidaqmx/examples/".

Full documentation on the nidaqmx API can be found at "/usr/local/natinst/nidaqmx/docs/daqmxcfunc.chm/_main.html"

Useful Links