catluoq 发表于 2013-6-19 01:34:48

atmega16+BASCOM玩出MPU-6050的DMP

    几个月前买了几片L3G4200和MPU-6050,想做个三轴陀螺仪,用于气动外形不稳定的飞机,像仿真的二代喷气式F104、J-10、幻影2000 ,还有F117、B2等类型,用atmega88及L3G4200或MPU-6050弄出来了,但过程比较坎坷,有许多滤波和漂移的处理,比较麻烦,虽然基本达到了初衷,但完成后的程序杂乱无章,自己都不想多看一眼。后来看到介绍MPU-6050有DMP功能,就在网上搜索相关信息,基本上都是MSP430的,好像还没有用AVR单片机的,只好努力读程序,用一片带LCD的atmega16自制洞洞测试板(上面很费神的焊了L3G4200、HMC5883L、ADXL345、MPU-6050各一片),摸索了几天,多消耗了几包烟, 也算稳定读出了MPU-6050的DMP数据,比起原先自己凑出的程序,姿态数据准确又稳定,不佩服INVENSENS公司都不行。
    firmware用的是Jeff Jrowberg公开的库,库名 MPU6050 I2C device class, 6-axis MotionApps20.h,这个库比lotsbiss的帖子http://www.amobbs.com/forum.php?mod=viewthread&tid=5528472&highlight=6050里的库小一点,只有不到2k,但其功能都至少能满足我的要求(实际上到底有多少功能,没几个人知道),又参照一篇名为《全角度欧拉角与四元数转换研究》的PDF文章,对角度作了转换,下一步就打算用ATMEGA328重造几个三轴飞控陀螺仪了。
    在网上晃悠了好久,发现各位大侠都用比较高端的单片机操作MPU-6050,如MSP430、STM32,开始还真以为6050有那么挑剔,8位单片机配不上,后来仔细读了Jeff Jrowberg的代码,发现不过 so so,也就是i2c操作,先设置一下6050寄存器,再在6050内存中写入firmware,然后是config,最后是update,然后就可以直接读出FIFO里的quarternion数据,当然还有gyro和accel数据,值得关注的是,陀螺仪数据居然可以自动校正(传感器8秒保持不动),四元数处理后得到的角度数据非常稳定,对我能设想到的飞控需求都不成问题。
    我的测试板没有对电脑的接口,因为在屏幕上翻动一块砖头,实在很无趣。
    下面发几张图片,看看单片机最简单可以怎么玩6050。具体的程序段子以后再补上。   





ajdd 发表于 2013-6-19 14:36:55

高手!能否分享一下

xou822 发表于 2013-6-19 17:33:35

楼主用51操作的?
mark一下先

catluoq 发表于 2013-6-19 22:36:30

ajdd 发表于 2013-6-19 14:36 static/image/common/back.gif
高手!能否分享一下

程序写得有点乱,还得整理一下,现在是BSCOM的,还准备做出winavr的,到时候会全部贴出来。

catluoq 发表于 2013-6-19 22:43:17

xou822 发表于 2013-6-19 17:33 static/image/common/back.gif
楼主用51操作的?
mark一下先

不是51,是AVR 的atmega16,用51弄倒是能弄出来,不过运算速度就不太容易达到要求,用avr的atmega(带16m或20m晶振)能保证计算时间不超过5ms(浮点运算),51算起来时间会超过40ms,达不到飞控要求。

a20084666 发表于 2013-6-19 23:01:04

很厉害的样子

colgate 发表于 2013-6-19 23:19:40

高手能共享一下你写的bascom程序吗? 邮箱:cgjchen@gmail.com

catluoq 发表于 2013-6-20 01:50:18

先把BASCOM的程序发上来, C 的以后再补

欢迎拍砖

好人不学坏 发表于 2013-6-20 08:54:36

非常感谢楼主,研究去。

rantingting 发表于 2013-6-20 10:39:27

好东西………………

cai_mouse 发表于 2013-6-23 08:34:11

编译出来2k字节,很牛逼

ajdd 发表于 2013-6-24 20:52:21

catluoq 发表于 2013-6-20 01:50 static/image/common/back.gif
先把BASCOM的程序发上来, C 的以后再补

欢迎拍砖

效果怎么样?我移植到AVR的六轴dmp,感觉稳定性不是很好。平放在桌面,它的yaw角就从360度,较快地下降到340度附近,之后又开始较缓慢地下降,这是怎么回事,能帮我分析一下吗?

catluoq 发表于 2013-6-24 22:51:45

ajdd 发表于 2013-6-24 20:52 static/image/common/back.gif
效果怎么样?我移植到AVR的六轴dmp,感觉稳定性不是很好。平放在桌面,它的yaw角就从360度,较快地下降到3 ...

MPU-6050内部的DMP运算,roll和pitch两个参数,用了片内的加速度传感器(感应重力)对陀螺仪数据进行了校正,而yaw轴就没有相应的校正参考,陀螺仪的输出会漂移是很正常的,只能采用磁感传感器校正(使用invensense的9轴DMP或自己校正)。这是没有办法的事,这个级别的芯片,只能这样了,相信这芯片放到卫星,或夸张点,放在神十上,另外两个参数也会漂移得够呛。

ajdd 发表于 2013-6-25 08:26:15

catluoq 发表于 2013-6-24 22:51 static/image/common/back.gif
MPU-6050内部的DMP运算,roll和pitch两个参数,用了片内的加速度传感器(感应重力)对陀螺仪数据进行了校 ...

听说,dmp只是通过Aux_I2C将mag数据读出,而不处理mag的数据,也就是不进行九轴融合,是这样的吗?
另外,帮我看一下我10分钟读到的数据,分析一下质量怎么样,谢谢。

catluoq 发表于 2013-6-25 10:07:22

ajdd 发表于 2013-6-25 08:26 static/image/common/back.gif
听说,dmp只是通过Aux_I2C将mag数据读出,而不处理mag的数据,也就是不进行九轴融合,是这样的吗?
另外 ...

