1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2026-08-18 10:22:31 +02:00

Convert class <movingAvg> to accept flexible data types

This commit is contained in:
Ulrich Meine
2026-03-26 21:57:17 +01:00
parent aecc3c775f
commit a445726757
4 changed files with 108 additions and 77 deletions
+2 -2
View File
@@ -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<int> batV(arrayBatV);
movingAvg<int> batC(arrayBatC);
batV.begin();
batC.begin();
-67
View File
@@ -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 <movingAvg.h>
// 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<nPoints; ++n) {
if (i == 0) {
i = m_interval - 1;
}
else {
--i;
}
sum += m_readings[i];
}
return (sum + nPoints / 2) / nPoints;
}
}
// start the moving average over again
void movingAvg::reset()
{
m_nbrReadings = 0;
m_sum = 0;
m_next = 0;
}
+18 -8
View File
@@ -3,27 +3,37 @@
// 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
#ifndef MOVINGAVG_H_INCLUDED
#define MOVINGAVG_H_INCLUDED
template <typename T>
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<std::is_floating_point<T>::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
+88
View File
@@ -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 <typename T>
//movingAvg<T>::movingAvg(int interval)
// : m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0}, m_readings{nullptr}
//{}
// initialize - allocate the interval array
template <typename T>
void movingAvg<T>::begin()
{
m_readings = new T[m_interval];
}
// add a new reading and return the new moving average
template <typename T>
T movingAvg<T>::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 <typename T>
T movingAvg<T>::getAvg()
{
if (m_nbrReadings == 0) return 0;
// Apply rounding for integers only
if (std::is_floating_point<T>::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 <typename T>
T movingAvg<T>::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<nPoints; ++n) {
if (i == 0) {
i = m_interval - 1;
}
else {
--i;
}
sum += m_readings[i];
}
if (std::is_floating_point<T>::value) {
return sum / nPoints;
} else {
return (sum + (SumType)nPoints / 2) / nPoints; //
}
}
// start the moving average over again
template <typename T>
void movingAvg<T>::reset()
{
m_nbrReadings = 0;
m_sum = 0;
m_next = 0;
}