LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Continuous filtering in a loop

Solved!
Go to solution

I'm developing an application that continuously measures voltage on an arbitrary number of DAQmx channels. I want to low-pass filter the readings before logging & displaying the data.

 

Since the number of channels can change at runtime, I plan to process the waveform data in a loop. That means I can't use the (stateful) Butterworth Filter PtByPt.vi. But even the regular Butterworth Filter.vi is stateful. It has an init/cont flag, and stores state in a shift register. The init/cont flag gets passed all the way down into lvanlys.dll (IIR_Filter2), suggesting that even the underlying C library is stateful!

OneOfTheDans_0-1639507829264.png

 

There's a feature request from 2012 describing this problem: Stateless Mathematics and Signal Processing VIs

 

Am I misinterpreting the VIs? Does anyone have have experience working around this limitation? I'd really prefer using an known library rather than re-implementing filters with math primitives.

0 Kudos
Message 1 of 7
(3,993 Views)

The signal processing palette includes filtering functions that accept an array of waveforms.  Internally, they hold separate state information for each waveform in the array so you don't get the kind of "contamination" that concerns you.  You can dive down into them to see how it's done -- using various off-palette helper functions.  Basically, the filter's internal state is stored in in a kind of higher-level "wrapper" function which calls the core stateless low-level function that performs the filter math.

 

There are actually quite a few different available approaches to filtering within the palettes.  Also be sure to right-click the functions and look for even more "polymorphic" options if there's an option to "Select Type" in the context menu.

 

If you get your data from a DAQ device, use the version of DAQmx Read that puts the data into a 1D array of waveforms (each containing a 1D array of sample data) instead of directly reading a 2D array of sample data that carries no timing information along with it.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 2 of 7
(3,960 Views)

@OneOfTheDans wrote:

I'm developing an application that continuously measures voltage on an arbitrary number of DAQmx channels. I want to low-pass filter the readings before logging & displaying the data.

 

Since the number of channels can change at runtime, I plan to process the waveform data in a loop. That means I can't use the (stateful) Butterworth Filter PtByPt.vi. But even the regular Butterworth Filter.vi is stateful. It has an init/cont flag, and stores state in a shift register. The init/cont flag gets passed all the way down into lvanlys.dll (IIR_Filter2), suggesting that even the underlying C library is stateful!

OneOfTheDans_0-1639507829264.png

 

There's a feature request from 2012 describing this problem: Stateless Mathematics and Signal Processing VIs

 

Am I misinterpreting the VIs? Does anyone have have experience working around this limitation? I'd really prefer using an known library rather than re-implementing filters with math primitives.


I had this problem before. The solution is to use a unique filter for each channel. (Can't post the VI due to company limitations, but can post screenshots)

 

The first thing I do is open a bunch of filter primitives dynamically and create a "Reference" for each filter, see below

Create a reference for the filter primitiveCreate a reference for the filter primitive

Then I use that filter reference for each channel with a dynamic call, see below. Note In the screenshot below, I have some feedback nodes. Those nodes are there in case the user changes the filter somehow and I want to reset it. By using the same filter reference for each channel the "history/state" is preserved correctly.

Call the filter dynamically. You can even do it in parallel!Call the filter dynamically. You can even do it in parallel!

Lastly, when your program is finished be sure to close the filter references. See below.

Close the references to avoid a memory leak.Close the references to avoid a memory leak.

 

Message 3 of 7
(3,953 Views)

@OneOfTheDans wrote:

I'm developing an application that continuously measures voltage on an arbitrary number of DAQmx channels.


Can you a bit more specific on the "arbitrary" number? Is there a relatively small upper limit or can it be gigantic? If the number is not too large, you could use a parallel FOR loop with sufficient parallel instances

0 Kudos
Message 4 of 7
(3,945 Views)

@altenbach wrote:

@OneOfTheDans wrote:

I'm developing an application that continuously measures voltage on an arbitrary number of DAQmx channels.


Can you a bit more specific on the "arbitrary" number? Is there a relatively small upper limit or can it be gigantic? If the number is not too large, you could use a parallel FOR loop with sufficient parallel instances


This becomes problematic if running continuously because of the state information for the filter. The filter is either resetting or you may use the previous state from a different channel. This important for the OP because he wants to save the filtered data.

 

By creating specific instances of the filter that you can reference, you can keep state information, even when running in parallel. 

 

0 Kudos
Message 5 of 7
(3,943 Views)
Solution
Accepted by topic author OneOfTheDans

Unless you really *need* For Loop parallelism, it'll be easier to use the available waveform filter functions.  Like this:

filter waveforms.png

 

Note: I'm assuming a pretty normal DAQ application where the user may specify a fairly arbitrary # channels to collect, but once they start running, that # stays constant throughout that particular run.  DAQmx won't allow the # channels in a task to vary during a given run anyway.

 

Further note: I've illustrated the case where all channels are filtered according to the same filter specs (though each will retain its own unique state information).  There's a different polymorphic instance that allows you to define unique filter specs for each channel.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 6 of 7
(3,915 Views)

Thanks for the great responses everyone!

 

@altenbach wrote:

Can you a bit more specific on the "arbitrary" number? Is there a relatively small upper limit or can it be gigantic? If the number is not too large, you could use a parallel FOR loop with sufficient parallel instances


Yes, I could reasonably bound it as 2-64. As mentioned, I think the parallel for loop wouldn't work, but I could build a giant subVI that indexes my array to 64 manually-dropped instances. It's a good work around, but I'd rather avoid building & maintaining that.

 

 


@mcduff wrote:
OneOfTheDans_0-1639577923539.png 

I love this solution, thanks for sharing! It also means you can use a different type of filter for some of the channels, if needed.

 

 


@Kevin_Price wrote:

filter waveforms.png


This is exactly what I was looking for, thank you! I'm already taking a 1D WFM from DAQmx. I missed this VI in the palette, and went down looking at the specific Butterworth filters, and their core VIs, which don't support N chans. But this is perfect for my application.

 

Thanks again!

0 Kudos
Message 7 of 7
(3,902 Views)