DMP有两种版本firmware,9轴或6轴,一种融合了数字罗盘,一种没有,从磁传感器得到的数据是实时的,自己校正也很方便。看了你的DMP,数据很正常,已经达到了DMP处理的目的,做飞控没问题。

ajdd 发表于 2013-6-25 13:34:51

自己用磁传感器怎么校正?
手头上有HMC5883L,也买了一片配合九轴融合算法的AK8975。
看了九轴融合算法的范例,发现用其它的磁传感器可能不行,估计只能用AK8975,因为程序有个片段,读了10个字节的数据,其中包括AK8975的四个控制/状态寄存器(另外六个是测量数据寄存器),在程序的其它部分也没有明显的处理过程,那只能是MPU6050也明白这些AK8975寄存器的实际意义。换作其它的磁传感器,MPU可能无法处理它们的数据。
不知道我这些话,是不是正确的?

catluoq 发表于 2013-6-25 21:26:34

其实不需要9轴DMP,磁传感器测到的数据都是实时数据,也就是不需要积分,是确定的方位,虽然不一定它的120度等于真实的120度,但在不是极限状态的应用里(俯仰角非常接近90度),就可以直接用5883数据代替yaw参数,如果下级接收还是需要四元数,可以直接反推回去。
9轴DMP并不一定用AK8975,JJeff Jrowberg公开的9轴库里有用5883的内容,因为不是很感兴趣,所以没有仔细读,他的库是经过修改的,你可以自己试试看。我的C水平还在门外,仍在突击中,你可能更快弄清楚怎么用 。

ajdd 发表于 2013-6-25 22:33:56

catluoq 发表于 2013-6-25 21:26 static/image/common/back.gif
其实不需要9轴DMP,磁传感器测到的数据都是实时数据,也就是不需要积分,是确定的方位,虽然不一定它的120 ...

使用AK8975的九轴已经弄出来了,可是地磁加上去,一点也没有用处。地磁数据能正常读出来,但是对于姿态定位,没什么用处,唉....

灬琥珀川灬 发表于 2013-6-26 20:11:57

求教:dmp只用刷一次以后也可以接到其他单片机上 按流程读出数据了吧?

catluoq 发表于 2013-6-26 20:24:59

灬琥珀川灬 发表于 2013-6-26 20:11 static/image/common/back.gif
求教:dmp只用刷一次以后也可以接到其他单片机上 按流程读出数据了吧?

这不太容易,6050一掉电,DMPfirmware就没了,程序不是存在非易失性储存器里,不断电换单片机好像有点不太好实现。

灬琥珀川灬 发表于 2013-6-26 20:40:04

catluoq 发表于 2013-6-26 20:24 static/image/common/back.gif
这不太容易,6050一掉电,DMPfirmware就没了,程序不是存在非易失性储存器里,不断电换单片机好像有点不 ...

额 谢谢啦 那么快就回复
看来还是要移植到开发用的板子上才行
新手要学的还很多{:dizzy:}

catluoq 发表于 2013-6-27 09:49:32

灬琥珀川灬 发表于 2013-6-26 20:40 static/image/common/back.gif
额 谢谢啦 那么快就回复
看来还是要移植到开发用的板子上才行
新手要学的还很多...

不用客气,我也是新手,共同进步吧

liang_work 发表于 2013-6-30 14:17:22

看贴,留名

小黑鱼1148 发表于 2013-6-30 14:37:03

好贴,留名

ajdd 发表于 2013-7-1 16:06:25

请问一下,我的DMP输出,静止放置板子时,大约需要20s秒钟才能稳定(一直接少或者增加,直到某一个值),这是为什么呢?你有没有遇到过?

catluoq 发表于 2013-7-1 21:16:07

ajdd 发表于 2013-7-1 16:06 static/image/common/back.gif
请问一下,我的DMP输出,静止放置板子时,大约需要20s秒钟才能稳定(一直接少或者增加,直到某一个值),这是 ...

差不多,你看一下总的变化,除yaw以外的另外两个值,漂移幅度其实是很小的,都不到0.1度(deg)。invensense没有提供具体的数据,不过我认为,比自己的处理,已经好了不止一点点,用起来精度足够了,我自己弄了很复杂的运算(包括三维的加速度校正,滤波还有临时想出来的非线性衰减等),结果都比这个差远了,相对于专业的姿控陀螺仪(¥??),不能太计较了。

ajdd 发表于 2013-7-1 22:39:22

catluoq 发表于 2013-7-1 21:16 static/image/common/back.gif
差不多,你看一下总的变化,除yaw以外的另外两个值,漂移幅度其实是很小的,都不到0.1度(deg)。invense ...

也是。如果应用这个设计到产品上,还要用户在使用前,等待若干秒,感觉挺奇怪的了

catluoq 发表于 2013-7-3 13:35:48

   这两天终于有了点时间,可以把C语言的源码整理一下,现在发上来,对比BASCOM的程序,减少了用陀螺仪数据判断pitch在超过+ - 90度时计算值的部分,本来是想用winavr的,后来发现编写LCD操作的函数有点麻烦,偷了个懒,改用CodeVision AVR了,本人对C语言几乎一窍不通,也不知道写得是否规范,可能大家会感觉,明明点的是烤鱼,盘子上也写着烤鱼,内容却像烤兔子,没办法,将就看吧。
    用AVR8位单片机实现MPU-6050 DMP功能的折腾基本到此为止,如果能对别人有些许帮助,我会很高兴的。



Andre.Gorz 发表于 2013-7-4 17:16:56

谢谢楼主。

芽芽小宝 发表于 2013-7-7 14:28:37

