Hi - LabVIEW newbie here, trying to modify an existing program designed to log 50,000 data points which are generated by sampling at 100Hz for 500 seconds. It would be immensely helpful if I could somehow poll this data every 5 or 10 seconds to see how the experiment is progressing WITHOUT jeopardising the contiguity of data being logged in the main buffer. I really hope there is a simple way to do this! The important DAQ components are included in the attached JPEG.
Thanks in advance!
So far I've tried to do this by generating a new channel/task (by copying the one being passed to the clock/counter setup and running the task through a sample clock running with a shorter window - i.e. "please tell me what you've got once every 100 data points"), but this seems a deadend because I don't think it's possible to carry out two tasks simultaneously. I think this may be the crux of the problem...
Right now my jerry-rigged solution has been to simply run the whole thing inside a For loop and poll every 100 data points so I can see what's happening up on screen quickly, but this is quite certain to break the contiguity of my data set and so is absolutely useless for simulataneously seeing what's happening AND data logging. I'd love to be able to data log AND see periodic polling of what I have so far.
Certainly you can.
Have a look at the "Count Digital Events -- Buffered Continuous -- Ext Clk" example. (Find Examples...Hardware Input and Output...DAQmx...Counter Measurements...Count Digital Events...)
You will see that the acquisition is set up as a continuous acquisition instead of a finite one, and it takes place inside a while loop. A chunk of data is acquired in each loop iteration. So if you are acquiring at 100Hz, and you want to grab 100 samples, your loop will iterate once per second. The data acquired during each loop iteration can be displayed on the front panel, written to a file, etc. So you'll be acquiring data in chunks of 100 instead of in one big chunk.
Use the iteration terminal of the loop as your "stop" condition. If you want to acquire for 500 seconds, and your loop is iterating once per second, then compare the value of the iteration terminal to 499 (it starts at 0, not 1). When the value of the iteration terminal = 499, stop the loop.
Right now you have your task set up as a finite acquisition, so you are grabbing all of the samples at once. As you have rightly noted, this means you don't have access to any of them until they're all available.
Give this a try. Also have a look at producer-consumer architectures. You will want your file write to take place in a separate loop so that it doesn't interfere with your acquisition loop.
Thanks very much for the response. It's encouraging to hear that I should be able to do this - I refuse to believe this is an unusual or difficult task to accomplish!
I am concerned, though, that iterating through a While loop might result in "missed" data. I cannot risk missing a single beat in between cycles, because correlation between data points critically important.
I'll post once I've attempted an implementation this afternoon. Thanks again!
I've been sidetracked by your recommendation that I look into producer-consumer architecture, and have been working on a program structure involving data queues (in which I am uncomfortably out of my depth). Modifying a LabVIEW example VI (here: https://decibel.ni.com/content/docs/DOC-2431), I've come up with something that seems like it is structurally what I'm looking for (see attached). Obviously this VI doesn't do anything with the data, but that's the easy bit once I've got it running smoothly.
My problem at the moment is that I can't get what I've labelled Master/Slave Channel Volume to give me anything other than an array of size zero, and I'm not sure why this is happening. My sample rate is set to 200Hz, and I'm trying to poll every 100 data points. So I expect the data stream from DAQmx Read to have array size 100 and iterate twice a second, but no dice. Am I doing something obviously wrong?
Also - am I even close to using data queues sensibly? The LabVIEW example revolves around a waveform with dt data attached, so they pass around a brown "task", whereas I'm passing around an array of unsigned longs (which I imagine should be a pretty straightforward and appropriate use of queue structures?).
Many thanks in advance
P.S. I should point out that I am aware that a TDMS approach is probably the best approach here, but I'm interested in getting this master-slave/producer-consumer structure working first.
First of all, I want to congratulate you on doing an outstanding job of implementing the advice you were given. Your program is excellent. You have implemented the producer/consumer architecture very well, you are indeed using queues properly, and you are correctly performing a continuous acquisition. Very, very nice job. You should be proud of yourself.
Because I don't have your DAQ card here, I ran your code using a simulated board on my computer. (Did you know you can do that? If you're interested, we can start another thread or you can search "simulated DAQ device" on this forum to find out how to set that up -- it's super easy and it's a really handy way of testing your DAQ code without actually having any hardware.) Anyway, I had to make a couple of changes to the task setup:
- I replaced "PFI39" with "PFI15" since my simulated board has only 15PFI channels
- I replaced "ctr2InternalOuput" with "ctr1InternalOutput" since my simulated board only has 2 counters
- I changed the sample rate to 200 (your default is something like 100000!) and the #samples to 100 (the default was 1000)
After I did that, I ran your VI and it worked perfectly. The loops iterated twice per second, and both "Master Channel Volume" and "Slave Channel Volume" read 100, just as they were supposed to. I didn't write the code to read the datafile, but you are doing that properly also so I'm sure it's fine!
So your VI is working great for me. (small consolation, I imagine, but at least you know that there's nothing intrinsically wrong with the VI) Are you seeing any errors anywhere, specifically with the DAQ task? If so, what is the error code? Are you certain that there is a signal on your counter (i.e. do you have anything to read)?
I have one teeny-tiny criticism, and it's not even really criticism. It's generally considered a bad idea to have indicators inside of case structures, so you might want to move your "Slave Channel Volume" indicator (along with your "array size" function) outside the case structure.
There's nothing at all wrong with writing to a binary file, but certainly you can change to TDMS at some point if you want.
You have really done a great job and written a very good program. You should be proud of yourself. Do you know about probes and other debugging techniques? As I said, after I modified your DAQ channel to work with my simulated board, your VI worked perfectly, so that might be somewhere to start. By all means post back with more questions, we'll figure it out. Nicely done!