10-31-2025 09:50 AM
Hi everyone,
I'm working with a NI 9260 analog output module in a cDAQ-9185 chassis, connected to my PC via Ethernet. The goal is to continuously stream a generated waveform to an AO channel.
Here’s how the system is structured:
DAQmx Write (autostart = false, regeneration disabled), only when an element is available in the queue (queue timeout = 0).DAQmx Timing to run at 10 kHz, with continuous samples, and a buffer size of e.g. 10,000 or 50,000 samples.The system initially works as expected, but:
Eventually, the AO task fails with either error -200621 or error -200018, seemingly at random.
Here is the full error message for -200621:
Error -200621 occurred at SimApp.vi
Possible reason(s):
Onboard device memory underflow. Because of system and/or bus-bandwidth limitations, the driver could not write data to the device fast enough to keep up with the device output rate.
Reduce your sample rate. If your data transfer method is interrupts, try using DMA or USB Bulk. You can also reduce the number of programs your computer is executing concurrently.
Task Name: unnamedTask<12>
System details:
Has anyone encountered this kind of systematic buffer drain during AO streaming, even when the data rate should match the configured sample rate?
Are there known limitations or considerations when streaming AO data to a cDAQ device over Ethernet?
Any insights would be greatly appreciated!
Greetings, derFliXX
11-01-2025 07:49 AM
Why are you streaming samples? can it not be pre-determined?
11-03-2025 01:56 AM - edited 11-03-2025 02:01 AM
I'm streaming the samples because I want the signal to be generated as close to real time as possible. The parameters that define the signal can be adjusted during runtime, so the waveform needs to be built dynamically rather than precomputed. This allows for flexible, responsive behavior during simulation.
11-05-2025 07:25 AM
Btw - added the full blockdiagram if this helps.
11-15-2025 09:09 AM
It sounds to me like you've overconstrained your timing, based on your statement that your generator loop runs every 10 msec and that you are generating 10 msec worth of data each iteration. Loop timing is software based, thus variable and unreliable. Signal output timing is hardware based, thus consistent and reliable. Apparently, there's a systematic reason that your software timing causes your generation loop to run a little slower on average than 100 Hz.
So rather than try to keep software timing sync'ed with hardware timing, I would recommend you avoid relying on software timing at all.
1. Remove any manual delays from the generator loop. Set it up as though it can run as fast as it likes. (We'll get back to this and throttle it a different way).
2. Use a fixed-size queue between generator loop and output loop. Make it fairly small such that you can accept the implied latency. But it should probably be an integer multiple of the # samples you'll be feeding it at a time.
3. Let your output loop simply dequeue then DAQmx Write, dequeue then DAQmx write, ... It will get throttled by DAQmx when you fill up the DAQmx task buffer and the device's onboard FIFO. (Note: there are ways to configure your task that give you some control over the latency caused by these buffers.)
4. Here's the key. In your generator loop, wrap a while loop around the enqueue function and set a very small timeout like 0 or 1 msec.
If the enqueue times out (or gives an error related to a full queue), continue iterating until you get a successful enqueue (or a different and more catastropic queue error).
Once you've run your generator loop enough to pre-fill this queue, subsequent attempts to enqueue will get stuck in the inner loop attempting to enqueue until the output loop gets around to doing a dequeue to make room for the enqueue to succeed.
5. Once this whole system "winds up" and all the buffers are full, you'll get a pretty steady latency and should no longer run into the DAQmx underflow error.
6. All of this assumes that the code inside your generator loop can always execute in well under 10 msec. If that's not the case (and I have mild suspicion about the "read data" vi), you'll just need to deal in larger time chunks. The whole thing depends on the generator loop being able to calculate new samples *faster* than the output loop will put them into the real world. The generator loop's timing should *only* get constrained by the limited rate at which the output loop consumes data from the usually-full fixed-size queue.
-Kevin P