您的方法会导致不精确和累积错误。
- 您应该避免使用浮点数(尤其是在没有 FPU 的情况下),尤其是如果此代码在定时器中断处理程序中。
- 您应该避免在每个样本上不必要地转换为度/秒 - 仅在演示时才需要转换,因此您应该只在需要该值时执行它 - 在内部,积分器应该以陀螺仪样本单位工作。李>
此外,如果您在 ISR 和普通线程中都进行浮点运算并且您有一个 FPU,您也可能会遇到不相关的错误,因为 FPU 寄存器不会在中断处理程序。总而言之,浮点数只能谨慎使用。
所以让我们假设你有一个函数 gyroIntegrate() 每 10 毫秒调用一次精确:
static int32_t ax = 0
static int32_t ay = 0
static int32_t az = 0
void gyroIntegrate( int32_t sample_x, int32_t sample_y, int32_t sample_z)
{
ax += samplex ;
ay += sampley ;
az += samplez ;
}
ax 等不是原始样本值的积分,因此与相对于起始位置的角度成正比。
将ax 转换为度数:
度数 = ax × r-1 × s
地点:
-
r 是以度/秒为单位的陀螺仪分辨率 (0.07)
-
s 是采样率 (100)。
现在你最好避免使用浮点数,这里完全没有必要; r-1 x s 是一个常数(在本例中为 1428.571)。所以要读取积分器表示的当前角度,你可能有一个函数:
#define GYRO_SIGMA_TO_DEGREESx10 14286
void getAngleXYZ( int32_t* int32_t, int32_t* ydeg, int32_t* zdeg )
{
*xdeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
*ydeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
*zdeg = (ax * 10) / GYRO_SIGMA_TO_DEGREESx10 ;
}
getAngleXYZ() 应该在您需要结果时从应用程序层调用 - 而不是从积分器中调用 - 您在需要时进行数学运算,并留出 CPU 周期来做更多有用的事情。
请注意,在上面我忽略了积分器算术溢出的可能性。因为它适用于大约 +/-150 万度 +/-4175 旋转),因此在某些应用中可能不是问题。您可以使用int64_t,或者如果您对旋转次数不感兴趣,则可以在积分器中使用绝对角度:
ax += samplex ;
ax %= GYRO_SIGMA_360 ;
其中GYRO_SIGMA_360 等于 514286 (360 x s / r)。