Messwert-Mittelungscode mit festen Zeitfenstern für Mikrocontroller (C++)
English
Deutsch
Diese Klasse führt Mittelung mit einem festen Zeitfenster durch (variable Anzahl von Werten).
Von der Plattform benötigt sie nur eine Methode, um die aktuelle Zeit zu erhalten. Dieser Code enthält Implementierungen für sowohl ESP-IDF als auch Arduino
TimeThresholdAccumulatingAverager.hpp
#pragma once
#include <optional>
// Find the correct driver
#ifdef ARDUINO
#include <Arduino.h>
#define TTAA_GETTIME_MILLIS millis()
#elif defined(IDF_VER) && !defined(ARDUINO)
#include <esp_timer.h>
#define TTAA_GETTIME_MILLIS esp_timer_get_time() / 1000
#else
#error "Could not determine how to get the current time (Arduino or ESP-IDF)"
#endif
/**
* @brief This class is designed to accumulate and average values over a specified time threshold.
*
* The class is templated to allow accumulation of different numerical types, defaulting to float. It uses the Arduino `millis()`
* function to track elapsed time, automatically calculating the average of accumulated values once the predefined time threshold is reached.
* The `add()` method adds a new value to the accumulation, returning the average as a `std::optional<T>` when the threshold is reached,
* and `std::nullopt` otherwise. The `lastAverage()` method allows retrieval of the last calculated average at any time.
*/
template<typename T = float>
class TimeThresholdAccumulatingAverager {
public:
/**
* Constructs a new TimeThresholdAccumulatingAverager object.
*
* @param threshold The time threshold in milliseconds over which to accumulate and average values.
*/
TimeThresholdAccumulatingAverager(unsigned long threshold) : _threshold(threshold), _startTime(TTAA_GETTIME_MILLIS), _sum(), _count() {}
/**
* Adds a value to the accumulator. If the time threshold has been reached,
* calculates and returns the average of the accumulated values since the last threshold reset.
* Resets the accumulator for the next period if the threshold is reached.
*
* The given value is not added to the current average if the threshold has been
* exceeded. It is automatically added to the next period's average.
*
* @param value The value to add to the accumulator.
* @return std::optional<T> The average of accumulated values if the threshold is reached, otherwise std::nullopt.
*/
std::optional<T> add(T value) {
unsigned long currentTime = TTAA_GETTIME_MILLIS;
if (currentTime - _startTime >= _threshold) {
// Time threshold exceeded. Calculcate average
T average = _count > 0 ? _sum / static_cast<T>(_count) : 0;
_lastCount = _count;
// Reset sum & count to zero, but add the current value immediatey
_sum = value;
_count = 1;
_startTime = currentTime;
_lastAverage = average;
return average;
} else { // Time threshold not exceeded
_sum += value;
_count++;
return std::nullopt;
}
}
/**
* Returns the average of the last completed accumulation period.
*
* @return T The average value of the last completed period.
*/
inline T lastAverage() const {
return _lastAverage;
}
/**
* Returns the count value of the last completed accumulation period.
*
* @return The last count value.
*/
inline unsigned int lastCount() const {
return _lastCount;
}
private:
unsigned long _threshold;
unsigned long _startTime;
T _sum;
int _count = 0;
T _lastAverage = 0;
unsigned int _lastCount = 0;
};Verwendungsbeispiel:
usage_example.cpp
#include <optional>
#include <iostream>
#include "TimeThresholdAccumulatingAverager.hpp"
int main() {
TimeThresholdAccumulatingAverager<float> averager(1000); // 1 Sekunde Schwellwert
while (true) {
float newValue = acquireValue(); // Pseudocode zum Erfassen eines neuen Werts
auto maybeAverage = averager.add(newValue);
if (maybeAverage.has_value()) {
std::cout << "Mittelwert über Schwellwertperiode: " << average.value() << std::endl;
}
// Fügen Sie eine Verzögerung hinzu oder warten Sie auf einen echten neuen Wert in einer echten Anwendung
delay(10);
}
}Check out similar posts by category:
Arduino, Embedded, ESP8266/ESP32, PlatformIO
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow