LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Glitches in DAQmx signal generation

I've got some simple code which is generating a sine wave on the analog output and reading it back on the input (reading multiple channels), and it works *most* of the time. But occasionally (1 in every 8 times or so) the output waveform will get corrupted and go flat-line for part of the waveform. I have checked the actual output on a scope, and it shows the glitch exactly as it appears on the graph on screen, so it's not the input routine at fault, it has to be the output routine.
I run this routine every time I hit a button and it simply updates the graph.
 
I am running two Task handles, one for the Output waveform generation, and on for the Input waveform generation, I assume this is how it's supposed to be done?
 
I can't understand how the same code executed time and time again can give a different result occasionally.
 
Also, when it does work, there is a slight (but significant) phase difference between the output waveform and the input waveform (I simply have them looped back on the DAQ card). How do a "synchronise" the waveform generation and the waveform reading? The DAQmxStartTask routine doesn't seem to make a difference.
 
Anyone got any idea? 
 
Thanks
Dave 🙂
 
Here is my code:
 
    DAQmxCreateTask ("DAQtaskOutput", &DAQtaskHandleOutput);
    DAQmxCreateTask ("DAQtaskInput", &DAQtaskHandleInput);
    DAQmxCreateAOVoltageChan (DAQtaskHandleOutput, "Dev1/ao0", "AOchannel", -10.0, 10.0, DAQmx_Val_Volts, "");
    DAQmxCreateAIVoltageChan (DAQtaskHandleInput, "Dev1/ai0:2", "", DAQmx_Val_RSE, -10.0, 10.0, DAQmx_Val_Volts, "");
    DAQmxCfgSampClkTiming (DAQtaskHandleOutput, "", 40000, DAQmx_Val_Rising, DAQmx_Val_ContSamps, NumSineSamples);
    DAQmxCfgSampClkTiming (DAQtaskHandleInput, "", 40000, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, NumInputSamplesTotal);
    DAQmxWriteAnalogF64 (DAQtaskHandleOutput, NumSineSamples, 0, 10.0, DAQmx_Val_GroupByChannel, SineWaveData, &sampleswritten, 0);
    DAQmxStartTask (DAQtaskHandleOutput);
    DAQmxReadAnalogF64 (DAQtaskHandleInput, DAQmx_Val_Auto, 60, DAQmx_Val_GroupByChannel, InputWaveforms, NumInputSamples, &sampleswritten, 0);
    DAQmxClearTask(DAQtaskHandleOutput);
    DAQmxClearTask(DAQtaskHandleInput);
    DeleteGraphPlot (panelHandle, PANEL_GraphWindow, -1, VAL_IMMEDIATE_DRAW);
    PlotY (panelHandle, PANEL_GraphWindow, InputWaveforms, NumInputSamples, VAL_DOUBLE, VAL_THIN_LINE, VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_RED);

 
0 Kudos
Message 1 of 5
(3,491 Views)

I can now answer my own question!

It turns out I was using a greater sample rate than the DAC is capable of. My PCI-6024E card only has a DAC sample rate of 10KS/s recommended maximum, and I was using 40KS/s. Dropping the rate to 10KS/s works fine, and even 20KS/s works fine too.

Guess I learnt the lesson the hard way, the DAQ card DAC sample rate specs can be "typical" and not guaranteed - NASTY!

I presume the PCI-6024E does not have a hardware DAC buffer? More expensive cards would I guess.

 

Still didn't fix my "phase" problem though, anyone know how to fix that?

Thanks

Dave 🙂

 

0 Kudos
Message 2 of 5
(3,484 Views)
Dave,

If you want your input task to be synchronized with your output task, you will need to use a start trigger for your input task.  Without a start trigger, your output task will begin writing samples before your input task has been started, so you will see a phase shift.

...
DAQmxCfgSampClkTiming (DAQtaskHandleOutput, ...);
DAQmxCfgSampClkTiming (DAQtaskHandleInput, ...);
DAQmxCfgDigEdgeStartTrig(DAQtaskHandleInput,  "/Dev1/ao/StartTrigger", DAQmx_Val_Rising);
DAQmxStartTask (DAQtaskHandleInput);
DAQmxWriteAnalogF64 (DAQtaskHandleOutput, NumSineSamples, 1, 10.0, DAQmx_Val_GroupByChannel, SineWaveData, &sampleswritten, 0);
...

Configure the start trigger after configuring your timing, then start the task.  It will wait for the output task to begin generating samples (now started implicitly by passing 1 for the "Auto-start" parameter) before it begins acquiring.


(Note that if your
input and output tasks were on different devices, you would also have to share a signal to synchronize the input and output sample clocks, in addition to using a start trigger.)

Hope that helps.

Mert Akinc
National Instruments
0 Kudos
Message 3 of 5
(3,478 Views)

That did the trick, thanks!

Although I found the The DAQmxReadAnalogF64 routine must come *after* the DAQmxWriteAnalogF64 routine, otherwise it wouldn't trigger at all. This is not very intuitive (i.e. starting the Input read task before actually calling the Input read routine!), but it's the only way it would work.

Thanks
Dave 🙂

0 Kudos
Message 4 of 5
(3,465 Views)
You're right that the read call must come after the write call (if you compare code snippets, the read call would actually immediately follow the "..."). 

The reason for calling the input start before the input read is that once timing is configured for your task, it is the DAQmxStartTask call that actually begins the acquisition of samples from your input channels.  As soon as the task starts running, it begins sampling and transfers those samples into the DAQmx driver's memory.  The call to DAQmxReadAnalogF64 just fetches those samples from the driver's memory into your program's memory.  This is why you can have "samples overwritten" errors in continuous acquisition tasks if you don't call DAQmxReadAnalogF64 often enough.  This is also the reason that a DAQmxReadAnalogF64 call before the task is started will always timeout (if one is specified).

I hope that helps clear up what is actually going on.  Good luck!

Mert Akinc
National Instruments
0 Kudos
Message 5 of 5
(3,457 Views)