LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchronizing Angular Position Across Multiple Sample Rates; Best Practices.

Background:

Haven’t used Labview in 15 years. I’m coming from exclusively using Simulink on a daily basis for the past 10.

 

I want Read, record, and display from several different NI cards at different sample rates (per card, analog and digital) with a time channel per TDMS group and align angular position to the highest speed input capture.

 

For a TL:DR, please jump to the bottom for the questions

 

My current hardware is as follows:

 

Chassis: cDAQ-9189, connected to my PC via Ethernet.

 

Cards:

NI 9862 (CAN)

NI 9203 (Pressure Sensors 1000Hz)

NI 9401 (Digital Encoder for angular position – 51200Hz, should be synced when Accelerometers are sampled)

NI 9213 (Thermocouples – 10Hz)

NI 9220 (Accelerometers and Mics– 51200Hz)

NI 9234 (Mics – 51200Hz)

NI 9231 (Accelerometers – 51200Hz)

 

 

Current Status:

I can record all of the following information at the rates I want except for the angular position (and CAN but that only exists in a separate VI I haven’t attempted to incorporate yet) into a TDMS file.

 

For all the analog inputs, first I create the task for each of the different cards I listed above and specify the necessary signal names and units as needed. From there I am run the tasks into their own sample clock per each unique sample rate using “Continuous Samples” and then onto the “Start Task VI”. I do not specify a clock.

 

I noticed that doing this, using the “Continuous Samples”, that the while loop it feeds into is completed every 1 second (A display is hooked up to the “i” in the bottom). Is that normal? If I set the clock to HW Timed Single Point, the loop counter goes as fast as I would expect (51.2KHz? Not sure, but fast).

 

I then run the each of the 3 tasks (3 Sample Clocks) into a Consumer / Producer style of structure. From the “Producer Loop”  I “Read” the tasks as “Analog 1d Waveform, N Channels, N Samples” and I specify the number of samples per channel for each, (10, 1000, and 51200). After they have been read in the producer loop, I run the data output into an “Enqueue Element” and move that into a shift register.

 

Note there is no “wait” block in the producer loop. Should there be? As noted above, it seems to execute very slowly already, ~1Hz

 

Back, outside of the producer loop, the queue is initialized into the number of queues and their appropriate labels and a datatype is given and these queues are passed back into the producer loop via the original shift register.

 

Theses qeueus also enter the “Consumer Loop” as well. The queues enter, and then a “Dequeue Element” block is used to extract the data from the queue for data logging and display purposes. I also create a timer channel in the consumer loop with “Get Date / Time”

 

Within this consumer loop, the time array and the 1D Array Waveforms(DBL) and feed them into a T/F case structure for enabling and disabling the TDMS recording. All the data goes into one single TDMS file.

 

Questions and Problems:

Is this even close to the right way to go about doing things?

 

Sample Clock for Analog Inputs:

  • Should it be continuous?
  • Should “Samples Per Channel” be 2x “Rate”?
  • Should I specify a “source”?

 

Producer Loop:

  • Is it normal for it to run at ~1Hz according to the iteration counter?
  • Should I have a “wait” block in there set to the fastest sample rate I have (51200Hz)?

 

Consumer Loop:

  • Should I have a “wait” block in there set to ~10Hz
    • Will that mess up my TDMS write blocks?
  • Currently, if I put a chart in the Consumer Loop for any of the high speed signals (51200Hz), it get a memory issue after 5 minutes. I can see the memory usage in Task Manager continue to count up until ~4GB and then Labview has an error. Typically it sits around 120MB. The lower sample rate (10Hz and 1000Hz) signals, a chart works just fine.

Datatypes:

  • I’m not sure if I’m doing this right, coming from a Simulink background it was much easier for me to visualize or fix mismatched datatypes than in LabVIEW. Perhaps I’m just overlooking something or what, but this has always been a missing piece to the puzzle for me.

 

Angular Position Problems:

