我是一位经验丰富的软件工程师,正在研究智能手机传感器。我已经学习了DSP的基础EE课程,并正在尝试运用我的知识。我相信我了解卷积,传递函数,z变换等。我对FIR和IIR滤波器有所了解。

现在,当阅读软件API和文档时,我看到人们正在应用一个LPF来在时域中传感数据。我知道您可以通过使用差分方程式来做到这一点(例如y [i] = y [i-1] + 2 * x [i]),但是我在EE类中了解到LPF通常通过卷积运算来应用您可以将时间信号与正弦波的系数(例如)和特定的截止频率进行卷积。因此,“低通滤波器”的口语用法对我来说还不够准确。

例如,Google Android API包含以下文档:
http://developer.android.com/reference/android/hardware/SensorEvent.html#values

 public void onSensorChanged(SensorEvent event)
 {
      // alpha is calculated as t / (t + dT)
      // with t, the low-pass filter's time-constant
      // and dT, the event delivery rate

      final float alpha = 0.8;

      gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
      gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
      gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

      linear_acceleration[0] = event.values[0] - gravity[0];
      linear_acceleration[1] = event.values[1] - gravity[1];
      linear_acceleration[2] = event.values[2] - gravity[2];
 }


我该如何解释低通滤波器?截止频率是多少?过渡带宽是多少?他们是仅使用该LPF进行平均吗?

评论

好,这也困扰着我

#1 楼

您的示例中的滤波器是一阶无限冲激响应(IIR)滤波器。其传递函数为:

$$
H(z)= \ frac {1-\ alpha} {1-\ alpha z ^ {-1}}
$$

对应于以下等式的差分方程: x [n]
$$

其中$ x [n] $是过滤器输入,$ y [n] $是过滤器输出。

此滤波器类型通常用作低复杂度低通滤波器,通常被称为漏积分器。由于其实现简单,计算复杂度低和可调性而受到青睐:其截止频率取决于$ \ alpha $的值。 $ \ alpha $的取值范围为$ [0,1)$。 $ \ alpha = 0 $完全不进行过滤(输出等于输入);随着$ \ alpha $增加,滤波器的截止频率降低。您可以将$ \ alpha = 1 $视为边界频率,其中截止频率无限低(滤波器输出始终为零)。

通过注意到滤波器输入由$ \ alpha $加权,因此随着参数的增加,数量$ 1- \ alpha $减小,因此每个输入样本对任何特定输出样本的值的比例影响较小。这样会在较长的时间段上模糊掉滤波器的脉冲响应。较长时间的求和类似于计算长均线。随着移动平均线长度的增加,平均线的截止频率减小。

例如,在$ \ alpha = 0.8 $的情况下,滤波器的频率响应如下:


从该示例中,我猜想该滤波器将用于消除传感器测量的时间序列中的高频噪声,试图找出相对低频的信号出于兴趣。对于这种类型的过滤器,这将是非常典型的应用。

在另一个子问题上,您是正确的,通常是通过将输入信号与滤波器的脉冲响应进行卷积来实现滤波。在大多数情况下,这只能通过有限脉冲响应(FIR)滤波器完成。这样的IIR滤波器通常使用滤波器的差分方程来实现。由于IIR系统的脉冲响应是无限长的,因此必须将其截断为有限的长度以使其易于处理,此时滤波器不再是IIR。虽然该结构固有的反馈会导致必须解决的数字问题(例如内部溢出和舍入误差累积),但差动方程格式几乎总是较便宜地通过计算实现。

评论


$ \ begingroup $
谢谢!一些后续问题:(1)您说方程H(z)= ...是一个差分方程;这真的是传递函数,对吗?我认为差分方程严格来说是时域的。 (2)在您的泄漏积分器中,1.0是否对应于ampling_frequency / 2(例如在Matlab中)? (3)关于FIR与IIR,我的理解是否正确,即可以将IIR差分方程应用于O(N),但基于FFT的卷积是O(N ^ 2)或O(N lgN)? (4)您能推荐一本面向软件程序员的书来实现这些DSP思想吗?就像Android代码示例所做的一样。
$ \ endgroup $
–stackoverflowuser2010
2011-12-21 18:57



