我正在通过2.4 GHz无线链路控制的移动机器人上工作。接收器连接到板载作为主控制器的Arduino Uno。来自接收器的最关键(也是主要)输入通道会产生非常嘈杂的信号,即使不需要这些信号,也会导致执行器的输出出现许多细微的变化。
以30秒为间隔绘制Arduino输入的图。
我正在寻找可以执行有效平滑的库。Arduino(Uno)是否有可用的信号平滑库?
我正在通过2.4 GHz无线链路控制的移动机器人上工作。接收器连接到板载作为主控制器的Arduino Uno。来自接收器的最关键(也是主要)输入通道会产生非常嘈杂的信号,即使不需要这些信号,也会导致执行器的输出出现许多细微的变化。
以30秒为间隔绘制Arduino输入的图。
我正在寻找可以执行有效平滑的库。Arduino(Uno)是否有可用的信号平滑库?
Answers:
Microsmooth是我目前正在开发的轻量级信号平滑库。
它仍在研究中,目的是使其在存储和快速方面轻巧。该库提供了用于平滑的多个过滤器:
要使用该库,请下载并将其添加到源目录。另外,将以下行添加到您的源文件:
#include "microsmooth.h"
我想我在您的嘈杂信号中看到很多单样本噪声尖峰。
与任何线性滤波器相比,中值滤波器在消除单样本噪声尖峰方面表现更好。(就其响应时间和忽略此类单样本噪声尖峰离群值的能力而言,它比任何低通滤波器,移动平均值,加权移动平均值等都要好)。
实际上,有许多用于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);
}
这两个库均具有从您选择的模拟传感器读取的数据列表,该列表是经过平均的。每个新的传感器值都会添加到列表中,最后一个值将被抛出,如下所示:
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
您可以使用低通滤波器对此进行数字滤波:
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);
}