Віримо в перемогу ЗСУ!
Працюємо з 09:00 до 18:00 Пн-Сб

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

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


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

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

Следующая программа для контроллера 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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Arduino закачивание детской кроватки по крику

Arduino закачивание детской кроватки по крику

Привет друзья!  Представляю интересный проект для новоиспеченных папочек. Это - автоматическ..

Ниодимовый магнит 12mm x 3mm N35

Ниодимовый магнит 12mm x 3mm N35

Цилиндрический ниодимовый магнит N35Размеры 12мм x 3ммИдеально подходит для работы в связке с магнит..

13.44грн.

Понижающий преобразователь напряжения с ограничением по току 8...36В в 1,25...32В 5А

Понижающий преобразователь напряжения с ограничением по току 8...36В в 1,25...32В 5А

Импульсный преобразователь напряжения постоянного тока с 8 ... 36В в 1,25 ... 32В на основе мик..

95.69грн.

Модуль блока питания 3,3В 1А

Модуль блока питания 3,3В 1А

Удобный модуль питания из 220В AC в 3,3В постоянного тока. Разработан для установки на печатную плат..

147.77грн.

Стерео усилитель 2х5Вт  PAM8406

Стерео усилитель 2х5Вт PAM8406

Стерео усилитель звуковой частоты класса D с подстроечными резисторами регулирования громкости на ми..

65.09грн.