moving-average

andrey-doc/moving-average/moving-average

Calculates moving averages. Operates in the integer domain.
moving-average
@/moving-average
Calculates moving averages. Operates in the integer domain.
INnumber
Adds new data point to the moving average.
NUMnumber
Specifies the interval (number of data points) for the moving average.
RSTpulse
Restarts the moving average. Zeros the interval array and associated data.
moving-average
IN
OUT
NUM
RST
OUTnumber
Returns the new moving average value.
To use the node in your project you should have the andrey-doc/moving-average library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.

C++ implementation

// Based on the Arduino Moving Average Library
// https://github.com/JChristensen/movingAvg


node {
    // Internal state variables defined at this level persists across evaluations

    int m_interval;     // number of data points for the moving average
    int m_nbrReadings;  // number of readings
    long m_sum;         // sum of the m_readings array
    int m_next;         // index to the next reading
    int *m_readings;    // pointer to the dynamically allocated interval array

    // initialize - allocate the interval array
    void init()
    {
        m_readings = new int[m_interval];
    }

    // add a new reading and return the new moving average
    int reading(int newReading)
    {
        // add each new data point to the sum until the m_readings array is filled
        if (m_nbrReadings < m_interval)
        {
            ++m_nbrReadings;
            m_sum = m_sum + newReading;
        }
        // once the array is filled, subtract the oldest data point and add the new one
        else
        {
            m_sum = m_sum - m_readings[m_next] + newReading;
        }

        m_readings[m_next] = newReading;
        if (++m_next >= m_interval) m_next = 0;
        return (m_sum + m_nbrReadings / 2) / m_nbrReadings;
    }

    // just return the current moving average
    int getAvg()
    {
        return (m_sum + m_nbrReadings / 2) / m_nbrReadings;
    }

    // start the moving average over again
    void reset()
    {
        m_nbrReadings = 0;
        m_sum = 0;
        m_next = 0;
    }


    void evaluate(Context ctx) {

        if (isSettingUp()) {
            // This run once
            m_interval = getValue<input_NUM>(ctx);
            init();
        }

        if (isInputDirty<input_RST>(ctx))
            reset();

        emitValue<output_OUT>(ctx, reading(getValue<input_IN>(ctx)));
    }
}