Jump to content
luiz.felipe

Shared Variable RT FIFO: Logging Application

Recommended Posts

Hello everyone,

I'm trying to make a data acquisition and logging application for a PXI-8133 with PXI-4300 analog voltage input module, using shared variable single process with RT-FIFO enabled, but I'm having some issues with that.

I'm using a determinist loop for data aquisition and other while loop for logging. But, my log file is losing data, sometimes part of the signal is lost, sometimes the buffer is larger than the amount of data and saves a sequence of zeros. I'm having difficulty adjusting the values for the fifo buffer.

Here are some questions:
1- Should I use single element or multi-element at FIFO type? I believe a multi-element allows me to have a buffer, right?
2.1- Points per waveform in RF-FIFO settings should be exactly equal to the size of the waveform read in each execution of the timed loop or can it be larger?
2.2- The number points in the waveform read in the timed loop keeps oscillating, depending on the sampling rate. Is it normal?
4- Should the logging loop run faster than the timed loop or at the same rate?

Thank-you !!

 

Capturar.JPG.e6d7d56fc2bcb83deffbbd9404ce7bda.JPG

Capturar2.JPG.18f388c9a8eba605acb96635dd258da7.JPGCapturar3.JPG.b5c176227c973fcdf36a8b2b16d6974e.JPG

 

Share this post


Link to post
Share on other sites

I'm not too familiar with the FIFOs so I can't answer those questions but I noticed your error handling is a little weak and doesn't capture errors while you're inside the loop.

Usually you want to run your timed loop at your control rate (some target rate you choose). It's a little less common to try and run it losslessly as you might trying to do. If you wanted to run losslessly, you could maybe set the loop time to 0 or maybe create a timing source from your task:

http://zone.ni.com/reference/en-XX/help/371361R-01/glang/create_timing_source/

Share this post


Link to post
Share on other sites

There is no need for the timed loop as the DAQ itself has a timing source. Just use a regular loop and ask the DAQ for a certain number of samples. This will accurately fix the loop rate.

Also, to get up and running just try using a regular queue. Although you need to be a bit more careful on RT there is no good reason they will not work unless you really need to get every last ounce of performance from the system. I have never been a fan of shared variables, too much "magic" going on behind the scenes for my liking.

Edited by Neil Pate

Share this post


Link to post
Share on other sites
On 5/8/2019 at 12:15 PM, Neil Pate said:

There is no need for the timed loop as the DAQ itself has a timing source. Just use a regular loop and ask the DAQ for a certain number of samples. This will accurately fix the loop rate.

Also, to get up and running just try using a regular queue. Although you need to be a bit more careful on RT there is no good reason they will not work unless you really need to get every last ounce of performance from the system. I have never been a fan of shared variables, too much "magic" going on behind the scenes for my liking.

To go further, the timed loop is the not the right choice, and the RT FIFO has a negative performance impact on this application.

The data source (daqmx) is nondeterministic, the data client (tdms) is nondeterministic, so using an RT FIFO as I understand it will result in performing a memory copy on every iteration to copy from the (newly allocated and thus non-deterministic) daqmx buffer to the preallocated RT FIFO buffer. In contrast a normal queue (again as I understand) will simply shuffle around a pointer to the buffer provided by daqmx*. No allocation past the one performed by daqmx and a minor one to allocate the queue structure.

By using a timed loop you're forcing everything to run in a single thread, so if you add any additional code later into the daqmx loop, it would have to run in series with the daqmx api reads. You're also telling the RT OS that the HIGHEST priority loop/thread in your entire codebase is something which immediately hits an asynchronous call and waits for that call to return.

*I think technically its passing around a struct with an inline timestamp and dt, and then a variant pointer and an array pointer, but you get the idea.

 

On 5/8/2019 at 9:12 AM, luiz.felipe said:

2.2- The number points in the waveform read in the timed loop keeps oscillating, depending on the sampling rate. Is it normal?

4- Should the logging loop run faster than the timed loop or at the same rate?

2.2: you can make it fixed by passing in a samples to read per channel input on the daqmx read VI. The default is -1, which tells the driver to return whatever is available but don't wait for new data.

4 By definition the two loops have to run at the same rate...on average. As shown (a kind of producer-consumer implementation), you really want the daqmx loop to be driving the logger loop, which is easy to do with a fifo or queue -- you pass in -1 for the timeout, and as data arrives the bottom loop will run. As you have it, the tdms loop is simply running every 5 ms.

Instead of a queue or shared variable, you can also use channel wires which are intended to make data communication a bit more user friendly. They even have an RT FIFO option if you ever do need that: https://www.ni.com/product-documentation/53423/en/

Edited by smithd

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.