楼主您好,i有几个问题请教一下:
1.四元数的初始读数是多少?我用官方库上电运行第一次读到的是1073709240,8329102,755311,-167732,第二次之后就读到1046468651,-367723,-30597167,-238513195,而且每次都围绕第二次的值有跳动。
2.四元数具体如何转换为角度,我想用6050来做角度计量(各轴-180至+180°),可以实现吗?如何确定角度计量的初始值,还是都相对于上电时刻的坐标系?

芽芽小宝 发表于 2013-7-7 15:43:27

芽芽小宝 发表于 2013-7-7 14:28 static/image/common/back.gif
楼主您好,i有几个问题请教一下:
1.四元数的初始读数是多少?我用官方库上电运行第一次读到的是1073709240 ...

看到了您上传的代码了,我从四元数到欧拉角的转换方法跟您是一样的。难道是四元数采集的不对?我按照您的初始化配置试一下去。

芽芽小宝 发表于 2013-7-8 22:10:42

如何设定四元数输出的初始角度?

catluoq 发表于 2013-7-9 00:43:25

芽芽小宝 发表于 2013-7-8 22:10 static/image/common/back.gif
如何设定四元数输出的初始角度?

抱歉,几天没登录,现在才看到。四元数初始值一般是接近 1,0,0,0,是读取的原始数字除以1073741824(2^30)得到的,你的第一组数据看起来没什么问题,不过我不太明白你的采样频率是多少,有没有可能高了?还有我发现,6050的sample rate如果能被DMP采样频率整除,波动就会小一些,你可以试试。
初始读数我没有设定,跟传感器的位置有关,一般来说,水平放置(IC印字朝上)的情况下,roll 和 pitch 值因为有加速度传感单元的校正,都能保持0度,漂移很小,yaw 值就漂移大一些,可能到+ - 15度。我选择的DMP输出是100HZ,程序每个显示周期约为250ms,显示的DMP数据是取最后一个,确认FIFO里有效的数据读完,这个要查看0x72和0x73确认。
四元数转欧拉角,roll 和 yaw 都没什么问题,不过 pitch 值有点麻烦,在超出+ - 90度时,要根据实际情况决定计算公式,我是顺便采集 gyro 的 y 轴数据,作了积分来决定选取公式的。C 版的程序里没有,偷懒了,BASCOM 版的有,可以参考一下。

芽芽小宝 发表于 2013-7-9 16:01:56

