Skip to content

Commit

Permalink
Fix calculation for most recent "n" points, i.e. the getAvg(int) func…
Browse files Browse the repository at this point in the history
…tion.

Change getAvg(int) so that if given an improper number of points, it returns zero.
  • Loading branch information
JChristensen committed Mar 3, 2022
1 parent 36c5413 commit 23290e2
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
64 changes: 43 additions & 21 deletions examples/Subset/Subset.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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 <movingAvg.h> // https://github.com/JChristensen/movingAvg
#include <movingAvg.h> // https://github.com/JChristensen/movingAvg
#include <Streaming.h> // 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() {}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=movingAvg
version=2.3.0
version=2.3.1
author=Jack Christensen <[email protected]>
maintainer=Jack Christensen <[email protected]>
sentence=A simple Arduino library for calculating moving averages.
Expand Down
17 changes: 12 additions & 5 deletions src/movingAvg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<nPoints; ++n) {
if (i == 0) {
i = m_interval - 1;
}
else {
--i;
}
sum += m_readings[i];
}
return (sum + nPoints / 2) / nPoints;
Expand Down
2 changes: 1 addition & 1 deletion src/movingAvg.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class movingAvg
{
public:
movingAvg(int interval)
: m_interval(interval), m_nbrReadings(0), m_sum(0), m_next(0) {}
: m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0} {}
void begin();
int reading(int newReading);
int getAvg();
Expand Down

0 comments on commit 23290e2

Please sign in to comment.