Sensors & Signal Processing
How an exponential moving average filter works
An exponential moving average (EMA) smooths a noisy reading with one line of code: each sample, move a running value a fraction alpha of the way toward the new reading. Recent readings count most, and older ones fade away exponentially. A small alpha is smooth but slow to follow real changes; a large one is quick but lets noise through.
One line
With α = 0.125, filtered at 400 and a reading of 480, the gap is 80 and an eighth of it is 10, so filtered moves to 410. The next reading nudges it again. A noisy reading jumps around, but each jump only moves the value an eighth of the way, and the jumps in opposite directions largely cancel.
float filtered = 0;
void setup() {
filtered = analogRead(A0); // start from a real reading
}
void loop() {
int reading = analogRead(A0);
filtered = filtered + 0.125 * (reading - filtered);
}
Live experiment
Alpha is the trade
The filter has settled on a knob at 30 %, and the lamp lights above 480. At 1 s the knob jumps to 70 %, at 2 s it drops to 45 %. Alpha 1 follows at once and flickers on the noise; 0.125 lights within 0.05 s and stays calm; 0.016 takes a third of a second and is still lit at 3 s.
“Smooth it out” is lesson 2 of 6 in Signal Sands, Sensors & Signal Processing World 1. Free with an account. Lessons unlock in order, so you’ll do the one before it first.
Alpha is the trade
- α = 1 copies every reading: no smoothing at all.
- α = 0.5 moves halfway each time: quick, but half of every jitter gets through.
- α = 0.125 is a common choice: calm, and still quick.
- α = 0.016 is very smooth, and very slow, to rise and to fall.
As a rule of thumb, the filter takes about 1 ÷ α samples to cover most of a sudden change, about 63% of it. Sampled 100 times a second, α = 0.125 responds in about 8 samples, 80 ms.
It's a low-pass filter
An EMA is the digital twin of an RC low-pass filter: slow changes pass, fast wobbles shrink. For small alpha its cutoff frequency is about:
So α = 0.02 at 100 samples a second cuts off around 0.32 Hz. Run the same code ten times as fast and the cutoff rises ten times: alpha is per sample, not per second.
Why it's everywhere
It needs one variable, no buffer and one multiply per sample, which makes it ideal for small microcontrollers. Battery gauges, fan speed readouts, audio level meters and the D term of many PID controllers all use it. For a sharper trade between smoothness and delay, chain two in a row; for wild one-off spikes, put a median filter in front.
Free lesson
Now build it yourself
Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.
“Smooth it out” is lesson 2 of 6 in Signal Sands, Sensors & Signal Processing World 1. Free with an account. Lessons unlock in order, so you’ll do the one before it first.
Or start from the very first lesson, no account neededPractice questions
Three quick questions from the lessons. Pick an answer to check it.
Show the answer
Answer: Smoother but slower to follow a change. A smaller step each sample means more samples to get anywhere, and more averaging of the noise along the way.
- Why not “Noisier”? Smaller steps average more readings together, so the noise shrinks rather than grows.
- Why not “Unchanged”? Alpha sets how far each sample moves the value, so changing it changes both the smoothing and the speed.
- Why not “Faster”? A smaller alpha moves less of the gap each sample, so it gets anywhere more slowly, not faster.
Show the answer
Answer: Copy every reading: no smoothing at all. filtered + (reading − filtered) × 1 is just the reading. Alpha 0 would never move at all.
- Why not “Halve each reading”? Halving each reading isn't what the line does. With alpha 1 the value simply becomes the reading.
- Why not “Never move”? Never moving is alpha 0: each sample would move the value by none of the gap.
- Why not “Twice as smooth”? Alpha 1 smooths less, not more. Each sample jumps the whole gap, straight to the reading.
Show the answer
Answer: An int would throw away the fraction of each nudge and get stuck short of the reading. With an int, (reading − filtered) × 0.125 rounds to 0 once the gap is under 8, and the value stops moving. A float keeps the fractions.
- Why not “It doesn't matter”? It matters: an int rounds away each small nudge and the filter stops short of the reading.
- Why not “analogRead returns a float”? analogRead returns a whole number. The filtered value needs fractions because of the small nudges.
- Why not “Floats are faster”? Speed isn't the point; on a small board floats are slower. They're used to keep the fractions.
“Smooth it out” is lesson 2 of 6 in Signal Sands, Sensors & Signal Processing World 1. Free with an account. Lessons unlock in order, so you’ll do the one before it first.
Questions people ask
What is an exponential moving average filter?
A running value that moves a fixed fraction, alpha, of the way toward each new reading: filtered = filtered + alpha × (reading − filtered). Recent readings count most and older ones fade away exponentially. It's the digital version of an RC low-pass filter.
How do I choose alpha?
Smaller alpha is smoother but slower. Roughly, the filter takes about 1 ÷ alpha samples to follow a change most of the way, and its cutoff is about alpha × sample rate ÷ 2π. Pick the largest alpha that makes the noise small enough.
Why does my filtered value get stuck short of the reading?
It's stored in an int. Once the gap is small, alpha times the gap is a fraction of a count and the int throws it away, so the value stops short. Use a float, or keep the value scaled up by a power of two.
Related topics
- How a moving average filter smooths a noisy sensorAverage 16 readings for a quarter of the noise, and know what it costs.
- Low-pass filter explainedA resistor and a capacitor that pass the bass and fade the treble, and where the cutoff sits.
- How a median filter removes spikes from a sensorSort three readings and keep the middle one: a lone spike never gets a say.
- How a complementary filter blends a gyro and accelerometerTrust the gyro for quick moves and the accelerometer for the long run.