Showing results for 
Search instead for 
Did you mean: 

Clock Rates and Periodic Data Logging

Hey all,


I'm having some trouble in programming LabView. My overall project goal is to drive a piezoelectric using a high voltage, high speed amplifier. The amp is driven by a function generator, and has a gain of 200:1. I am driving at about 5000 Hz and reading displacement with a Keyence LK-G 30. The piezo is good for approximately 10^9 cycles. My DAQ is a USB-6221.


To summarize, what I need from Labview is:


  • One high priority voltage reading of a laser displacement sensor where 1V = 0.5 mm. This will be running at 10kHz.
  • Two lower priority voltage readings. A voltage monitor (1V = 200V high voltage output) and a curent monitor (1V = 10mA output).
  • A cycle counter, currently hooked to the TTL sync on my function generator.
  • A digital TTL level output to act as a remote enable. High disables the amp, low enables the amp.
  • Front panel monitoring of cycles and voltage. Low priority, mostly for my benefit as a researcher.
  • Log Data. Primarily I would like Time, Cycles and Displacement. I don't need everything, I just need enough data to show that a displacement trend exists or doesn't in the lifetime response of the piezo.
  • Failure criteria. At this point I know there are fluctuations in the voltage and current when the piezo fails as a result of changing load. When the piezo fails I would like to send an off signal to the amp.

I have taken a couple stabs at this, but I think I need help. From what I have read on the forums thus far, I understand that parallel loops with producer/consumer structures would be great. However I have no expierence in their implementation in labview. I also am having trouble understanding what I want my timing structrues to be. In my mind, I want continuous samples at a rate that satisfies the nyquist condition, but I keep running into buffer issues..


I'm attaching my latest stab at this thing. There is no data logging, no front panel indicators, or falure criteria programmed in this VI yet.


Thanks in advance for your help.



0 Kudos
Message 1 of 18

One of your biggest issues appears to be a lack of understanding of dataflow.  Everything to the left of the while loops and the case structure will execute first.  That is probably what you want.  Then the Analog read will run until you hit stop (although you are not doing anything with the data). After stopping, the count loop will run exactly one time.  Why? Because the value wired to the stop terminal is True when the data enters the loop.  After reading the counter once the case structure will execute the True state exactly once, setting the amplifier to its disabled state.  Of course it never was enabled.


You probably only need one loop, although producer/consumer has more flexibility for the future.  Look at a state machine. All the initialization stuff to the left of the loops could go into an Initialize state (or perhaps a state each for AI, CI, and DO initializations). One state to read AI. One state to read the counter, one state to write to the amplifire enable. One state to monitor cycle counts and failure criteria. A state for display and logging. A state for shutting down and clearing the DAQ tasks.  You can add states for error handling or anything else which comes along later.


To set your priorities you just go to certain states more often.  Make sure that no state contains any activity which will take longer than the minimum time you can wait to repeat the highest priority task.  If some states such as saving to file might take too long, move thoses tasks to a parallel loop which can run at a slower rate.  If this situation occurs, something like producer/consumer becomes essential.



0 Kudos
Message 2 of 18

Hi Lynn,


Thanks for the response. You are correct that I am still working to understand the data flow. I thought that as programmed that the three loops were indeed parallel loops because they had independent timings. I'll take your word that they are not though.


I grasp the state machine concept, but I don't necessarily understand the timing between states. Will functions operate in the background or does only the active state function? For example, if I want to log one minute of data every hour, do the other states pause or do they continute to function for that minute? I obviously would not want to lose track of my cycles.


Thanks for your time,


0 Kudos
Message 3 of 18



The reason your loops are not parallel is that an output from one is an input to the next, specifically the stop boolean.  To see how this works use Highlight Execution (the Light Bulb icon on the block diagram toolbar).  It might be more convenient to make a little test VI without all the DAQ stuff for observing dataflow.  Replace your Read VIs with the Random Number function (dice on Numeric palette) and create indicators so you can see when things change. I just used Diagram Disable on your VI to show this. 


WARNING: Attached VI is set for Highlight Execution. It will run very slowly.


State timing: If you have only one loop with a case structure inside to implement a state machine, then only one state will execute at a time.  With parallel loops like the producer/consumer the loops operate independently.  Regarding your example of logging one minute of data every hour: If you Read 1000 samples from a DAQ device sampling at 10 kHz, you get about 10 readings per second.  If you accumulate 600000 samples over that minute, then write them all to file at once, you do not need to delay acquistion while writing (unless the file operation takes more than 100 ms, which is certainly possible as the file grows). Again, putting the file write operation in a parallel loop avoids the issue.





Message 4 of 18

Hey Lynn,


Thanks for outlining the flaws in my thinking. Its quite helpful. I am now examining the Producer/Consumer Template and I'm getting a little inspired. 😄


How does this sound for archetecture,

  1. Start with a State Machine.
  2. Initialize my DAQ I/O stuff in one state
  3. Move on to a new state with a producer/consumer setup.
    1. In the producer loop have my AI Read, CI Read, and DO Write, and a Write to file in the consumer loop.
    2. I beleieve the producer loop would be where I would want to have a conditional check for my failure critera, which would allow the last producer/consumer loops to run and then move the state machine to a shut down phase.

