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

Дистанційне управління двома лампочками

Дистанційне управління двома лампочками або іншими споживачамиПрацює на радіохвилях - можна керувати..

125.66грн.

Модуль WAV-плеєра

Модуль WAV-плеєра

Читає аудіо-файли формату WAV ADCPM 4біт (AD4)Напруга логічних рівнів 3,3 ВУправління від контр..

89.49грн.

Фоторезистивний датчик

Фоторезистивний датчик

Фоторезистивний датчик для вимірювання рівня освітлення.Змінює свій опір в залежності від інтенсивно..

3.11грн.

Кроковий двигун NEMA17

Кроковий двигун NEMA17

Дві фазиСила утримування 40N.cmМаксимальний струм споживання 1,7 ААктивний опір фази 1,5 ОмКут ..

330.59грн.

Ковпачок на змінний резистор 6мм

Ковпачок на змінний резистор 6мм

Чорно-білий декоративний ковпачок для змінних резисторів та енкодерів з отвором у вигляді зіркиВнутр..

7.39грн.