Существуют ли библиотеки сглаживания сигналов для Arduino?

Я работаю над мобильным роботом, управляемым через беспроводную связь 2,4 ГГц. Приемник подключен к Arduino Uno, который служит на борту в качестве основного контроллера. Самый критический (и основной) входной канал, исходящий от приемника, производит очень зашумленный сигнал, что приводит к множеству незначительных изменений на выходе исполнительных механизмов, хотя в этом нет необходимости.


График входных данных Arduino с интервалом в 30 секунд.

Я ищу библиотеки, способные выполнять эффективное сглаживание. Существуют ли какие-либо библиотеки сглаживания сигналов для Arduino (Uno)?

, 👍20

Обсуждение

Не знаю, сможете ли вы найти подобные библиотеки, но боюсь, что для Arduino им может потребоваться большая мощность процессора. Если возможно, я бы предпочел использовать электронное решение (фильтр нижних частот)., @jfpoilpret

Я поддерживаю jfpoilpret в этом вопросе. Я думаю, вам нужно электронное решение. Я бы попробовал стабилизирующий конденсатор (простой фильтр нижних частот). Я предполагаю, что вы используете канал постоянного тока, поэтому вам следует заземлить этот канал. Начните со значений около 100 пф и увеличивайте их., @John b


5 ответов


Лучший ответ:

13

Microsmooth — это легкая библиотека сглаживания сигналов, которую я сейчас разрабатываю.

Над этим все еще ведутся работы, и цель состоит в том, чтобы сделать его легким с точки зрения памяти и быстрым. Библиотека предоставляет несколько фильтров для сглаживания:

  • Простое скользящее среднее
  • Экспоненциальная скользящая средняя
  • Совокупное скользящее среднее
  • Фильтр Савицкого Голая
  • Алгоритм Рамера Дугласа Пекера
  • Фильтр Калмогорова Зурбенко

Чтобы использовать библиотеку, скачайте и добавьте ее в исходный каталог. Также добавьте следующую строку в исходный файл:

#include "microsmooth.h"
,

Привет, у меня проблемы с использованием вашей библиотеки. Вы бы не использовали «Импорт библиотеки...» для импорта библиотеки, верно? Я попытался просто скопировать исходный код в свою папку .ino, но получаю ошибки об отсутствии automicrosmooth.h, серийном номере не определен и отсутствующем ';'. Эта библиотека еще работает? Спасибо, @waspinator

@waspinator Извините. Исправлены ошибки. Спасибо за ответ!, @asheeshr


4

Вы пробовали фильтр нижних частот? Я нашел пример здесь и еще один здесь.

Обе эти библиотеки имеют список данных, считываемых с выбранного вами аналогового датчика, которые усредняются. Каждое новое значение датчика добавляется в список, а последнее выбрасывается, вот так:

List: 3 4 3 3 4 3 5 3 2 3 4 3 
new reading added. old one thrown out
      /--                     /--
List: 5 3 4 3 3 4 3 5 3 2 3 4
list averaged
,