Using DAQ assist to create the “DAQ Assist” feature, I can create a task that outputs angular position (0-360, on A & B Low, Z channel, 1440P/Rev) and I then “Generate Code” for it so that it fits better in my model.

 

I’m not sure what I should use for Acquisition Mode (On Demand, HW Timed, N Sample, or Continuous) but I do know that I want to save the position every time I one of the accelerometers (51200Hz). Basically I want sync / align the accelerometer output with the given position during that reading.

 

Further, I don’t know how to incorporate that in to my producer / consumer loop.

 

Attached is the VI (and subVI for the encoder start task) for everything that I described above. Please advise.

 

0 Kudos
Message 1 of 7
(192 Views)

I dont know what happened to my attachment on the original post (Perhaps that's why it was flagged for SPAM automatically?) but I've reattached them here.

Download All
0 Kudos
Message 2 of 7
(175 Views)

Thanks for the very thorough write up.  Here are a few comments:

 


Questions and Problems:

Is this even close to the right way to go about doing things?

Yes, it's at least pretty close.  A very good start.

 

Sample Clock for Analog Inputs:

  • Should it be continuous?
  • Should “Samples Per Channel” be 2x “Rate”?
  • Should I specify a “source”?

Continuous - Yes.  2x Rate - No.  Source - No.   Reasons:

- your producer/consumer structure strongly implies that you should configured for Continuous Sampling

- the 'Samples per Channel' input for DAQmx Timing has an unintuitive behavior when you configure for Continuous Sampling.  The task will make a buffer that's no smaller than the value you wire, but it could also be significantly bigger.  In fairness, exact buffer size isn't really critical for Continuous Sampling, all that should matter is "big enough."   Your 2x multiplier means that your buffers will be sized to hold *at least* 2 seconds worth of samples.

- when unwired, DAQmx uses an available internal source by default.  The 'Source' input is mainly important when you want to use some other signal to drive sampling

 

Producer Loop:

  • Is it normal for it to run at ~1Hz according to the iteration counter?
  • Should I have a “wait” block in there set to the fastest sample rate I have (51200Hz)?

- The speed of the producer loop is (and should be) predominantly driven by the # of samples you read per iteration.  You're requesting the same # as your sample rate, which is 1 second worth. That's why you iterate at 1 Hz.   A general rule of thumb is to read 0.1 sec worth of samples or more per iteration.  A lot of the problems here come from people trying to read 1 sample at a time from a multi-kHz task.  Not a good plan.

- No, don't use a "wait" function.  Similar behavior is built into the DAQmx driver.  When you ask for 1 sec worth of samples, the function call will wait until there's 1 second worth available.

 

Consumer Loop:

  • Should I have a “wait” block in there set to ~10Hz
    • Will that mess up my TDMS write blocks?

Again, no "wait" function.  The Dequeue functions have this behavior built in, waiting until a new block of samples is available after being enqueued by the producer loop.

 

  • Currently, if I put a chart in the Consumer Loop for any of the high speed signals (51200Hz), it get a memory issue after 5 minutes.

Are you sure it's a chart?  This sounds more like the behavior of a graph where you keep trying to redraw the entire growing history each iteration.

 

Datatypes:

  • I’m not sure if I’m doing this right, coming from a Simulink background it was much easier for me to visualize or fix mismatched datatypes than in LabVIEW.

Datatypes seem mostly ok.  Watch for the red coercion dots though.  They're often a clue that you need to match datatypes up more explicitly.  (Example: your 1D array of counter data getting coerced into a waveform type in the producer loop.)

 

Angular Position Problems:

I’m not sure what I should use for Acquisition Mode (On Demand, HW Timed, N Sample, or Continuous) but I do know that I want to save the position every time I one of the accelerometers (51200Hz). Basically I want sync / align the accelerometer output with the given position during that reading.

Caveat: I've only used cDAQ occasionally and my knowledge is limited.  You should definitely *want* to do Continuous sampling here, but I'm not sure if you can.  You've already used up 3 timing engines from your chassis for the 3 AI tasks, and the docs I could find aren't utterly clear about whether you can also do hardware-timed sampling for a counter task.  You'll have to try it.

    You might end up needing to query the Accelerometer task for its sample clock signal and then wire it into the Encoder task's 'Source' input for DAQmx Timing.  And you might need to perform a "reserve" or "commit" on the Accelerometer task first, to force DAQmx to make a decision about which timing engine it will use for that particular AI task.

    Another possible approach is try to use channel expansion for at least 2 of your AI tasks to preserve one of the timing engines in hopes that the Encoder task can use it.

 

 

-Kevin P

Message 3 of 7
(132 Views)

Just bumping to subscribe and get the thread on my recent list.

 

Well said Mr. Price!

 

About the only thing I could add is too point out that the timing engines available on a cDAQ chassis are limited.   Sometimes,  it is best to add a second or third chassis even if you have "Spare" slots! Just to get the right timing sources to the right DAQmx tasks. 

 

In your case the CAN, Thermocouple and pressure tasks really SHOULD be in a low speed Chassis that allows you to have a dedicated high speed chassis for the Acceleration etc.. 

Scientists STAND on the shoulders of giants! They don't ride "piggyback" to keep their heads down.

"Should be" isn't "Is" -Jay
0 Kudos
Message 4 of 7
(126 Views)

Thank you, both of you. 

 

I ended up leaving the encoder logic inside the "DAQ Assist" function and making a separate "Producer Loop" called "Digital Producer" and the other producer loop "Analog Producer". I was also able to use the timer for the high speed sampling hardware to drive the DAQ assist function and now I'm sampling at 51200hz.

 

Somewhat annoying is that the "increment" in the TDMS file for the encoder is "1" instead of 0.00002. Minor, but it would be nice if it were 0.00002

0 Kudos
Message 5 of 7
(67 Views)

@AMAGIS wrote:

Thank you, both of you. 


Thank you's are not necessary, although,  "Kudos" say thank you AND help others find posts with relevant advice .  There is a button for that!  Kevin's post deserves more than 1.  I'll have to go back and tag it too so I can find it again!

 

Somewhat annoying is that the "increment" in the TDMS file for the encoder is "1" instead of 0.00002. Minor, but it would be nice if it were 0.00002


That sounds like either a scaling issue or, a wrong float to string back to float from LabVIEW to TDMS to Excel (& note,LabVIEW and Excel do not have the same floating point exactness) can you elucidate?  That specific annoyance should be questioned for understanding. 

Scientists STAND on the shoulders of giants! They don't ride "piggyback" to keep their heads down.

"Should be" isn't "Is" -Jay
0 Kudos
Message 6 of 7
(42 Views)

1. Let me correct an earlier oversight.  Though you found *a* way to get hw-clocked sampling for your encoder, it probably isn't the best way.  Just trust me here for a minute.  It'll be better to have the Encoder task borrow the Accelerometer's task sample clock signal and then to start the Encoder task before the Accel task.

 

2. None of the DAQmx Read options for counter tasks allow direct reading of a waveform.  (This is probably due to a long history where counter tasks can't derive their own sample clocks from known internal timebases and also the fact that implicit timing tasks are conceptually incompatible with the waveform type.) 

    You'll have to sync the Accel and Enc tasks (the advice in #1 will accomplish that).  Then you can use the Accel task waveform timing info to construct an appropriate Encoder waveform that includes correct timing info. 

 

I whipped up an INCOMPLETE example to illustrate how to do *only* these specific things.  You'll have to cut and paste parts of this to fit in with your other config, reading, and logging code.  (Not shown: eventually you'll also want to change one or two built-in waveform attributes about the channel in question).

 

 

-Kevin P

 

encoder in waveform.png

0 Kudos
Message 7 of 7
(31 Views)