01-24-2025 11:39 AM
I am trying to take analog input measurements with the lowest amount of latency possible, ideally at a rate of around 500 Hz. I’ve done a good bit of research and have played around with my setup a lot, but I’m hitting a wall with the speed and latency values that I’ve been able to achieve. I need to measure 6 analog input channels, then send the measurements over UDP to another python program that runs a simulation. In order for this simulation to work, the measurements need to get there as quickly as possible.
My company does not allow me to share code, but I will give a description of our system and setup. We are using a PXIe-8840 chassis running Windows with a PXIe-4304 analog input card. The code is relatively simple, we are setting up the sample clock for continuous samples at a sample rate of 5000 Hz and before entering the read loop, we are using a DAQmx read property node to read the “Most Recent Sample” with an offset of -1. For the reads we have a while loop where I am using “Analog 2D DBL NChan NSamp”. I am reading 10 samples, next I take the “newest” of these samples, add it to a queue, where another while loop dequeues it, flattens it to a string, and then sends it over UDP to the other program.
This is setup is kind of working (the read loop is running at about 70 Hz). What seemed to be the breakthrough was setting the read position to “Most Recent Sample”. Once we did this our simulation started to work some of the time. As far as I can tell, this has helped to reduce latency by making sure that we aren’t reading “older” samples in the buffer. I’ve tried lots of other settings like eliminating the buffer altogether, but that has just made things worse. Admittedly I’ve never had to get “in the weeds” like this with DAQmx measurements before and I know there’s something I’m missing here. Does anyone have any advice or resources that could help me understand what I need to do here to improve my measurements? If anyone really wants some sample code I could probably make a sample VI.
01-24-2025 04:46 PM
Your hardware should be able to read all 32 channels simultaneously at up to 5 kHz. If you are getting less than that, either you have a seriously-damaged piece of hardware, or your software is not working.
If you run MAX and try to acquire data from the card in a Test Panel, can you resolve, say, a 60 Hz signal (put a 1 Mohm resistor across the inputs, and touch one of them -- you should see coupling from the A/C floating all around you). Taking 1000 samples at 1 kHz should give you around 16 (1000/60).
Write a very simple LabVIEW routine to do mimic the previous paragraph and display it on a Chart. Did you see 16 cycles? If not, attach your very simple LabVIEW routine (should be free of Company Secrets!) and we'll "teach you some LabVIEW".
Bob Schor
01-24-2025 10:17 PM
Well, here's one problem:
we are using a DAQmx read property node to read the “Most Recent Sample” with an offset of -1. For the reads we have a while loop where I am using “Analog 2D DBL NChan NSamp”. I am reading 10 samples, next I take the “newest” of these samples, add it to a queue,
Reading 10 samples with an offset of -1 means that you'll get 1 already-delivered sample and then wait for the next 9. After that, you apparently ignore all except the last one anyway. On the next read, you'll start by reading the sample you just enqueued followed by 9 new ones. Why? All this mucking about doesn't seem very sensible to me.
I don't think you're doing yourself any favors playing around with the offset this way. What happens when you don't set the offset at all and just run a tight reading loop asking for 10 samples per iteration? And maybe more to the point, IS your reading loop really lean and tight with no wasted processing?
A 500 Hz reading rate is a fairly tall order under Windows. It's not going to be rock solid reliable but I'm inclined to suspect that well-written code will "keep up" most of the time. But you *are* pushing things. The long-accepted norm is to aim for a 10 Hz reading loop to reduce the effects of per-call overhead while delivering higher data bandwidth. 50x is a lot to ask for, and the combo of per-call overhead and Windows task scheduling makes it much more iffy.
As an experiment, try an offset of -1 while reading only 1 sample. That should return *instantly* with the most recently delivered sample. See where you're at with latency under that scenario. There are other delay sources as you work through queues, parallel loops, UDP, python code, but this will at least minimize the DAQ part of the latency.
You may need to address the possible problem of reading the *same* recent sample if your DAQ read loop is really tight and fast. A simple next step would be to set an offset of 0 while reading 1 sample. That will read only the very next sample that gets delivered. See what effect that has and what iteration rate you can get from your reading loop.
-Kevin P
01-27-2025 05:29 AM
HINT: If you fetch the last samples from the DAQ , you also get the timestamp from these samples (based on the 4304 clock) .. if not already done, add that timestap to the UPD stream ...(maybe not used in the receiver system, but worthy on the long end 😉 )