Algorithm 故障过滤电位计数据(噪音、高峰值)

Algorithm 故障过滤电位计数据(噪音、高峰值),algorithm,matlab,filter,sensors,noise,Algorithm,Matlab,Filter,Sensors,Noise,我用Arduino微控制器从电位计收集了一些数据。以下是在500 Hz下采样的数据(数据量很大): 如果你放大,你可以看到基本上我有一个锅,只是来回旋转,也就是说,我应该看到一个线性增加,然后线性减少。虽然数据的总体形状证实了这一点,但几乎每一次都有一些非常令人讨厌(有时令人惊讶地宽)的尖峰阻碍了一个非常好的形状。有没有什么方法可以让我制作某种类型的算法或过滤器来解决这个问题?我尝试了中值滤波,并使用了百分位数,但都不起作用。我的意思是,我觉得这不应该是最难的事情,因为我可以清楚地看到它应该是

我用Arduino微控制器从电位计收集了一些数据。以下是在500 Hz下采样的数据(数据量很大):

如果你放大,你可以看到基本上我有一个锅,只是来回旋转,也就是说,我应该看到一个线性增加,然后线性减少。虽然数据的总体形状证实了这一点,但几乎每一次都有一些非常令人讨厌(有时令人惊讶地宽)的尖峰阻碍了一个非常好的形状。有没有什么方法可以让我制作某种类型的算法或过滤器来解决这个问题?我尝试了中值滤波,并使用了百分位数,但都不起作用。我的意思是,我觉得这不应该是最难的事情,因为我可以清楚地看到它应该是什么样子,基本上是峰值出现的最小值,但由于某种原因,我尝试的一切都失败了,或者至少失去了原始数据的完整性


如果能得到任何帮助,我将不胜感激

看起来你的罐子的最大点和最小点附近有很大的刺。例如,您可以将有效数据的范围限制在200到300之间

另一种选择是像这样的一阶低通滤波器

alpha = 0.01 %parameter to tune!

p_filtered(1) = p(1);
for i=2:length(p)
    p_filtered(i) = alpha*p(i) + (1-alpha)* p_filtered(i-1);
end

看起来你有一个很大的尖刺,接近你的最高点和最低点。例如,您可以将有效数据的范围限制在200到300之间

另一种选择是像这样的一阶低通滤波器

alpha = 0.01 %parameter to tune!

p_filtered(1) = p(1);
for i=2:length(p)
    p_filtered(i) = alpha*p(i) + (1-alpha)* p_filtered(i-1);
end

当旋钮转动时,水壶的雨刮器沿电阻轨道反弹,导致噪音峰值。这是他们的共同问题。将来,您应该考虑在POT输出中添加一个0.1uF电容器,这应该可以解决问题

对于当前数据,最简单的选择是只进行简单的移动平均,并直观地调整平均采样数,直到峰值得到充分抑制,同时不影响基础数据。请注意,移动平均只是一个具有频率响应的低通滤波器


对此类数据进行后处理的正常方法是进行FFT(使用适当的窗口函数),将感兴趣信号上方的噪声值归零,然后进行逆FFT。这也只是低通滤波(使用sinc*加窗函数加权移动平均),但您可以使用FFT提供的细节来选择截止频率。如果你对做这件事所涉及的数学不满意,那就用简单的移动平均滤波器吧。它应该可以满足您的需要。

当旋钮转动时,水壶的雨刮器沿电阻轨道反弹,从而产生噪音峰值。这是他们的共同问题。将来,您应该考虑在POT输出中添加一个0.1uF电容器,这应该可以解决问题

对于当前数据,最简单的选择是只进行简单的移动平均,并直观地调整平均采样数,直到峰值得到充分抑制,同时不影响基础数据。请注意,移动平均只是一个具有频率响应的低通滤波器


对此类数据进行后处理的正常方法是进行FFT(使用适当的窗口函数),将感兴趣信号上方的噪声值归零,然后进行逆FFT。这也只是低通滤波(使用sinc*加窗函数加权移动平均),但您可以使用FFT提供的细节来选择截止频率。如果你对做这件事所涉及的数学不满意,那就用简单的移动平均滤波器吧。它应该适合你的需要。

有很多方法可以解决你的问题。然而,它们中没有一个是完美的。这里我给你两种方法

移动平均(低通滤波器) 在Matlab中,“低通”过滤数据而不必显式使用FFT的一种简单方法是使用
filter
函数`(在基本包中提供,您不需要任何特定的工具箱)

您为过滤器创建一个内核,并应用它两次(每个方向一次),以取消引入的相移。这实际上是一个零相移的“移动平均”滤波器。 内核的大小(长度)将控制平均过程的重量

例如,两种不同的过滤器长度:

n = 100 ; %// length of the filter
kernel = ones(1,n)./n ;
q1 = filter( kernel , 1 , fliplr(p) ) ;  %// apply the filter in one direction
q1 = filter( kernel , 1 , fliplr(q1) ) ; %// re-apply in the opposite direction to cancel phase shift

n = 500 ; %// length of the filter
kernel = ones(1,n)./n ;
q2 = filter( kernel , 1 , fliplr(filter( kernel , 1 , fliplr(p) )) ) ; %// same than above in one line
将根据您的数据生成:

正如您所看到的,每个过滤器大小都有其优缺点。过滤越多,消除的尖峰越多,但对原始信号的变形越大。这取决于你找到你的最佳设置


2) 搜索导数异常 这是一种不同的方法。你可以在你的信号上观察到尖峰大多是突然的,这意味着你的信号值变化很快,幸运的是比你想要的信号的“正常”变化率要快。这意味着您可以计算信号的导数,并识别所有尖峰(导数将远高于曲线其余部分)。
由于这只识别尖峰的“开始”和“结束”(而不是中间偶尔出现的平台),因此我们需要稍微扩展通过该方法识别为故障的区域。
识别错误数据后,您只需丢弃这些数据点,并在原始间隔内重新插值曲线(在您留下的点上获得支持)

%%//方法2-重新插入已取消的数据
%//可选择稍微平滑初始数据,以获得更清晰的导数
n=10;内核=一(1,n)。/n;
ps=过滤器(内核,1,fliplr(过滤器(内核,1,fliplr(p)));
%//识别衍生异常(过高或过低)
dp=[0差异(ps)];%//计算最简单的导数形式(仅计算连续点之间的差值)
dpos=dp>=(标准(dp)/2);%//确定高于某个阈值的正导数(我选择STD,但你也可以选择