Шум аналогового входу
Будь-який аналоговий датчик, з'єднувальні дроти, та і сам аналоговий вхід контролера вносять у результуюче виміряне значення безліч шумів. Вони заважають нам отримати реальне значення параметру з повторюваною точністю.
Підключивши датчик до контролера, побачимо постійно стрибаюче значення фізичної величини. Якщо нам потрібно керувати яким-небуть виконавчим механізмом в залежності від величини такого стрибаючого значення, то механізм може вести себе доволі неадекватно. Так що будь-який аналоговий сигнал рекомендується згладжувати за допомогою програмного фільтру.
Давайте розглянемо два цікавих способи програмної фільтрації цих шумів.
Наступна програма для контролера 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);
Контроллер ESP32-WROOM-32 (8MB)
ESP32-WROOM-32 - це потужний універсальний модуль Wi-Fi + BT + BLE MCU, призначений для широкого спе..
243.36грн.
Модуль I2C 4-х реле 5В
Модуль 4-х реле з управлінням по шині I2C на основі мікросхеми MCP23008Напруга котушок реле 5 ВДозво..
391.38грн.
Уроки Arduino для новачків 1.1.2 Плата Arduino
Отже продовжимо розмову про плату Arduino. Поговоримо про різні електронні компоненти на ній.&n..
Стабілізатор напруги 5В 1,5А L7805CV
Стабілізатор напруги у вигляді мікросхеми з трьома ногамиВикористовується для стабілізації нестабілі..
12.03грн.
Парсер температури та вологості на WiFi-контролері
У меня есть задумка сделать у себя дома возле входной двери индикатор внешней температуры, а так же ..