LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

NIDAQmx non-blocking read ?

Hello all,

I'm tring to do fairly simple things with NIDAQmx, but that thing's a beast and not all the functions are in the FP.

 

I managed to do a non-blocking signal generation like this, where a callback is called when the generation is finished:

 

DAQmxCreateTask("AnalogTask", &Task);
DAQmxCreateAOVoltageChan(Task, PhyChan, ChanName, -10, 10, DAQmx_Val_Volts, "");
DAQmxSetChanAttribute(Task, ChanName, DAQmx_AO_TermCfg, DAQmx_Val_RSE);
DAQmxCfgSampClkTiming(Task, "OnboardClock", Rate, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, NbSamplesPerChan);
DAQmxSetWriteAttribute(Task, DAQmx_Write_RegenMode, DAQmx_Val_AllowRegen);
DAQmxRegisterDoneEvent (Task, 0, CBD_AnalogEnd, NULL);
DAQmxWriteAnalogF64 (Task, AOSamples, 0, 0, DAQmx_Val_GroupByChannel, WriteArray, &SamplesWritten, 0);
// this returns immediately
DAQmxTaskControl (Task, DAQmx_Val_Task_Commit);	// Necessary ?
DAQmxStartTask(Task); // this returns immediately
// Do something else - CBD_AnalogEnd will be called

 

 

But I can't do the same with analog input:

 

DAQmxCreateTask("AnalogTask", &Task);
DAQmxCreateAIVoltageChan(*Task, PhyChan, ChanName, DAQmx_Val_Cfg_Default, -10, 10, DAQmx_Val_Volts, NULL);
DAQmxCfgSampClkTiming (*Task, "OnboardClock", Rate, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, NbSamplesPerChan);
DAQmxSetReadAutoStart(Task, FALSE);	// Undocumented function
DAQmxReadBinaryI16 (Task, AISamples, -1, DAQmx_Val_GroupByChannel, ReadArray, AISamples*4, &SamplesRead, 0);
DAQmxTaskControl (Task, DAQmx_Val_Task_Commit);
DAQmxStartTask(Task);

 I get the following error message when calling ReadBinaryI16:

 

Read cannot be performed when the Auto Start property is false and the task is not running or committed.
Start the task before reading, or set Auto Start to true.
Property: DAQmx_Read_AutoStart
Corresponding Value: 0
Task Name: AnalogInTask
Status Code: -200473

 

If I place StartTask/TaskCommit before the ReadBinary call, I don't get any error but the read still takes the entire time before it returns. How does a non-bloacking read work ?

 

Thanks

0 Kudos
Message 1 of 6
(5,206 Views)

Bounced over here from a link in a DAQ board forum.  Though I do my DAQmx programming in LabVIEW, I think I can help at least a little with the problem you're seeing.

 

1. With the Write task you showed, it's necessary to perform a Write to the buffer *before* starting the task.  That way when the task is started, it knows what it's supposed to write.

   As you found from the error message, you *shouldn't* perform a Read before starting a Read task.  The task has to start so the board can add data to the buffer before you can find anything there to read.

 

2.  The special value -1 in your call to 'ReadBinaryI16' most likely refers to the "# of samples to read."   A DAQmx convention is that when you request -1, it's interpreted in a special way.   Because you've configured a Finite Sampling task, -1 means "read the entire buffer worth of samples."   Well, it can't do that until the buffer's been filled, and that's why the read consumes the entire time before it returns.

 

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 2 of 6
(5,171 Views)

One way to implement a non-blocking read would be to use a callback (DAQmxRegisterEveryNSamplesEvent) where you will get an event every time some interval of samples are transferred into the PC buffer (then you just read that number of samples every time you get the callback--the samples will already be in the buffer and the call wouldn't block).

 

If you want to just read in your main thread but have the read call return immediately with whatever samples are available, you can do this as well using DAQmxSetReadReadAllAvailSamp (this property is only used for finite tasks, continuous tasks will always read all available samples if the specified number of samples is -1).

 

 

Best Regards,

John Passiak
0 Kudos
Message 3 of 6
(5,162 Views)

Thank you for your answer. Actually the -1 is the timeout, saying to wait indefinetly if no data.

The parameters are:

DAQmxReadBinaryI16 (Task, NbSamplesPerChan, Timeout (-1), DAQmx_Val_GroupByChannel, Buffer, BufferSizeInSamples, &NbSamplesRead, Reserved);

 

You write: "The task has to start so the board can add data to the buffer before you can find anything there to read."

So does that mean that the acquisition starts as soon as you call start ? But then how does it know where to save the data since I haven't passed the buffer address yet ? Is it bufferized somewhere ?

0 Kudos
Message 4 of 6
(5,159 Views)

But then how does it know where to save the data since I haven't passed the buffer address yet ? Is it bufferized somewhere ?


Yes, DAQmx configures a buffer when the task is reserved (the task is implicitly reserved when it is started).  The buffer size is configurable (DAQmxSetBufInputBufSize) with a default determined by the sample rate for continuous tasks (for finite tasks the default buffer size is the total number of samples).

 

When you make the read call, you are reading from the data that is available in this buffer (or if you ask for data that isn't there yet, the read will block until it becomes available)

 

 

Best Regards,

John Passiak
0 Kudos
Message 5 of 6
(5,157 Views)

Apparently yes, that's exactly how it works: ReadBinary should be called inside the callback that says the task is finished. Weird. I feel like something is not quite right here and maybe not just because it's almost midnight...

0 Kudos
Message 6 of 6
(5,155 Views)