I am supposed to be untangling a mess of spaghetti code and adding documentation so that it can *at some point* get fixed. It's been a wild ride. This is supposed to be a data collection application for a PXIe system that will eventually also run the controller associated with the system. The guy who wrote it told me the biggest issue is that the sampling rates are too slow. I've figured out that the issue is probably the use of the Write to Measurement File express VI in a timed loop that is supposed to run for only 1ms, but I've hit a bit of a wall on part of the project. There are loads and loads of dynamic VI references in the project, and I can't figure out what exactly they are being used for (as opposed to just wiring outputs directly to inputs). I've attached a few screenshots and the main VI from this project, but a bunch of the subVIs referenced are missing even to me and it's just generally a mess so I wouldn't expect to get it running anyways.
Any help, or glaring errors you see that I missed would be great!
Also the project is much larger than my 2 monitors can fit (or any monitors for that matter) so bear with me
As you mentioned, trying to write to a file every ms in your data acquisition loop is probably limiting the acquisition rate so moving to a producer consumer architecture would probably be best. Beyond that, the thing that sticks out to me the most is the lack of error handling. Right now nothing is really being done if one step does happen to error out. In the case of an error, the functions after that will pass through the error but that won't stop the loop so you'll end up at the next iteration completely forgotting that you encountered an error in the previous iteration.
Thanks! I'm more confused on the purpose of the dynamic VI references in the program, however. I'm working on getting a P/C setup implemented (That's what the queue bits are in the actual VI). Any clues as to why the second screenshot is the way it is? I'm having a hard time gathering what he was even trying to do at that point (and everyone is gone for break here!)
Also thanks for pointing out the error handling! I had missed that.
It's hard to tell exactly what's going on but they aren't really dynamic VI references as you've been calling them. Each one of them is just a reference to a different front panel item so there is an array of LVDT Maximum and Minimum numeric indicators. To me, it looks like the for loop iterates through all the max and min indicators and changes the name of the caption to the channel name of that particular waveform. What's a little strange is that it looks like WaveformGraphConfiguration (SubVI).vi towards the beginning of the application is writing these channel names so why this needs to be done every iteration at this point of the program is unclear, especially because I can't look deeper into any of the VIs.
I'm with Matt on the purpose of the second screen shot. it just puts the Wfm name on the FP as captions for the controls. That For loop would benefit greatly from a Defer Panel Updates method before and after it. You are miss-understanding the time set-up or, the original author missunderstood DAQmx (more likely)
DAQmx input Tasks have there own timing. The timed loop is a bad choice of structure. run a While loop as fast as the Acquisition can be made.
Let me explain: it appears the Tasks (I'm guessing here that the intent was to switch between one of two Tasks set up for two flavors of cable harnesses) have a 5kHz sample rate and a 1250 sample size. it takes 250mSec to acquire those samples so, the loop will "Naturally" iterate at 4Hz there may be "jitter" in the rreading rate but it must Average @4Hz! If you try to go any faster you will need to wait for either:A)enough samples to be available (that takes a quarter second) or the Read to timeout. If you try to go any slower the Acquisition buffer will start to fill and the DAQmx read will return the oldest 1250 samples right away since they have been sitting in the buffer since they were first acquired just waiting to be read wenever you get around to reading them. So, a second timing element (like a timed loop) can't help at all but it can certainly create problems.
Worse: the Quit LabVIEW primitive is just a "Bad, Bad, Bad" choice. Stomp it out of the loop now!
Thank you both for your input.
@Jeff: The data is supposed to be sampled at 1kHz, is there any way to get it up to that speed if there is a 4Hz "cap"? Or am I misunderstanding what you said?
The data will be sampled at the DAQmx Task's Sample rate. Period. No faster, no slower. The number of samples requested for each read times the Sample rate determines how often the DAQmx Read must be called and how fast the calling loop can iterate. Any other iteration timing source is either pointless or hazardous. I don't know if you are miss-understanding that. Are You?
There are several "timing" considerations you need to consider. One is what sampling rate do you need to get meaningful data. You mention 1KHz, so you want to set you DAQmx acquisition function (I'm assuming you are doing Analog multi-channel input) to 1KHz.
The next question is what time course do you need to "make decisions"? I don't know what your task is, so here's an illustration from some studies we did. We were studying Sound Localization, and were sampling 16-24 channels at 1KHz. The trials ran pretty much on their own, but we wanted to monitor the signals. We decided to update our displays at 20 points/second, so we acquired 50 points at a time, streamed them to disk (saving the data) and displaying the average of these points on a scrolling chart. We use producer/consumer ideas. Our acquisition loop that acquires data continuously, 50 points at 1KHz, exports (via a Queue) a N-channel by 50-sample array 20 times a second. Each gets sent from our PXI to the PC via a Network Stream. The Consumer "receiver" loop on the PC gets a packet every 50 msec, plenty of time to write it to a file, average the 50 points and put an N-channel update on a chart.
So our Sampling rate (1KHz) is governed by the data we need, the speed of the Producer/Consumer loop is governed by the (much lower) speed we want to view the data in Real-Time. Your situation will have its own set of timing requirements which will govern how you structure your Producer/Consumer loops.
try_guy90 wrote: I've figured out that the issue is probably the use of the Write to Measurement File express VI in a timed loop that is supposed to run for only 1ms
If you are logging the data to a TDMS file, use the DAQmx Configure Logging VI before the task starts. This will allow DAQmx to stream the read data straight to a TDMS file. It will perform a lot better than a Producer/Consumer setup (it avoids layers of software to write the data to disk) and save you a lot of development time (assuming all you need to log is the raw data).