From ff52d491175c4b2e446bf94db11105211bbb998a Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sat, 19 Oct 2013 15:55:43 +0200 Subject: [PATCH] + version 0.1.06 + dynamic internal buffers + replace sorted buffer with "indirection buffer" + bubble sort + flag (faster) --- libraries/RunningMedian/RunningMedian.cpp | 77 +++---------------- libraries/RunningMedian/RunningMedian.h | 5 +- .../RunningMedian2/RunningMedian2.ino | 10 ++- 3 files changed, 21 insertions(+), 71 deletions(-) diff --git a/libraries/RunningMedian/RunningMedian.cpp b/libraries/RunningMedian/RunningMedian.cpp index d1950aff..eb7c9500 100644 --- a/libraries/RunningMedian/RunningMedian.cpp +++ b/libraries/RunningMedian/RunningMedian.cpp @@ -11,7 +11,7 @@ // 0.1.03 - 2013-09-30 added _sorted flag, minor refactor // 0.1.04 - 2013-10-17 added getAverage(uint8_t) - kudo's to Sembazuru // 0.1.05 - 2013-10-18 fixed bug in sort; removes default constructor; dynamic memory -// 0.1.06 - 2013-10-19 faster sort? more dyn test. +// 0.1.06 - 2013-10-19 faster sort, dynamic arrays, replaced sorted float array with indirection array // // Released to the public domain // @@ -21,10 +21,10 @@ RunningMedian::RunningMedian(uint8_t size) { _size = constrain(size, MEDIAN_MIN_SIZE, MEDIAN_MAX_SIZE); - + #ifdef RUNNING_MEDIAN_USE_MALLOC _ar = (float *) malloc(_size * sizeof(float)); - _p = (uint8_t *) malloc(size * sizeof(uint8_t)); + _p = (uint8_t *) malloc(_size * sizeof(uint8_t)); #endif clear(); @@ -45,15 +45,16 @@ void RunningMedian::clear() _idx = 0; _sorted = false; - // for (uint8_t i=0; i< _size; i++) _p[i] = i; + for (uint8_t i=0; i< _size; i++) _p[i] = i; } // adds a new value to the data-set // or overwrites the oldest if full. void RunningMedian::add(float value) { - _ar[_idx++] = value; + _idx++; if (_idx >= _size) _idx = 0; // wrap around + _ar[_idx] = value; if (_cnt < _size) _cnt++; _sorted = false; } @@ -64,7 +65,6 @@ float RunningMedian::getMedian() { if (_sorted == false) sort(); return _ar[_p[_cnt/2]]; - // return _as[_cnt/2]; } return NAN; } @@ -74,9 +74,8 @@ float RunningMedian::getHighest() { if (_cnt > 0) { - if (_sorted == false) sort(); + if (_sorted == false) sort(); // assumes other fields are also retrieved otherwise inefficient return _ar[_p[_cnt-1]]; - // return _as[_cnt-1]; } return NAN; } @@ -87,7 +86,6 @@ float RunningMedian::getLowest() { if (_sorted == false) sort(); return _ar[_p[0]]; - // return _as[0]; } return NAN; } @@ -110,9 +108,11 @@ float RunningMedian::getAverage(uint8_t nMedians) if (_cnt < nMedians) nMedians = _cnt; // when filling the array for first time uint8_t start = ((_cnt - nMedians)/2); uint8_t stop = start + nMedians; + if (_sorted == false) sort(); + float sum = 0; - for (uint8_t i = start; i < stop; i++) sum += _ar[_p[i]]; // _as[i]; + for (uint8_t i = start; i < stop; i++) sum += _ar[_p[i]]; return sum / nMedians; } return NAN; @@ -125,15 +125,7 @@ uint8_t RunningMedian::getCount() { return _cnt; }; void RunningMedian::sort() { - // Serial.print("befor:\t"); - // for (uint8_t i=0; i< _cnt; i++) - // { - // Serial.print(_ar[_p[i]]); - // Serial.print('\t'); - // } - // Serial.println(); - - // sort all + // bubble sort with flag for (uint8_t i=0; i< _cnt-1; i++) { bool flag = true; @@ -149,53 +141,8 @@ void RunningMedian::sort() } if (flag) break; } - - // for (uint8_t i=0; i< _cnt-1; i++) - // { - // uint8_t m = i; - // for (uint8_t j=i+1; j< _cnt; j++) - // { - // if (_ar[_p[j]] < _ar[_p[m]]) m = j; - // } - // if ( m != i ) - // { - // uint8_t t = _p[i]; - // _p[i] = _p[m]; - // _p[m] = t; - // } - // } - - // Serial.print("after:\t"); - // for (uint8_t i=0; i< _cnt; i++) - // { - // Serial.print(_ar[_p[i]]); - // Serial.print('\t'); - // } - // Serial.println(); + _sorted = true; } -// void RunningMedian::sort() -// { - // // copy - // for (uint8_t i=0; i< _cnt; i++) _as[i] = _ar[i]; - - // // sort all - // for (uint8_t i=0; i< _cnt-1; i++) - // { - // uint8_t m = i; - // for (uint8_t j=i+1; j< _cnt; j++) - // { - // if (_as[j] < _as[m]) m = j; - // } - // if (m != i) - // { - // float t = _as[m]; - // _as[m] = _as[i]; - // _as[i] = t; - // } - // } - // _sorted = true; -// } - // END OF FILE \ No newline at end of file diff --git a/libraries/RunningMedian/RunningMedian.h b/libraries/RunningMedian/RunningMedian.h index 35bc59f2..ec3a2681 100644 --- a/libraries/RunningMedian/RunningMedian.h +++ b/libraries/RunningMedian/RunningMedian.h @@ -32,8 +32,9 @@ // should at least be 5 to be practical // odd size results in a 'real' middle element. +// even size takes the lower of the two middle elements (TODO) #define MEDIAN_MIN_SIZE 1 -#define MEDIAN_MAX_SIZE 19 // can be adjusted if needed +#define MEDIAN_MAX_SIZE 19 // adjust if needed class RunningMedian @@ -64,11 +65,9 @@ protected: #ifdef RUNNING_MEDIAN_USE_MALLOC float * _ar; - // float * _as; uint8_t * _p; #else float _ar[MEDIAN_MAX_SIZE]; - // float _as[MEDIAN_MAX_SIZE]; uint8_t _p[MEDIAN_MAX_SIZE]; #endif void sort(); diff --git a/libraries/RunningMedian/examples/RunningMedian2/RunningMedian2.ino b/libraries/RunningMedian/examples/RunningMedian2/RunningMedian2.ino index 57b92939..bdc34afd 100644 --- a/libraries/RunningMedian/examples/RunningMedian2/RunningMedian2.ino +++ b/libraries/RunningMedian/examples/RunningMedian2/RunningMedian2.ino @@ -11,7 +11,7 @@ #include "RunningMedian.h" -RunningMedian samples = RunningMedian(15); +RunningMedian samples = RunningMedian(7); long count = 0; @@ -29,9 +29,9 @@ void loop() void test1() { - if (count % 20 == 0) Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(3) \tMed \tHigh")); + if (count % 20 == 0) Serial.println(F("\nmsec \tAnR \tSize \tCnt \tLow \tAvg \tAvg(7) \tAvg(3) \tMed \tHigh")); count++; - + long x = analogRead(A0); samples.add(x); @@ -39,6 +39,7 @@ void test1() float l = samples.getLowest(); float m = samples.getMedian(); float a = samples.getAverage(); + float a7 = samples.getAverage(7); float a3 = samples.getAverage(3); float h = samples.getHighest(); int s = samples.getSize(); @@ -56,6 +57,8 @@ void test1() Serial.print('\t'); Serial.print(a, 2); Serial.print('\t'); + Serial.print(a7, 2); + Serial.print('\t'); Serial.print(a3, 2); Serial.print('\t'); Serial.print(m); @@ -64,3 +67,4 @@ void test1() delay(100); } +