用于嵌入式设备的轻量级带通滤波器(无FFT)

时间:2017-05-18 23:05:08

标签: embedded filtering signal-processing

我想从离散数据集中删除某些频率(ADC采样的信号)。听起来很简单。然而,有一些限制会使事情变得更难:

  • 该芯片是32位NXP JN5168,具有硬件乘法,但没有硬件划分,没有浮动支持,或任何使DSP变得简单的工具。因此,基于FFT的滤波器很容易在ARM Cortex M芯片上实现,这是不可取的

  • 采样几乎设置为1 kHz

  • 实时和RAM使用是一个问题,因为芯片正在同时处理其他任务。

我尝试使用以下形式的众所周知的高/低通滤波器:

Filtered Value (L) = Previous Value - k*(Previous Value - Original Value) // LPF
Filtered Value (H) = Original Value - Filtered Value (L) // HPF

不幸的是,即使有多次传递,这种类型的过滤器也不能正常工作。频域中HPF响应的升高始终从0开始,并且只能通过调整k来控制那里的斜率。由于采样率无法改变,因此这是唯一的控制。

如果我想滤除120 Hz以下的任何信号,并保持200 Hz不变,那么上述滤波器是不可能的,这非常适用于低于80 Hz的尖锐截止频率(以我的采样率)。如果我降低截止积极性,并使滤波器工作在120 Hz,那么200 Hz也会受到影响(更少,但显着)。

下面您可以看到上述HPF的3次通过的频率响应,其中k = 1/2。 enter image description here

这对我不起作用。我正在寻找一些不同的东西:我正在寻找一种适用于嵌入式应用的轻量级滤波器算法,它可以在任意频率下以陡峭的截止线提供理想的完整或重要切割,从而使相邻频率不受影响或受到轻微影响。 / p>

谢谢!

编辑:我不想将信号转换为频域,而是继续使用时域中的清理信号。

编辑2:无法更改硬件。现有产品需要新功能。那个会发生。这就是生活。我的工作是找到解决方案,我相信它存在。

2 个答案:

答案 0 :(得分:3)

如果您的计算预算可以为每个样本提供5次乘法(MAC)(1 kHz采样率下每毫秒),并且您可以保存过去的几个样本,则可以使用双二阶IIR滤波器。双二阶系数有cookbook

如果您可以为每个样本提供5个MAC的小倍数,那么您可以级联双二阶并获得更高阶的IIR滤波器,甚至更清晰的滚降或截止。但您可能需要使用滤波器设计软件包(MatLab,et.al。)来优化高阶IIR滤波器的零极点位置,以满足您的特定要求。

答案 1 :(得分:1)

改编自The Scientist and Engineer's Guide to Digital Signal Processing - Chapter 19: Recursive Filters

static const float pi = 3.141592f ;
static const float pi2 = 2.0f * pi ;
static const float s = 48000 ;          // Sample rate

void bandpassFilter( float f_hz,           // Filter centre frequency
                     float bw_hz,          // Filter bandwidth
                     const float *x,       // Pointer to input sample block
                     float *y,             // Pointer to output buffer
                     int n                 // Number of samples in sample block
                )
{
    static float x_2 = 0.0f;                    // delayed x, y samples
    static float x_1 = 0.0f;
    static float y_1 = 0.0f;
    static float y_2 = 0.0f;

    static const float f = f_hz / s ;
    static const float bw = bw_hz / s ;

    static const float R = 1 - (3 * bw) ;

    static const float Rsq = R * R ;
    static const float cosf2 = 2 * cos(pi2 * f) ;

    static const float K = (1 - R * cosf2 + Rsq ) / (2 - cosf2) ;

    static const float a0 = 1.0 - K ;
    static const float a1 = 2 * (K - R) * cosf2 ;
    static const float a2 = Rsq - K ;
    static const float b1 = 2 * R * cosf2 ;
    static const float b2 = -Rsq ;

    for( int i = 0; i < n; ++i)
    {
        // IIR difference equation
        y[i] = a0 * x[i] + a1 * x_1 + a2 * x_2 
                         + b1 * y_1 + b2 * y_2;

        // shift delayed x, y samples
        x_2 = x_1;                             
        x_1 = x[i];
        y_2 = y_1 ;
        y_1 = y[i];
    }
}

由于在循环结束时,过滤器状态保留在静态变量x_1y_1x_2y_2中,过滤器可能会被重复调用任意数量的样本 - 一次一个样本或一个块(更高效)。

系数的静态计算和单精度浮点的使用使得它甚至对于软件浮点也相当快,只需要乘法加法。使用软件浮点可能会稍微增加代码大小 - 最明显的是使用cos(),但如果您的频率和带宽不可变,则可以预先计算系数并进行硬编码 - 我已将它们包括在内在代码中用于说明目的,并且因为它是我可用的真实代码,而不是专门针对该问题开发的。

如果浮点资源太多或时间太长,则可以进行定点实现。我使用了Anthony Williams' fixed point math library使用{{3}}的相同代码,它使用C ++和广泛的运算符重载,在大多数情况下只需将float替换为fixed即可实现定点实现。< / p>