Skip to content

Commit

Permalink
add getAverageLast(n) (#16)
Browse files Browse the repository at this point in the history
* add getAverageLast(n), getMinInBufferLast(n), getMaxInBufferLast(n)
* update keywords.txt
* update unit test
* update readme.md
  • Loading branch information
RobTillaart authored Nov 24, 2021
1 parent ac5f0b1 commit 58cddba
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 22 deletions.
10 changes: 5 additions & 5 deletions .arduino-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- due
- zero
- leonardo
# - due
# - zero
# - leonardo
- m4
- esp32
- esp8266
- mega2560
# - esp8266
# - mega2560
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ Allows to change the weight and history factor.
- **uint16_t getPartial()** returns the set value for partial.


## Last

These functions get the basic statistics of the last N added elements.
Returns NAN if there are no elements and it will reduce count if there are less than
count elements in the buffer.

- **float getAverageLast(uint16_t count)** get the average of the last count elements.
- **float getMinInBufferLast(uint16_t count)** get the minimum of the last count elements.
- **float getMaxInBufferLast(uint16_t count)** get the maximum of the last count elements.

These functions are useful in cases where you might want to calculate and display the
statistics of a subset of the added elements. Reason might be to compare this with the
numbers of the whole buffer to notice changes earlier.
Otherwise one should create multiple RunningAverage objects each with its own length,
effectively having multiple copies of the data added.

Note: if called with a value larger or equal to **getCount()** (incl **getSize()**) as
parameter, the functions will return the statistics of the whole buffer.




## Operation

See examples
Expand Down
100 changes: 88 additions & 12 deletions RunningAverage.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// FILE: RunningAverage.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.4.0
// VERSION: 0.4.1
// DATE: 2015-July-10
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
// URL: https://github.com/RobTillaart/RunningAverage
Expand Down Expand Up @@ -36,7 +36,9 @@
// 0.3.1 2020-06-19 fix library.json; minor refactor
// 0.3.2 2021-01-15 add add() + license + refactor
// 0.4.0 2021-05-18 increase size above 256 elements (16 bit version)
//
// 0.4.1 2021-11-22 updated buil-CI, readme, badges
// add getAverageLast() functions.
//


#include "RunningAverage.h"
Expand Down Expand Up @@ -135,12 +137,12 @@ float RunningAverage::getMinInBuffer() const
return NAN;
}

float min = _array[0];
float _min = _array[0];
for (uint16_t i = 1; i < _count; i++)
{
if (_array[i] < min) min = _array[i];
if (_array[i] < _min) _min = _array[i];
}
return min;
return _min;
}


Expand All @@ -152,12 +154,12 @@ float RunningAverage::getMaxInBuffer() const
return NAN;
}

float max = _array[0];
float _max = _array[0];
for (uint16_t i = 1; i < _count; i++)
{
if (_array[i] > max) max = _array[i];
if (_array[i] > _max) _max = _array[i];
}
return max;
return _max;
}


