2020-11-27 05:33:55 -05:00
|
|
|
#pragma once
|
2013-10-17 14:55:03 -04:00
|
|
|
//
|
2011-10-09 16:24:29 -04:00
|
|
|
// FILE: RunningMedian.h
|
2021-01-29 06:31:58 -05:00
|
|
|
// AUTHOR: Rob Tillaart
|
2011-10-09 16:24:29 -04:00
|
|
|
// PURPOSE: RunningMedian library for Arduino
|
2022-06-06 05:10:05 -04:00
|
|
|
// VERSION: 0.3.6
|
2020-11-27 05:33:55 -05:00
|
|
|
// URL: https://github.com/RobTillaart/RunningMedian
|
2011-10-09 16:24:29 -04:00
|
|
|
// URL: http://arduino.cc/playground/Main/RunningMedian
|
|
|
|
// HISTORY: See RunningMedian.cpp
|
|
|
|
//
|
2015-03-07 09:53:38 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2013-08-17 08:54:10 -04:00
|
|
|
#include "Arduino.h"
|
|
|
|
|
2022-06-06 05:10:05 -04:00
|
|
|
#define RUNNING_MEDIAN_VERSION (F("0.3.6"))
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
// fall back to fixed storage for dynamic version => remove true
|
2022-06-06 04:32:23 -04:00
|
|
|
#ifndef RUNNING_MEDIAN_USE_MALLOC
|
2021-01-29 06:31:58 -05:00
|
|
|
#define RUNNING_MEDIAN_USE_MALLOC true
|
2022-06-06 04:32:23 -04:00
|
|
|
#endif
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2013-09-30 13:10:10 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
// MEDIAN_MIN_SIZE should at least be 3 to be practical,
|
2022-06-06 04:32:23 -04:00
|
|
|
#ifndef MEDIAN_MIN_SIZE
|
2021-01-29 06:31:58 -05:00
|
|
|
#define MEDIAN_MIN_SIZE 3
|
2022-06-06 04:32:23 -04:00
|
|
|
#endif
|
2011-10-09 16:24:29 -04:00
|
|
|
|
2013-10-17 14:55:03 -04:00
|
|
|
|
2022-06-06 04:32:23 -04:00
|
|
|
#ifndef MEDIAN_MAX_SIZE
|
2021-01-29 06:31:58 -05:00
|
|
|
#ifdef RUNNING_MEDIAN_USE_MALLOC
|
2021-12-28 04:25:17 -05:00
|
|
|
// max 250 to not overflow uint8_t internal variables
|
2021-01-29 06:31:58 -05:00
|
|
|
#define MEDIAN_MAX_SIZE 255
|
|
|
|
#else
|
|
|
|
// using fixed memory will be limited to 19 elements.
|
|
|
|
#define MEDIAN_MAX_SIZE 19
|
|
|
|
#endif
|
2022-06-06 04:32:23 -04:00
|
|
|
#endif
|
2013-10-18 18:26:50 -04:00
|
|
|
|
|
|
|
|
2013-10-17 14:55:03 -04:00
|
|
|
class RunningMedian
|
2011-10-09 16:24:29 -04:00
|
|
|
{
|
2013-10-17 14:55:03 -04:00
|
|
|
public:
|
2020-11-27 05:33:55 -05:00
|
|
|
// # elements in the internal buffer
|
2021-01-29 06:31:58 -05:00
|
|
|
// odd sizes results in a 'real' middle element and will be a bit faster.
|
|
|
|
// even sizes takes the average of the two middle elements as median
|
2020-11-27 05:33:55 -05:00
|
|
|
explicit RunningMedian(const uint8_t size);
|
|
|
|
~RunningMedian();
|
|
|
|
|
2021-12-28 04:25:17 -05:00
|
|
|
// resets internal buffer and variables
|
2021-01-29 06:31:58 -05:00
|
|
|
void clear();
|
2020-11-27 05:33:55 -05:00
|
|
|
// adds a new value to internal buffer, optionally replacing the oldest element.
|
2021-01-29 06:31:58 -05:00
|
|
|
void add(const float value);
|
2020-11-27 05:33:55 -05:00
|
|
|
// returns the median == middle element
|
2021-01-29 06:31:58 -05:00
|
|
|
float getMedian();
|
2020-11-27 05:33:55 -05:00
|
|
|
|
|
|
|
// returns the Quantile
|
2021-12-28 04:25:17 -05:00
|
|
|
float getQuantile(const float quantile);
|
2020-11-27 05:33:55 -05:00
|
|
|
|
|
|
|
// returns average of the values in the internal buffer
|
2021-01-29 06:31:58 -05:00
|
|
|
float getAverage();
|
2020-11-27 05:33:55 -05:00
|
|
|
// returns average of the middle nMedian values, removes noise from outliers
|
2021-01-29 06:31:58 -05:00
|
|
|
float getAverage(uint8_t nMedian);
|
2013-10-17 14:55:03 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
float getHighest() { return getSortedElement(_count - 1); };
|
|
|
|
float getLowest() { return getSortedElement(0); };
|
2013-10-17 14:55:03 -04:00
|
|
|
|
2021-12-28 04:25:17 -05:00
|
|
|
// get n-th element from the values in time order
|
2021-01-29 06:31:58 -05:00
|
|
|
float getElement(const uint8_t n);
|
2021-12-28 04:25:17 -05:00
|
|
|
// get n-th element from the values in size order
|
2021-01-29 06:31:58 -05:00
|
|
|
float getSortedElement(const uint8_t n);
|
2020-11-27 05:33:55 -05:00
|
|
|
// predict the max change of median after n additions
|
2021-01-29 06:31:58 -05:00
|
|
|
float predict(const uint8_t n);
|
2020-11-27 05:33:55 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
uint8_t getSize() { return _size; };
|
2020-11-27 05:33:55 -05:00
|
|
|
// returns current used elements, getCount() <= getSize()
|
2021-01-29 06:31:58 -05:00
|
|
|
uint8_t getCount() { return _count; };
|
|
|
|
bool isFull() { return (_count == _size); }
|
2013-10-20 09:32:13 -04:00
|
|
|
|
2013-10-17 14:55:03 -04:00
|
|
|
|
|
|
|
protected:
|
2021-01-29 06:31:58 -05:00
|
|
|
boolean _sorted; // _sortIdx{} is up to date
|
|
|
|
uint8_t _size; // max number of values
|
|
|
|
uint8_t _count; // current number of values
|
|
|
|
uint8_t _index; // next index to add.
|
|
|
|
|
2013-10-18 18:26:50 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
// _values holds the elements themself
|
|
|
|
// _p holds the index for sorted
|
2022-06-06 04:32:23 -04:00
|
|
|
#if RUNNING_MEDIAN_USE_MALLOC
|
2021-01-29 06:31:58 -05:00
|
|
|
float * _values;
|
|
|
|
uint8_t * _sortIdx;
|
2013-10-18 18:26:50 -04:00
|
|
|
#else
|
2021-01-29 06:31:58 -05:00
|
|
|
float _values[MEDIAN_MAX_SIZE];
|
2022-06-06 04:32:23 -04:00
|
|
|
uint8_t _sortIdx[MEDIAN_MAX_SIZE];
|
2013-10-18 18:26:50 -04:00
|
|
|
#endif
|
2017-07-26 16:21:25 -04:00
|
|
|
void sort();
|
2011-10-09 16:24:29 -04:00
|
|
|
};
|
|
|
|
|
2021-12-28 04:25:17 -05:00
|
|
|
|
|
|
|
// -- END OF FILE --
|
|
|
|
|