The Challenge of Noisy Sensor Data in Embedded Systems
If you have ever worked with Arduino and analog sensors—whether it’s an ultrasonic distance sensor, an LDR, or a pressure transducer—you have undoubtedly encountered the "spike." One moment your data stream is smooth, and the next, a stray electrical surge or interference causes a reading to jump to the maximum or minimum range, throwing off your control loop or data analysis.
For many beginners, the immediate reaction is to use a Simple Moving Average (SMA). However, while the SMA is excellent for white Gaussian noise, it is abysmal at handling impulse noise. If a single spike is significantly larger than the true signal, it will disproportionately pull the moving average away from the actual value. This is where the median filter becomes the gold standard for robust signal processing.
Understanding the Median Filter Logic
Unlike an average filter, which performs arithmetic operations, the median filter is a non-linear digital filter. It works by collecting a window of samples, sorting them in numerical order, and selecting the middle value (the median).
Because the median is essentially the "center" value, outliers—regardless of how extreme they are—have virtually no impact on the result. If your signal is 10, 11, 10, 100 (the spike), and 12, the sorted array becomes 10, 10, 11, 12, 100. The median is 11. The spike (100) is completely discarded. This makes it an incredibly powerful tool for real-time median filter eliminate spike noise Arduino workflows.
Why Median Filters Outperform Moving Averages
In signal processing, the choice of filter determines the integrity of your control system. The following comparison highlights why you should pivot to median filtering for sporadic noise:
| Feature | Moving Average (SMA) | Median Filter |
|---|---|---|
| Noise Type | Best for Gaussian/Random | Best for Impulse/Spike |
| Outlier Resistance | Low (outliers affect result) | High (outliers are ignored) |
| Edge Preservation | Blurs sharp signal changes | Maintains sharp edges |
| Computational Cost | Very Low | Moderate (requires sorting) |
| Implementation | Simple Summation | Sorting Algorithm (Bubble/Insertion) |
Coding a Real-Time Median Filter for Arduino
To implement this efficiently, you don’t need to reinvent the wheel. We use a circular buffer to store a set number of samples, ensuring we don't need to shift memory around constantly.
The Algorithm Steps
- Initialize a circular buffer (e.g., size 5 or 7).
- Collect a new sample from the sensor.
- Overwrite the oldest sample in the buffer with the new one.
- Copy the buffer to a temporary array.
- Sort the temporary array.
- Return the middle element.
Implementation Example (Snippet)
```cpp
#define WINDOW_SIZE 5
int buffer[WINDOW_SIZE];
int index = 0;
int getMedian(int newValue) {
buffer[index] = newValue;
index = (index + 1) % WINDOW_SIZE;
int temp[WINDOW_SIZE];
for(int i = 0; i < WINDOW_SIZE; i++) temp[i] = buffer[i];
// Simple Insertion Sort
for(int i = 1; i < WINDOW_SIZE; i++) {
int key = temp[i];
int j = i - 1;
while(j >= 0 && temp[j] > key) {
temp[j + 1] = temp[j];
j--;
}
temp[j + 1] = key;
}
return temp[WINDOW_SIZE / 2];
}
```
Optimizing for Performance and Memory
While the code above works perfectly for small windows, scaling is critical. Sorting an array every time a new sample arrives is computationally expensive. If you increase the WINDOW_SIZE beyond 15 or 20, you will notice significant latency in your main loop.
Tips for Efficiency
- Keep the Window Small: For most Arduino spike-noise applications, a window size of 5 or 7 is sufficient to catch even multiple spikes without creating excessive lag.
- Use Insertion Sort: Because your array is "nearly sorted" from the previous iteration, insertion sort is significantly faster than Quicksort for small buffers.
- Data Types: Use
intoruint16_trather thanfloatif your sensor output permits, as floating-point math is slower on 8-bit AVR microcontrollers like the ATmega328P.
When to Avoid the Median Filter
While the median filter is a powerhouse, it is not a "silver bullet." If your signal noise is not spike-like (e.g., if you have constant white noise where the sensor fluctuates +/- 5 units), a median filter might actually make the output look "steppy" or quantized.
In scenarios where you have both spike noise AND high-frequency jitter, the professional approach is a "hybrid filter." You apply the median filter first to strip out the spikes, then feed that output into a low-pass or moving average filter to smooth out the remaining jitter. This two-stage approach provides the cleanest possible signal for sensitive applications like PID motor control or flight stabilization.
Final Thoughts: Building Robust Systems
Implementing a real-time median filter is a rite of passage for every serious Arduino developer. By decoupling your signal processing logic from your sensor acquisition, you move from "it mostly works" to "it is production-ready." Remember: sensors are inherently messy. Your code should be the filter that brings order to that chaos. Start small, test your window sizes, and watch your sensor data stabilize instantly.