Microcontroller AD Sampling and Filtering Algorithms

In microcontroller AD sampling systems, sensor signals are prone to fluctuations due to power noise, electromagnetic interference, and other factors after conversion. Filtering algorithms are key to suppressing noise and retaining valid signals. They must be selected based on the type of noise, signal speed, and microcontroller resources, balancing noise suppression and signal response speed to improve measurement accuracy.

Microcontroller AD Sampling and Filtering Algorithms

In microcontroller AD sampling systems, the analog signals output by sensors are often affected by power noise, electromagnetic interference, and the noise inherent in the sensors themselves, leading to fluctuations (noise) in the digital values. The core function of filtering algorithms is to suppress noise and retain valid signals, thereby improving measurement accuracy.

01

The goal of AD sampling filtering

The raw data noise in AD sampling can be categorized into three types:

Pulsed noise: Sudden spike interference (e.g., electromagnetic pulses, contact sparks);

Random noise: Continuous small fluctuations (e.g., thermal noise from electronic components);

High-frequency noise: Rapid high-frequency jitter (e.g., mechanical vibrations from sensors).

Filtering algorithms must be selected based on the type of noise, the speed of signal changes, and the resources of the microcontroller (computational power, memory), with the core goal of balancing between “noise suppression” and “signal response speed”.

02

Principles and Calculation Formulas

1.Clipping Filter (Program Judgement Filter)

By setting a threshold, determine whether the current sampled value is a valid signal, eliminating sudden pulse noise.

Calculation formula:

If ∣X(n)−Y(n−1)∣≤threshold, then Y(n)=X(n);

Otherwise Y(n)=Y(n−1).

Where X(n) is the current sampled value, Y(n−1) is the last valid value, and Y(n) is the current valid value.

2.Median Filter

Continuously sample n (odd) data points, sort them, and take the middle value as the valid value to suppress spike noise.

Calculation formula:

For sampled data [X(1),X(2),…,X(n)], sorting gives [Xsorted(1),…,Xsorted(n)], then Y(n)=Xsorted(n+1)/2.

3.Arithmetic Mean Filter

Continuously sample n data points, calculate the average to smooth random noise.

Calculation formula:

Y(n)=(X(1)+X(2)+⋯+X(n))/n

4.Sliding Average Filter

Use a buffer of length n to store the latest data, updating the buffer and calculating the average each time, balancing real-time performance and smoothing effect.

Calculation formula:

Let the buffer data be [B(1),B(2),…,B(n)], new data X(n) replaces B(1), then the buffer updates to [B(2),…,B(n),X(n)], thus:

Y(n)=(B(2)+⋯+B(n)+X(n))/n

5.Weighted Average Filter

Assign higher weights to recent data, emphasizing the influence of new data and tracking signal trends.

Calculation formula:

Y(n)=w1X(1)+w2X(2)+⋯+wnX(n)

Where ∑(i=1→n)wi=1, and wn>wn−1>⋯>w1, wi is the weight.

6.First-Order Low-Pass Filter

Analog RC low-pass filtering, updating by weighting the current value and historical value to suppress high-frequency noise.

Calculation formula:

Y(n)=α⋅X(n)+(1−α)⋅Y(n−1)

Where 0<α<1 is the filter coefficient, with a larger α resulting in faster response and weaker filtering.

7.Kalman Filter

Based on “predict-update” recursive optimization, predicting the state through the system model and correcting errors, suitable for dynamic signals.

Calculation formula:

Prediction:

Microcontroller AD Sampling and Filtering Algorithms

Microcontroller AD Sampling and Filtering Algorithms

Update:

Microcontroller AD Sampling and Filtering Algorithms

Microcontroller AD Sampling and Filtering Algorithms

Microcontroller AD Sampling and Filtering Algorithms

Where A is the state transition matrix, B is the control matrix, H is the measurement matrix, Q is the process noise covariance, and R is the measurement noise covariance.

8.Composite Filtering

Combining basic algorithms to address complex noise (e.g., pulse + random noise), common combinations include “clipping + average” and “median + sliding average”.

03

Differences Between Various Filtering Algorithms

Algorithm Type

Differences

Clipping Filter

Only removes pulse noise through thresholds, with minimal computation, but cannot handle random noise and relies on empirical threshold values.

