Працюємо з 09:00 до 20: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 = i; 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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Модуль питания 5В, 3,3В для макетных плат

Модуль питания 5В, 3,3В для макетных плат

Модуль питания для удобной подачи напряжения питания на макетную плату.Внешнее питание 5В через USB ..

29.49грн.

Шаговый двигатель NEMA17

Шаговый двигатель NEMA17

Две фазыСила удержания 40N.cmМаксимальный ток  потребления 1,7 ААктивное сопротивление фаз..

329.18грн.

STM32F103C8T6 ARM STM32

STM32F103C8T6 ARM STM32

Минимальная плата контроллера от мирового лидера по производству контроллеров - фирмы STM32.Для зали..

74.52грн.

Винтовой коннектор на три провода

Винтовой коннектор на три провода

Монтируется на печатную плату или макетную платуРасстояние между выводами 5 мм..

4.14грн.

USB Паяльник 8 Вт

USB Паяльник 8 Вт

Напряжение питания 5 В Мощность потребления 8 Вт Время нагрева <15 сек Время остывания <30 ..

166.12грн.