IIR振荡器在MATLAB中产生稳定的输出,在芯片上不稳定,我该如何调整它?

信息处理 无限脉冲响应 振荡器
2022-02-13 06:46:01

我正在尝试使用 IIR 滤波器制作振荡器,但在调整它以使其在我使用的平台上稳定(ARM Cortex M4F 和 CMSIS DSPLib 的arm_biquad_cascade_df1_f32)时遇到问题。请注意,这是我第一次这样做,而且我对控制理论知之甚少,所以我可能在这里遗漏了一些非常明显的东西。

翻阅一些教科书,我发现了以下振荡器传递函数的公式:

H(z)=Asin(ω0)1(2rcos(ω0))z1+r2z2
其中,据我所知,A 是振荡器的振幅,ω0是归一化的角频率,计算为ω0=2frealfsampling并且 r 是设置极点到单位圆的距离的参数,并决定系统的输出是否会被阻尼,与阻尼相反(暂时不记得这个词)还是恒定的。

我使用从其他一些要求中获得的以下参数设计了一个振荡器:采样频率Fs=759493.7, 振荡器频率f1=25630, 幅度A=1(我计划稍后对此进行微调),r=1.

这给了我然后ω0=2f1Fs=0.0674923和传递函数:

H(z)=0.067441111.9954464z1+1z2

查看 MATLAB 中的脉冲响应,我得到了预期的结果:
滤波器的脉冲响应

到现在为止还挺好。然后我尝试使用 arm_biquad_cascade_df1_f32 来实现它。这是根据文档的滤波器的框图: arm_biquad_cascade_df1_f32 框图
由于我的振荡器中只有一个二阶部分,所以我只使用了一个部分,如图所示。我将系数设置为:
b0=0.0674923,b1=0,b2=0
a1=1.9954464,a2=1

当我开始执行此过滤器时,输出不稳定并迅速变为无穷大。手动试验参数r,我设法得到一个缓慢衰减的响应r=0.5. 我怀疑我看到的是 MCU 只能处理 32 位浮点数并且缺乏精度的结果。

所以我的问题是:如何在考虑数值精度误差的同时对振荡器进行建模?

2个回答

我会尽量简化你在这里的内容。所以,作为一个振荡器,没有输入,只有输出。但是您可以将其视为以脉冲为输入的滤波器(状态为零)。但该脉冲本质上设置了滤波器的状态,其余输入为零。

反馈方程(从你的图表,设置b0,b1, 和b20) 是

y[n] = 2cos(ω0) y[n1]  y[n2]

ω0=2πf0fsfs是采样频率。

这个等式将频率设置为ω0但不设置幅度或相位。您通过明智地设置两种状态的初始值来设置幅度和相位,y[n1]y[n2]. 假设您的初始输出样本是y[0],你的初始状态是y[1]y[2].

所以如果你希望你的输出是

y[n]=Acos(ω0n+ϕ)

对于给定的Aϕ, 那么你只需将方程追溯到时间n=1n=2得到你的初始状态y[1]y[2].

就这么简单。

第一件事:我认为有一个π在频率和角频率之间的转换中丢失。您的脉冲响应显示大约 90 个周期,而您的周期应该是大约 29 个样本 - 这里显然有问题。

您在目标硬件上看到的情况是由于 matlab 隐式使用双精度(64 位)与您选择使用的例程使用 32 位之间的精度差异。

即使这通过传递函数或双二阶结构不是很明显,这个没有输入的“滤波器”所做的只是旋转它的初始条件。使用 32 位精度,不能保证输入向量的大小会通过旋转保留 - 它可以增长(不稳定)或衰减。

如果您打算将其用作振荡器(也就是说,如果输入将始终为空,但初始条件除外):

  • 定期 - 比如说每 100 个样本 - 弄乱你的状态变量以将向量的范数重新调整为 1。
  • 或者使用另一种更简单、更稳定的技术,如相位累加器和正弦查找表。