04-15-2011 12:33 AM
I have a C++ application that uses DAQmxWriteAnalogScalarF64 to set an analog output voltage based on data received from an outside source (via Ethernet). This is working correctly. However, the call to DAQmxWriteAnalogScalarF64 takes ~1msec each time; even after I sped it up a bit by starting the DAQmx task before calling DAQmxWriteAnalogScalarF64. Switching to a DAQmxWriteAnalogF64 call did not improve the timing. This is using a USB-6229 box and DAQmx 9.1.7 on a 2.67GHz quad-core system running Windows XP SP3. I can actually tolerate a 1msec latency between the call and the actual D/A output: but waiting ~1msec for the call to return is a bit painful in terms of the % of available processing time. It's a pretty big chunk of the overall processing time.
Is there a way to cut down how long the call to DAQmxWriteAnalogScalarF64 takes or a lower level interface call with less overhead? I did not find anything searching through the DAQmx C function reference manual. I thought about setting a hardware sample rate for the analog output (I already do this for analog input), but the data received by my application will always be asynchronous to any sample clock available so I don't see how I can do the output buffering correctly while keeping the latency reasonable.
Any ideas? I'd rather not switch to another manufacturer's product that provides a lower overhead interface for software driven D/A output, but I may be forced to.
04-15-2011 02:59 PM - edited 04-15-2011 03:02 PM
Hi wmallory,
USB sends data in packets with a frame size of 1 ms. USB 2.0 added "microframes" which are 125 us. Therefore, the theoretical lower bound of the latency that you might see is 125 us if a new sample were sent on each microframe using USB 2.0.
However, in practice the theoretical rates are simply not achievable. There is too much overhead with the Windows USB stack etc. With this in mind 1 ms doesn't seem too unreasonable to me. What kind of latency were you hoping to achieve on USB?
For some added information, I decided to run the following benchmark on my 32-bit Windows 7 System with the hardware I had immediately available:
USB-6211: 627 microseconds per iteration (10k iterations).
PCI-6070E: 751 nanoseconds per iteration (1mil iterations).
PCIe-6353: 796 nanoseconds per iteration (1mil iterations).
As would be expected, PCI- and PCIe- based devices are about 3 orders of magnitude faster than USB in performing single-point writes. I would expect similar level of performance with software-driven D/A products from other companies.
So, I think the ideal case (if latency is a concern) would be to switch to a PCI- or PCIe- based solution. If you don't actually care about writing this quickly but just don't want the DAQmx Write task to block other software from executing, I would suggest calling DAQmx Write in a separate thread from the rest of your application if you want to stick with USB. The Write function blocks until it has successfully written data to the device, which I think is desirable behavior in the majority of applications.
Best Regards,
04-15-2011 04:51 PM
Hi John,
Thanks for the detailed reply and confirming that the latency is indeed due to the transfer details of USB 2.0. It's good to know that if I do need to reduce the D/A signal latency, I can switch (or add) one of your PCI based products and quickly "fix" that issue. I can still probably get by with the existing ~1msec D/A signal latency as a portion of my overall system end-to-end latency budget (~5msec total). I'll have to test and see soon to make sure.
I had considered threading off the call to DAQmxWriteAnalogScalarF64 so I can get back to my execution thread quicker: as you suggest. Of course, I had originally assumed(hoped?) that the DAQmx driver would do the equivalent itself: basically taking my input data in the DAQmxWriteAnalogScalarF64 call, returning immediately, and then sending out the data via USB at the driver's "leisure". I guess not. 😮 Maybe a future enhancement option? 🙂 The only concern I have with threading the call is that I'm not positive I can guarantee that my application won't occasionally overlap calls to DAQmxWriteAnalogScalarF64. Do you know whether the DAQmx driver can handle a 2nd call to DAQmxWriteAnalogScalarF64 before the 1st one has finished? If not, I guess I can manage the calls myself via a semaphore or similar mechanism, but it would be much simpler for me if the DAQmx driver can handle the situation itself.
Thanks again for the information.
Walter Mallory