0.4.4 RunningAverage

This commit is contained in:
Rob Tillaart 2023-11-13 17:57:14 +01:00
parent 202f133a21
commit bc3d53c51f
22 changed files with 224 additions and 93 deletions

View File

@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.4] - 2023-10-18
- update readme.md badges
- update examples
- add two step example
- minor edits
## [0.4.3] - 2022-11-23
- add changelog.md
- add RP2040 to build-CI
@ -13,7 +20,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- add getAverageSubset(start, count) - experimental
- update readme.md
## [0.4.2] - 2021-12-28
- update license
- minor edits

View File

@ -2,8 +2,11 @@
[![Arduino CI](https://github.com/RobTillaart/RunningAverage/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/RunningAverage/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/RunningAverage/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/RunningAverage/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/RunningAverage/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/RunningAverage.svg)](https://github.com/RobTillaart/RunningAverage/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/RunningAverage/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/RunningAverage.svg?maxAge=3600)](https://github.com/RobTillaart/RunningAverage/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/RunningAverage.svg)](https://registry.platformio.org/libraries/robtillaart/RunningAverage)
# RunningAverage
@ -21,14 +24,31 @@ The size of the internal buffer can be set in the constructor.
By keeping track of the **\_sum** the runningAverage can be calculated fast (only 1 division)
at any time. This is done with **getFastAverage()**.
However the constant adding and subtracting when adding new elements possibly introduces an ever increasing error.
However the constant adding and subtracting when adding new elements to the RA object possibly
introduces an ever increasing error.
In tests adding up to 1500000 numbers this error was always small. But that is no proof.
In version 0.2.16 a fix was added that uses the calculation of the sum in **getAverage()** to
update the internal **\_sum**.
#### Related
- https://github.com/RobTillaart/Correlation
- https://github.com/RobTillaart/GST - Golden standard test metrics
- https://github.com/RobTillaart/Histogram
- https://github.com/RobTillaart/RunningAngle
- https://github.com/RobTillaart/RunningAverage
- https://github.com/RobTillaart/RunningMedian
- https://github.com/RobTillaart/statHelpers - combinations & permutations
- https://github.com/RobTillaart/Statistic
## Interface
```cpp
#include "RunningAverage.h"
```
### Constructor
- **RunningAverage(uint16_t size)** allocates dynamic memory, one float (4 bytes) per element.
@ -40,8 +60,10 @@ No default size (yet).
- **void clear()** empties the internal buffer.
- **void add(float value)** wrapper for **addValue()**
- **void addValue(float value)** adds a new value to the object, if internal buffer is full, the oldest element is removed.
- **void fillValue(float value, uint16_t number)** adds number elements of value. Good for initializing the system to z certain starting average.
- **void addValue(float value)** adds a new value to the object, if the internal buffer is full,
the oldest element is removed.
- **void fillValue(float value, uint16_t number)** adds number elements of value.
Good for initializing the system to a certain starting average.
- **float getValue(uint16_t position)** returns the value at **position** from the additions.
Position 0 is the first one to disappear.
- **float getAverage()** iterates over all elements to get the average, slower but accurate.
@ -68,7 +90,7 @@ Needs more than one element to be calculable.
- **uint16_t getCount()** returns the number of slots used of the internal array.
## Partial
## Partial functions
- **void setPartial(uint16_t partial = 0)** use only a part of the internal array.
Allows to change the weight and history factor.
@ -76,7 +98,7 @@ Allows to change the weight and history factor.
- **uint16_t getPartial()** returns the set value for partial.
## Last
## Last functions
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
@ -92,7 +114,7 @@ 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
Note: if called with a value larger or equal to **getCount()** (including **getSize()**) as
parameter, the functions will return the statistics of the whole buffer.
@ -109,15 +131,40 @@ See examples
## Future
#### must
#### Must
- update documentation, explain better
#### should
- add error handling (important?)
#### Should
- check for optimizations.
- divide by count happens often ...
- clear(bool zero = true) to suppress setting all to 0. ?
#### could
- default size for constructor
- create a double based derived class? Template class?
#### Could
- create a double based derived class? Template class?
- add error handling (important?).
- investigate **modus()** most frequently occurring value.
- difficult with floats ?
- what to do when on two or more values are on par?
#### Wont
- default size for constructor
- unknown what would be a good choice.
- clear(bool zero = true) to suppress setting all to 0. ?
- makes **addValue()** slightly more complex
- could introduce conflicts due to randomness data?
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

View File

@ -1,8 +1,8 @@
//
// FILE: RunningAverage.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.4.3
// DATE: 2015-July-10
// VERSION: 0.4.4
// DATE: 2011-01-30
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
// URL: https://github.com/RobTillaart/RunningAverage
//
@ -39,7 +39,7 @@ void RunningAverage::clear()
_max = NAN;
for (uint16_t i = _size; i > 0; )
{
_array[--i] = 0.0; // keeps addValue simpler
_array[--i] = 0.0; // keeps addValue simpler
}
}
@ -57,7 +57,7 @@ void RunningAverage::addValue(const float value)
_sum += _array[_index];
_index++;
if (_index == _partial) _index = 0; // faster than %
if (_index == _partial) _index = 0; // faster than %
// handle min max
if (_count == 0) _min = _max = value;
@ -82,7 +82,7 @@ float RunningAverage::getAverage()
{
_sum += _array[i];
}
return _sum / _count; // multiplication is faster ==> extra admin
return _sum / _count; // multiplication is faster ==> extra admin
}
@ -246,10 +246,6 @@ void RunningAverage::setPartial(const uint16_t partial)
}
////////////////////////////////////////////////////////////////
//
// 0.4.1 added.
//
float RunningAverage::getAverageLast(uint16_t count)
{
uint16_t cnt = count;
@ -308,11 +304,6 @@ float RunningAverage::getMaxInBufferLast(uint16_t count)
}
////////////////////////////////////////////////////////////////
//
// Experimental 0.4.3
//
float RunningAverage::getAverageSubset(uint16_t start, uint16_t count)
{
if (_count == 0)
@ -334,5 +325,5 @@ float RunningAverage::getAverageSubset(uint16_t start, uint16_t count)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -1,9 +1,9 @@
#pragma once
//
// FILE: RunningAverage.h
// AUTHOR: Rob.Tillaart@gmail.com
// VERSION: 0.4.3
// DATE: 2016-dec-01
// AUTHOR: Rob Tillaart
// VERSION: 0.4.4
// DATE: 2011-01-30
// PURPOSE: Arduino library to calculate the running average by means of a circular buffer
// URL: https://github.com/RobTillaart/RunningAverage
@ -11,7 +11,7 @@
#include "Arduino.h"
#define RUNNINGAVERAGE_LIB_VERSION (F("0.4.3"))
#define RUNNINGAVERAGE_LIB_VERSION (F("0.4.4"))
class RunningAverage
@ -26,7 +26,7 @@ public:
void fillValue(const float value, const uint16_t number);
float getValue(const uint16_t position);
float getAverage(); // iterates over all elements.
float getAverage(); // iterates over all elements.
float getFastAverage() const; // reuses previous calculated values.
// return statistical characteristics of the running average
@ -76,5 +76,5 @@ protected:
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -17,7 +17,7 @@ void setup(void)
{
Serial.begin(115200);
Serial.print("Demo RunningAverage lib - fillValue ");
Serial.print("Version: ");
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
delay(10);
@ -60,5 +60,5 @@ void measure_duration(int n)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,8 +14,9 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear();
@ -37,5 +38,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,8 +14,9 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear();
@ -50,5 +51,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -20,9 +20,9 @@ uint32_t start, stop;
void setup(void)
{
Serial.begin(115200);
Serial.print("\nDemo ");
Serial.println();
Serial.println(__FILE__);
Serial.print("Version: ");
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
@ -90,5 +90,5 @@ void test(long n)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,11 +14,11 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.print("\nDemo ");
Serial.println();
Serial.println(__FILE__);
Serial.print("Version: ");
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
Serial.println("\nCNT\tMIN\tMINBUF\tMAX\tMAXBUF");
}
@ -49,5 +49,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,10 +14,11 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("\nDemo runningAverageMinMaxTest");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
Serial.println("\nCNT\tMIN\tAVG\tMAX");
}
@ -46,5 +47,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -16,8 +16,9 @@ uint32_t start, stop;
void setup(void)
{
Serial.begin(115200);
Serial.print("Demo RunningAverage lib - fillValue ");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
delay(10);
@ -68,4 +69,4 @@ void check_statistics()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,10 +14,12 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
for (int i = 0; i < 20; i++)
{
@ -34,7 +36,7 @@ void setup(void)
Serial.println();
delay(10000);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
}
@ -59,4 +61,4 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,10 +14,11 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
}
@ -39,7 +40,7 @@ void loop(void)
}
Serial.println();
// note first values (0..2) will be overwritten by 10..12
// note first values (0..2) will be overwritten by 10..12
myRA.clear();
for (uint16_t i = 0; i < 13; i++)
{
@ -55,7 +56,7 @@ void loop(void)
Serial.println();
Serial.print("\t get last 5 elements added: ");
int last = myRA.getCount() - 1; // -1 as first idx == 0
int last = myRA.getCount() - 1; // -1 as first idx == 0
for (int i = last; i > last - 5 && i >= 0; i--)
{
Serial.print("\t");
@ -67,5 +68,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -18,8 +18,9 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib - average per minute & hour");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
raHour.clear();
raMinute.clear();
@ -41,5 +42,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -14,8 +14,9 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear();
@ -90,5 +91,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -17,11 +17,13 @@ volatile float x;
void setup(void)
{
Serial.begin(115200);
Serial.print("\nPerformance RunningAverage lib: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
Serial.println();
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
for (int i = 0; i < 10; i++)
{
@ -30,6 +32,7 @@ void setup(void)
test_clear();
test_addvalue();
test_fillValue();
test_getValue();
@ -235,5 +238,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -1,5 +1,5 @@
//
// FILE: runningAverageTest.ino
// FILE: ra_test.ino
// AUTHOR: Rob Tillaart
// DATE: 2012-12-30
// PUPROSE: show working of runningAverage
@ -14,10 +14,24 @@ int samples = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println("Demo RunningAverage lib");
Serial.print("Version: ");
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
myRA.clear(); // explicitly start clean
myRA.clear(); // explicitly start clean
for (int i = 0; i < 10; i++)
{
myRA.add(i * 0.01 + 1 );
// Serial.print(myRA.getCount());
// Serial.print("\t");
// Serial.print(myRA.getAverage(), 3);
// Serial.print("\t");
Serial.print(myRA.getStandardDeviation(), 3);
Serial.print("\t");
Serial.println(myRA.getMaxInBuffer(), 3);
}
}
@ -40,5 +54,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -19,11 +19,12 @@ float humidity = 40.0;
void setup(void)
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.print("Version: ");
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
// explicitly start clean
// explicitly start clean
RAT.clear();
RAH.clear();
}
@ -31,14 +32,14 @@ void setup(void)
void loop(void)
{
// random function simulates 2 sensors
temperature = temperature - 1 + random(0, 200) * 0.01; // fluctuate +- 1°C
humidity = humidity - 0.2 + random(0, 400) * 0.001; // fluctuate +- 0.2 %
// random function simulates 2 sensors
temperature = temperature - 1 + random(0, 200) * 0.01; // fluctuate +- 1°C
humidity = humidity - 0.2 + random(0, 400) * 0.001; // fluctuate +- 0.2 %
RAT.addValue(temperature);
RAH.addValue(humidity);
// print a header every 20 lines
// print a header every 20 lines
if (samples % 20 == 0)
{
Serial.println("\nCNT\tT\tTavg\tH\tHavg");
@ -60,5 +61,5 @@ void loop(void)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -0,0 +1,58 @@
//
// FILE: ra_two_step.ino
// AUTHOR: Rob Tillaart
// PUPROSE: demo two stage statistics.
#include "RunningAverage.h"
RunningAverage raHours(24); // holds hourly measurements
RunningAverage raDays(14); // holds min and max of the last seven days.
int samples = 0;
int day = 0;
void setup(void)
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.print("RUNNINGAVERAGE_LIB_VERSION: ");
Serial.println(RUNNINGAVERAGE_LIB_VERSION);
raHours.clear();
raDays.clear();
}
void loop(void)
{
// simulate a new hourly measurement.
long rn = random(0, 1000);
raHours.addValue(rn);
samples++;
if (samples % 24 == 0)
{
raDays.addValue(raHours.getMaxInBuffer()); // track maximum of the day
raDays.addValue(raHours.getMinInBuffer()); // track minimum of the day
samples = 0;
day++;
Serial.println();
}
Serial.print(day);
Serial.print("\t");
Serial.print(raDays.getMinInBuffer());
Serial.print("\t");
Serial.print(raHours.getAverage(), 2);
Serial.print("\t");
Serial.print(raDays.getMaxInBuffer());
Serial.print("\t");
Serial.println();
delay(100);
}
// -- END OF FILE --

View File

@ -34,6 +34,8 @@ getAverageLast KEYWORD2
getMinInBufferLast KEYWORD2
getMaxInBufferLast KEYWORD2
getAverageSubset KEYWORD2
# Instances (KEYWORD2)

View File

@ -15,9 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/RunningAverage.git"
},
"version": "0.4.3",
"version": "0.4.4",
"license": "MIT",
"frameworks": "arduino",
"frameworks": "*",
"platforms": "*",
"headers": "RunningAverage.h"
}

View File

@ -1,5 +1,5 @@
name=RunningAverage
version=0.4.3
version=0.4.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=The library stores the last N individual values in a circular buffer to calculate the running average.