Expand All @@ -177,7 +179,10 @@ float RunningAverage::getElement(uint16_t index) const
// If buffer is empty or has only one element, return NAN.
float RunningAverage::getStandardDeviation() const
{
if (_count <= 1) return NAN;
if (_count <= 1)
{
return NAN;
}

float temp = 0;
float average = getFastAverage();
Expand All @@ -195,7 +200,10 @@ float RunningAverage::getStandardDeviation() const
// If buffer is empty or has only one element, return NAN.
float RunningAverage::getStandardError() const //++
{
if (_count <= 1) return NAN;
if (_count <= 1)
{
return NAN;
}

float temp = getStandardDeviation();
if (temp == NAN) return NAN;
Expand Down Expand Up @@ -226,8 +234,14 @@ void RunningAverage::fillValue(const float value, const uint16_t number)

float RunningAverage::getValue(const uint16_t position)
{
if (_count == 0) return NAN;
if (position >= _count) return NAN; // cannot ask more than is added
if (_count == 0)
{
return NAN;
}
if (position >= _count)
{
return NAN; // cannot ask more than is added
}

uint16_t _pos = position + _index;
if (_pos >= _count) _pos -= _count;
Expand All @@ -243,5 +257,67 @@ void RunningAverage::setPartial(const uint16_t partial)
}


////////////////////////////////////////////////////////////////
//
// 0.4.1 added.
//
float RunningAverage::getAverageLast(uint16_t count)
{
uint16_t cnt = count;
if (cnt > _count) cnt = _count;
if (cnt == 0) return NAN;

uint16_t idx = _index;
float _sum = 0;
for (uint16_t i = 0; i < cnt; i++)
{
if (idx == 0) idx = _size;
idx--;
_sum +=_array[idx];
}
return _sum / cnt;
}


float RunningAverage::getMinInBufferLast(uint16_t count)
{
uint16_t cnt = count;
if (cnt > _count) cnt = _count;
if (cnt == 0) return NAN;

uint16_t idx = _index;
if (idx == 0) idx = _size;
idx--;
float _min = _array[idx];
for (uint16_t i = 0; i < cnt; i++)
{
if (_array[idx] < _min) _min = _array[idx];
if (idx == 0) idx = _size;
idx--;
}
return _min;
}


float RunningAverage::getMaxInBufferLast(uint16_t count)
{
uint16_t cnt = count;
if (cnt > _count) cnt = _count;
if (cnt == 0) return NAN;

uint16_t idx = _index;
if (idx == 0) idx = _size;
idx--;
float _max = _array[idx];
for (uint16_t i = 0; i < cnt; i++)
{
if (_array[idx] > _max) _max = _array[idx];
if (idx == 0) idx = _size;
idx--;
}
return _max;
}


// -- END OF FILE --

13 changes: 11 additions & 2 deletions RunningAverage.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: RunningAverage.h
// AUTHOR: [email protected]
// VERSION: 0.4.0
// VERSION: 0.4.1
// DATE: 2016-dec-01
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
// URL: https://github.com/RobTillaart/RunningAverage
Expand All @@ -13,7 +13,7 @@
#include "Arduino.h"


#define RUNNINGAVERAGE_LIB_VERSION (F("0.4.0"))
#define RUNNINGAVERAGE_LIB_VERSION (F("0.4.1"))


class RunningAverage
Expand Down Expand Up @@ -56,6 +56,15 @@ class RunningAverage
void setPartial(const uint16_t partial = 0); // 0 ==> use all
uint16_t getPartial() { return _partial; };


// get some stats from the last count additions.
float getAverageLast(uint16_t count);
float getMinInBufferLast(uint16_t count);
float getMaxInBufferLast(uint16_t count);




protected:
uint16_t _size;
uint16_t _count;
Expand Down
59 changes: 59 additions & 0 deletions examples/ra_300_last/ra_300_last.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// FILE: ra_300.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2021-05-26
//
// PUPROSE: demonstrate large (16 bit) buffer
//


#include "RunningAverage.h"

RunningAverage myRA(300);
int samples = 0;


void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);

myRA.clear();
for (uint16_t i = 0; i < 1000; i++)
{
myRA.addValue(i); // random(1000)); (i);
// Serial.print(i);
// Serial.print("\t");
// Serial.print(myRA.getCount());
// Serial.print("\t");
// Serial.print(myRA.getAverage());
// Serial.println();
}

Serial.println();
for (uint16_t i = 1; i < 1000; i++)
{
Serial.print(i);
Serial.print("\t");
Serial.print(myRA.getMinInBufferLast(i));
Serial.print("\t");
Serial.print(myRA.getAverageLast(i));
Serial.print("\t");
Serial.print(myRA.getMaxInBufferLast(i));
Serial.println();
}



}


void loop(void)
{
}


// -- END OF FILE --
4 changes: 4 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ getCount KEYWORD2
setPartial KEYWORD2
getPartial KEYWORD2

getAverageLast KEYWORD2
getMinInBufferLast KEYWORD2
getMaxInBufferLast KEYWORD2


# Instances (KEYWORD2)

Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/RunningAverage.git"
},
"version": "0.4.0",
"version": "0.4.1",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=RunningAverage
version=0.4.0
version=0.4.1
author=Rob Tillaart <[email protected]>
maintainer=Rob Tillaart <[email protected]>
sentence=The library stores the last N individual values in a circular buffer to calculate the running average.
Expand Down
35 changes: 34 additions & 1 deletion test/unit_test_001.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ unittest_teardown()

unittest(test_zero_elements)
{
fprintf(stderr, "VERSION: %s\n", RUNNINGAVERAGE_LIB_VERSION);
fprintf(stderr, "VERSION: %s\n", (char *) RUNNINGAVERAGE_LIB_VERSION);

RunningAverage myRA(10);
myRA.clear();
Expand Down Expand Up @@ -141,6 +141,39 @@ unittest(test_partial)
}



unittest(test_last)
{
RunningAverage myRA(300);
myRA.clear();
assertFalse(myRA.bufferIsFull());

for (int i = 0; i < 1000; i++)
{
myRA.addValue(i);
}
assertNAN(myRA.getMinInBufferLast(0));
assertNAN(myRA.getAverageLast(0));
assertNAN(myRA.getMaxInBufferLast(0));

assertEqualFloat(999.0, myRA.getMinInBufferLast(1), 0.001);
assertEqualFloat(999.0, myRA.getAverageLast(1), 0.001);
assertEqualFloat(999.0, myRA.getMaxInBufferLast(1), 0.001);

assertEqualFloat(990.0, myRA.getMinInBufferLast(10), 0.001);
assertEqualFloat(994.5, myRA.getAverageLast(10), 0.001);
assertEqualFloat(999.0, myRA.getMaxInBufferLast(10), 0.001);

assertEqualFloat(900.0, myRA.getMinInBufferLast(100), 0.001);
assertEqualFloat(949.5, myRA.getAverageLast(100), 0.001);
assertEqualFloat(999.0, myRA.getMaxInBufferLast(100), 0.001);

assertEqualFloat(700.0, myRA.getMinInBufferLast(1000), 0.001);
assertEqualFloat(849.5, myRA.getAverageLast(1000), 0.001);
assertEqualFloat(999.0, myRA.getMaxInBufferLast(1000), 0.001);
}


unittest_main()

// --------

0 comments on commit 58cddba

Please sign in to comment.