Median Filter

Suppresses spike noise by taking the median through sorting, effective against pulse interference, but real-time performance decreases with the number of samples, unsuitable for fast signals.

Arithmetic Mean Filter

Smooths random noise using the average, with effectiveness increasing with the number of samples, but poor real-time performance and sensitivity to pulse noise (easily raised/lowered).

Sliding Average Filter

Rolling updates data in the buffer, better real-time performance than arithmetic mean, continuously smooths random noise, but pulse noise may persist in the buffer.

Weighted Average Filter

Recent data has higher weight, can track signal trends, but weights need empirical adjustment and are weak against pulse noise.

First-Order Low-Pass Filter

Only uses current and historical values for weighting, with minimal computation, suppresses high-frequency noise, but lags in tracking fast signals and cannot handle pulse noise.

Kalman Filter

Dynamic optimization estimation, optimal for filtering dynamic signals, but requires a system model, complex calculations (matrix operations), and relies on noise statistical parameters.

Composite Filter

Combines algorithms to cover various noise, with strong flexibility, but implementation complexity is higher than single algorithms.

04

Code Examples (C Language, Based on Microcontroller)

1.Clipping Filter

#define THRESHOLD 5  // Threshold, adjust based on signal characteristics
float limitFilter(float currentVal, float lastVal) {
    if (fabs(currentVal - lastVal) <= THRESHOLD) {
        return currentVal;  // Valid signal, update value
    } else {
        return lastVal;     // Pulse noise, retain old value
    }
}

By setting the threshold THRESHOLD to determine whether the current sampled value currentVal is a valid signal. If the difference from the last valid value lastVal does not exceed the threshold, it is considered a valid signal and updated to the current value; otherwise, it is considered pulse noise and retains the old value. This method is simple and efficient, suitable for resource-constrained microcontrollers, especially effective when the signal changes slowly and occasional pulse interference occurs, but the threshold needs to be reasonably adjusted based on actual signal characteristics.

2.Median Filter

#define N 5  // Number of samples (odd)
float medianFilter() {
    float buf[N];  // Continuously sample N data points
    for (int i = 0; i < N; i++) {
        buf[i] = AD_Read();  // Assume AD_Read() is the AD sampling function
    }
    // Bubble sort
    for (int i = 0; i < N-1; i++) {
        for (int j = 0; j < N-1-i; j++) {
            if (buf[j] > buf[j+1]) {
                float temp = buf[j];
                buf[j] = buf[j+1];
                buf[j+1] = temp;
            }
        }
    }
    return buf[N/2];  // Return the middle value
}

Continuously sample N data points (N is odd) and store them in the array buf. Sort the sampled data using bubble sort, then take the middle value as the valid value to return. This algorithm effectively suppresses spike noise and has a good filtering effect against pulse interference. However, as the number of samples N increases, real-time performance may decrease, and it is not suitable for rapidly changing signals.

3.Arithmetic Mean Filter

#define N 10  // Number of samples
float arithmeticMeanFilter() {
    float sum = 0;
    for (int i = 0; i < N; i++) {
        sum += AD_Read();
    }
    return sum / N;  // Return the average
}

Continuously sample N data points, accumulate these data, and divide by N to obtain the average as the valid value. This method can effectively smooth random noise and reduce data fluctuations, suitable for scenarios where the signal changes slowly and contains random noise. However, its disadvantage is poor real-time performance, as it requires waiting for N samples to complete before calculating the result, and it has weak suppression of pulse noise.

4.Sliding Average Filter

#define N 8  // Buffer length
float buf[N];
int index = 0;  // Buffer index
float sum = 0;  // Sum of buffer data
float slidingMeanFilter(float newVal) {
    sum -= buf[index];  // Subtract the old value to be replaced
    buf[index] = newVal;  // Store the new value
    sum += newVal;
    index = (index + 1) % N;  // Update index (circular buffer)
    return sum / N;  // Return the average
}
// Initialization: fill the buffer and calculate initial sum
void slidingInit() {
    sum = 0;
    for (int i = 0; i < N; i++) {
        buf[i] = AD_Read();
        sum += buf[i];
    }
}

