Displaying Running Average of Rate of Event on Supertrend


#1

I have a need to display a running average of the rate of an event on our machine. Let me give a fictitious example:
[I][INDENT]An operator loads widgets into a bag then heat seals the bag. They may do anywhere from 5-8 bags a minute.[/INDENT][/I]

I want to show a running average of the parts per minute rate over the last 10 minutes.

I’ve been experimenting for the past few hours trying to find the best way to achieve this in PAC Control or Display. I know how I would do this in C++ but to do the same in chart logic is a bit daunting. If I had to do it now I would use a looping chart with a main loop delay of say 1 second. I would then user timers or manually adjusted variables to detect and store the periods of data. Then the purging of old period data and the averaging needs to be done. It’s doable I’m sure, but it seems like maybe there is a better way?

So I’d like to ask if any of you here have implemented something like this where you display a rolling average of the rate of some event? If so, how did you do it?


#2

I went ahead and pushed on with an OptoScript based solution and it’s working pretty good. I used a Integer Table for the circular buffer and a countdown timer for my period detection. There is an off rounding problem with the line that calculates the average, even when the result in 3.9 it will store 3 in the result. I have tried wrapping the expression in a Round() call but it had no effect.

Here is the first pass of the code, if you see any helpful methods or opto techniques I’m missing please let me know.

//  If the 1 minute period has expired store the count in the table
if (HasDownTimerExpired(Stat_MinutePeriodDownTimer)) then

  // Increment the elapsed periods count, clamp it to the buffer size
  IncrementVariable(var_CyclesPerMinutePeriodCount);
  ClampInt32Variable(var_NUM_CYCLES_PER_MINUTE_PERIODS, 0, var_CyclesPerMinutePeriodCount);

  //  Knock out the last data point
  for var_i = var_NUM_CYCLES_PER_MINUTE_PERIODS-1 to 1 step -1
    Stat_CyclesPerMinuteBuffer[var_i] = Stat_CyclesPerMinuteBuffer[var_i-1];
  next

  //  Store the new data point
  Stat_CyclesPerMinuteBuffer[0] = Cycle_Count;
  Cycle_Count = 0;

  //  Reset the minute period timer. Using GetRestartTimer() so we don't have the timer target
  //  defined in multiple places.
  GetRestartTimer(Stat_MinutePeriodDownTimer);
  

  //  Calculate the average of the periods
  var_SumCyclesPerMinute = 0;
  for var_i = 0 to var_CyclesPerMinutePeriodCount-1 step 1
    var_SumCyclesPerMinute = var_SumCyclesPerMinute + Stat_CyclesPerMinuteBuffer[var_i];
  next

  Stat_AvgCyclesPerMinute = (var_SumCyclesPerMinute/var_CyclesPerMinutePeriodCount);

endif

This is the line that is thwarting me:

Stat_AvgCyclesPerMinute = (var_SumCyclesPerMinute/var_CyclesPerMinutePeriodCount);

BTW I really, really wish we could have chart-local variables defined in OptoScript! :wink:
I get why they aren’t, but even if you made it “feel” like the support was there (e.g. hiding them from the main variable list and not exposing as tags in Display.


#3

Check out [B]this thread[/B] which talks about another option using the built-in totalize function to do an average.

Re: chart-local, have you tried using subroutines? If you move (copy/paste) your chart logic into a sub, you can have a chart that just calls a subroutine, then all those variables are “local” to the sub, and won’t appear in the big tag tree and won’t be exposed in Display. There are some limitations to subroutines, which I talk about in [B]this post on subs in general[/B]… which also talks about averaging!

Hope that helps…
-OptoMary