我在使用整数运算在微控制器上实现正交信号发生器 (OSG) 算法时遇到问题。我将此算法用于单相锁相环 (PLL) 算法,为此我需要电网电压的正交分量。
OSG算法定义如下:
其中是测量的电网电压,是估计的电网频率,和是估计的分量,对于理想估计等于为此,我们假设电网频率是已知的。
数值积分器实现如下:
其中是采样时间。
现在,该算法在浮点实现中运行良好,但在整数算术实现中效果不佳。在这里,我给出了两种实现:
浮点实现
代码声明。
float w = (2*PI)*50;
float Ts = 50e-6;
float i1u1, i1u2, i1u3, i1y1;
float i2u1, i2u2, i2u3, i2y1;
float NumInt3rd(float u1, float u2, float u3, float y1) {
return (Ts/12)*(23*u1-16*u2+5*u3)+y1;
}
主功能。
float vg = floor(Input(0));
float vg_x = NumInt3rd(i1u1,i1u2,i1u3,i1y1);
float vg_y = NumInt3rd(i2u1,i2u2,i2u3,i2y1);
i1u3 = i1u2;
i1u2 = i1u1;
i1u1 = ((vg-vg_x)-vg_y)*w;
i1y1 = vg_x;
i2u3 = i2u2;
i2u2 = i2u1;
i2u1 = vg_x*w;
i2y1 = vg_y;
这Input(0)
的正弦波)的宏。
整数算术实现
代码声明。
int w = 643398L; // (2*PI)*50*2048
int i1u1, i1u2, i1u3, i1y1;
int i2u1, i2u2, i2u3, i2y1;
int NumInt3rd(int u1, int u2, int u3, int y1) {
int iu = 23*u1-16*u2+5*u3;
int iy = 240000L*y1;
return (iu+iy)/240000L;
}
主功能。
int vg = (int) Input(0);
int vg_x = NumInt3rd(i1u1,i1u2,i1u3,i1y1);
int vg_y = NumInt3rd(i2u1,i2u2,i2u3,i2y1);
i1u3 = i1u2;
i1u2 = i1u1;
i1u1 = ((vg-vg_x)-vg_y)*w/2048;
i1y1 = vg_x;
i2u3 = i2u2;
i2u2 = i2u1;
i2u1 = vg_x*w/2048;
i2y1 = vg_y;
请注意,我已经检查了可能的溢出,它永远不会发生。此外,有趣的是相同的算法适用于。
我对整数算术实现没有那么有经验。你能给我一个建议如何解决这个问题吗?谢谢!
这是两种实现的估计误差(在 y 轴上:估计误差的百分比)。整数算法实现的估计误差约为。