03-20-2021 02:33 PM
I am trying to use the DAQmxRegisterEveryNSamplesEvent with an analog output channel to do continuous waveform generation. Here is a simple example which reproduces the errors I am observing:
#include <stdio.h>
#include <NIDAQmx.h>
#include <math.h>
#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else
#define DATA_SIZE 1000
#define BUFF_SIZE 20000
int32 CVICALLBACK EveryNSamplesCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void* callbackData);
int32 write_to_buffer(int32 samples);
void Cleanup(void);
static TaskHandle taskHandle = 0;
static float64 data[DATA_SIZE];
float64 sample_rate = 1000.0;
uInt64 samples_written = 0;
int32 gap = 1000;
int main(void)
{
int32 error = 0;
char errBuff[2048] = { '\0' };
/*********************************************/
// DAQmx Configure Code
/*********************************************/
DAQmxErrChk(DAQmxCreateTask("", &taskHandle));
DAQmxErrChk(DAQmxCreateAOVoltageChan(taskHandle, "Dev1/ao0", "", -10.0, 10.0, DAQmx_Val_Volts, NULL));
DAQmxErrChk(DAQmxSetWriteRegenMode(taskHandle, DAQmx_Val_DoNotAllowRegen));
DAQmxErrChk(DAQmxCfgOutputBuffer(taskHandle, BUFF_SIZE));
DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandle, "", sample_rate, DAQmx_Val_Rising, DAQmx_Val_ContSamps, BUFF_SIZE));
DAQmxErrChk(DAQmxRegisterEveryNSamplesEvent(taskHandle, DAQmx_Val_Transferred_From_Buffer, gap/2, 0, EveryNSamplesCallback, NULL));
DAQmxErrChk(write_to_buffer(gap));
/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk(DAQmxStartTask(taskHandle));
printf("Acquiring samples continuously. Press Enter key to interrupt\n");
getchar();
DAQmxErrChk(DAQmxStopTask(taskHandle));
printf("\nWrote %d total samples.\n", (int)samples_written);
Error:
if (DAQmxFailed(error))
{
DAQmxGetExtendedErrorInfo(errBuff, 2048);
Cleanup();
printf("DAQmx Error: %s\n", errBuff);
}
printf("End of program, press Enter key to quit\n");
getchar();
return 0;
}
int32 CVICALLBACK EveryNSamplesCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void* callbackData)
{
printf("samples written:\t%d\n", samples_written);
char errBuff[2048] = { '\0' };
int32 error;
uInt64 samples_generated;
DAQmxErrChk(DAQmxGetWriteTotalSampPerChanGenerated(taskHandle, &samples_generated));
uInt64 sample_gap = samples_written - samples_generated;
int32 samples = gap - sample_gap;
DAQmxErrChk(write_to_buffer(samples));
Error:
if (DAQmxFailed(error))
{
DAQmxGetExtendedErrorInfo(errBuff, 2048);
Cleanup();
printf("DAQmx Error: %s\n", errBuff);
}
return 0;
}
int32 write_to_buffer(int32 samples)
{
int32 error_code = 0;;
while (samples > 0) {
int32 chunk = samples < DATA_SIZE ? samples : DATA_SIZE;
for (int i = 0; i < chunk; i++) {
data[i] = (samples_written+i) % 5;
}
int32 delta_samples_written;
error_code = DAQmxWriteAnalogF64(taskHandle, chunk, 0, 0, DAQmx_Val_GroupByChannel, data, &delta_samples_written, NULL);
printf("delta samples written: %d\n", delta_samples_written);
if (error_code != 0) {
return error_code;
}
samples_written += delta_samples_written;
samples -= delta_samples_written;
}
return 0;
}
void Cleanup(void)
{
if (taskHandle != 0)
{
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
taskHandle = 0;
}
}
When I run this using a simulated USB-6341 device, I get the expected behavior:
With my (non-simulated) USB-6211 device, I get the following:
The program just hangs in this state. To summarize the issues:
I can accomplish this same task just using a loop where I poll the device using DAQmxGetWriteTotalSampPerChanGenerated and write samples accordingly. So why is the callback behavior completely wrong for this device?