# Average over a minute?

Hey guys, I'm working on a lightning detector at the moment, and I'm trying to get my head around the best way to do this.

I have the actual detector circuit connected to an interrupt, which already increments a total number of strikes variable.

I somehow want to generate a "running average" over a minute so I can produce a "strikes per minute" value.

Problem is, I'm not quite sure how to go about that. Get a value from millis and count strikes within the minute? I'm not really sure. I could have the interrupt trigger a 2nd function that would increment the average value or something. This is where I get lost.

Thanks

I somehow want to generate a "running average" over a minute so I can produce a "strikes per minute" value.

A "running average" and "strikes per minute" are two completely different things.

You can use millis() to determine how long it has been since some previous event:

``````unsigned long currMillis = millis();
if(currMillis - prevMillis >= interval)
{
// Enough time has elapsed. Do something
// Reset the counter...
prevMillis = currMillis;
}
``````

The interrupt routine is already counting the strikes, isn't it? Reset it at the desired interval.

Hi Paul, thanks for the reply. Yeah, that wasn't really clear.

Basically what I'm trying to do is sort of like a bar graph on a LCD.

This video shows it well, starts at about 40 seconds in, and on the 2nd line of the LCD, you can see if gives sort of a running average value: Lightning Detector Kit 1.0 - YouTube

I'm trying to avoid a harsh roll over every minute, I suppose I could say.

Thanks

For the moving average, you can use a Circular buffer. For example, you can store the number of strikes per 12 seconds in so called bucket, and average all the buckets once you change buckets.

``````time window(sec) | strikes
0-12  | 5
12-24 | 0
24-36 | 2
36-48 | 10
48-60 | 3
``````

I think I'd try something like this, using a 61-element ring buffer so that the running average would just be the sum of the strikes in the past 60 seconds:

``````int ring_buffer[61] = 0;               /* Past 60 secs + current sec          */
int *bucket = &ring_buffer[0];         /* Pointer to current bucket           */
/*----------------------------------------------------------------------------*/
/* Interrupt routine called when strike detected - use attachInterrupt()      */
/*----------------------------------------------------------------------------*/
void strike(void)
{  ++*bucket;
}
/*----------------------------------------------------------------------------*/
/* Calculate strikes per minute (called every 1000 msec)                      */
/*----------------------------------------------------------------------------*/
int update(void)
{  static int filled = 0;              /* nr buckets containing strikes       */
static int current_bucket = 0;      /* Current bucket subscript            */
int average = 0;                    /* Average (set to zero each call)     */
/*-------------------------------------------------------------------------*/
/* Advance the current bucket pointer and set current count to zero        */
/*-------------------------------------------------------------------------*/
*(bucket = &ring_buffer[current_bucket = ++current_bucket % 61]) = 0;
/*-------------------------------------------------------------------------*/
/* Compute number of strikes over the past 60 seconds                      */
/*-------------------------------------------------------------------------*/
if (filled == 60)
{  for (i=0; i < 61; i++)
if (i != current_bucket)      /* Don't include current bucket        */
average += ring_buffer[i];
}
else                                /* Haven't filled 60 buckets yet       */
{  ++filled;
for (i=0; i<filled; i++) average += ring_buffer[i];
/*----------------------------------------------------------------------*/
/* Since all buckets aren't filled, extrapolate average from available  */
/*----------------------------------------------------------------------*/
average = (average * 60 + (filled / 2)) / filled;
}
return average;
}
``````