I am sure I will have questions on the queue opperations, but I will research those and build the outlined VI for the time being and come back when I have something new.


Please let me know if the outline I have is sound. Again, thank you so much for your guidance thus far.



0 Kudos
Message 5 of 18



Almost.  You are making a lot of progress in a short amount of time.


The producer/consumer is not inside the state machine. One or both of the loops may be state machines themselves, but you probably do not want to embed that level of complexity inside a state.  Generally each state should perform a well defined task or subtask.  Each state also determines which state will execute next based on the current state and the values of the data available in that state.  In some cases the next state will be the same state.


In LV a state machine is typically implemented as a while loop containing a case structure.  Each case of the case structure contains the code for one state. The case selector is the state identifier and is often a typedefed enum.


The way I would approach the architecture for your system (as I understand it) is the have the producer handle all the DAQ.  It would be a state machine  with state(s) to initialize each of the DAQ tasks. One state each for AI Read, CI Read, and AO Write. The data would be passed to the consumer via one or more queues.  Similarly, the data to be written by the AO Write would come from the consumer via another queue.  {OK. At this point the terms producer and consumer start to get confused because the "consumer" is producing data to be consumed by the "producer" in the AO Write mode!} The producer would also have a shutdown state where all the DAQ tasks are cleared.


The Consumer loop could also be a state machine. It would have states for initalizing all indicators, for opening or creating files, for retrieving the raw data from the queues and processing it, for updating displays, for saving to files, for analyzing data for failure checks, for generating data and sending it to the producer for AO Write, and for shutting down.


My preference is for the DAQ loop (producer) to do absolutely no analysis of the data.  As soon as you say, "I am just going to do this one check...," you begin to lose control of where analysis and decision making takes place.  Then you end up in the same kind of situation where the non-DAQ stuff starts taking too much time and you lose data.


If the process is such that extremely rapid decision making is necessary to avoid hazardous events or excessively expensive consequences, then you should be making those decisions in hardware or with a carefully designed real-time system.



Message 6 of 18



So I made some progress, and I read the stuff you laid out in the post, "NI-DAQ continuous logging while measuring frequency," but I guess I still need some help on building an array from my Voltage and Counter inputs.To be fair, I assume that I need to build a 2-D array and add the "two" signals together. I say two signals, but I mean 3 AI signals and the 1 CI signal.


A question I have then is if I need to build and initialize an array, that I don't know how fast I can run labview timings. My USB-6221 will run 250,000 Samples per second (I believe that is per channel). So am I running 5 channels total? My piezo is running ~5kHz, and my Laser is running at 10kHz to satisfy nyquist. Like I said, I am happy to collect bursts of data, and even averaged data (since I really only care about trends in displacement and electrical characteristics) periodically as long as I can be assured that I am not aliasing my data. Will my DAQ support those speeds?


I've attached what I have so far. Thanks for your help!

Download All
0 Kudos
Message 7 of 18

Since you have a 2D array of analog signals and a single scalar from the counter it might make more sense to use a cluster containing a 2D array of numerics and one numeric. Put that on the queue.  Use Bundle by Name in the producer and Unbundle by Name in the consumer.  See images below for how this can work.


I never saw anyone initialize an array with a size of -1 before. The detailed help does not describe that situation, so I tried it.  It produces an empty array.  You probably want to set the array size to match the array produced by the Analog Read.


You do not appear to set the analog read timing.  I have no idea what the default value is, although it may be 1000 samples per second.  You have also left the number of samples per channel on the Analog Read set to the default of -1, which causes it to read all the available samples.  I am not sure what you want so I can only make general suggestions.  First, put the appropriate DAQmx Timing VI in the Initialization state. Set the sampling rate. Then specify the number of samples you want to read on each iteration of the loop. Use that value to initialize the array. If you use the cluster approach I suggested above, you will not need any array manipulations. Just Bundle and Enqueue.


When you set the sample rate and then specify a finite number of samples to read, that will determine the timing.  You just need to make sure you can read all the samples before any buffer on the DAQ board overflows.




Cluster.png  Cluster in queue.png


Message 8 of 18

Hey Lynn,


Thanks again for your awesome feedback. I was able to try running this VI on the hardware today. So far reading the data is going well, in the time spans I ran the program I didn't see any glaring errors. However, I'm getting a bit lost in the woods writing the data to a file.


I added some TDMS stuff from the built in example, and it worked for the most part. I obviously want all the data to come together in one file, but I am not sure where to combine that data. The Cluster stuff worked well for transfering the data between loops, but I feel like I should be building an array in the producer loop that will be simple to write to a file. As it stands I can deliver content to the consumer loop but then what?


In addition to the write stuff, I changed the enqueue to a lossy enqueue because I don't care about the data I didn't collect, just the data happening during the "writing window" I specify. I figured I could play with the max queue size to get the results I want. Does that seem logical?


I know I'm close but I guess I'm not quite there yet.I attached the latest. I took out most of the graphs/indicators/probes.


Thanks again, I'm sure its not easy to look at someone elses VI and provide feedback like this.



PS Do you care what version of LV the VI is saved as?



0 Kudos
Message 9 of 18

Whoops, wrong version. This is the latest

0 Kudos
Message 10 of 18