Using a buffer of length N to store the latest data. Each time new data newVal is sampled, it replaces the oldest data in the buffer, and the buffer data and sum are updated. This way, the algorithm can calculate the average of the data in the buffer in real-time, thus improving real-time performance while maintaining a certain smoothing effect. This algorithm is suitable for scenarios where the signal changes quickly but the noise is relatively stable, and it has a small computational load.

5.Weighted Average Filter

#define N 4  // Number of data points
float weights[N] = {0.1, 0.2, 0.3, 0.4};  // Weights (sum to 1, higher weight for recent data)
float buf[N];  // Store historical data
float weightedMeanFilter(float newVal) {
    // Move historical data (latest data stored in the last position)
    for (int i = 0; i < N-1; i++) {
        buf[i] = buf[i+1];
    }
    buf[N-1] = newVal;
    // Calculate weighted sum
    float result = 0;
    for (int i = 0; i < N; i++) {
        result += buf[i] * weights[i];
    }
    return result;
}

Assign different weights to data at different time points, with higher weights for recent data to emphasize the influence of new data and track signal trends. The algorithm multiplies the historical data stored in buf by the corresponding weights and sums them to obtain the weighted average as the valid value. This method is suitable for scenarios where the signal has trend changes, better reflecting the dynamic characteristics of the signal. However, the setting of weights needs to be adjusted based on actual signal characteristics, and its suppression effect on pulse noise is average.

6.First-Order Low-Pass Filter

#define ALPHA 0.3  // Filter coefficient (0<ALPHA<1)
float lastResult = 0;  // Last filtering result
float firstOrderFilter(float currentVal) {
    float result = ALPHA * currentVal + (1 - ALPHA) * lastResult;
    lastResult = result;  // Update historical value
    return result;
}

By using the filter coefficient ALPHA to weight the current sampled value currentVal and the last filtering result lastResult. A larger ALPHA value gives more influence to the current data, resulting in weaker filtering and faster response; conversely, stronger filtering and slower response. This algorithm has minimal computation and excellent real-time performance, suitable for signals with high-frequency noise, effectively suppressing high-frequency jitter, but has weak tracking ability for rapidly changing signals and cannot handle pulse noise.

7.Simplified Kalman Filter (One-Dimensional Scenario, e.g., Dynamic Temperature Measurement)

// Kalman parameters
float x_hat = 0;  // State estimate
float P = 1;      // Estimate error covariance
float Q = 0.01;   // Process noise covariance (adjust based on noise characteristics)
float R = 0.1;    // Measurement noise covariance (adjust based on sensor accuracy)
float K;          // Kalman gain
float kalmanFilter(float z) {  // z is the measurement value
    // Prediction
    float x_hat_minus = x_hat;  // State prediction (simplified model: x_k = x_{k-1})
    float P_minus = P + Q;      // Error covariance prediction
    // Update
    K = P_minus / (P_minus + R);  // Kalman gain
    x_hat = x_hat_minus + K * (z - x_hat_minus);  // State update
    P = (1 - K) * P_minus;  // Covariance update
    return x_hat;
}

Using parameters such as state estimate x_hat, estimate error covariance P, process noise covariance Q, measurement noise covariance R, and Kalman gain K to filter dynamic signals. This algorithm can adapt to noise changes and has excellent filtering effects for dynamic signals, theoretically providing optimal estimates. However, it requires establishing a system model, has high computational complexity, involves matrix operations, and has higher resource requirements for microcontrollers, with parameter determination being relatively complex.

8.Composite Filtering (Clipping + Sliding Average)

// First clipping, then sliding average
float limitSlidingFilter(float newVal, float lastVal) {
    // Step 1: Clipping filter
    float limitedVal;
    if (fabs(newVal - lastVal) <= THRESHOLD) {
        limitedVal = newVal;
    } else {
        limitedVal = lastVal;
    }
    // Step 2: Sliding average filter (reuse sliding average function)
    return slidingMeanFilter(limitedVal);
}

By using clipping filtering to eliminate pulse noise, and then using sliding average filtering to smooth random noise. In the code, first determine whether the current value newVal is a valid signal based on the threshold THRESHOLD; if it is a valid signal, perform sliding average filtering; otherwise, retain the old value. This combination method is suitable for complex noise scenarios, effectively addressing both pulse noise and random noise, but has relatively high implementation complexity and requires reasonable settings for the threshold and sliding average parameters.

Leave a Comment