由于原始数据有噪声,所以我们需要均值滤波。然而,对过多数据均值会让传感器输出延迟大,进而增大误差,对过少数据均值又会无法有效抑制噪声,所以我们要选择一个合适的值。
当然,如果要使得效果最好,应该分段。发动机工作阶段各物理量变化较为剧烈,应该略减小参与均值滤波的数据个数,发动机停止工作后,再增加。这个可以靠对加速度大小来判断发动机是否停止工作。比如,加速度大小小于某个值(停止工作后若无空气,传感器传回的加速度数据应该是零,但是对探空火箭这种高速物体,复杂的流体力学效应不能忽视。不过对业余探空火箭,这些流体力学效应带来的加速度基本不可能超过发动机工作带来的加速度)。当然,这些会在后面(大概第九章)再实现。
还有一点,由于使用了mpl库简化代码,它的姿态更新速率被限制了,最大只能到200Hz。这里我用Timer外设实测了(Timer的文件是我另写的,而且前面还有初始化啥的,不过后面才用,到时候发上来,现在不重要,重要的是测量值)
结果如下:
我的定时器是每100us增加一,所以是更新间隔大概50ms,执行一次更新大概2ms。50ms相对来说太长了,下一代看看能不能从改进协议,比如用硬件I2C或者干脆用SPI的方式改进,不过现在先凑合着用吧。
由于用的是中断,所以其中等待的48ms都没有在解算姿态,所以可以读取大量的原始数据用于均值滤波。
在其中姿态虽然没有更新,但是速度和位置还是要更新多次的,算法后面再说,这里提前给一个公式,可以看出为什么,证略。来自《惯性导航》
以下量除了姿态转移矩阵外都是向量
$V_m = V_{m-1} + C_{m-1}\Delta V_{sfm}+\Delta V_{g/cotm}$(2)
右侧第一项是上次速度矢量,第三项是由于重力、科里奥利力(我们暂时忽略)等因素带来的速度增量。
而第二项就是和惯性传感器测量有关的。$C_{m-1}$是姿态转移矩阵,后面再说。
$\Delta V_{sfm} = \int_{t_{m-1}}^{t_m}(f(t)+\Delta\theta(t)\times f(t))dt$
$f(t)$是比力,大小等于加速度传感器的微质量块测得的力除以质量,物理上等于在传感器的非惯性系中微质量块受到的惯性力和重力的合力除它质量,加速度的量纲,书上这么写应该是为了区分,毕竟它不是真实加速度。
$\Delta\theta(t) = \int_{t_{m-1}}^{t}\omega(\tau)d\tau$
角位移是角速度的积分。
问题有二。
一是角速度是矢量,角位移的微分是矢量,但是角位移不是矢量。这是刚体定点转动那块的结论,想了解的可以看看理论力学。所以,如果积分时间太长,那个矢量叉乘那里就会有严重偏差。
二是这个积分,我们是不知道这些量的每时每刻的值的,所以积分肯定有误差,《惯性导航》上介绍了几种算法,不过我们这里应该是选择最简单的一子样(直接把这个被积函数在这个积分区间内当作常函数,用它的一个值确定)或者二子样(把被积函数当成一次函数,用它的两个值确定),具体如何还是后面开发到了再说。所以积分时间太长,这个积分也会有严重的偏差。
综上,即便姿态没有更新,我们手动更新速度也是有必要的,所以均值滤波不能用太多数据,不能把两次姿态更新中所有数据都均值滤波了。
这里我们看看两次姿态更新之间计算机能获取几次原始数据。(变量加减运算比起I2C通信所需时间短很多,到时候更新姿态虽然涉及复杂的计算,但是由于精度要求不高,用的是最简单的算法,再加上软件I2C的频率还不到100kHz,姿态更新间隔中限制程序速度的主要是获取原始数据的过程。不过这里还是猜测,后面把更新算法放上来再说吧。)
输出是这样的。
大概能获取80个数据。
这比我想象的少,看样子是I2C的频率限制太大。
不妨发动机工作时取4个数据一组滤波,工作结束后取16个数据为一组滤波。实验程序中先选16吧。这里选二的倍数,是方便用移位代替除法,不过似乎也没必要优化这一点……
这里要声明一件事情:本代仍使用最简单的均值滤波,下一代会加入卡尔曼滤波,并脱离MPL库。而且滤波本应在校准后,但是这里主要原因时为了低成本,硬件受限,尽量减少计算次数。所以肯定有不足的地方。也就是说,本代主要改进的是系统误差的校准,对随机误差的处理只用了最简单的均值法,这个后面会改进的。
接下来我去想办法能不能用硬件I2C,可以的话就在下面继续讨论,不行的话就先不管了,下面发下写了均值滤波后的程序。
写完四才实验发现温漂不可忽略……我决定还是在三这里就更完温漂吧。
emm……我搞了好久硬件i2c,都搞不定,只有频率为200kHz左右时才能用……鬼知道发生了啥……之前听说stm32f1系列单片机的硬件i2c有问题,现在我也觉得大概是的了……既然这样,就不跟它耗了……
我刚刚估算了下软件i2c的频率。
之前算时间的时候没考虑串口发送,有些不准,但是都估算了就不管了。
48ms时间,80次,每次600us,然后有加速度角速度磁感应强度三个量的读取,每个200us。每次读取需要收发的位数至少84位(i2c指定地址读的时序,先发起始信号,然后7位芯片地址,1位写标志位,然后8位寄存器地址,然后再起始信号,然后再7位芯片地址,1位读标志位,然后每个方向数据分为上下8位存在两个寄存器中,是要连续读6个8位寄存器,然后停止信号,然后还有每个字节都要应答,共九个)。除一下200us,420kHz。然而mpu9250的最大i2c频率是400kHz,所以实际上应该是400kHz左右,估算和制造有误差。i2c通信由于需要弱上拉,它的速度是受限的,过快高电平切换来不及,没有特殊的外设一般上限就是400kHz。
所以,没有必要换硬件i2c,以后的版本自己打板子看看可不可以用spi,这个速度就快多了。(这个芯片有spi接口,但是市面上的廉价模块没有引出来)
只在main.c里面有改动
这里应该不用说了,很简单,这个TEST_DATANUM是宏定义,值是16,然后带_sum的量是均值滤波中用来保存和的,long类型(32位有符号),那个带_mpl的量是以后校准后传给mpl库的,后面会说。
ok第3篇就到这里,下面的456篇的校准是重头戏,
有点非常麻烦……这一代打算第9篇更完,不过456篇的校准方法可以在日后继续使用。
这里改了一下。加了LED指示灯,初始化成功了就会打开。(防止后面校准的时候出现各种抽象的情况不知道问题在电脑还是单片机……)
然后每组之间分隔符也改成了回车换行,这样串口输出的话人看比较方便。
然后由于改了分隔符,第四章的最终那个程序也要改,正好发现有一些问题顺便改了。有需要的话每个程序都下载最新的就行。
接下来开始更温漂补偿。
实测温漂影响相对不大,我们打算先用着mpl库的补偿,把这个问题留到第二代。
还有到第二代应该是吧温漂补偿放到标定之后。
嗯,更完了。
(敷衍)不过的确搞他太麻烦了,用mpl自带的补偿就行了……