![ESP32 MicroPython EMA filter](http://ardudevelop.eu/wp-content/uploads/2024/08/ESP32-MicroPython-EMA-filter.png)
Въведение
В света на вградени системи и сензори, получаването на стабилни и надеждни данни е от съществено значение. Често данните, които се събират от аналогово-цифрови преобразуватели (АЦП), са шумни и съдържат нежелани колебания. Един от ефективните методи за изглаждане на тези данни е използването на Exponential Moving Average (EMA) филтър. В тази статия ще разгледаме как да приложим EMA филтър с помощта на MicroPython на ESP32, като създадем библиотека, която можем да използваме във вашите проекти.
Какво е EMA филтър?
Exponential Moving Average или на кратко (EMA) е тип филтър, който придава по-голяма тежест на последните наблюдения, което го прави по-чувствителен към нови данни. Формулата за EMA е следната:
EMAt=α×Pt+(1−α)×EMAt−1
Където:
- EMAt е текущата стойност на EMA.
- α (alphaα) е изглаждащият фактор, който определя колко тежест се дава на новите данни (обикновено между 0 и 1).
- Pt е текущата измерена стойност.
- EMAt−1 е предишната стойност на EMA.
Защо да използваме EMA филтър?
- Изглаждане на данни: EMA филтърът помага да се изгладят шумните данни, като намалява ефекта от краткосрочните колебания.
- Реактивност: Поради своята природа, EMA филтърът е по-реактивен към последните промени, което го прави полезен за приложения, които изискват бърза реакция.
- Лесно имплементиране: Формулата на EMA е проста и лесна за реализиране в микроконтролери.
Създаване на библиотека за EMA филтър в MicroPython
Създаване на EMA филтър библиотека
След, когато ESP32 е готов за работа, ще създадем библиотека за EMA филтъра. Създайте файл с име ema_filter.py и добавете следния код:
from machine import ADC, Pin
import time
class EMAFilter:
def __init__(self, pin, alpha=0.2, num_samples=100):
self.adc = ADC(Pin(pin))
self.adc.atten(ADC.ATTN_11DB)
self.adc.width(ADC.WIDTH_12BIT)
self.alpha = alpha
self.num_samples = num_samples
self.ema = 0
self.first_reading = True
def read_adc(self):
total = 0
for _ in range(self.num_samples):
total += self.adc.read()
time.sleep(0.001) # Малко забавяне между прочитанията (1 ms)
return total / self.num_samples
def update_ema(self):
current_reading = self.read_adc()
if self.first_reading:
self.ema = current_reading
self.first_reading = False
else:
self.ema = self.alpha * current_reading + (1 - self.alpha) * self.ema
return self.ema
Стъпка 3: Използване на библиотеката в основния скрипт
За да използваме библиотеката в нашия основен скрипт, можем да създадем нов файл, например main.py, и да импортираме класа EMAFilter:
from ema_filter import EMAFilter
import time
pin = 1 # Задаване на аналогов пин за изчитане
alpha = 0.1 # Избрана стойност за alpha
num_samples = 100 # Брой изчитания на аналоговия вход
filter = EMAFilter(pin, alpha, num_samples)
while True:
ema_value = filter.update_ema()
#print('EMA Value:', round(ema_value,2))
print(round(ema_value,2))
time.sleep(0.1) # Забавяне за следващото четене
Обяснение на кода
- from ema_filter import EMAFilter : импортиране на класа EMAFilter от файла ema_filter.py
- time : импортиране на библиотеката “time”, която се използва за добавяне на забавяне между четенията на аналоговия вход.
- pin : задава аналоговия пин, който ще се използва за изчитане на стойности от АЦП/ADC (аналогово-цифров преобразувател).
- alpha : задава стойността на изглаждащия фактор за EMA (Exponential Moving Average). Тази стойност определя колко тежест се дава на новите данни в сравнение със старите данни. Ако не зададете тази стойност по дефиниция в библиотеката е заложена стойността 0.2.
- num_samples : задава броя на изчитанията, които ще се използват за осредняване на аналоговата стойност преди прилагане на EMA филтъра.
- filter = EMAFilter(pin, alpha, num_samples) : Този ред създава инстанция на класа
EMAFilter
с зададените параметриpin
,alpha
иnum_samples
. - ema_value = filter.update_ema() : актуализира и връща новата стойност на EMA чрез метода
update_ema
на класаEMAFilter
. Този метод първо чете и осредняваnum_samples
на брой изчитания от АЦП, след което изчислява новата стойност на EMA на базата на текущата осреднена стойност и предишната стойност на EMA. - print(round(ema_value, 2)) : извежда стойността на EMA, закръглена до две десетични места.
- time.sleep(0.1) : добавя забавяне от 0.1 секунди преди следващото изчитане, за да намали честотата на четене и обработка на данни.
Това е пример за изчитане на няколко аналогови пина с тази билиотека:
from ema_filter import EMAFilter
import time
# Задаване на аналогови пинове
pin1 = 1 # Задаване според вашата ESP32 платформа
pin2 = 0 # Задаване според вашата ESP32 платформа
pin3 = 3 # Задаване според вашата ESP32 платформа
# Избрана стойност за alpha и брой изчитания на аналоговия вход
alpha = 0.1 # ако не бъде зададена стойността и ще е 0.2
num_samples = 100
# Създаване на EMA филтри за всеки пин
filter1 = EMAFilter(pin1, alpha, num_samples)
filter2 = EMAFilter(pin2, alpha, num_samples)
filter3 = EMAFilter(pin3, alpha, num_samples)
while True:
# Актуализиране на EMA стойности за всеки пин
ema_value1 = filter1.update_ema()
ema_value2 = filter2.update_ema()
ema_value3 = filter3.update_ema()
# Отпечатване на стойностите
print("EMA Value 1:", round(ema_value1, 2))
print("EMA Value 2:", round(ema_value2, 2))
print("EMA Value 3:", round(ema_value3, 2))
# Забавяне за следващото четене
time.sleep(0.1)
За да зададете правилните аналогови входове може да разгледате раздела ни Ревюта, където ще намерите спецификациите на някои ESP32 платформи.
Заключение
Използването на EMA филтър с MicroPython на ESP32 е ефективен начин за изглаждане на данните от сензори и намаляване на шума. Създадената библиотека е лесна за използване и може да бъде интегрирана във вашите проекти за вградени системи. Независимо дали работите с температурни сензори, светлинни датчици или други аналогови устройства, EMA филтърът може да ви помогне да получите по-надеждни и стабилни данни. Може да прочетете повече за този математичен модел тук.
Надявам се тази статия да ви е помогнала да разберете как да използвате EMA филтър с MicroPython и ESP32. Ако имате въпроси или нужда от допълнителна помощ, не се колебайте да се свържете с мен!