#include <AH/Filters/EMA.hpp>
Exponential moving average filter.
Fast integer EMA implementation where the weight factor is a power of two.
Difference equation: \( y[n] = \alpha·x[n]+(1-\alpha)·y[n-1] \) where \( \alpha = \left(\frac{1}{2}\right)^{K} \), \( x \) is the input sequence, and \( y \) is the output sequence.
An in-depth explanation of the EMA filter
K | The amount of bits to shift by. This determines the location of the pole in the EMA transfer function, and therefore the cut-off frequency. The higher this number, the more filtering takes place. The pole location is \( 1 - 2^{-K} \). |
input_t | The integer type to use for the input and output of the filter. Can be signed or unsigned. |
state_t | The unsigned integer type to use for the internal state of the filter. A fixed-point representation with \( K \) fractional bits is used, so this type should be at least \( M + K \) bits wide, where \( M \) is the maximum number of bits of the input. |
Some examples of different combinations of template parameters:
analogRead
: analogRead returns an integer between 0 and 1023, which can be represented using 10 bits, so \( M = 10 \). If input_t
and output_t
are both uint16_t
, the maximum shift factor K
is \( 16 - M = 6 \). If state_t
is increased to uint32_t
, the maximum shift factor K
is \( 32 - M = 22 \).input_t
is int16_t
, and \( M = 16 \). (2¹⁵ = 32768) Let's say the shift factor K
is 1, then the minimum width of state_t
should be \( M + K = 17 \) bits, so uint32_t
would be a sensible choice. Public Member Functions | |
EMA (input_t initial=input_t{0}) | |
Constructor: initialize filter to zero or optional given value. | |
void | reset (input_t value=input_t(0)) |
Reset the filter to the given value. | |
input_t | filter (input_t input) |
Filter the input: Given \( x[n] \), calculate \( y[n] \). | |
input_t | operator() (input_t input) |
Filter the input: Given \( x[n] \), calculate \( y[n] \). | |
Static Public Member Functions | |
template<class T > | |
static constexpr bool | supports_range (T min, T max) |
Verify the input range to make sure it's compatible with the shift factor and the width of the state type. | |
Static Public Attributes | |
static constexpr state_t | max_state = std::numeric_limits<state_t>::max() |
static constexpr state_t | half_state = max_state / 2 + 1 |
static constexpr state_t | zero = std::is_unsigned<input_t>::value ? state_t{0} : half_state |
static constexpr state_t | half = K > 0 ? state_t{1} << (K - 1) : state_t{0} |
Private Attributes | |
state_t | state |
|
inlinestaticconstexpr |
Verify the input range to make sure it's compatible with the shift factor and the width of the state type.
Examples: