Step7 - creating a running average of 256 values

RMA

Member
Join Date
Sep 2004
Location
North of Hamburg, Germany
Posts
2,052
I want to monitor the cycle times of some of our stations (the process, not the CPU cycle time). We had a case recently where throughput was down and nobody new why and we discovered that a station which normally completes its work cycle in about 35 secs had drifted up to about 42 secs over the last three months.

I intend to save the cycle times in a 256 Byte array in a DB and compare the average with a Target time and issue a warning on the OP if this time is exceeded.

Does anybody know if there is a Siemens FC or SFC which will do this for me, I can't find any likely candidates in the Standard Library.

I know can do this in a loop, but I'm a bit nervous about cycle time contraints if I do it all in one fell swoop and I don't like loops that only perform one step per cycle, because I find people sometimes have problem figuring out what's going on with them.

If anybody's got a boxed function which does something similar, I be interested to see it.

Cheers

Roy
 
Why 256 points? Why not use a simple low pass filter.
http://www.plctalk.net/qanda/showthread.php?t=20246&highlight=Filter
Now you can change the amount of filtering by changing a constant instead of the size of the array.

If you must use a 256 point array you need to keep a sum that is initialized to 0. The array must be initialize to 0 too.

Now for each NewTime

I = I + 1
if I >= 256 Then I = 0
SumTime = SumTime - Array
SumTime = SumTime + NewTime
Array = NewTime
AvgTime=SumTime / 256 // I would shift right by 8 or multiply by (1/256) to avoid the divide.

This should be easy and fast enough.
 
I would put into a table 256 long and use like a FIFO.

As a value goes in I would ADD it to a running total and add 1 to the total number of values. Then divide the total by the number of values.

If the FIFO is full, then I would unload and subtract that value from the running total before loading in the new value.

So the Logic

Is FIFO Full?
If NO - Goto Load FIFO

UNLOAD FIFO
Running Total = Running Total - FIFO Value Unloaded
No. of Values = No. of Values - 1


Load FIFO:

Running Total = Running Total + New Value
No. of Values = No. of Values + 1
LOAD FIFO

Average = Running Total / No. of values

END




Ensure if the FIFO is empty, then zero everything.


There are two ways, use the FIFO in the S5 converstion blocks or move values using two SFC20 calls, two are needed as you cannot overlap data, so you would have to move the data to a temp and then back again, but offset by 1, zero the first and see if anything came out of the end.
 
With Peter's suggestion you would start again after every 256, my suggestion would always give you the last 256, depends on what you want.
 
One simple way to do a running average without a lot of data shifting is:



((Average - (Average/N)) + C)/N

Where N is the number of data points and C is the value of the newest data point.

Left alone, this is an infinite sum average, which may not be desirable. But nothing keeps you from resetting it.

The longer it runs the stronger it becomes as an indicator of what an average run time is if you are using if for comparison.
 
I've had a look at the basic performance figures for the 315 and have come to the conclusion that I'm worrying unnecessarily about the effect on cycle time. (I wish I could find the Siemens manual which has the exact operation times for all the operations under all conditions!)

Peter N's example is exactly what I had in mind, apart from the fact I'll be doing it in STL. I don't like the idea of using a filter, because I think that's unnecessarily complicated for anyone following me.

I want to reinitialise the DB to zero after an alarm anyway, although the rest of the time I'll just be wrapping the index round as in a FIFO. 256 values represents a bit more than half a shift's production, so I want them to have enough time to do something without having a alarm coming up once a minute, but I don't want to let them forget it altogether either.

Cheers

Roy

Edit: I was busy typing as Alaric posted. That takes me a long way back, I'd forgotten that formula. I still think the simpler loop is adequate and more easily understood though.

By the way Peter, I'm old enough that using SLW and SRW etc. to multiply and divide by a factor of 2, is automatic, I do it without thinking. So much for keeping things simple for those coming behind me!
 
Last edited:

Similar Topics

Hello Inside a FB, I´m trying to transfer a string from a DB to a IN_OUT var that was define as a UDT. The problem is that i can´t determine the...
Replies
4
Views
69
Hi all, I am trying to convert RSLogix 5000 program to Step7. I need to bit shift left my array of double integers for tracking the product on...
Replies
2
Views
504
I have a word in some DB which I want to load to AR1 and use as a pointer. In order to do this I need to write L DBxy.DBW xy SLD 3 LAR1 I...
Replies
3
Views
506
Hi, is there any way to export all contents of Block folder (OBs, FBs, DBs, etc) to a text file? I know it is possible to export symbol table, but...
Replies
5
Views
1,197
Hello, When trying to enable the Operator Control & Monitoring features in Data blocks of the Step 7 5.7 project it gives the Error of Operator...
Replies
0
Views
894
Back
Top Bottom