Re: [foxboro] DTIME block

  • From: Roger D Nugent <roger.nugent@xxxxxxxx>
  • To: foxboro@xxxxxxxxxxxxx
  • Date: Thu, 14 Feb 2013 15:55:34 -0600

I gave up on trying to use DTIME for rolling averages a long time age.  I 
got this code from a friend.  Works like a charm.
===================================================================================
The following code performs a rolling average calculation. The average is 
initiaized to the first value read from the input, and then it goes from 
there.

The NUM_SAMPLES constant determines the number of "buckets" to use for 
calculating the rolling average, and the SAMPLE_PERIOD is the interval 
between samples (should be some multiple of the
parent IND block's PERIOD). Therefore, your rolling average interval is 
NUM_SAMPLES * SAMPLE_PERIOD seconds. In this example, it is a 1-hour 
rolling average of 1-minute samples.

INDEPENDENT_SEQUENCE

{******************************************************
**
** Rolling Average Calculation (IND block version) 
**
** Calculate rolling average over a time period 
** equal to NUM_SAMPLES * SAMPLE_PERIOD secs.
** Here we use a ring buffer to hold the samples.
** We initialize by filling the ring buffer with the
** first reading and get a starting "average" value =
** that reading.  We then start a loop, getting the
** input value, poking it in the ring buffer after
** saving the value in that ring buffer location.
** We then calculate the sum of the ring buffer values 
** by adding the new value to the sum and subtracting
** the saved old value, and get the average by dividing
** that sum by the number of samples (size of ring
** buffer. Finally we wait one sample interval, and
** lather rinse repeat.
******************************************************}

CONSTANTS
    NUM_SAMPLES = 60;
    SAMPLE_PERIOD = 60; { secs; IND block period should
                          be an integer multiple of this }

VARIABLES
    ring_buf    : R[NUM_SAMPLES];
    i           : I;

USER_LABELS
    input       : RI0001; { Live input value }
    roll_avg    : RO0001; { Calculated rolling average }
    roll_sum    : RO0002; { Sum of input values over
                           averaging period }
    st_inp      : RO0003; { Stored input value }
    rb_oldest   : RO0004; { Saved ring buf value @ ptr loc }
    rb_ptr      : IO0001; { Ring buffer index pointer }


STATEMENTS

{ Initialize ring buffer }
ring_buf := SET_ARRAY(input);
rb_ptr := 1;

{ Starting "rolling sum" }
roll_sum := ring_buf[1] * NUM_SAMPLES;

{ Wait until next scan before starting main loop }
WAIT 1.0;

{ Main loop }
<<loop_lbl>>

    { Get input, save old value at current ring buffer
      pointer location, and save input value. Store to
      an output for troubleshooting.
    }
    st_inp := input;
    rb_oldest := ring_buf[rb_ptr];
    ring_buf[rb_ptr] := st_inp;

    { Calculate rolling sum and average }
    roll_sum := roll_sum + ring_buf[rb_ptr] -
        rb_oldest;
    roll_avg := roll_sum / NUM_SAMPLES;

    { Move ring buf pointer to next slot }
    IF rb_ptr < NUM_SAMPLES THEN
        rb_ptr := rb_ptr + 1;
    ELSE
        rb_ptr := 1;
    ENDIF;

    { Wait until next calculation cycle }
    WAIT SAMPLE_PERIOD;

GOTO loop_lbl;

ENDSEQUENCE

===================================================================================



Roger Nugent 
Control Systems Coord
Phone: 409-960-5392, E-Mail: roger.nugent@xxxxxxxx
BASF Corporation, P. O. Box 2506, Hwy 366, Gate 99, Port Arthur, TX 77643

 
 
_______________________________________________________________________
This mailing list is neither sponsored nor endorsed by Invensys Process
Systems (formerly The Foxboro Company). Use the info you obtain here at
your own risks. Read http://www.thecassandraproject.org/disclaimer.html
 
foxboro mailing list:             //www.freelists.org/list/foxboro
to subscribe:         mailto:foxboro-request@xxxxxxxxxxxxx?subject=join
to unsubscribe:      mailto:foxboro-request@xxxxxxxxxxxxx?subject=leave
 

Other related posts: