diff --git a/lib/obp60task/OBPSensorTask.cpp b/lib/obp60task/OBPSensorTask.cpp index 1424907..5d355aa 100644 --- a/lib/obp60task/OBPSensorTask.cpp +++ b/lib/obp60task/OBPSensorTask.cpp @@ -66,8 +66,8 @@ void sensorTask(void *param){ const int avgsize = 300; constexpr int arrayBatV{avgsize}; constexpr int arrayBatC{avgsize}; - movingAvg batV(arrayBatV); - movingAvg batC(arrayBatC); + movingAvg batV(arrayBatV); + movingAvg batC(arrayBatC); batV.begin(); batC.begin(); diff --git a/lib/obp60task/movingAvg.cpp b/lib/obp60task/movingAvg.cpp deleted file mode 100644 index b9a46ab..0000000 --- a/lib/obp60task/movingAvg.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Arduino Moving Average Library -// https://github.com/JChristensen/movingAvg -// Copyright (C) 2018 by Jack Christensen and licensed under -// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html - -#include - -// initialize - allocate the interval array -void movingAvg::begin() -{ - m_readings = new int[m_interval]; -} - -// add a new reading and return the new moving average -int movingAvg::reading(int newReading) -{ - // add each new data point to the sum until the m_readings array is filled - if (m_nbrReadings < m_interval) { - ++m_nbrReadings; - m_sum += newReading; - } - // once the array is filled, subtract the oldest data point and add the new one - else { - m_sum = m_sum - m_readings[m_next] + newReading; - } - - m_readings[m_next] = newReading; - if (++m_next >= m_interval) m_next = 0; - return (m_sum + m_nbrReadings / 2) / m_nbrReadings; -} - -// just return the current moving average -int movingAvg::getAvg() -{ - return (m_sum + m_nbrReadings / 2) / m_nbrReadings; -} - -// return the average for a subset of the data, the most recent nPoints readings. -// for invalid values of nPoints, return zero. -int movingAvg::getAvg(int nPoints) -{ - if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings) { - return 0; - } - else { - long sum{0}; - int i = m_next; - for (int n=0; n 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}, m_readings{nullptr} {} + ~movingAvg() { delete[] m_readings; } void begin(); - int reading(int newReading); - int getAvg(); - int getAvg(int nPoints); - int getCount() {return m_nbrReadings;} + T reading(T newReading); + T getAvg(); + T getAvg(int nPoints); + int getCount() { return m_nbrReadings; } void reset(); - int* getReadings() {return m_readings;} + T* getReadings() { return m_readings; } private: int m_interval; // number of data points for the moving average int m_nbrReadings; // number of readings - long m_sum; // sum of the m_readings array + // Sum type adapts to T: long for integers, T for floating point + using SumType = typename std::conditional::value, T, long>::type; + SumType m_sum; int m_next; // index to the next reading - int* m_readings; // pointer to the dynamically allocated interval array + T* m_readings; // pointer to the dynamically allocated interval array }; + +// Include the implementation to satisfy template instantiation requirements +#include "movingAvg.tpp" + #endif diff --git a/lib/obp60task/movingAvg.tpp b/lib/obp60task/movingAvg.tpp new file mode 100644 index 0000000..4468ee0 --- /dev/null +++ b/lib/obp60task/movingAvg.tpp @@ -0,0 +1,88 @@ +// Arduino Moving Average Library +// https://github.com/JChristensen/movingAvg +// Copyright (C) 2018 by Jack Christensen and licensed under +// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html + +// Extended to template class for handling of multiple data types + +//template +//movingAvg::movingAvg(int interval) +// : m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0}, m_readings{nullptr} +//{} + +// initialize - allocate the interval array +template +void movingAvg::begin() +{ + m_readings = new T[m_interval]; +} + +// add a new reading and return the new moving average +template +T movingAvg::reading(T newReading) +{ + // add each new data point to the sum until the m_readings array is filled + if (m_nbrReadings < m_interval) { + ++m_nbrReadings; + m_sum += newReading; + } + // once the array is filled, subtract the oldest data point and add the new one + else { + m_sum = m_sum - m_readings[m_next] + newReading; + } + + m_readings[m_next] = newReading; + if (++m_next >= m_interval) m_next = 0; + return getAvg(); +} + +// just return the current moving average +template +T movingAvg::getAvg() +{ + if (m_nbrReadings == 0) return 0; + + // Apply rounding for integers only + if (std::is_floating_point::value) { + return m_sum / m_nbrReadings; + } else { + return (m_sum + (SumType)m_nbrReadings / 2) / m_nbrReadings; + } +} + +// return the average for a subset of the data, the most recent nPoints readings. +// for invalid values of nPoints, return zero. +template +T movingAvg::getAvg(int nPoints) +{ + if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings) { + return 0; + } + + SumType sum{0}; + int i = m_next; + for (int n=0; n::value) { + return sum / nPoints; + } else { + return (sum + (SumType)nPoints / 2) / nPoints; // + } +} + +// start the moving average over again +template +void movingAvg::reset() +{ + m_nbrReadings = 0; + m_sum = 0; + m_next = 0; +} \ No newline at end of file