Multifunction DAQ

Showing results for 
Search instead for 
Did you mean: 

Help with triggering and sampling rate on USB-6341 DAQ

Go to solution

I am working on a LabVIEW program which uses the USB-6341 DAQ to control a motor-controller mirror. LabVIEW sends the X/Y positions for the mirror through the DAQ, and then reads them back. All signals are analog.


I am using a trigger signal to tell the mirror when to read and write. It is a fixed 2ms signal with a 48ms delay (50ms cycle). I am writing ten positions total. I want to write the mirror position on the falling edge of the first trigger signal, and read the mirror position on the rising edge of the following trigger (or at any point between). If the mirror is not in the expected position, I terminate the program immediately. See picture for details


However, the USB-6341 does not allow for me to use hardware-timed triggering on multiple channels while also doing computational work in between each read and write. I found this article on hardware-time single point triggering that says USB DAQ devices don't have this capability:


So, in order to incorporate all of the functionality I need, I wired the trigger signal to a digital input and configured my VI to write the position, wait for the trigger to change, then read. See below picture for this configuration:


However, the DAQ is too slow to run at 20 Hz (50ms cycles) and misses every other trigger signal. I can run at 10 Hz but at 20 Hz, the DAQ does not finish its tasks quick enough. Note that in the above VI, all of the actions are happening in the FOR loop. I left out the processing of data for simplicity.


What I want to happen is the below VI. But, the USB-6341 will give an error when trying to configure a port with only 1 sample per channel when using a hardware-timed trigger (see link above). I can do multiple write and reads, but not 1. Thus I cannot check to make sure the mirror is in the correct position after each write in the time I want.


I am considering other options to get this working at 20 Hz. I'm looking to get the PXIe-6341 which will allow hardware-time single triggers, but I am running on a laptop and a PXI chassis is too big for my project.


I'm pretty deep into this project. Any insight, advice, or otherwise is greatly appreciated. I'm also open to a non-NI piece of hardware but I've no clue what to get, and don't want to risk not having the full support of NI.


Thank you!


**edit: Just noticed in the last picture, "rising" and "falling" should be swapped.

0 Kudos
Message 1 of 12
Accepted by topic author ianscandela

1 word = 1 milli-picture.  My thousand words are mostly in the attachments.


I think the following is a better starting point but there's an awful lot of details that I can't exhaustively explain in text.  


- Disconnect from hardware before running the attached code. 

- Note that the 20 Hz pulses are treated as "sample clock" cycles rather than "triggers".   

- Adjust the array of AO voltage values as needed.  Note that the AI channels are special ones that measure the AO channels internally.

- despite appearances, very little of what you see is arbitrary or haphazard especially as it relates to the specific DAQmx function calls and the dataflow sequencing that drives them.

- this ran successfully on a desktop PCIe-6341 board.



-Kevin P


AO AI sync with real time evaluation.png

Message 2 of 12

Thank you so much for your time and effort - I wanted to reply just to say I'm still working to get this going. I have it running on my pc but need to wait for lab space to clear up to do the final test.


You're right in that your VI seems complicated to explain. I am doing my best to figure out the logic you used and why it works. I think the most complicated part is the clock setup, which you seem to have a deep understanding of.


*Crossing my fingers that this works with my USB-6341 - will let you know!

0 Kudos
Message 3 of 12

Go ahead and ask any specific questions you're trying to puzzle out.  I just can't try to anticipate and exhaustively explain all *possible* questions.  Let me start with brief explanations of 3 things:

  1. CO "commit" action - the commit action forces the counter output into its idle state.  Without it, you might get an unexpected extra transition when starting the CO task.
  2. Sequence frame - used to make sure both AO & DO tasks are started and therefore ready for sample clock signals before the CO task starts generating them.
  3. Available samples per channel query - this is used to confirm that your software loop is keeping up with the hardware sample rate.  The code only reads 1 sample per loop iteration.  If there are any samples remaining in the buffer after the read it means the software is lagging behind.  I treated it as a condition that would terminate the software loop early.


- Kevin P

0 Kudos
Message 4 of 12

Thanks Kevin, I understand most of the structure. My one question is regarding the purpose of setting up another trigger source on top of using PFI0.


