Embedded 用于嵌入式设备的轻型带通滤波器(无FFT)
我想从离散数据集中删除某些频率(由ADC采样的信号)。听起来很简单。然而,有一些限制使事情变得更加困难: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
- 该芯片是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];
}
}