09-12-2013 05:45 AM
Hi All
I am writing an application that has to do months of testing of a hardware system continuously. I am using a USB-6211 D/A converter and a PC to generate a contant stream of analogue waveform data.
The PC is a fast modern computer running Window7. The output sample rate is 50kHz and I am only using one D/A channel.
When I run the program, the systems works as expected for about 100 hours. Then I get the following error on the screen:
"DAQmx Error: Task could not be started, because the driver could not write enough data to the device. This was due to system and/or bus-bandwidth limitations.
Status Code: -200946"
Once it has failed, re-running the program will bring the same error up after seconds. The only way to clear the error is to unplug the USB-6211 and plug it back in. It will then run for another 100 hours. This is not a solution as the system must run continuously for 3000 hours.
It looks as though the error is in the NI driver but I do not know how to debug this. My code only makes 1 memory alloc at the start of the program and continuously generates samples into this memory buffer. I can provide the relavent code sections if required.
Many Thanks
John
09-16-2013 04:31 AM
Hi John,
If you could provide the code so I can look into the problem for you, that would be great. also if you could let me know what software versions you are using that would also be useful.
Kind regards,
09-16-2013 04:49 AM - edited 09-16-2013 04:52 AM
Hi Matt
Here are the 2 main routines. InitialiseOutputSystem is called once at the start of the program and OnEveryNSamplesEventCallback is called whenever the USB buffer has been emptied.
I should also add that I set up the NI drivers (all 2GB of them) 1 week ago from the NI web site so they should be the latest.
Thanks for any help you can provide.
Cheers
John
#define PI 3.14159265359
#define OUTPUT_FREQ 100.0 // output frequency of waveform in Hz
#define NUM_SAMPLES 10000L // number of samples in output waveform
#define SAMPLE_RATE 50000L
void InitialiseOutputSystem ()
{
int32 error=0;
float64 tmpOutput;
// ***** OUTPUT INITIALISATION *****
// create task for analogue output
DAQmxErrChk ( DAQmxCreateTask("",&outputTaskHandle) );
DAQmxErrChk ( DAQmxCreateAOVoltageChan(outputTaskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL) );
// set initial voltage to zero volts (no drive)
tmpOutput = 0.0;
DAQmxErrChk ( DAQmxWriteAnalogF64(outputTaskHandle, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &tmpOutput, NULL, NULL) );
// wait for task to complete then stop it again
DAQmxErrChk ( DAQmxWaitUntilTaskDone(outputTaskHandle,10.0) );
DAQmxErrChk ( DAQmxStopTask(outputTaskHandle) );
// get start trigger handle
//DAQmxErrChk ( GetTerminalNameWithDevPrefix(outputTaskHandle,"ao/StartTrigger",trigName) );
// configure sample timing
DAQmxErrChk ( DAQmxCfgSampClkTiming(outputTaskHandle, "", SAMPLE_RATE, DAQmx_Val_Rising, DAQmx_Val_ContSamps, NUM_SAMPLES) );
// register N samples callback event
DAQmxErrChk ( DAQmxRegisterEveryNSamplesEvent(outputTaskHandle, DAQmx_Val_Transferred_From_Buffer, NUM_SAMPLES, 0, OnEveryNSamplesEventCallback, NULL) );
// configure system to not regenerate the waveform automatically
DAQmxErrChk ( DAQmxSetWriteAttribute(outputTaskHandle, DAQmx_Write_RegenMode, DAQmx_Val_DoNotAllowRegen) );
// reconfigure output buffer size
DAQmxErrChk ( DAQmxCfgOutputBuffer(outputTaskHandle, 2*NUM_SAMPLES) );
// write waveform into driver
DAQmxErrChk ( DAQmxWriteAnalogF64(outputTaskHandle, NUM_SAMPLES, 0, 10.0, DAQmx_Val_GroupByChannel, ptrOutputWaveform, NULL, NULL) );
Error:
if( DAQmxFailed(error) )
{
CloseNISystem ();
}
return;
}
int32 CVICALLBACK OnEveryNSamplesEventCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData)
{
int32 error=0;
char errBuff[2048]={'\0'};
//Record the time we last serviced the callback;
LastCallBack = time (&LastCallBack);
if ( fFinish )
{
//We have finished - make sure the outputted waveform is a continuous zero volts
for ( int i = 0; i < NUM_SAMPLES; i++ )
ptrOutputWaveform[i] = 0.0;
}
else
{
nWaveformCyclesCompleted++;
}
// write next waveform into buffer
DAQmxErrChk ( DAQmxWriteAnalogF64(outputTaskHandle, NUM_SAMPLES, 1, 10.0, DAQmx_Val_GroupByChannel, ptrOutputWaveform, NULL, NULL) );
if (!fFinish)
{
if (CalCycleRequired == true)//Generate audio into the buffer with the cal cycle frequency. Reset the phasor so that it starts from 0
{
if (CreateFrequency( ptrOutputWaveform, OpParams.CalFreq, 0, 10, 0, true, NUM_SAMPLES ) == true)
{
CalCycleRequired = false;
}
}
else //Standard frequency generation - make the next 10000 points
{
CreateFrequency( ptrOutputWaveform, OpParams.NoiseFreq, OpParams.DriftFreq, OpParams.NoiseAmp, OpParams.DriftAmp, false, NUM_SAMPLES );
}
}
Error:
if( DAQmxFailed(error) )
{
if( DAQmxFailed(error) ) printf("DAQmx Error: %s\n",errBuff);
DAQmxGetExtendedErrorInfo(errBuff,2048);
CloseNISystem ();
}
return (0);
}
09-16-2013 05:54 AM
Hi John,
As the error states, it sounds like an error with the bandwidth capabilities of the communication bus. You are probably filling the bus faster than the bus can send the data, which then gives the resulting error you described. By unplugging the device and plugging it in again, you are simply clearing the bus, which means you start from the beginning and fill the bus to the same point again.
If the data is repeating, you can turn on regeneration, which means the pc only needs to write to the bus once, and the data will be repeated. You can acheive this by changing your DAQmxSetWriteAttribute function line to allow regeneration with the following code
DAQmxErrChk (DAQmxSetWriteAttribute (outputTaskHandle, DAQmx_Write_RegenMode, DAQmx_Val_AllowRegen));
If the data is non-repeating then you will need to either sample at a slower rate to not lose data, or use hardware that is designed for faster sampling.
One other possible thing you could try is to take more samples at a lower rate if this is viable, as this is a more efficient in terms of the buffer not being filled so quickly.
Kind regards,