What exactly is this supposed to accomplish? It seems that you are creating a digital signal to replicate the hardware trigger. It seems redundant to me.


I tried running using this method and was not successful. However, when I removed this feature and write/read using the hardware trigger, it did run the correct amount of movements and reads. However, it would always miss the first 3 readings, and ran successfully for the rest of the loops.


I attached my complete VI to help with explanation. The "Move and Check" case is the setup you provided. "Move and Check 3" is the same without the manual pulse generation. "Move and Check 3" provided me with the following data on 10 movements:



Note that I'm watching the read and write voltages on a scope and they are all correct - but the DAQ is not reading the first three positions.


Sorry for the messy code - I'm working on a remote laptop.


I really appreciate your quick replies!


Another note: I do need to be able to operate on a range of frequencies from 0.5 Hz to 20 Hz, and do not want to have to change any values on the GUI - it should react to the PFI0 hardware trigger automatically, up to a max of 20 Hz. When I set the "freq" value to 20 Hz, my program runs correctly at all slower frequencies as well, using the "Move and Check 3" method.

0 Kudos
Message 5 of 12

When I change the ai to read channels "ai2:1" I do get readings for each movement, though the values are 1/2 of what I expect. I am okay with that, though.

0 Kudos
Message 6 of 12

It seems the max reading that the analog input can read is ~5.38V. Not sure why... the datasheet says "Input range ±0.2 V, ±1 V, ±5 V, ±10 V" which is a bit confusing.

0 Kudos
Message 7 of 12

Re: the "extra" counter task

   I misunderstood.  Back in the original post, you said "I am using a trigger signal to tell the mirror when to read and write."  That sounded to me like your were in control of *generating* this signal.

   The sync scheme I posted *depends* on carefully sequencing when AO and AI tasks start relative to when the pulse signal starts.  If the pulse signal is external and free running, i.e., If you can't be sure that AO and AI tasks are started *before* any pulses are present at PFI0, then you can't be sure the tasks will be in sync.


I'm not able to look at your code now so I can't really interpret what's wrong about the data in the front panel screencap.  I can only guess it's related to the sync issue I mentioned in the last paragraph.


Here's a method to re-guarantee sync without the CO task.

  • Configure AO to be triggered by the rising edge of the external pulse while using the falling edge as a sample clock.
  • AI should be triggered by the terminal signal "/Dev1/ao/SampleClock" while using the rising edge of the external pulse as a sample clock. 
  • The AI task needs to be started *before* the AO task.

This combo will satisfy the timing diagram you showed in msg #1.  AI is started first, but external pulses won't cause any samples to be taken until AI gets triggered by AO.  Later, AO starts and gets triggered by the next pulse rising edge.  AI still doesn't take a sample because it still hasn't been triggered.  The pulse's next falling edge will cause AO to generate its 1st sample, and this sample clock signal will in turn trigger AI.  Then the 1st AI sample will be taken on the *next* pulse rising edge.



-Kevin P

0 Kudos
Message 8 of 12

Thanks so much for your help. I didn't know there was so many options for clock and trigger manipulation with the DAQmx package.


In case you're curious, here is the final code I ended up with, which works for all frequencies up to 20 Hz. I didn't have to use the trigger function at all: 


0 Kudos
Message 9 of 12

While the code looks simpler without triggering, it carries a subtle sync problem.


Your original timing diagram showed a falling edge AO sample happening first, then some idle time, then a rising edge AI sample.  Your code will *usually* (but not always) produce an AI sample first before the first AO sample is generated.


It just depends when you happen to start your program relative to the phasing of the external pulse signal.  With a 2 msec pulse time and 50+ msec total period, you've got a minimum 96% likelihood of starting during the idle time and having the AI sample come first before AO.

   Further, it's possible that the AI task is started just in time for the rising edge but that the AO task starts just a little too late to catch the subsequent falling edge.  So the 1st AO sample may not occur until after the 2nd AI sample.


I recommend you add the triggering I described earlier.  You'll then be assured of getting the sync and correlation you're aiming for.



-Kevin P

0 Kudos
Message 10 of 12