Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Writing an Every N Samples Event for AO on NI-DAQ in C

Hi there,
 
I'm trying to write some code that writes out to my NI-6731 board quickly (1 kHz) but I need to be able to change the output voltage in real time.  I.E. I don't know what voltage I need to output until just before I need to send it out.  Later, I will read these values from a file, but for now, I can write it internally in the callback routine.  I wrote some code based on the example ContAcq-IntClk-EveryNSamplesEvent.c so that every N Samples it writes a different set of samples.
 
The problem is that my code does not work.  I get the error:
 
DAQmx Error: Measurements: DAQmx Every N Samples Event is not supported within non-buffered tasks.
 
To receive Every N Samples Event notifications, configure your task to use buffering.
Task Name: _unnamedTask<0>
 
Status Code: -200848
 
I am pretty sure my code is set up for buffering tasks, so I am quite confused.  The code is designed to be slow right now, but eventually I will speed it up.  For now, I just want it to work!  If you could take a look at it and help me sort out what the problem is, I would really appreciate it.
 
Cheers
 

#include

<stdio.h>

#include <math.h>

#include

"C:\NI-DAQ\DAQmx-ANSI-C-Dev\include\NIDAQmx.h"

#define

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

int32 CVICALLBACK EveryNSamplesCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples,

void *callbackData);

void

Cleanup (void);

static

TaskHandle taskHandle=0;

static

int32 totalWrite=0;

static

float64 data[4000];

int

main(void)

{

int error=0;

char errBuff[2048]={'\0'};

int i=0;

for(;i<2000;i++) {

data[i] = 4;

data[i+2000] = 4;

}

/*********************************************/

// DAQmx Configure Code

/*********************************************/

DAQmxErrChk (DAQmxCreateTask(

"",&taskHandle));

DAQmxErrChk (DAQmxCreateAOVoltageChan(taskHandle,

"Dev1/ao0:1","",-10.0,10.0,DAQmx_Val_Volts,NULL));

DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,

"",2000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,2000));

/*********************************************/

/* Tell the code to do another event once a certain

number of samples have been written*/

/*********************************************/

DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle,DAQmx_Val_Transferred_From_Buffer,2000,0,EveryNSamplesCallback,NULL));

/*********************************************/

// DAQmx Start Code

/*********************************************/

DAQmxErrChk (DAQmxStartTask(taskHandle));

/*********************************************/

// DAQmx Write Code

/*********************************************/

DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,2000,0,10.0,DAQmx_Val_GroupByChannel,data,NULL,NULL));

printf(

"Generating samples continuously. Press Enter key to interrupt\n");

getchar();

DAQmxErrChk (DAQmxStopTask(taskHandle));

printf(

"\nWrote %d total samples.\n",totalWrite);

/*********************************************/

// DAQmx Wait Code

/*********************************************/

DAQmxErrChk (DAQmxWaitUntilTaskDone(taskHandle,10.0));

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);

return 0;

}

int32 CVICALLBACK EveryNSamplesCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples,

void *callbackData)

{

int32 error=0;

int32 write;

char errBuff[2048]={'\0'};

int j=0;

float64 data2[4000];

for(;j<2000;j++) {

data2[j] = 2;

data2[j+2000] = 2;

}

/*********************************************/

// DAQmx Write Code

/*********************************************/

DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,2000,0,10.0,DAQmx_Val_GroupByChannel,data2,&write,NULL));

if( write>0 ) {

printf(

"Wrote %d samples. Total %d\r",write,totalWrite+=write);

fflush(stdout);

}

Error:

if( DAQmxFailed(error) ) {

DAQmxGetExtendedErrorInfo(errBuff,2048);

/*********************************************/

// DAQmx Stop Code

/*********************************************/

DAQmxStopTask(taskHandle);

DAQmxClearTask(taskHandle);

printf(

"DAQmx Error: %s\n",errBuff);

}

return 0;

}

void

Cleanup (void)

{

if( taskHandle!=0 )

{

/*********************************************/

// DAQmx Stop Code

/*********************************************/

DAQmxStopTask(taskHandle);

DAQmxClearTask(taskHandle);

taskHandle = 0;

}

}

0 Kudos
Message 1 of 5
(4,133 Views)

Hello Astro Mark,

The NI-DAQmx C Reference Help file states that if you configure timing for your task, that the task is a buffered task.  Furthermore, if you don't manually configure the buffer size using DAQmxCfgOutputBuffer, DAQmx automatically configures the buffer when you configure sample timing.  I recommend explicitly configuring the output buffer using the DAQmxCfgOutputBuffer function, and give it the appropriate parameters to see if you can eliminate the error.

Best wishes,

Wallace F.

National Instruments
Applications Engineer
0 Kudos
Message 2 of 5
(4,112 Views)
Correction: if you don't write before start or set an output buffer size, then your task is NOT buffered.  It is what we refer to as hardware-timed non-buffered.  This use case is pretty specialized and is similar to hardware-timed single-point but without some of the benefits that HWTSP provides. 

It is almost always recommended that if you set up timing, then write your data prior to calling Start.  Alternatively, you can set your output buffer size and write after Start, but I am not 100% sure what data (if any?) will be generated when you call Start.  I would lean towards a race condition where you may get FIFO Underflows almost immediately.  I'll give it a shot, and update this when I find out.
------
Zach Hindes
NI R&D
0 Kudos
Message 3 of 5
(4,098 Views)

I tested out my theory of configuring an output buffer size but not writing any data, and it turns out you get an error: "-200462: Generation cannot be started, because the output buffer is empty.  Before starting a buffered generation, write data. ..."  There you have it!

------
Zach Hindes
NI R&D
0 Kudos
Message 4 of 5
(4,095 Views)
Hey Zach,

Thanks for the tip.  I now operate with less than a 6 micro-sec delay.

Cheers,
Mark
0 Kudos
Message 5 of 5
(4,090 Views)