Працюємо з 09:00 до 19:00 без вихідних
Самовивіз не працює до 03.08

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

Будь-який аналоговий датчик, з'єднувальні дроти, та і сам аналоговий вхід контролера вносять у результуюче виміряне значення безліч шумів. Вони заважають нам отримати реальне значення параметру з повторюваною точністю.


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

Давайте розглянемо два цікавих способи програмної фільтрації цих шумів. 

Наступна програма для контролера 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 размітка не підтримується! Використовуйте звичайтий текст.
    Погано           Добре
Модуль твердотільного реле 4-канальний

Модуль твердотільного реле 4-канальний

Модуль призначений для комутації 4-х навантажень зі змінною напругою живлення 75 ... 264 ВМаксимальн..

156.14грн.

Джойстик двохосьовий

Джойстик двохосьовий

Джойстик двохосьовий з кнопкою. Має два аналогових виходи для передачі даних про положення джой..

28.22грн.

Корпус пластиковий 85x58x33мм

Корпус пластиковий 85x58x33мм

Герметичний корпус для саморобних електронних пристроївМатеріал - пластикРозміри 85 x 58 x 33 мм..

66.89грн.

Муфта на кроковий двигун 5x8x25мм

Муфта на кроковий двигун 5x8x25мм

Ця муфта слугує перехідником між валами 5 мм та 8 мм. Тобто містить з одного боку отвір діаметром 5 ..

36.10грн.

Драйвер крокового двигуна L298N

Драйвер крокового двигуна L298N

Модуль драйвера для керування роботою одного двохполюсного крокового двигуна або двома двигунами пос..

60.85грн.