Average the last N samples with a fixed-size ring buffer.
Application scenarios
- Battery voltage or temperature changes slowly, and the display must not flicker.
- An ADC channel has white noise but no large impulses.
- A control loop needs a simple, bounded-lag smooth.
Contract
void moving_average_init(moving_average_t *filter, uint16_t *window, uint8_t size);
uint16_t moving_average_step(moving_average_t *filter, uint16_t sample);
void moving_average_reset(moving_average_t *filter);
- The caller supplies
window, an array ofsizeelements. sizemust be 1..255.- A
uint32_tsum holds up to 255uint16_tsamples without overflow. - Output is rounded to the nearest integer.
- O(1) per sample.
Parameters
- Larger
size: smoother but slower; the step response reaches about 63% after N samples. - A spike still moves the mean by
spike/N; usemedianfirst if spikes exist.
Memory and timing
- State is 12 bytes plus the caller's
2*sizebytes. - O(1) per sample; no division until the output is computed.
Integration
uint16_t window[8];
moving_average_t filter;
moving_average_init(&filter, window, 8);
uint16_t smooth = moving_average_step(&filter, adc_read());
When not to use
- Impulses matter; one spike contaminates the window.
- Very fast response is required; use
emawith a small shift.
Verification
make test covers warm-up, wrap, rounding, size 1, size 0, and reset.
Behavior reference: Padauk Soft_Filter/AD_filter_04.
Extracted from the public header at the catalog tag. The README contract above is the behavior reference.
Functions
void moving_average_init(moving_average_t *filter, uint16_t *window, uint8_t size);uint16_t moving_average_step(moving_average_t *filter, uint16_t sample);void moving_average_reset(moving_average_t *filter);Types
moving_average_t structuint16_t *window;
uint8_t size;
uint8_t count;
uint8_t index;
uint32_t sum;