Arduino有信号平滑库吗?


14

我正在通过2.4 GHz无线链路控制的移动机器人上工作。接收器连接到板载作为主控制器的Arduino Uno。来自接收器的最关键(也是主要)输入通道会产生非常嘈杂的信号,即使不需要这些信号,也会导致执行器的输出出现许多细微的变化。

在此处输入图片说明
                    以30秒为间隔绘制Arduino输入的图。

我正在寻找可以执行有效平滑的库。Arduino(Uno)是否有可用的信号平滑库?


不知道是否可以找到这种库,但恐怕这些对于Arduino可能需要大量的CPU能力。如果可能,我宁愿使用电子解决方案(低通滤波器)。
jfpoilpret 2014年

我在这方面与jfpoilpret在一起。我认为您需要一个电子解决方案。我会尝试使用稳定电容(简单的低通滤波器)。我假设您使用的是adc通道,因此您应该从该通道到地面放置一个上限。从大约100pf的值开始,然后从那里开始。
约翰b

Answers:


8

Microsmooth是我目前正在开发的轻量级信号平滑库。

它仍在研究中,目的是使其在存储和快速方面轻巧。该库提供了用于平滑的多个过滤器:

  • 简单移动平均线
  • 指数移动平均线
  • 累积移动平均线
  • Savitzky Golay过滤器
  • Ramer Douglas Pecker算法
  • Kalmogorov Zurbenko过滤器

要使用该库,请下载并将其添加到源目录。另外,将以下行添加到您的源文件:

#include "microsmooth.h"

嗨,我在使用您的图书馆时遇到问题。您不会使用“导入库...”来导入库吗?我尝试仅将源复制到我的.ino文件夹中,但是却收到有关缺少automicrosmooth.h,未定义序列号和缺少';'的错误。这个图书馆还在运作吗?谢谢
waspinator 2015年

@waspinator抱歉。修复了错误。感谢您的反馈!
asheeshr 2015年

7

我想我在您的嘈杂信号中看到很多单样本噪声尖峰。

与任何线性滤波器相比,中值滤波器在消除单样本噪声尖峰方面表现更好。(就其响应时间和忽略此类单样本噪声尖峰离群值的能力而言,它比任何低通滤波器,移动平均值,加权移动平均值等都要好)。

实际上,有许多用于Arduino的信号平滑库,其中许多包含中值滤波器。

arduino.cc上的信号平滑库:

github上的信号平滑库:

这样的事情会在您的机器人中起作用吗?(3位中位数需要非常少的CPU能力,因此速度很快):

/*
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 );
    // unnecessarily clever code
    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);
    // read first value, initialize with it.
    oldest = random(200);
    recent = oldest;
    newest = recent;
    Serial.println("median filter example: ");
}

void loop()
{
    // drop oldest value and shift in latest value
    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);
}

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滤波器在将所有抽头值都设置为1的情况下几乎可以完成操作。轻敲抽头值可以进一步改善信号,但是需要更高的数学运算能力。
jippie 2014年

注意:第二个链接计算累计移动平均值,这不是执行器控制的实际选择,尤其是可能涉及频繁启动和停止的累计移动平均值。平滑后的信号将始终落后于实际信号的峰值一定幅度。
asheeshr 2014年

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);
}

1
请注意,这将非常慢,因为它会进行很多隐式强制转换以浮动和返回。
康纳·沃尔夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.