From 63dfeb53e0ea8255b47f582efdd37eb029bb043d Mon Sep 17 00:00:00 2001 From: JChristensen Date: Mon, 4 Nov 2024 10:07:26 -0500 Subject: [PATCH] Add an optional parameter to the constructor to cause getAvg() to return zero instead of causing a divide-by-zero situation if it is called before any readings are recorded. --- README.md | 9 +++++++-- library.properties | 2 +- src/movingAvg.cpp | 5 ++++- src/movingAvg.h | 16 +++++++++------- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 41211f2..b028bcf 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,15 @@ along with this program. If not, see The user specifies the interval (number of data points) for the moving average in the constructor. When the `begin()` function is called, an array is dynamically allocated to hold the number of data points in the interval. This array is never deallocated, and the user should call `begin()` only once (for a given `movingAvg` instance) in setup or other initialization code. Dynamic allocation is used strictly with the intent of creating the proper size array for the user's purposes, and not to free up the memory at a later point. It is strongly recommended that `movingAvg` objects remain allocated as long as the code is running. Failure to observe these guidelines can result in heap fragmentation, crashes and other undesired behavior. ## Constructor -### movingAvg(int interval) +### movingAvg(int interval, bool avoidDivByZero=false) ##### Description Defines a `movingAvg` object where the average is calculated using *interval* data points. ##### Syntax `movingAvg(interval);` ##### Parameters -**interval:** The number of data points to use when calculating the moving average. *(int)* +**interval:** The number of data points to use when calculating the moving average. *(int)* + +**avoidDivByZero:** Optional parameter that causes `getAvg()` ([see caution below](#getavg)) to return zero if called before any readings are recorded. *(bool, defaults to false if not given)* ##### Returns None. ##### Example @@ -53,6 +55,7 @@ mySensor.begin(); ### reading(int dataPoint) ##### Description Adds a new data point to the moving average. Returns the new moving average value. Until the interval array is filled, the average is calculated from those data points already added, i.e. a fewer number of points than defined by the constructor - thanks to Tom H. (Duckie) for this idea! + ##### Syntax `reading(dataPoint);` ##### Parameters @@ -68,6 +71,8 @@ int sensorMovingAvg = mySensor.reading(sensorData); ### getAvg() ##### Description Returns the current moving average value without adding a new reading. + +**Caution:** If `getAvg()` is called before any data points (readings) are recorded, a divide-by-zero situation will occur, likely with unpredictable/undesirable results. To instead have `getAvg()` return a value of zero in this case, set the optional `avoidDivByZero` parameter in the [constructor](#movingavgint-interval-bool-avoiddivbyzerofalse) to `true`. Note that this may require the caller to implement additional logic to differentiate between a "no data" situation and one where the average is actually zero. ##### Syntax `getAvg();` ##### Parameters diff --git a/library.properties b/library.properties index 230891e..c32f088 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=movingAvg -version=2.3.1 +version=2.3.2 author=Jack Christensen maintainer=Jack Christensen sentence=A simple Arduino library for calculating moving averages. diff --git a/src/movingAvg.cpp b/src/movingAvg.cpp index b9a46ab..b3e5314 100644 --- a/src/movingAvg.cpp +++ b/src/movingAvg.cpp @@ -32,7 +32,10 @@ int movingAvg::reading(int newReading) // just return the current moving average int movingAvg::getAvg() { - return (m_sum + m_nbrReadings / 2) / m_nbrReadings; + if (m_nbrReadings || !m_avoidDivByZero) + return (m_sum + m_nbrReadings / 2) / m_nbrReadings; + else + return 0; } // return the average for a subset of the data, the most recent nPoints readings. diff --git a/src/movingAvg.h b/src/movingAvg.h index dadd2c3..dbee275 100644 --- a/src/movingAvg.h +++ b/src/movingAvg.h @@ -9,8 +9,9 @@ class movingAvg { public: - movingAvg(int interval) - : m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0} {} + movingAvg(int interval, bool avoidDivByZero=false) + : m_interval{interval}, m_avoidDivByZero{avoidDivByZero}, + m_nbrReadings{0}, m_sum{0}, m_next{0} {} void begin(); int reading(int newReading); int getAvg(); @@ -20,10 +21,11 @@ class movingAvg int* 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 - int m_next; // index to the next reading - int* m_readings; // pointer to the dynamically allocated interval array + int m_interval; // number of data points for the moving average + bool m_avoidDivByZero; // return a zero average if requested when there are no data points + int m_nbrReadings; // number of readings + long m_sum; // sum of the m_readings array + int m_next; // index to the next reading + int* m_readings; // pointer to the dynamically allocated interval array }; #endif