В данном уроке мы рассмотрим работу двух фильтров которые работают по принципу бегущего среднего арифметического. Первый фильтр — экспоненциальное бегучее среднее Второй фильтр — бегущее среднее арифметическое  Экспоненциальное бегучее среднее:
  • Один из легкий (по ресурсам) и быстрый фильтр, при этом он не теряет своей эффективности.
  • Диапазон коэффициента лежит от 0.0 до 1.0 (чем меньше коэффициент, тем плавнее фильтр).
  • Делает только одно измерение за раз, не блокирует код.
  • Чем чаще измерения, тем лучше работает
Бегущее среднее арифметическое:
  • Усредняет последние N измерений, за счёт чего значение запаздывает.
  • Качество фильтрации  настраивается размером выборки.
  • Делает только одно измерение за раз, не блокирует код.
Рассмотрим программный код данный фильтров:
int count = 0; // счётчик процесса
bool n = 0;
float signals = 0.0; // чистый сигнал
float noises = 0.0; // сигнал с помехами
float filtrs0 = 0.0; // отфильтрованный сигнал
float filtrs1 = 0.0; // отфильтрованный сигнал
float filtrs2 = 0.0; // отфильтрованный сигнал
float filtrs3 = 0.0; // отфильтрованный сигнал
float filtrs4 = 0.0; // отфильтрованный сигнал
float filtrs5 = 0.0; // отфильтрованный сигнал
float filtrs6 = 0.0; // отфильтрованный сигнал
float filtrs7 = 0.0; // отфильтрованный сигнал

float k0 = 0.05;  // коэффициент фильтрации, 0.0-1.0
float k1 = 0.2;  // коэффициент фильтрации, 0.0-1.0
float k2 = 0.4;  // коэффициент фильтрации, 0.0-1.0
float k3 = 0.6;  // коэффициент фильтрации, 0.0-1.0
float k4 = 0.8;  // коэффициент фильтрации, 0.0-1.0
float k5 = 1;  // коэффициент фильтрации, 0.0-1.0

float expRunningAverag0(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k0;
  return filVal;
}

float expRunningAverag1(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k1;
  return filVal;
}

float expRunningAverag2(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k2;
  return filVal;
}

float expRunningAverag3(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k3;
  return filVal;
}

float expRunningAverag4(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k4;
  return filVal;
}
float expRunningAverag5(float newVal) {
  static float filVal = 0;
  filVal += (newVal — filVal) * k5;
  return filVal;
}

const int NUM_READ = 8;  // количество усреднений для средних арифм. фильтров
// оптимальное бегущее среднее арифметическое
float runMiddleArifmOptim(float newVal) {
  static int t = 0;
  static float vals[NUM_READ];
  static float average = 0;
  if (++t >= NUM_READ) t = 0; // перемотка t
  average -= vals[t];         // вычитаем старое
  average += newVal;          // прибавляем новое
  vals[t] = newVal;           // запоминаем в массив
  return ((float)average / NUM_READ);
}

const int NUM_READ1 = 16;  // количество усреднений для средних арифм. фильтров
// оптимальное бегущее среднее арифметическое
float runMiddleArifmOptim1(float newVal) {
  static int t = 0;
  static float vals[NUM_READ1];
  static float average = 0;
  if (++t >= NUM_READ1) t = 0; // перемотка t
  average -= vals[t];         // вычитаем старое
  average += newVal;          // прибавляем новое
  vals[t] = newVal;           // запоминаем в массив
  return ((float)average / NUM_READ1);
}

void setup() {
Serial.begin(9600);
Serial.flush();
}

void loop() {
Signal();
Serial.print(signals);
Serial.print(«,»);
noise();
Serial.print(noises);
Serial.print(«,»);
//filtrs0=expRunningAverag0(noises);
//Serial.print(filtrs0);
//Serial.print(«,»);
filtrs1=expRunningAverag1(noises);
Serial.print(filtrs1);
Serial.print(«,»);
filtrs2=expRunningAverag2(noises);
Serial.print(filtrs2);
Serial.print(«,»);
filtrs3=expRunningAverag3(noises);
Serial.print(filtrs3);
Serial.print(«,»);
filtrs4=expRunningAverag4(noises);
Serial.print(filtrs4);
Serial.print(«,»);
//filtrs5=expRunningAverag5(noises);
//Serial.print(filtrs5);
//Serial.print(«,»);
filtrs6=runMiddleArifmOptim(noises);
Serial.print(filtrs6);
Serial.print(«,»);
filtrs7=runMiddleArifmOptim1(noises);
Serial.print(filtrs7);
Serial.println(» «);
count++;
}

void Signal() {
// синусоида
signals = 5.0 * sin(15 * radians(count));

// прямоугольный сигнал
// if (count % 10 == 0) n = !n; // каждые 10 тиков инвертируем сигнал
 //signals = n * 5; //амплитуда сигнала 5
}

float noise() {
noises = signals;
// постоянный шум
//noises += (random(-9, 9) / 10.0);
// случайные выбросы
if (!random(10)) noises += random(-5, 5);
//для прясоугольного импульса
//if(signals<=0) noises=abs(noises);
return noises;
}