Шум аналогового входа

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


Подключив датчик к контроллеру, увидим постоянно скачущие значения физической величины. Если нам нужно управлять каким-либо исполнительным механизмом в зависимости от величины такого прыгающего значения, то механизм может вести себя довольно неадекватно. Так что любой аналоговый сигнал рекомендуется сглаживать при помощи программного фильтра.

Давайте рассмотрим два интересных способа программной фильтрации этих шумов. 

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

int sensorPin = A0; // номер аналогового входа

// функция считывает аналоговый вход заданное количество раз
// и возвращает отфильтрованное значение
int readMean(int pin, int samples){
// переменная для хранения суммы считанных значений
int sum = 0;
// чтение и складывание значений
for (int i = 0; i < samples; i++){
sum = sum + analogRead(pin);
}
// делим сумму значений на количество измерений
sum = sum/samples;
// возвращаем среднее значение
return sum;
}
// функция считывает аналоговый вход заданное количество раз
// и возвращает медианное отфильтрованное значение
int readMedian (int pin, int samples){
// массив для хранения данных
int raw[samples];
// считываем вход и помещаем величину в ячейки массива
for (int i = 0; i < samples; i++){
raw[i] = analogRead(pin);
}
// сортируем массив по возрастанию значений в ячейках
int temp = 0; // временная переменная
for (int i = 0; i < samples; i++){
for (int j = 0; j < samples - 1; j++){
if (raw[j] > raw[j + 1]){
temp = raw[j];
raw[j] = raw[j + 1];
raw[j + 1] = temp;
}
}
}
// возвращаем значение средней ячейки массива
return raw[samples/2];
}
void setup(){
Serial.begin(9600);
}
void loop(){
// выводим значение на аналоговом входе в монитор порта
Serial.print(analogRead(sensorPin));
Serial.print(" ");
// выводим среднеизмеренное значение
Serial.print(readMean(sensorPin, 15));
Serial.print(" ");
// выводим медианное отфильтрованное значение
Serial.println(readMedian(sensorPin, 15));
delay(100);
}

Изобретено множество программных фильтров, но мы здесь рассматриваем два самых используемых типа: фильтр по среднему значению и медианный фильтр.

Первый - фильтр по среднеизмеренному значению

Данный алгоритм собирает несколько значений и вычисляет по ним среднее значение. Он довольно хорошо убирает шум, но требует больших затрат времени цикла от контроллера. Из-за того, что необходимо сделать несколько выборок сигнала с аналогового входа. Таким образом увеличивается время ответа при опросе входного значения главной программой. Но медленное получение значения лучше чем скачущее значение.

1) Объявляем функцию с двумя параметрами: первый содержит номер аналогового входа Arduino, куда подключен датчик; а второй задает количество выборок.

2) Далее мы циклически считываем значение аналогового входа и каждый раз прибавляем его к переменной sum
int sum = 0;
for (int i = 0; i < samples; i++){
sum = sum + analogRead(pin);
}

3) Дальше находим среднее значение. Сумму всех значений выборок делим на количество выборок
sum = sum/samples;

Второй фильтр - медианный

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

1) Объявляем функцию медианного фильтра, принимающую номер аналогового входа и количество выборок
int readMedian (int pin, int samples){
2) Дальше объявляем массив для хранения данных и в цикле заполняем этот массив считываемыми с аналогового входа данными
int raw[samples];
for (int i = 0; i < samples; i++){
raw[i] = analogRead(pin);
}

Дальше алгоритм делает сортировку массива по значению. Для этого используется так называемый пузырьковый алгоритм. Он выстроит ячейки массива по порядку от меньших значений до больших.

И в конце функции возвращаем значение средней ячейки отсортированного массива.

return raw[samples/2];

Основной цикл программы

В основном цикле программы мы просто циклически выводим полученные данные в монитор порта, чтобы проследить за изменениями измеряемого параметра во времени. В одну строку программа должна выводить нефильтрованное значение и два фильтрованных разными алгоритмами значения. Таким образом мы сможем оценить качество фильтрации разными способами.

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

Serial.print(analogRead(sensorPin));
Serial.print(" ");
Serial.print(readMean(sensorPin, 15));
Serial.print(" ");
Serial.println(readMedian(sensorPin, 15));
delay(100);
<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Модуль i2c для LCD индикаторов

Модуль i2c для LCD индикаторов

Модуль припаивается на LCD-индикатор типа LCD 2004, LCD 1602.Обеспечивает связь жидкокристаллическог..

55.23грн.

Задатчик тока 4 20мА. Схема простого в изготовлении токового задатчика

Задатчик тока 4 20мА. Схема простого в изготовлении токового задатчика

Прибор позволяет получать на выходе 0...20 мА, 4...20 мА. Области применения представленного устр..

Arduino Nano 3.0

Arduino Nano 3.0

Миниатюрная плата контроллера из линейки Aduino на базе микропроцессора ATMEGA328P-AU (это тот же ко..

179.44грн.

АЦП ADS1115 4-х канальный

АЦП ADS1115 4-х канальный

АЦП ADS1115 4-х канальный ADS1115 — это 4-х канальный 16-разрядный аналого-цифровой преобразовате..

99.62грн.

ЦАП цифро-аналоговый преобразователь I2C

ЦАП цифро-аналоговый преобразователь I2C

Цифро-аналоговый преобразователь с I2C интерфейсом на основе микросхемы MCP4725Используетс..

139.58грн.