Примерно то же самое делает простой [FIR-фильтр](https://en.wikipedia.org/wiki/Finite_impulse_response), когда все значения отводов установлены на 1. Изменение значений отводов может еще больше улучшить сигнал, но требует более сложных математических вычислений., @jippie

Примечание. Вторая ссылка вычисляет [кумулятивное скользящее среднее](http://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average), что не является практичным выбором для управления приводом, особенно такого, которое может включать частые запуски и остановки. Сглаженный сигнал всегда будет значительно отставать от пикового значения фактического сигнала., @asheeshr


2

Вы можете отфильтровать это в цифровом виде, используя фильтр нижних частот:

int valueFilt = (1-0.99)*value + 0.99*valueFilt;

Измените значение 0,99, чтобы изменить частоту среза (ближе к 1,0 — более низкая частота). Фактическое выражение для этого значения — exp(-2*pi*f/fs), где f — желаемая частота среза, а fs — частота выборки данных.

Другой тип «цифрового фильтра» — фильтр событий. Он хорошо работает с данными, имеющими выбросы; например 9,9,8,10,9,25,9 . Фильтр событий возвращает наиболее частое значение. По статистике это именно такой режим.

Статистические средние значения, такие как среднее значение, режим и т. д., можно рассчитать с помощью Библиотеки средних значений Arduino.

>

Пример взят со страницы библиотеки Arduino:

#include <Average.h>
#define CNT 600
int d[CNT];

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

void loop()
{
  int i;

  for(i=0; i<CNT; i++)
  {
    d[i] = random(500);
  }  

  Serial.print("Mean: ");
  Serial.print(mean(d,CNT),DEC);
  Serial.print(" Mode: ");
  Serial.print(mode(d,CNT),DEC);
  Serial.print(" Max: ");
  Serial.print(maximum(d,CNT),DEC);
  Serial.print(" Min: ");
  Serial.print(minimum(d,CNT),DEC);
  Serial.print(" Standard deviation: ");
  Serial.print(stddev(d,CNT),4);
  Serial.println("");
  Serial.println("");

  delay(5000);
}
,

Обратите внимание, что это будет очень медленно, поскольку выполняется множество неявных приведений для плавания и обратно., @Connor Wolf


7

Мне кажется, я вижу в вашем зашумленном сигнале множество одновыборочных всплесков шума.

Медианный фильтр лучше устраняет всплески шума одной выборки, чем любой линейный фильтр. (Он лучше, чем любой фильтр нижних частот, скользящее среднее, взвешенное скользящее среднее и т. д. с точки зрения времени отклика и способности игнорировать такие выбросы шума в одной выборке).

На самом деле для Arduino существует множество библиотек сглаживания сигналов, многие из которых включают медианный фильтр.

Библиотеки сглаживания сигналов на arduino.cc:

  • Пол Бэджер: плавный цифровой фильтр нижних частот
  • Пол Бэджер: цифровой фильтр нижних частот digitalSmooth с подавлением выбросов
  • Дэвид А. Меллис и Том Айго: руководство по сглаживанию
  • Маженки: Средняя библиотека

Библиотеки сглаживания сигналов на github:

  • AsheeshR/Microsmooth
  • jeroendoggen: Arduino-signal-filtering-library
  • karlward: библиотека фильтрации данных Arduino
  • sebnil: FIR-filter-Arduino-Library
  • daPhoosa: MedianFilter
  • arc12: Коллекция фильтров цифровых сигналов (предназначена для использования с Arduino)
  • sebnil: Самобалансирующийся робот в Arduino. Реализовано с ПИД-регуляторами, КИХ-фильтрами, дополнительным фильтром.

Подойдет ли что-то подобное для вашего робота? (Медиана-3 требует очень мало мощности процессора и, следовательно, быстро):

/*
median_filter.ino
2014-03-25: started by David Cary
*/

int median_of_3( int a, int b, int c ){
    int the_max = max( max( a, b ), c );
    int the_min = min( min( a, b ), c );
    // излишне умный код
    int the_median = the_max ^ the_min ^ a ^ b ^ c;
    return( the_median );
}

int newest = 0;
int recent = 0;
int oldest = 0;

void setup()
{
    Serial.begin(9600);
    // читаем первое значение, инициализируем его.
    oldest = random(200);
    recent = oldest;
    newest = recent;
    Serial.println("median filter example: ");
}

void loop()
{
    // удаляем самое старое значение и сдвигаем последнее значение
    oldest = recent;
    recent = newest;
    newest = random(200);

    Serial.print("new value: ");
    Serial.print(newest, DEC);

    int median = median_of_3( oldest, recent, newest );

    Serial.print("smoothed value: ");
    Serial.print(median, DEC);
    Serial.println("");

    delay(5000);
}
,

0

Ознакомьтесь с библиотекой Arduino Smooth. Он не использует абсолютно никаких массивов, не имеет циклов по прошлым значениям, работает быстро, имеет постоянное время вычислений, а объекты занимают 8 байт независимо от размера окна выборки.

,

Стоит отметить, что эта библиотека, как и некоторые другие, уже упомянутые, реализует экспоненциально взвешенное скользящее среднее. В том, что он работает с постоянным временем и постоянным размером, нет ничего особенного: именно так всегда реализуется этот тип фильтра. Существуют хорошие варианты использования экспоненциально взвешенной скользящей средней, но резкий шум исходного вопроса не входит в их число: для этого лучше подойдет скользящая медиана., @Edgar Bonet