diff --git a/README.md b/README.md index 95b08cf..41211f2 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ int sensorMovingAvg = mySensor.getAvg(); ### getAvg(int nPoints) ##### Description -Like `getAvg()` except only uses the most recent `nPoints` data points to calculate the average. This allows calculation of shorter term and longer term averages. If `nPoints` is less than one, or larger than the number of points given in the constructor, then the overall average is returned, i.e. the same value as `getAvg()` would return. +Like `getAvg()` except only uses the most recent `nPoints` data points to calculate the average. This allows calculation of shorter term and longer term averages. If `nPoints` is less than one, or larger than the number of points given in the constructor, or larger than the number of data points so far accumulated, then zero is returned. ##### Syntax `getAvg(nPoints);` ##### Parameters diff --git a/examples/Subset/Subset.ino b/examples/Subset/Subset.ino index 532c92f..b65db86 100644 --- a/examples/Subset/Subset.ino +++ b/examples/Subset/Subset.ino @@ -3,40 +3,62 @@ // Copyright (C) 2020 by Jack Christensen and licensed under // GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html // -// Example sketch to demonstrate calculating shorter term averages +// Example sketch to test/demonstrate calculating shorter term averages // from a subset of the data, using just the most recent data points. -#include // https://github.com/JChristensen/movingAvg +#include // https://github.com/JChristensen/movingAvg +#include // https://github.com/janelia-arduino/Streaming -constexpr int arraySize {30}; +constexpr int arraySize{30}; movingAvg foo(arraySize); void setup() { Serial.begin(115200); + Serial << F( "\n" __FILE__ "\nCompiled " __DATE__ " " __TIME__ "\n\n" ); foo.begin(); - // generate some sample data - for (int i=1; i<=arraySize; ++i) { + // generate sample data, more points than interval size + for (int i=1; i<=42; ++i) { foo.reading(i); } - Serial.print("Average overall: "); - Serial.println(foo.getAvg()); - Serial.print("Average last 10: "); - Serial.println(foo.getAvg(10)); - Serial.print("Average last 3: "); - Serial.println(foo.getAvg(3)); - Serial.print("Average last 2: "); - Serial.println(foo.getAvg(2)); - Serial.print("Average last 1: "); - Serial.println(foo.getAvg(1)); - Serial.print("Average last 0: "); - Serial.println(foo.getAvg(0)); - Serial.print("Average last 30: "); - Serial.println(foo.getAvg(30)); - Serial.print("Average last 31: "); - Serial.println(foo.getAvg(31)); + avgTest("Average overall", foo.getAvg(), 28); + avgTest("Average last 10", foo.getAvg(10), 38); + avgTest("Average last 3 ", foo.getAvg(3), 41); + avgTest("Average last 2 ", foo.getAvg(2), 42); + avgTest("Average last 1 ", foo.getAvg(1), 42); + avgTest("Average last 0 ", foo.getAvg(0), 0); + avgTest("Average last 30", foo.getAvg(30), 28); + avgTest("Average last 31", foo.getAvg(31), 0); + + Serial << endl; + foo.reset(); + // generate sample data, fewer points than interval size + for (int i=1; i<=17; ++i) { + foo.reading(i); + } + avgTest("Average overall", foo.getAvg(), 9); + avgTest("Average last 10", foo.getAvg(10), 13); + avgTest("Average last 3 ", foo.getAvg(3), 16); + avgTest("Average last 2 ", foo.getAvg(2), 17); + avgTest("Average last 1 ", foo.getAvg(1), 17); + avgTest("Average last 0 ", foo.getAvg(0), 0); + avgTest("Average last 30", foo.getAvg(30), 0); + avgTest("Average last 31", foo.getAvg(31), 0); + avgTest("Average last 17", foo.getAvg(17), 9); +} + +// function to compare the average returned by the library to the known correct value +void avgTest(const char* msg, int val, int correctVal) +{ + Serial << msg << ": " << val << " ... "; + if (val == correctVal) { + Serial << "OK\n"; + } + else { + Serial << "ERROR, expected " << correctVal << endl; + } } void loop() {} diff --git a/library.properties b/library.properties index eb4c02f..230891e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=movingAvg -version=2.3.0 +version=2.3.1 author=Jack Christensen maintainer=Jack Christensen sentence=A simple Arduino library for calculating moving averages. diff --git a/src/movingAvg.cpp b/src/movingAvg.cpp index c11808b..b9a46ab 100644 --- a/src/movingAvg.cpp +++ b/src/movingAvg.cpp @@ -36,15 +36,22 @@ int movingAvg::getAvg() } // return the average for a subset of the data, the most recent nPoints readings. -// for invalid values of nPoints, just return the overall average. +// for invalid values of nPoints, return zero. int movingAvg::getAvg(int nPoints) { - if (nPoints < 1 || nPoints > m_interval - 1) { - return (m_sum + m_nbrReadings / 2) / m_nbrReadings; + if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings) { + return 0; } else { - long sum {0}; - for (int i=m_nbrReadings-1; i>=m_nbrReadings-nPoints; --i) { + long sum{0}; + int i = m_next; + for (int n=0; n