catluoq 发表于 2013-7-9 00:43 static/image/common/back.gif
抱歉,几天没登录,现在才看到。四元数初始值一般是接近 1,0,0,0,是读取的原始数字除以1073741824(2^30 ...

谢谢楼主大哥,您解释的非常详细也很快,非常感谢。我现在水平放置(IC丝印朝上),无论什么角度,第一次读到的四元数转换为角度以后为0,0,0(此值是相对于什么坐标系的?),但是静止不动几十秒以后会慢慢变化为25,0,0左右(有一个变化过程,2,0,0--4,0,0--6,0,0--------25,0,0,)然后就比较稳定了,可能过几分钟会跳到,23,0,0或18,0,0,但是在一定的时间内还是比较稳定了。所以说还并不是一直处于不稳定状态。这也许就是您说的yaw 值就漂移比较大的原因(垂直于芯片的Z轴)。我想问的是能不能将初始值置零,比如我任意摆放一个姿态,稳定后读到角度45,45,45,我想以此姿态作为初始值(我自己理想中的0,0,0,然后再有的转动就在此基础上计量)。
还有个问题,我看官方例程里有个定义:
# Sensor sensitivities
ACCEL_SENS = 16384.0
GYRO_SENS= 16.375
QUAT_SENS= 1073741824.0
而我看您选择的是32768.0,16.384,1073741824.0,前两个值不一样,是为什么?

芽芽小宝 发表于 2013-7-9 16:54:59

catluoq 发表于 2013-7-9 00:43 static/image/common/back.gif
抱歉,几天没登录,现在才看到。四元数初始值一般是接近 1,0,0,0,是读取的原始数字除以1073741824(2^30 ...

我的mpu_set_sample_rate为100Hz,DMP_SAMPLE_RATE为200Hz。

catluoq 发表于 2013-7-10 00:40:13

芽芽小宝 发表于 2013-7-9 16:54 static/image/common/back.gif
我的mpu_set_sample_rate为100Hz,DMP_SAMPLE_RATE为200Hz。

DMP_SAMPLE_RATE为200Hz,确实高了,我知道的是应该不超过100Hz,虽然实验中有时用200也能表现得正常,但经常重新加电后又不稳定了,还有我前面说了,6050的sample rate如果能被DMP采样频率整除,波动就会小一些,这是试出来的,没有其他人提过。比如说6050的采样频率200,DMP 频率100,就很好。似乎你的刚好相反,有可能是不稳定的原因之一。
我选择的转换比例因子是根据实测决定的,跟说明书上不一样,加速度如果用16384,三维加速度计算,重力就差不多是接近20米秒平方,而不是9.8 ,16.384应该是正确的,16.375反而没有理由,自己觉得怎么对就怎么用,反正又没人给我打分。
关于把初始值置零,要从DMP的firmware方面修改,可能有点难度,因为其内部运行机理和参数根本就没公开。要达到你的需求,最好自己做偏置调整,也不过是多一步运算而已。

芽芽小宝 发表于 2013-7-11 10:24:40

catluoq 发表于 2013-7-10 00:40 static/image/common/back.gif
DMP_SAMPLE_RATE为200Hz,确实高了,我知道的是应该不超过100Hz,虽然实验中有时用200也能表现得正常,但 ...

嗯,非常感谢。我清楚了,我尝试了各种采样率的组合,感觉效果改善不是很明显,不过对初始的yaw 漂移值有影响。我现在还有两个问题,您帮忙分析一下:
1. 上电后,芯片不动,yaw 值会在几十秒内慢慢漂移到某个值,有一个变化过程,2,0,0--4,0,0--6,0,0--------25,0,0,然后就比较稳定了。这是否正常。(改变采样率能影响到这个稳定后的漂移值)。我现在是以此值为基准,后面减去它来计算转过的角度,有点担心在使用的过程中会不会还有随机的漂移。
2. 处理速度很慢,以很正常的速度转过90度,FIFO中读出的值需要在几秒内,慢慢0--20--50--70--90,就是感觉有一定的延迟。不知这个是什么原因,我用的是MSP430内部16M晶体,与这个速率有关系吗?有时候我读取FIFO挺长时间才能读上来(我是在一个死循环里反复读取,成功后break),有时候会很快,亦或是6050或是DMP的速率的原因?

catluoq 发表于 2013-7-15 22:22:04

芽芽小宝 发表于 2013-7-11 10:24 static/image/common/back.gif
嗯,非常感谢。我清楚了,我尝试了各种采样率的组合,感觉效果改善不是很明显,不过对初始的yaw 漂移值有 ...

可能是你读FIFO不够次数,应该取最后一组数据,先读0x72和0x73(fifocount >=42),保证能够读到最近一组数据,直到读完为止(fifocount<42),我从没发现像你遇到的问题,几秒钟才变,有点稀奇。如果不行,在本次读取后,可以考虑试着写 0b11001100 到 0x6a, 清空FIFO ,然后再读,肯定没问题,但这样只能向你表明DMP在正常工作而已,该怎么弄,还得自己多试试才能搞清楚。不同的单片机,即使差别比较大,对I2C的操作也没什么不同,都是同样的指令,问题一般都出在细节上。   

cshp138 发表于 2013-7-18 13:46:25

do
    {
       do
   {
         fifocounts=i2cread(0x72);
         fifocounts=fifocounts<<8;
         fifocounts=fifocounts+i2cread(0x73);   //读出FIFO里有多少数据
         //showlong(12,3,fifocounts);
       }
       while (fifocounts<42);
       readdmp();
       fifocounts=i2cread(0x72);
       fifocounts=fifocounts<<8;
       fifocounts=fifocounts+i2cread(0x73);
   }while(fifocounts>=42);
请问LZ的C语言版有测试运行吗,我移植来用,程序一直死在do{}while();里面,不大明白这段代码的作用

catluoq 发表于 2013-7-19 00:42:48

我是用CodevisionAVR 2.05版本测试的,从本网站里能搞到,atmega16 晶振16M,运行很正常,不可能拿个不能运行的玩意贴出来,这个程序段已经添加到飞控板上,准备飞了。
   do
      {
         fifocounts=i2cread(0x72);
         fifocounts=fifocounts<<8;
         fifocounts=fifocounts+i2cread(0x73);   //读出FIFO里有多少数据
         //showlong(12,3,fifocounts);
       }
       while (fifocounts<42);
这一段的作用是确保FIFO里有足够的数据再读,0x72和0x73拼成一个unsigned int,即fifocounts要够42字节,要不可能会错位。如果在这个循环里退不出来,那就是FIFO不正常,根本没有数据输出,应该是firmware或是config、update写入,还有使能FIFO及DMP阶段出了问题。
后一个循环中类似的语句则是保证把FIFO里的有效数据读完,取最后一组,也就是最新的,处理后显示出来

wcm_e 发表于 2013-7-19 01:24:36

学习,mark, 谢谢了哎!

cshp138 发表于 2013-7-19 09:28:41

本帖最后由 cshp138 于 2013-7-19 10:58 编辑

catluoq 发表于 2013-7-19 00:42 static/image/common/back.gif
我是用CodevisionAVR 2.05版本测试的,从本网站里能搞到,atmega16 晶振16M,运行很正常,不可能拿个不能运 ...

感谢你的回答,第一个循环可以跳出,但在第二个循环体就跳不出来,通过仿真查看FIFOCOUNTS在第二循环体一直大于42,这样的话应该是readdmp()这函数没读好FIFO导致fifocount无法清零,但逻辑分析查看I2C也挺正常,MPU6050应答也很顺利,这可真想破头皮。fifocounts的值是0x400,看你说明应该不会这么大,是什么原因导致。

cshp138 发表于 2013-7-19 15:41:35

catluoq 发表于 2013-7-19 00:42 static/image/common/back.gif
我是用CodevisionAVR 2.05版本测试的,从本网站里能搞到,atmega16 晶振16M,运行很正常,不可能拿个不能运 ...

这情况解决了,是I2C读操作出了问题。还有一个问题是,欧拉角输出FLOAT型数值,是-180到180的角度范围吗

catluoq 发表于 2013-7-20 13:34:29

cshp138 发表于 2013-7-19 15:41 static/image/common/back.gif
这情况解决了,是I2C读操作出了问题。还有一个问题是,欧拉角输出FLOAT型数值,是-180到180的角度范围吗 ...

对 ROLL 和 YAW 是正负180度有效,PITCH 值在 C版程序里,只是 + - 90度,还要有辅助计算才能到+ - 180度。

cshp138 发表于 2013-7-21 12:02:19

请问LZ处理数据输出欧拉角循环周期是多少,现在我读出的数据怎么看都不是像正确的,无论是原始数据还是最终输出,显示出来的欧拉角是突变的完全没有规律。我是用STM8单片机8M主频做MPU6050初始化,算出欧拉角然后输出到另外一个主控器上显示。不知道是否因为这样影响了数据处理周期。

catluoq 发表于 2013-7-21 14:39:55

cshp138 发表于 2013-7-21 12:02 static/image/common/back.gif
请问LZ处理数据输出欧拉角循环周期是多少,现在我读出的数据怎么看都不是像正确的,无论是原始数据还是最终 ...

我的实际显示周期约250ms,每次都读完FIFO,最后一组计算后显示,读数不正确,有可能是DMP取样频率太高,最高应该不超过100HZ,还有就是读FIFO时错位了,如果错误还可以用写0b11001100 到 0x6a,即清除FIFO和DMP数据,短延时(约15ms)后读取试试。

cshp138 发表于 2013-7-21 15:36:01

catluoq 发表于 2013-7-21 14:39 static/image/common/back.gif
我的实际显示周期约250ms,每次都读完FIFO,最后一组计算后显示,读数不正确,有可能是DMP取样频率太高, ...

感谢你的回复,DMP采样频率我都是设置100HZ以下的,如何判断读FIFO是否错位。

芽芽小宝 发表于 2013-7-23 11:17:04

catluoq 发表于 2013-7-15 22:22 static/image/common/back.gif
可能是你读FIFO不够次数,应该取最后一组数据,先读0x72和0x73(fifocount >=42),保证能够读到最近一组 ...

这几天没上来,谢谢您的耐心答复。{:handshake:}

芽芽小宝 发表于 2013-7-23 11:22:16

芽芽小宝 发表于 2013-7-23 11:17 static/image/common/back.gif
这几天没上来,谢谢您的耐心答复。

对了,还有个问题,您说的陀螺仪数据居然可以自动校正(传感器8秒保持不动),是什么意思,怎么实现?
再就是我看设计到速率的地方有三个:mpu采样速率、dmp采样速率和FIFO速率,FIFO的速率需要有讲究吗?

芽芽小宝 发表于 2013-7-24 23:06:57

陀螺仪数据居然可以自动校正(传感器8秒保持不动),这个是怎么实现的?

catluoq 发表于 2013-7-25 00:14:57

cshp138 发表于 2013-7-21 15:36 static/image/common/back.gif
感谢你的回复,DMP采样频率我都是设置100HZ以下的,如何判断读FIFO是否错位。 ...

如果在DMP运行的状态下,读出的数据不稳定,应该就是错位,fifo控制位0x23只能写零(i2cwrite(0x23 , 0b00000000)),不能写入0b11111000,也就是在这里不能设定GYRO,ACCEL、及温度的输出,否则就干扰了DMP输出,fifo读42个字节,就不能保证读到的是想要的数据。

catluoq 发表于 2013-7-25 00:46:26

芽芽小宝 发表于 2013-7-23 11:22 static/image/common/back.gif
对了,还有个问题,您说的陀螺仪数据居然可以自动校正(传感器8秒保持不动),是什么意思,怎么实现?
再 ...

我不太清楚FIFO的速率,有关的速率有三个:
1.gyro速率,有两种, 8K 不带低通滤波,或 1K 带低通滤波
2.非DMP模式下的采样速率,由gyro速率除以0x19值+1
3.DMP模式下的采样速率,程序中firmware config段有注解

我自己测试下来,似乎2项如果能被3项整除,数据更稳定一些

关于陀螺仪数据自动校正,是在DMP模式下才有的,42个字节的DMP中,有12个是陀螺仪的(第17至第28,或数组的16至27),自己读一下数据就知道了,约8秒钟静止后,陀螺仪数据会自动校正,我自己的数据是从约+ - 200自动降到 + - 20~80,其零值并不能保证是0,都会有一定的偏移,还可能随电压、温度等环境变化,实际使用还是一样要测量计算平均值,减小漂移。

longwu537 发表于 2013-7-25 10:10:27

楼主是大牛啊

芽芽小宝 发表于 2013-7-25 22:17:20

longwu537 发表于 2013-7-25 10:10 static/image/common/back.gif
楼主是大牛啊

确实很牛{:smile:}

cshp138 发表于 2013-7-26 11:13:01

catluoq 发表于 2013-7-25 00:14 static/image/common/back.gif
如果在DMP运行的状态下,读出的数据不稳定,应该就是错位,fifo控制位0x23只能写零(i2cwrite(0x23 , 0b0 ...

这里我也是设置对的。但是输出的值无论怎样就是不对,难道DMP这处理器坏了?,如果我不用DMP直接普通方式读取6轴的数据,看上去正常多了。

cshp138 发表于 2013-7-30 14:26:22

现在读出四元数原始数据是对的,但是转成欧拉角之后就不行了,貌似除去1073741824.0f这值就会有问题,假如把四元数传到PC再运算就行,这说明在8位机上这运算会出错,但什么原因引起真不知道如何解决,LZ用ATmega16缺没这问题,真搞不懂,难道是编译器问题?



rantingting 发表于 2013-7-30 21:02:17

高手学习学习

指点江山 发表于 2013-8-15 23:46:49

最近我也在做这个,最终也有了自己要的数据,可是解算姿态角需要资源较多,自己算速度慢的不行了。说实在的我的姿态角算法要是不太熟。幸好遇到此贴,今天下移植了楼主的C版,区别是uart9600发PC,晶振11.0592,没用LCD.       (fifocounts>=42)此条件不满足,跳不出do{}while().          不知道原因????????????

catluoq 发表于 2013-8-21 16:20:01

指点江山 发表于 2013-8-15 23:46 static/image/common/back.gif
最近我也在做这个,最终也有了自己要的数据,可是解算姿态角需要资源较多,自己算速度慢的不行了。说实在的 ...

应该还是 I2C 读写的问题,可以从头校验 I2C 的读写是否正常,从寄存器开始,然后是 DMP firmware ,这是个很简单的小程序,找错不该难。

lqjesse 发表于 2013-8-24 15:23:42

楼主你的这个 dmpmemorydata 和官方的dmp_memory差别很大啊?官主的大小是3062个节字的,不知功能上差别有多大?

lqjesse 发表于 2013-8-24 16:09:23

请教各位,当Pitch倾斜时,只往Roll方向运动时,为什么Yaw数据也在变化?

指点江山 发表于 2013-8-24 21:03:57

catluoq 发表于 2013-8-21 16:20 static/image/common/back.gif
应该还是 I2C 读写的问题,可以从头校验 I2C 的读写是否正常,从寄存器开始,然后是 DMP firmware ,这是 ...

应该是是吧,读寄存没问题。可能是固件的事

KingYoung 发表于 2013-8-24 21:07:28

感谢分享!

catluoq 发表于 2013-8-27 01:10:38

lqjesse 发表于 2013-8-24 15:23 static/image/common/back.gif
楼主你的这个 dmpmemorydata 和官方的dmp_memory差别很大啊?官主的大小是3062个节字 ...

这个版本的 firmware 其实应该是 Jeff Jrowberg 的同伙 Noah Zerkin 根据官方 firmware 载入运行后 ,再回头读取 6050 内存,搞的反设计,我想功能是一样的。

lqjesse 发表于 2013-8-30 14:04:36

catluoq 发表于 2013-8-27 01:10 static/image/common/back.gif
这个版本的 firmware 其实应该是 Jeff Jrowberg 的同伙 Noah Zerkin 根据官方 firmware 载入运行后 ,再 ...

试了一下确实我官方的一样,问题同样存在,Pitch不旋转时,ROLL和YAW数据正常,但是只要Pitch旋转一定角度后,ROLL和YAW数据就不正常了;
平放时数据(Pitch = -0.027330Roll = 0.818385Yaw = -0.941145)
往ROLL旋转一定角度后,(Pitch = 0.751704Roll = -42.787109Yaw = -0.686597)
保持ROLL不变,此时只往Pitch方向旋转(Pitch = -35.260311Roll = -42.027378Yaw = 19.004519)

rockyyangyang 发表于 2013-8-30 14:50:04

你好,请教下,你用M16做四轴,那四路PWM怎么解决?

catluoq 发表于 2013-8-30 22:37:31

rockyyangyang 发表于 2013-8-30 14:50 static/image/common/back.gif
你好,请教下,你用M16做四轴,那四路PWM怎么解决?

这里只是用M16试验6050的DMP处理,不是直接做四轴的。
还有你的概念好像有点问题,用M16做四轴没太大问题,你的意思可能是控制四个电机,一定要用PWM的话,确实不知道怎么控制,除非是有刷电机。
一个单片机上又做姿控又包括四个无刷电调,这不是8位机适合干的事,我知道一般飞控板和无刷电调是分开的,飞控板控制无刷电调的方法大概有这几种:
1. I2C (TWI)
2.UART
3.SPI
4.PPM (也就是商品无刷电调通常的方式)
这几种方法M16控制4个电机都很容易实现

catluoq 发表于 2013-8-30 22:45:57

lqjesse 发表于 2013-8-30 14:04 static/image/common/back.gif
试了一下确实我官方的一样,问题同样存在,Pitch不旋转时,ROLL和YAW数据正常,但是只要Pitch旋转一定角 ...

在角度接近90度时,确实不太正常,几个版本的计算公式结果都一样。对游戏机或游戏手柄问题不大,用到飞控上,还是得加上陀螺仪积分运算才行

rockyyangyang 发表于 2013-8-31 14:39:08

catluoq 发表于 2013-8-30 22:37 static/image/common/back.gif
这里只是用M16试验6050的DMP处理,不是直接做四轴的。
还有你的概念好像有点问题,用M16做四轴没太大问 ...

嗯,非常感谢你的回答{:smile:}

bigrocks 发表于 2013-9-1 21:23:22

cshp138 发表于 2013-7-19 15:41 static/image/common/back.gif
这情况解决了,是I2C读操作出了问题。还有一个问题是,欧拉角输出FLOAT型数值,是-180到180的角度范围吗 ...

你好,我遇到了和你一样的问题,也是第一个循环能够出来但是第二个循环就出不来了,也是0x400,我是用IO端口模拟的,然后readdmp这个函数我移植的时候有点疑惑,下面是我移植之后的版本,

void readdmp(void)
{
unsigned char dmpnum;
I2C_Start();
I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
I2C_SendByte(0x74);   //发送存储单元地址,从0开始
I2C_Start();
I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
for (dmpnum=0;dmpnum<41;dmpnum++)
   {
    dmpdatas=I2C_RecvByte();
    I2C_SendACK(1);//!!!这儿移植的时候有疑问!!要不要有应答信号?
   };
dmpdatas=I2C_RecvByte();
I2C_SendACK(1);                //接收应答信号
I2C_Stop();                  //停止信号();
}

我感觉应该是这边出了问题,因为程序的死循环里只有这个涉及I2C的读写,但是我用我的这个函数GetData(ACCEL_XOUT_H);是可以读到加速度值的,
uint GetData(uchar REG_Address)
{
        char H,L;
        H=Single_ReadI2C(REG_Address);
        L=Single_ReadI2C(REG_Address+1);
        return (H<<8)+L;   //合成数据
}

不知道是什么情况?你后来是怎么解决的?谢谢!

bigrocks 发表于 2013-9-1 23:40:46

cshp138 发表于 2013-7-19 15:41 static/image/common/back.gif
这情况解决了,是I2C读操作出了问题。还有一个问题是,欧拉角输出FLOAT型数值,是-180到180的角度范围吗 ...

已经解决~仔细琢磨你说的I2C时序问题~仔细检查了一下我发现也是I2C的时序问题~前面的没问题,是读dmp的那个函数严格按照连续读的格式来写就好了~{:smile:}

xl1736 发表于 2013-9-2 11:31:10

顶一下,谢谢猫大(catluoq),代码已经拷贝,正在理解!{:handshake:}

paooap 发表于 2013-9-2 21:10:34

感谢楼主移植了c,拯救我等大菜鸟,目前只会c51。。。。虽然运算速度会不够,但是也没有办法了,电赛要来了,只能强上。。

prow 发表于 2013-9-2 21:25:51

mark 正在用6050正好是avr的程序 用得上

paooap 发表于 2013-9-3 10:45:00

超级菜鸟求问楼主,我只学过c51。。不过这两天得强上6050的dmp看一看。用1t的stc12c5a60s2。就算是运算能力不够我也会要试试
不过看您的c板dmp以后发现里面是给avr写的,我发现里面有一些头文件不是c51的。。。不知道会有什么影响

我把flash改为code可以么- -

catluoq 发表于 2013-9-4 11:45:41

paooap 发表于 2013-9-3 10:45 static/image/common/back.gif
超级菜鸟求问楼主,我只学过c51。。不过这两天得强上6050的dmp看一看。用1t的stc12c5a60s2。就算是运算能力 ...

我对 C 了解很少,STC 的从来没试过,据说比以前的 51(89S51类) 强了许多,运算应该不成问题,CVAVR 里的 flash 定义是数据保存在程序储存器里, STC 里怎么定义不太清楚。

paooap 发表于 2013-9-4 18:51:27

catluoq 发表于 2013-9-4 11:45 static/image/common/back.gif
我对 C 了解很少,STC 的从来没试过,据说比以前的 51(89S51类) 强了许多,运算应该不成问题,CVAVR 里的 ...

嗷嗷,thx!

_yibei_ 发表于 2013-9-5 09:49:02

bigrocks 发表于 2013-9-1 23:40 static/image/common/back.gif
已经解决~仔细琢磨你说的I2C时序问题~仔细检查了一下我发现也是I2C的时序问题~前面的没问题,是读dmp的那 ...

你好,我和你遇到了相同的问题,请问具体你是怎么解决的,,?能发程序看一下吗?

steven888 发表于 2013-9-6 17:32:35

感谢楼主的BASCOM程序,直接用没问题。
调试成功了,得到比较稳定的角度值。
其实就C语言来讲,参考那个开源的程序就可以了。
就是换算角度的几个值跟开源程序的不一样,还要继续琢磨一下怎么回事。

tianxingweichen 发表于 2013-9-8 19:39:21

刚把楼主的程序移植到msp430单片机上发现程序卡在
                do {
                        do {
                                fifocounts = i2c_read_byte(0xd0, 0x72);
                              Showint(0,2,"%d",fifocounts);
                                fifocounts = fifocounts << 8;                           
                                fifocounts = fifocounts + i2c_read_byte(0xd0, 0x73);
                              Showint(0,3,"%d",fifocounts);
                        } while(fifocounts<42);
                        readdmp(dmpdatas);
                        fifocounts = i2c_read_byte(0xd0, 0x72);
                        fifocounts = fifocounts << 8;
                        fifocounts = fifocounts + i2c_read_byte(0xd0, 0x73);
                } while(fifocounts>=42);
这个循环中,0x72和0x73拼成一个unsigned int,fifocount得出来时0x400,将0x72的数据左移八位再加上0x73成一个unsigned int数据,怎么也比42大吧
这里一直很不解

catluoq 发表于 2013-9-9 00:33:58

tianxingweichen 发表于 2013-9-8 19:39 static/image/common/back.gif
刚把楼主的程序移植到msp430单片机上发现程序卡在
                do {
                        do {


程序里,fifocount值一方面随6050的检测计算在增加,另一方面,每执行一次 readdmp(dmpdatas) ,fifocount值就减少42,直到值小于42,才退出循环,你移植(实在不喜欢这个词)到430上,在读取的过程中增加了showint ,不知道是用 LCD 还是串口,,这个函数两次执行占用了太多时间,结果读取速度跟不上产生速度,自然跳不出循环。

tianxingweichen 发表于 2013-9-9 08:33:38

catluoq 发表于 2013-9-9 00:33 static/image/common/back.gif
程序里,fifocount值一方面随6050的检测计算在增加,另一方面,每执行一次 readdmp(dmpdatas) ,fifocoun ...

showint使显示在LCD上,去掉它还是走不出循环,最主要的问题是为什么每执行一次 readdmp(dmpdatas) ,fifocount值就减少42,直到值小于42。我发现我的程序每执行一次readdmp,fifocount并没有减少42

芽芽小宝 发表于 2013-9-12 11:14:05

楼主,您有没有遇到坐标系混乱的情况,也就是说,把芯片立起来,原来的X轴变成了Z轴,Z轴变成了X轴之类的。

芽芽小宝 发表于 2013-9-12 11:57:17

lqjesse 发表于 2013-8-30 14:04 static/image/common/back.gif
试了一下确实我官方的一样,问题同样存在,Pitch不旋转时,ROLL和YAW数据正常,但是只要Pitch旋转一定角 ...

好像是坐标系变了似的,比如当y轴转过90度后,转到X轴直接成了Z轴输出了。但是在中间位置,就不是那么明显,像是几个轴数据同时在变。

芽芽小宝 发表于 2013-9-12 11:58:22

lqjesse 发表于 2013-8-24 16:09 static/image/common/back.gif
请教各位,当Pitch倾斜时,只往Roll方向运动时,为什么Yaw数据也在变化?

是有这个问题,请楼主帮忙给分析一下。

jiang887786 发表于 2013-9-12 12:32:19

好贴,留名{:handshake:}

tianxingweichen 发表于 2013-9-13 14:05:47

楼主,MPU6050转换的到的欧拉角,该怎么判断其旋转的方向

SHIYOULAN 发表于 2013-9-13 22:51:35

楼主,请问一下您有没有遇到DMP输出不连续的现象?

wdskyi 发表于 2013-9-18 14:26:21

楼主威武,DMP果然霸气,不用在纠结啥卡尔曼或者互补了。就是这里
unsigned char i2cwbyte(unsigned char c)
{
unsigned char ack=1;
TWDR=c;
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT))){};
if((TWSR&0xF8)!=TW_MT_SLA_ACK)
    ack=0;
return ack;
}

TW_MT_SLA_ACK没有定义,参照马潮老师的书,应该是0x18

ostrich12 发表于 2013-10-10 20:32:41

感谢楼主,bascom的程序直接用了,串口显示。就是不知道dmp出来的角度能不能用在平衡车里。

放了3年的车希望有盼头了。

再次感谢!

xl1736 发表于 2013-10-12 22:12:44

cshp138 发表于 2013-7-19 15:41 static/image/common/back.gif
这情况解决了,是I2C读操作出了问题。还有一个问题是,欧拉角输出FLOAT型数值,是-180到180的角度范围吗 ...

您好,我也出现了你之前说的“跳不出do{}函数”,请问您所说的I2C读出问题是个怎么回事?

cshp138 发表于 2013-10-13 01:00:13

xl1736 发表于 2013-10-12 22:12 static/image/common/back.gif
您好,我也出现了你之前说的“跳不出do{}函数”,请问您所说的I2C读出问题是个怎么回事? ...

读FIFO周期要快点,不然会溢出报错

xl1736 发表于 2013-10-13 22:52:39

cshp138 发表于 2013-10-13 01:00 static/image/common/back.gif
读FIFO周期要快点,不然会溢出报错

这个周期是怎么决定的?
do
    {
       do {
         fifocounts=i2cread(0x72);
         fifocounts=fifocounts<<8;
         fifocounts=fifocounts+i2cread(0x73);    //读出FIFO里有多少数据
         //showlong(12,3,fifocounts);
          }
       while (fifocounts<42);
       readdmp();
           fifocounts=i2cread(0x72);
       fifocounts=fifocounts<<8;
       fifocounts=fifocounts+i2cread(0x73);
   }while(fifocounts>=42);
这里面有决定DMP FIFO的读取速度的设定么?

cshp138 发表于 2013-10-14 09:11:38

xl1736 发表于 2013-10-13 22:52 static/image/common/back.gif
这个周期是怎么决定的?
do
    {


你程序的大循环影响读FIFO的速度,所以你大循环里有延时程序的话就减少掉,或者如果你的单片机工作频率太低,估计来不及处理,就需要提高晶振或者倍频。

xl1736 发表于 2013-10-14 12:30:59

cshp138 发表于 2013-10-14 09:11 static/image/common/back.gif
你程序的大循环影响读FIFO的速度,所以你大循环里有延时程序的话就减少掉,或者如果你的单片机工作频率太 ...

您好,非常感谢您之前的回复。
我现在已经把代码做到最简:

while(1)
{USART_char_send('A');
   do
    {        USART_char_send('B');
       do {USART_char_send('C');
         fifocounts=i2cread(0x72);
         fifocounts=fifocounts<<8;
         fifocounts=fifocounts+i2cread(0x73);    //读出FIFO里有多少数据
         //showlong(12,3,fifocounts);
          }
       while (fifocounts<42);
       readdmp();
           fifocounts=i2cread(0x72);
       fifocounts=fifocounts<<8;
       fifocounts=fifocounts+i2cread(0x73);
   }while(fifocounts>=42);
         
// getquaternion();
   //getgyro();
   //getaccel();
// getyawpitchroll();
   // showlong(12,0,dmpdatas);      //显示一下原始数据,看有没有规律
   // showlong(12,1,dmpdatas);
   // showfloat(0,0,yprf);   //显示 ROLL PITCH YAW 值
   // showfloat(0,1,yprf);
   // showfloat(0,2,yprf);
    //_delay_ms(200);      
   // lcd_clear();
}
}
其中USART_char_send('');是我用来做调试的,结果串口一直输出‘C’程序还是卡在循环里边,我的单片机是ATMEAGE16,晶振用的是16M,和楼主一样,现在我都愁死了。还请您再花宝贵的时间,帮我看看,我的程序有什么问题。谢谢了!

cshp138 发表于 2013-10-14 16:47:05

xl1736 发表于 2013-10-14 12:30 static/image/common/back.gif
您好,非常感谢您之前的回复。
我现在已经把代码做到最简:



这样应该是你I2C对MPU6050初始化不成功,先确定I2C时序正常,能正常操作器件。有逻辑分析仪就看看I2C是不是不对。

xl1736 发表于 2013-10-15 20:48:17

cshp138 发表于 2013-10-14 16:47 static/image/common/back.gif
这样应该是你I2C对MPU6050初始化不成功,先确定I2C时序正常,能正常操作器件。有逻辑分析仪就看看I2C是不 ...

I2C没问题,是6050初始化问题,谢谢你!{:tongue:}

smurfjack 发表于 2013-10-15 21:44:13

大侠,请加我一下,119476954,我没权限给你发消息,我也用mega16 winavr 一直搞不定dmp

gswgcc 发表于 2013-11-16 21:09:12

搜索了好多DMP资料,这个让我看到了希望。

麦田里的稻田 发表于 2013-12-23 16:59:02

楼主,你好!这几天在弄MPU6050的 dmp,我在STM32上移植了MPU6050的dmp,代码参考至论坛中另外一个帖子。
我PCB上MPU6050的焊接方向如下图的红色箭头标注所示,从MPU6050的芯片手册上来看,陀螺仪的X,Y,Z和和加速度的X,Y,Z是这样的。测试的时候,串口输出的数据顺序为pitch,roll,yaw。我分别移动板子
测试了一下,发现我在俯仰角上移动板子时,角度对应的是输出数据的roll,板子roll方向的变化对应的是输出数据的pitch。刚好相反。



我看了哈你给出的C代码,发现在计算pitch,roll时和我移植的dmp中计算的公式有点不一样,看了一天的四原数,旋转矩阵,欧拉角,基本上看了之后只晓得一个大概,很多都没记住和理解。



另外,楼主做个完整的四轴吗?我在求出姿态角后,怎样根据根据pitch和row来控制四路电机的PWM值勒?我只用了MPU6050,没有外挂电子罗盘,偏航我用不着,实际偏航时,我是按照定好的方向控制电机使四轴左右偏航。
我想了一下,没想出什么好的点子,刚弄几天,很多都不懂。还望楼主指点一下。非常谢谢。
页: [1] 2
查看完整版本: atmega16+BASCOM玩出MPU-6050的DMP