From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Multifunction DAQ

Showing results for 
Search instead for 
Did you mean: 

Continuous waveform generation?

What is the proper way to do this using NIDAQmx? In my program I am using a ping-pong buffer to generate outputData to be written out. Semaphores take care of the data generation and consumption synchronization. The code below does not work. The output sample rate is not the Fs that I set it to be. Instead it is 800 kHz (the max rate for my 6120 board).

I can't find any examples that show how to do continuous generation (without repeating 1 buffer over and over again).

// DAQmx Configure Code
DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateAOVoltageChan (taskHandle, chan0, "", -10.0, 10.0, DAQmx_Val_Volts, NULL));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",Fs,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps ,sampsPerChan));
DAQmxErrChk (DAQmxGetTaskAttribute(taskHandle,DAQmx_Task_NumChans,&numChannels));

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

while( gRunning ) {
// DAQmx Write Code
result = WaitForSingleObject(DAQReadSem[bufNum], 10000); // Blocking sempahore acquire
DAQmxWriteAnalogF64 (taskHandle, sampsPerChan, 0, TIMEOUT, DAQmx_Val_GroupByScanNumber, outputData[bufNum], &numWritten, 0);
result = ReleaseSemaphore(DAQWriteSem[bufNum], 1, NULL);
bufNum = 1 - bufNum;
0 Kudos
Message 1 of 5

Dear Eric,

It sounds like you want to do a continuous analog output that does not rewrite old data. If this is the case, use the property DAQmxSetWriteRegenMode set to DAQmx_Val_DoNotAllowRegen before your timing function. Then write your data in a while loop. With this method the buffer is handled for you. Have a great day!


Marni S.

0 Kudos
Message 2 of 5
Thanks. With your input and the help of an NI applications engineer I was able to get my code to work. A couple of notes:

- As posted by Marni, DAQmxSetWriteAttribute() needs to be called with DAQmx_Val_DoNotAllowRegen.

- DAQmxCfgSampClkTiming() needs to be called with DAQmx_Val_ContSamps as the 5th arg.

- DAQmxWriteAnalogF64() must be called **BEFORE** DAQmxStartTask() is called.
*** Note that this isn't clearly explained in the documentation. ***

One more note: DAQmxWriteAnalogF64() acts as a blocking call when used with my PCI-MIO-16E-4 card, but it is non-blocking when used with my PCI-6120 card. I don't understand why I get differing behavior. Again, there is a lack of documentation on this subject.
0 Kudos
Message 3 of 5
DAQmxWriteAnalogF64() should always be a blocking call.  Basically the write call will block until the number of samples specified have been written.  I suspect that the difference in behavior you are seeing is due to the fact that your 6120 has a huge amount of onboard memory (16 or 32 MSamples).  As a result, when write is called, data is able to be immediately transferred to the 6120.  The PCI-MIO-16E-1 has a much smaller amount of onboard memory.  As a result, when you write 10,000 samples to it, it fills up the onboard memory (with data still waiting to be written).  This causes the write call to block untill that data has been output, and there is again room on the onboard memory to transfer more of the data.  As a result, when writing large amounts of data to the 16E-1, you will be somewhat limited by the your output rate.  For the 6120, there is enough memory available on the device to transfer all of it in one shot.  Hence it appears as though the DAQmxWrite is behaving differently between the two devices.
Hope this make sense,
0 Kudos
Message 4 of 5
I see. I thought that the DAQ cards would block based on a double-buffer of whatever size you specify. I wish that was the case, that would simplify the programming.
0 Kudos
Message 5 of 5