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

Embedded 用于嵌入式设备的轻型带通滤波器(无FFT),embedded,filtering,signal-processing,Embedded,Filtering,Signal Processing,我想从离散数据集中删除某些频率(由ADC采样的信号)。听起来很简单。然而,有一些限制使事情变得更加困难: 该芯片是32位NXP JN5168,具有硬件乘法功能,但不支持硬件除法、浮点运算或任何使DSP变得简单的工具。因此,基于FFT的滤波器很容易在ARM Cortex M芯片上实现,这是不可能的 采样几乎设置为1 kHz 实时性和RAM使用是一个值得关注的问题,因为芯片同时还处理其他任务 我尝试使用以下形式的知名高/低通滤波器: Filtered Value (L) = Previous V

我想从离散数据集中删除某些频率(由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赫兹的任何东西,并保持200赫兹不变,这是不可能与上述过滤器,这是非常好的在80赫兹以下(在我的采样率)有尖锐的截止。如果我降低截止攻击性,使滤波器工作在120 Hz,那么200 Hz也会受到影响(较小,但显著)

下面,您可以看到上述HPF的3次传递的频率响应,k=1/2。

这对我不起作用。我正在寻找一些不同的东西:我正在寻找一种适用于嵌入式应用程序的轻量级滤波算法,理想情况下,该算法可以在任意频率下提供一个完整或有效的截止线,从而使相邻频率不受影响,或影响不大

谢谢

编辑:我不想将我的信号转换到频域,而是继续在时域中处理已清理的信号


编辑2:更改硬件不是选项。已有产品需要新功能。这种情况经常发生。这就是生活。我的工作是找到解决方案,我确信它是存在的。

如果您的计算预算能够承受每个样本5次乘法(MAC)(以1 kHz的采样率为每毫秒),并且您可以保存过去的两个样本,那么您可以使用双四阶IIR滤波器。对于双四次方系数,有一个简单的定义


如果你能负担得起每个样本5 MAC的小倍数,那么你可以级联双四元,得到一个更高阶的IIR滤波器,具有更锐利的滚降或截止。但是,您可能需要使用滤波器设计软件包(MatLab等)来优化高阶IIR滤波器的零极点位置,以满足您的特定要求。

如果您的计算预算能够承受每个采样5次乘法(MAC)(以1kHz采样率),并且您可以保存过去的两个采样,您可以使用双四路IIR滤波器。对于双四次方系数,有一个简单的定义

如果你能负担得起每个样本5 MAC的小倍数,那么你可以级联双四元,得到一个更高阶的IIR滤波器,具有更锐利的滚降或截止。但您可能需要使用滤波器设计软件包(MatLab等)来优化高阶IIR滤波器的零极点位置,以满足您的特定要求。

改编自:

static const float pi=3.141592f;
静态常数浮点pi2=2.0f*pi;
静态常数浮点s=48000;//采样率
空心带通滤波器(浮点f_hz,//滤波器中心频率
浮点bw_hz,//滤波器带宽
常量float*x,//指向输入样本块的指针
float*y,//指向输出缓冲区的指针
int n//样本块中的样本数
)
{
静态浮点x_2=0.0f;//延迟的x,y采样
静态浮动x_1=0.0f;
静态浮动y_1=0.0f;
静态浮动y_2=0.0f;
静态常数浮点f=f_hz/s;
静态常数浮点bw=bw_hz/s;
静态常数浮点R=1-(3*bw);
静态常数浮点Rsq=R*R;
静态常数浮点cosf2=2*cos(pi2*f);
静态常数浮点K=(1-R*cosf2+Rsq)/(2-cosf2);
静态常数浮点数a0=1.0-K;
静态常数浮点a1=2*(K-R)*cosf2;
静态常数浮点a2=Rsq-K;
静态常数浮点b1=2*R*cosf2;
静态常量浮点b2=-Rsq;
对于(int i=0;i
由于在循环结束时,过滤器状态保留在静态变量
x_1
y_1
x_2
y_2
中,因此可以使用任意数量的样本重复调用过滤器-一次一个样本或以块的形式(更有效)

然而,系数的静态计算和单精度浮点的使用使得即使对于软件浮点,它也相当快,只需要乘法和。使用软件浮点可能会在一定程度上增加代码大小-最显著的是使用
cos()
,但如果频率和带宽不可变,则可能会预先计算并硬编码系数-我已将其包含在代码中以供说明,因为这是我可以得到的真实代码,而不是专门为这个问题开发的

如果浮点仍然太耗资源或时间,则可以实现定点。我使用了相同的代码,用于定点使用C++和泛运算符
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];
    }
}