买了mpu-6050模块一段时间了,一直没有时间试,乘五一放假,总算是可以玩一下了。先找了一点简介:
——————————
MPU-6000为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时之轴间差的问题,减少了大量的包装空间。MPU-6000整合了3轴陀螺仪、3轴加速器,并含可藉由第二个I2C端口连接其他厂牌之加速器、磁力传感器、或其他传感器的数位运动处理(DMP: Digital Motion Processor)硬件加速引擎,由主要I2C端口以单一数据流的形式,向应用端输出完整的9轴融合演算技术 。
MPU-6000的角速度全格感测范围为±250、±500、±1000与±2000°/sec (dps),可准确追緃快速与慢速动作,并且,用户可程式控制的加速器全格感测范围为±2g、±4g±8g与±16g。产品传输可透过最高至400kHz的I2C或最高达20MHz的SPI。
MPU-6000可在不同电压下工作,VDD供电电压介为2.5V±5%、3.0V±5%或3.3V±5%,逻辑接口VVDIO供电为1.8V± 5%。MPU-6000的包装尺寸4x4x0.9mm(QFN),在业界是革命性的尺寸。其他的特征包含内建的温度感测器、包含在运作环境中仅有±1%变动的振荡器。
——————————————
总的来说,6050算是现在比较便宜好用的加速度陀螺仪芯片了,但是直接读取时噪声大,需要进行滤波。因此开始还找了一下卡尔曼滤波方面的资料,并且在网上发现了一种做好的6050+卡尔曼滤波集成的模块,不贵,35-58元,从网站的图片看效果很好,而且输出改成了串口,连接比较简单。刚看到有人对此提出质疑:,觉得其实就是用了一块8位的stm8调用了6050自带的dmp功能。模块的采样率100hz,后面说的dmp也可以做到。呵呵,谁对谁错就不好说了,不过用这个模块省了自己琢磨dmp了,懒人福音吧。用卡尔曼动态滤波算法,或者简化版的滤波,这种方法用好了效果会非常好,有些参数可以根据实际应用进行调整,改进效果。另一种是利用MPU6050内部的姿态融合器DMP,直接输出姿态角,优点是CPU参与少,但融合参数不可调整,调试困难(主要是可参考的资料很少)。
连线:首先把6050和arduino连起来,6050模块有8个插口,不用都用到,只需要把SCL和SDL连在A5和A4端就可以用了,有时需要中断时,把INt和D2连接,如下图。
Jeff Jrowberg 的DMP库(库名 MPU6050 I2C device class, 6-axis MotionApps20.h;当然这个库不是AVR的),这个库,是作者通过“反向工程“得到的,不是官方的!
如果你仔细读Jeff Jrowberg的代码,其实就是i2c操作,先设置6050寄存器,再在6050内存中写入firmware,然后是config,最后是update,然后就可以直接读出FIFO里的quarternion数据,当然还有gyro和accel数据!注意,陀螺仪数据是可以自动校正,只需要传感器8秒保持不动即可,四元数处理后得到的角度数据是非常稳定的!自动校正功能是在DMP模式下才有的.
MPU-6050内部的DMP运算,roll和pitch两个参数,用了片内的加计(重力)对陀螺仪数据进行了校正,而yaw轴就没有相应的校正参考,陀螺仪的输出会漂移是很正常的,只能采用磁感传感器校正(使用invensense的9轴DMP或自己校正)!很不莘,当你用5883时,请一定记得先将5883做8字校准,不然你的YAW轴不会得到能用的数据的!
——————
9轴mpu-9150要贵一些,但是集成了地磁传感器。也可以用别的磁场传感器,后面可以试试。先说说直接读取的数据吧。导入I2Cdev.h和mpu6050.h两个库函数,运行示例程序,可以得到三个轴的角速度和加速度。数据的波动比较大,见图。ax-az是加速度,单位10E-3 g,gx-gz是角速度。未经滤波处理的数据是不能直接用的。而且如何从这6个参数得到模型的空间姿态,也是很麻烦的,后面摘抄了一段相关帖子,说的比较明白。
Serial.print(ax/16.384); Serial.print(",");
Serial.print(ay/16.384); Serial.print(",");
Serial.print(az/16.384); Serial.print(",");
Serial.print(gx/131); Serial.print(",");
Serial.print(gy/131); Serial.print(",");
Serial.println(gz/131);
未经处理的数据:
mpu-6050 加速度、陀螺仪传感器的调试(1)
dmp后得到的欧拉角:
mpu-6050 加速度、陀螺仪传感器的调试(1)
MPU6050模块是InvenSense公司推出的一款低成本的6轴传感器模块,包括三轴加速度,三轴角速度。其体积小巧,用途非常广。做平衡小车,四轴飞行器,飞行鼠标等等,都是必不可少而且是最优的传感器解决方案。本人根据自己的一些实际工作经验和使用体会来谈谈MPU6050的相关问题吧,抛砖引玉,如有不当之处,欢迎大家批评指正。
不论是做平衡还是四轴飞行器,关键的问题在于两方面,一是模块姿态的确定,通常需要用到积分运算与卡尔曼滤波算法,需要较强的数学功底与编程能力,二是稳定控制,方法比较单一,就是经典的PID控制算法,难点在于需要根据实际情况调整PID的参数,需要做实验确定,不难,只是费时间。因此以下主要分析姿态确定问题。
虽然6050模块能够输出三轴加速度和三轴角速度的数据,但实际应用的时候,直接使用的确不是这些量,而是需要根据这些数据解算出三轴的角度数据。比如平衡小车,需要算出
模块的俯仰角,然后控制算法根据角度大小控制小车轮子的移动。四轴飞行器需要根据俯仰角度、滚转角度,和飞行指令来调节四个电机的转速。
从6轴的原始数据得到三轴的角度计算是一个比较复杂的运动学解算过程,有的童鞋可能会说,不就是三轴角速度积分不就行了吗?这就是没有实践,想当然的说法。有三点需要注意的问题:
1.三轴姿态的解算不能直接积分。因为三轴是有耦合的,只有在三轴角度为小角度的时候可以这么算,角度大了以后,比如60度了,这么算的误差就很大。标准的做法是用四元数的方法做姿态解算,积分的方法可以用4阶龙格-库塔法,或者4阶Gill法。详情请参考:航空航天器运动的建模——飞行动力学的理论基础 肖业伦著 北京航空航天大学出版社。
2.积分运算的累积误差。角速度积分运算是有累积误差的,累积误差在短时间内表现不明显,只要零点漂移处理得好了,1分钟以内的漂移都不大,但时间长了,就会有累积误差,5分钟就漂到不知道哪里去了。
3.角速率零点漂移。所谓零点漂移就是模块静止的时候,我们认为正常的输出应该是0,或者均值为0的数据,但是实际上6050的输出不是,可能在2°/s或者其他,而且每次都不一样,如果不校准,别说1分钟了,10秒钟误差就有20度。
根据上面的分析,似乎要获得角度非常困难呀。又有些聪明的朋友会想,用角速率积分这么麻烦,我不怎么算好了,条条大路通罗马,为啥非得用这个方法。6050不是能输出加速度吗?我用重力在3轴的分量的反正切值,作为滚转角和俯仰角不久行了。
用加速度计算的确也是一种方法,但使用加速度也有三方面的问题:
1.无法在动态情况下使用,使用重力的来解算姿态的前提条件是模块本身没有加速度,因此模块输出的三轴加速度值,正好是重力在模块本体坐标系下的分量,从而能够求出俯仰和滚转的姿态角度。一旦模块运动起来,这种方法就傻了,因为模块无法分辨出哪些是重力的分量,那些是模块本身的加速度引起的。目前市面上很多倾角仪就是这种思路,但问题就是没法在动态情况下使用,最简单的测试方法就是把模块水平放置桌面上,缓慢运动,发现X,Y轴的角度基本不变化,都在0度左右,一旦快速运动起来,X,Y轴就显示有很大的角度了。而实际上模块一直水平,没有变化。
2.精度差。6050模块的加速度本身的精度不高,就算是在静态情况下,角度测量的精度也只能到1°左右。
3.三轴耦合问题。利用加速度求解姿态的时候,也会有三轴耦合的问题,因为姿态表示与坐标旋转顺序有关,这样只有一种一个轴能用反正切值计算,另一个轴不能用反正切值计算。
那么怎么才能得到高精度不漂移的三轴角度呢?陀螺仪精度高,但时间长了会有漂移,加速度动态精度差,但没有长期漂移。能否综合利用陀螺仪和加速度计的特点,优势互补获得准确的姿态角度呢?答案是肯定的,方法就是用卡尔曼滤波做数据融合。大致的思路是将模块的姿态用四元素表示,作为系统的状态量,模块的姿态运动学方程作为滤波的状态转移方程,加速度信息作为滤波的观察量信息,然后利用卡尔曼滤波的计算方法迭代计算更新,详细的过程可以参考惯性导航方面的书籍。不过卡尔曼滤波算法比较复杂,需要用到矩阵运算等等,数学功底和编程基础要求都较高,不是初学者能够快速掌握的。而且MPU6050模块是IIC接口输出的,也给初学者带来了不少障碍与困难。
————————————————————
默认陀螺仪的量程是250度/s,可以设置到最高2000度/s。调用
MPU6050 accelgyro;
accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_8);
参数为:
#define MPU6050_GYRO_FS_250 0x00
#define MPU6050_GYRO_FS_500 0x01
#define MPU6050_GYRO_FS_1000 0x02
#define MPU6050_GYRO_FS_2000 0x03
#define MPU6050_ACCEL_FS_2 0x00
#define MPU6050_ACCEL_FS_4 0x01
#define MPU6050_ACCEL_FS_8 0x02
#define MPU6050_ACCEL_FS_16 0x03
这些定义可以在MPU6050.h和cpp文件中找到。
相应地,测量数据到角速度之间转换比例也要变,如:
Serial.print(ax/4.096); Serial.print(",");
Serial.print(ay/4.096); Serial.print(",");
Serial.print(az/4.096); Serial.print(",");
Serial.print(gx/16.4); Serial.print(",");
Serial.print(gy/16.4); Serial.print(",");
Serial.println(gz/16.4);
——————————————
调用DMP:
下载DMP的库文件:https://github.com/jrowberg/i2cdevlib
添加 MPU6050_6Axis_MotionApps20.h
运行其自带的例子MPU6050_DMP6,发现不能正确得到结果,数据是乱的,有一定规律,隔几个数就出现一个FIFO溢出错误,说明问题出在FIFO读取上。不是很明白,于是上网找结果,最后找到一句话“在arduino loop代码最后mpu.resetFIFO();采样数据就稳定了”解决了问题。但是有点治标不治本,等有空再看看库函数学习学习。
DMP后的结果可以是欧拉角(ypr)yaw(偏航),pitch(俯仰),roll(滚转)角度,也可以是四元数等等。
对于欧拉角表示:
roll 是绕y轴旋转的角度
pitch 是绕x轴旋转的角度
yaw 是绕z轴旋转的角度
mpu-6050 <wbr>加速度、陀螺仪传感器的调试(2) <wbr>dmp
——————————
数据的稳定性:
得到的数据的噪声很小,pitch和roll的变动幅度在0.1度以内,而yew一直在漂移。和上一篇中的转载一致。简单做了一下记录,可以看出漂移的量很大:
21:50
52.09,1.96,-2.01
52.09,1.97,-2.00
21:55
50.56,1.97,-1.96
50.56,1.97,-1.96
22:05
48.41,1.96,-1.96
48.41,1.96,-1.96
22:20
44.52,1.96,-1.92
44.52,1.96,-1.92
22:30
42.17,1.97,-1.95
42.17,1.97,-1.95
24:01
19.12,1.97,-1.92
19.12,1.97,-1.92
因此必须校准。同时可以看出角度也是相对量,即和初始位置相关。
****MPU6050库的安装方法*************************johnsonzzd
1. 下载arduino编译器,目前版本为1.0.5。
2. 下载MPU6050库。进入“https://github.com/jrowberg/i2cdevlib”,点击“zip”即可。
3. 安装。将上一步下载的“I2Cdev”、“MPU6050”两个文件夹拷贝到“arduino-1.0.5\libraries”目录下。
运行arduino可以在例子中看到MPU6050。OK!
——————————————————————
MPU6050数据处理实验一
关于dmp,我的实验结果是数据非常稳定,应该没有其它方法比这个更稳定了,数据可以直接拿来用不用任何滤波。数据也应该是最准确的了。当然稳定和准确是要付出时间代价的。默认输出中断频率是100Hz,对头文件的数组最后一位改为0可输出200Hz(这是最快的了),对于一般的应用应该是最好的选择,如果做随动方面的设备,延迟非常明显,不过可以用角速度积分来改善(我是昨天才想到的,这几天有时间来验证一下)。希望能成功吧。如果成功,那mpu6050的稳定精确和实时性就能达到随动的要求了。
---------------------SuperAnt
平衡控制系统中最复杂的两部分内容,一部分是滤波,另一部分是PID稳定控制。
滤波是为了获得对真实状态的最佳估计,如姿态信息等,而PID控制是为了实现对状态偏差的矫正。其中滤波通常是最复杂也是最难的部分。
好的滤波算法可以获得非常准确地系统状态,提高精度,通常使用动态卡尔曼滤波算法,算法比较复杂,数学功底要求高,是技术活儿。PID控制看似复杂,其实非常简单,运算量不大,关键是三个控制参数的调整,一般需要进行很多次试验才能找到合适的参数,是个体力活儿。