Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Async sample polling with mx-base

We have several NI-DAQ devices: 6229, 6035E, 6035E, and USB-6009.  We're using mx-base on Linux RH WS to interface with the devices from C++ code.  We're trying to do something that sounds very simple, but is turning out to be incredibly difficult (which makes me think we're not using mx-base correctly).  All we want is to allow multiple processes to either set channel values or sample one or more channels and get the most recent value.  So when we're sampling, it's asynchronously and we want the sample quickly (< 5 ms, but we're not doing anything real-time so it's not a hard constraint).  The first thing we discovered was that the mxbase library cannot be initialized and shut down between processes.  So for instance, if one process opens a DO device, writes a channel, and exits, the next time another process opens the DO device and writes to a different channel, the previous channel state gets reset!  The solution we thought was to create an mxbase server that always runs and clients make requests on this.  This is working OK, but seems pretty complicated for what we're doing IMHO. 

And then the next thing we discovered was that when we called DAQmxBaseReadAnalogF64, we were getting stale values.  We modeled our code after the ai/acquire1Scan.c example.  The server had been setting up the task upon initialization and only calling the read function when the client requested it.  The only way we could fix this was to start and stop the task every time the client asked for a value.  This gave us fresh values alright, but the transaction took nearly 200 ms!  So then I tried to use a coninuous task (modeled after the contAcquireNChan.c example) but discovered that it refuses to overwrite samples I haven't read, which means the buffer quickly overflows.  So my solution was to spawn a thread whose sole purpose is to keep the AI read FIFO empty.  All this just so I can get the current value with low latency!  This works, but we occasionally get DMA buffer errors because either we're not reading fast enough or we're readng too fast (probably because we're not using an RTOS).  I can't find a reliable way to stay in the middle.  Nor can I see a simpler way to do this.

Surely there's a better way!  Are we completely abusing mx-base?  Is there a configuration that I'm missing that will do what we want in a much simpler fashion?  Or was mx-base simply not designed for our use case?

Thanks.
Keith.

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

Hello Keith,

How fast would you like to read and write your values?  From your post, it looks like you would like different processes to be able to read and write analog and digital values at varying times.  But it also looks like you are only writing or reading one sample at a time.  Let me know if this is not your desired outcome. 

You could try creating a task that includes all of your digital output lines.  Then, you could pass your digital output task name and current output values around to the different processes without closing the task.  This way you do not have to reinitialize your task each time you would like to update a single digital value.  Each time you would like to update a single line, you could modify the current output set and then call the write function.  Grouping your task name and your current output into a single object/class could simplify the code expansion.  A similar class could be used for your input tasks as well.  By calling the DAQmxBaseReadAnalogF64 several times, you will retrieve several measurements. 

As for the continuous acquire, whenever you perform a continuous input task, the DAQ device will constantly be acquiring data to its onboard FIFO.  This data is then transferred to the PC buffer.  If this data is not transferred fast enough, error -200361 can result.  At this point, reducing the sample rate or reducing the number of programs running concurrently can help improve this measurement. 

Regards,
Browning G
FlexRIO R&D
0 Kudos
Message 2 of 5
(3,641 Views)
Hi,

Sorry it took so long to reply.  Been working other issues and just now getting back to this.  The AI problem is really hurting us right now. 

As for the continuous acquire, whenever you perform a continuous input task, the DAQ device will constantly be acquiring data to its onboard FIFO.  This data is then transferred to the PC buffer.  If this data is not transferred fast enough, error -200361 can result.  At this point, reducing the sample rate or reducing the number of programs running concurrently can help improve this measurement. 
My point is that we don't WANT to do continuous acquire.  All we need is to sample the CURRENT AI channel values asynchronously with minimal latency.  Surely there is a way to do this without starting/stopping a task every time we poll for the channel values, or worse creating a separate thread that does a continuous acquire just so we have the latest value on-hand when asked for it.  Are we the only folks asking for the latest AI channel values without caring about a FIFO full of past samples?

Thanks,
Keith.

0 Kudos
Message 3 of 5
(3,575 Views)
Hi Keith,

What you will want to do is not setup timing for your channel.  That way DAQmx will not setup a PC buffer and whenever you call the read function, DAQmx will just read the current voltage off of your channel. 

So you code might look something like this:
DAQmxCreateTask(...);
DAQmxCCreateAIVoltageChan(...);
DAQmxStartTask();
while (!done)
{
    if (button_pressed)
       DAQmxReadAnalogScalarF64(...);
}
DAQmxStopTask();
DAQmxClearTask();

If you have any questions about this, please let me know.

Thank You,

Nick F.
Applications Engineer
0 Kudos
Message 4 of 5
(3,548 Views)
Well, that's what we started with but we were getting stale data, which led us down the long and complicated path to where we are today.  I'll revert back to that method and then I'll be able to send you exactly how we're configuring it.

Thanks,
Keith.

0 Kudos
Message 5 of 5
(3,544 Views)