$ \ begingroup $
(1)没错,我打错了字。我会改正答案。 (2)是; X轴是归一化频率,除以$ \ pi $,因此1对应于$ + \ pi $,即采样率的一半。 (3)使用任一方法计算特定样本的输出为$ O(N)$,其中$ N $为过滤器阶数。 IIR滤波器通常只有一个小得多的$ N $。 (4)我建议使用Lyons了解DSP。这是一本很棒的入门书。
$ \ endgroup $
–Jason R
2011年12月21日19:00

$ \ begingroup $
我知道(i)应用差分方程是O(N)。但是我认为(ii)在基于FFT的实现中使用相加乘积(songho.ca/dsp/convolution/convolution.html)进行卷积运算是O(N ^ 2)或O(N lgN) 。在所有情况下,N是滤波器阶数-我假设滤波器阶数和时间信号长度是相同的数量级(例如均为256)。那么(i)和(ii)是否不同?此外,我确实在Lyon上看到了Lyons的书,但是我希望能为C / Java软件程序员写更多的东西。
$ \ endgroup $
–stackoverflowuser2010
2011-12-21 19:14

$ \ begingroup $
用差分方程计算一次采样输出的复杂度为$ O(N)$。如果输入信号长度也是$〜N $,则计算每个输入样本的输出的总复杂度为$ O(N ^ 2)$。对于IIR滤波器,更常见的是,输入信号长度是一个更大的值$ M $,因为滤波器阶次$ N $很小,因此复杂度可以写成$ O(MN)$。如果$ M $明显小于$ N $,则可能会带来一些计算上的好处。
$ \ endgroup $
–Jason R
2011年12月21日在20:11

$ \ begingroup $
抱歉打败一匹死马。对于一般的差分方程(ccrma.stanford.edu/~jos/fp/Difference_Equation_I.html),复杂度真的不是$ O(M \ times(N + M))$,其中N是输入和输出信号长度,M是滤波器阶数?循环遍历每个输出y [i],N $中的$ i是O(N),每个y [i]需要O(N + M)个循环。我想正如您所说,根据N和M的相对大小,结果是$ O(N ^ 2)$或$ O(NM)$。
$ \ endgroup $
–stackoverflowuser2010
2011-12-21 22:03



#2 楼

总而言之,基于简单理想化物理模型的IIR滤波器(例如RC滤波器)具有极点和零点的数量很少,因此通常实现为差分方程,因为极点或零点的数量意味着很少的算术运算每个样本都使用差分方程。

由于IIR意味着无限长的脉冲响应,卷积要么需要永远进行计算,要么使用近似值。

FIR滤波器通常通过使用有限长度的脉冲响应进行卷积来实现(如果滤波器足够长以提高计算效率,则可以通过FFT快速卷积实现)。当人们可以用有限长度的脉冲响应来近似所需的频率响应规格时,而不是知道Z平面的极点和零点可能位于何处时,会更常使用这类滤波器。

具有严格规格的FIR滤波器意味着FIR卷积很长,FIR滤波器的实现可能要慢得多,并且设置可能涉及更多的代码行,这可能就是为什么FIR滤波器在简单的软件示例中可能不经常使用的原因。 br />

#3 楼

我发现自己一次又一次回到这篇文章。谢谢你问这个问题。这是C中泄漏积分器的一个很好的,计算友好的实现(打算用于微控制器)。

首先,进行一些重新排列:
y =α* x +(1 −α) * y_last
=α*(x-y_last)+ y_last

如果我们将α限制为大约12%,25%,50%,(1 / 8、1 / 4、1 / 2,...)。我们可以利用一些有效的位移位。以1/8为例,8 => 2 ^ 3 =>(降档3次)

=(x-y_last)/ 8 + y_last

#define SMOOTHING_FACTOR       (3)

int16_t FilterSample(int16_t new_sample)
{
  static int16_t last_result = 0;

  // Each bit shift down is equivalent to dividing-by-two
  last_result = (new_sample - last_result) >> SMOOTHING_FACTOR) + last_result;

  return last_result;
}


希望有帮助。