Среднее скользящее (сглаживание измерений на микроконтроллерах STM32, AVR, PIC, Arduino)

Получая измеренные значения от АЦП напрямую мы наблюдаем как они скачут, для конечного пользователя (да и для нас) это не очень хорошо. Нужно фильтровать значения, чтобы на экран выводилось четкая цифра. Посмотрим наглядные примеры сглаживания методом скользящего среднего (simple moving average).

Пример реальных шумящих данных

Это измерения с  датчика температуры HTU21D (уже преобразованные в температуру). На первый взгляд кажется все что красиво и гладко:

Но увеличив масштаб видно, что даже когда датчик никто не трогал регистрировались изменения из-за его высокой чувствительности.

Это значение я вывожу на экране телефона (связь с которым происходит через Bluetooth с помощью классного модуля JDY-23 BLE 5.0), если они будут так скакать, то это будет сбивать с толку пользующегося и оставит неприятные впечатления, не давая никаких преимуществ в точности показаний.

Как работает

Создаем массив данных, с количеством элементов равным порядку фильтра.

1) В последнюю ячейку загружаем новое "сырое" значение
2) Вычисляем среднее арифметическое (сумма всех элементов делится на их количество) - это и будет отфильтрованное значение.
3) Сдвигаем все элементы влево.
4) Возвращаемся к пункту 1.

Фильтруем данные в Mathcad

Здесь фильтр сделан чутка по другому (применена скользящая средняя формула в виде суммы начиная с числа m), в том смысле, что первые m значений (m - порядок фильтра) не вычисляются (нули), ну а все остальные отфильтрованные значения будут такие же, как описано в алгоритме и реализовано в программке на C.

Здесь видно насколько хорошо можно подавлять постоянный шум.

Скачать файл Mathcadsma_example.zip
(пароль: cxemka.com)

Выбор порядка фильтра

Следующие графики позволили выбрать порядок фильтра для моего применения, при этом нужно стремится к тому, чтобы получить кривую без мелких шумов, но с адекватной скоростью реакции на резкие изменения.

Здесь конечно не так хорошо видно разницу, но все же. Думаю, здесь оптимальным будет фильтр с шестым порядком.

Программная реализация на языке C

Задается порядок фильтра и создается массив с тем же размеров и нужным вам типом данных (файл filter_sma.h):

#include "main.h" /* Choose filter order */ #define FILTER_SMA_ORDER 12 /** * @brief Simple Moving Average (SMA) filter. * @note Before use define filter order. * @param[in] Input raw (unfiltered) value. * @retval Return filtered data. */ uint16_t Filter_SMA(uint16_t For_Filtered);

Ну и простая функция собственно, принимающая сырое значение и возвращающая отфильтрованное (файл filter_sma.c): 

#include "filter_sma.h" uint16_t Filter_Buffer[FILTER_SMA_ORDER] = {0,}; /** * @brief Simple Moving Average (SMA) filter. * @note Before use define filter order. * @param[in] Input raw (unfiltered) value. * @retval Return filtered data. */ uint16_t Filter_SMA(uint16_t For_Filtered) { /* Load new value */ Filter_Buffer[FILTER_SMA_ORDER - 1] = For_Filtered; /* For output value */ uint32_t Output = 0; /* Sum */ for(uint8_t i = 0; i < FILTER_SMA_ORDER; i++) { Output += Filter_Buffer[i]; } /* Divide */ Output /= FILTER_SMA_ORDER; /* Left Shift */ for(uint8_t i = 0; i < FILTER_SMA_ORDER; i++) Filter_Buffer[i] = Filter_Buffer[i+1]; /* Return filtered value */ return (uint16_t) Output; }

Пример фильтрации

Вот данные опять же с датчика температуры HTU21D, стоял он на подоконнике у окна (примерно с 3:00 до 6:00), а измерения проводились раз в секунду.

Ну тут вообще колебания с большим размахом, увеличим масштаб:

Ну, а теперь смотрим на красный график скользящей средней. Для такого большого количества отсчетов и порядок был выбран большой ( m = 26).

В данном случае такие частые измерения не нужны, т.к разница в экстремумах шума Δ T = 0.02 °C, при абсолютной погрешности датчика ΔT = 0.2-0.3 °C.

А вот вообще порядок m = 256:

Увеличено:

Еще пример (отображение на экране)

Здесь действие фильтра не очень наглядно показано, но оно на самом деле есть 

Скачать

https://github.com/Egoruch/Filter-Simple-Moving-Average

Filter-Simple-Moving-Average-master.zip
Файл filter_sma.c и filter_sma.h

Видео

Перечень ссылок

Статья написана при использовании:

Выводы

На наглядном примере вы увидели действие  метода  простого среднего скользящего, широко применяемого и действительно простого в воплощении даже на мелком МК способа фильтрации. Его легко использовать в разных встраиваемых системах на различных платформах STM32, AVR, PIC, Arduino. В частности SMA использовался при работе с датчиком HTU21DAHT10, фоторезистором, терморезистором...

Пройдя по ссылкам из перечня можно ознакомится с более усложненными видами фильтров для сглаживания шумов, которые эффективно будет уже применять для работы с данными на ПК/телефоне, чтобы не грузить микроконтроллер. В моих простых применениях они будут избыточны, но взять на заметку их нужно.

124
RSS
Нет комментариев. Ваш будет первым!
Загрузка...