LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Moving Average VI without using an array.

Hi all,

I am using a VI to calculate a simple moving average. I have attached the same below.

Satvikpai_1-1729012081680.png

 

I have to build a VI to average 20 parameters. 20 parameters will take 20 counters and 20 arrays which might slower the computing power, consume a lot of development space and eventually slower the VI as my loop time is 1ms.

 

Is there any other way to implement a single moving average where we avoid using an array and thus reduce the computing power as we don't remember all the datapoints in the array.

 

As I am acquainted with C, I am thinking of using a single variable which keeps on adding n samples to itself until the counter reaches n. This way we don't have to store multiple datapoints in an array. Every next datapoint will be added to the variable which can then be linked to a summation block to calculate the average.

 

Thanks for the reply in advance.

 

0 Kudos
Message 1 of 7
(433 Views)

One way to implement is a similar solution as you proposed, using a non-initialized Shift register. 

On first Iteration, the innitialize array creates an array with fixed number (5 on this example), 

LVNinja_0-1729013838810.png

Then on the next iterations, use replace array having the index coming from the reminder of the quotient of the iteration by 5. This way you allocate fixed memory for the array and keep reusing at every new data by replacing their content. Calculate average at every iteration 

LVNinja_2-1729013937074.png

If you need to average 20 parameters, you can adapt do the same but initializing a 2D array then averaging each line (using an additional for loop). 

 

0 Kudos
Message 2 of 7
(413 Views)

There is a function that does EXACTLY that on the point by point pallet. 

 

The block diagram is even unlocked so, you can see how it is done right!


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

To be honest I think your concerns about memory and CPU load is unwarranted.

 

20 20 element numeric arrays are not going to use that much memory. 

 

Doing a simple averaging on an array of floats is not going to take much CPU power at all. 

 

But I will give you some tips. 

 

Preallocate your arrays (Use initialize array to set the size and fill it with zeros or NAN.

 

Each time you have a new "X" rotate the array one position and replace array element 0 with the new value.

 

Then do your averaging 

========================
=== Engineer Ambiguously ===
========================
0 Kudos
Message 4 of 7
(382 Views)

There's a whole pallete of Point-by-Point functions. If you really want to do a moving average, try Mean PtByPt.vi. It's at Signal Processing -> Point by Point -> Probability and Statistics -> Mean PtByPt.vi.

 

Now that I've sort of answered the question you asked, let me throw out a few other things.

 

First, if you're running on Windows, a 1 ms loop time isn't going to be consistently achievable. You might average 1 ms, but you'll have plenty of jitter.

 

Second, if you're doing this to 20 signals, you shouldn't plop down 20 instances of this function. You should make it a 2D array as LVNinja said, or find some other way to do this math in a loop. The PtByPt functions only work with one instance at a time, so if you put it in a For loop your math will be off.

 

Third, memory on modern computers is VERY abundant. 20 arrays is nothing. Even if each array had 1,000 Double values in them, that's only 20,000 Doubles, or 160 kB. I'm not sure I'd worry about it array memory usage here.

0 Kudos
Message 5 of 7
(379 Views)

@RTSLVU  a écrit :

 

Each time you have a new "X" rotate the array one position and replace array element 0 with the new value.

 

Then do your averaging 


Array's rotation is unfortunately not very efficient (because the data will be copied and execution time will grow with size as O(n)). It's better to just replace the oldest element (classical ring buffer). Complete averaging is also not necessary. In general, once the buffer is filled, we only need to keep the sum of all elements. Then, when a new one arrives, subtract the oldest from the saved sum, replace the oldest in the array with the newest, and then add the newest to the sum. Finally, divide by n, and this is the new average. As a result, this will take just three arithmetic operations per iteration, regardless of the size of the averaging window. This will definitely fit into 1 ms for 20 buffers on almost any average PC

Message 6 of 7
(346 Views)

@Satvikpai wrote:

As I am acquainted with C, I am thinking of using a single variable which keeps on adding n samples to itself until the counter reaches n. This way we don't have to store multiple datapoints in an array. Every next datapoint will be added to the variable which can then be linked to a summation block to calculate the average.

 


That will only work for an infinite history where you can just keep track of the sum and N. For any finite averaging window, once the size is reached, you need to add the new value and subtract the oldest, meaning you need to store the last N points in an array. Even C cannot go around that!

 

Since your voltage is a data source, why is it an indicator instead of a control, forcing the detour over a local variable? 

 

(The "without using arrays" is a silly requirement, even the mentioned mean ptbypt internally uses an array.) 

 

A detailed summary and performance considerations was discussed in our NI-Week talk a few years ago (part II) , so start there (slides 12-14, you can also download the code examples).

 

altenbach_0-1729090338502.png

 

 

0 Kudos
Message 7 of 7
(318 Views)