OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15170|回复: 8

MPU6050读取FIFO数据时FIFO溢出问题解决方法

[复制链接]

7

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
270
金钱
270
注册时间
2015-12-11
在线时间
42 小时
发表于 2016-4-5 12:39:40 | 显示全部楼层 |阅读模式
  先说明一下问题:本人将原子F4第37章mpu6050的DMP读取姿态角移植到MINISMT32战舰上的时候,DMP初始化正常,但是读书数据时候出现错误,返回值一直为1,检查的时候发现问题出现在mpu_dmp_get_data()->dmp_read_fifo()->mpu_read_fifo_stream()->if (tmp[0] & BIT_FIFO_OVERFLOW) {  mpu_reset_fifo();  return -2;}此处位置。 看了度娘和坛友前辈的一些经验之后,发现原来这个问题经常出现,故此把自己的解决方案分享一下,希望对坛友有些帮助。  在此先引申一下前人发过的一个帖子,是里面的前辈给的启发:http://www.openedv.com/thread-52109-1-1.html

  对问题做个简单的分析:为什么FIFO数据会溢出?MPU6050的DMP在工作的时候,其实大概的工作过程是mpu6050对陀螺仪和加速度计按照一定的采样速率进行采样,对采样得到的陀螺仪和加速度计数据通过DMP处理后得到姿态角(pitch,roll,yaw),然后存入FIFO中,这个过程在你初始化完DMP后就会不受人为控制的持续进行,那么如果你不及时读取FIFO的数据,FIFO数据很快就会溢出,那么就会出现以上的问题啦!
  好了,说了那么一大堆,问题该如何解决呢?  其实很简答啦,只要一个简单循环其实就解决了!看如下的程序:
  while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){}
  就是上面这么一句话,如果读取失败,马上进行第二次读取,这时候FIFO一般没有溢出,搞定!(因为检测到FIFO溢出后会马上reset一下FIFO)。(以上所说纯属个人见解,我还是个小菜鸟,如果有不对的地方各位大侠还望轻喷~~)
  最后上一发图:

P60405-122142.jpg
rool pitch.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-9-29
在线时间
8 小时
发表于 2020-1-16 19:09:43 | 显示全部楼层
成为嵌入式大佬 发表于 2019-9-14 11:38
大哥们  我卡在了这条函数上
不知道怎么处理
  if (fifo_count < length) {

我也是,你怎么解决的呀
回复 支持 1 反对 0

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2019-8-2
在线时间
3 小时
发表于 2019-9-14 11:38:36 | 显示全部楼层
大哥们  我卡在了这条函数上
不知道怎么处理
  if (fifo_count < length) {
        more[0] = 0;
        printf("//4//");
        return -1;
    }
回复 支持 1 反对 0

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2016-4-30
在线时间
2 小时
发表于 2016-4-30 15:23:20 | 显示全部楼层
int dmp_read_fifo(short *gyro, short *accel, long *quat,
    unsigned long *timestamp, short *sensors, unsigned char *more)
{
    unsigned char fifo_data[MAX_PACKET_LENGTH];
    unsigned char ii = 0;

    /* TODO: sensors[0] only changes when dmp_enable_feature is called. We can
     * cache this value and save some cycles.
     */
    sensors[0] = 0;

    /* Get a packet. */
    if (mpu_read_fifo_stream(dmp.packet_length, fifo_data, more))
        return -1;

    /* Parse DMP packet. */
    if (dmp.feature_mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT)) {
#ifdef FIFO_CORRUPTION_CHECK
        long quat_q14[4], quat_mag_sq;
#endif
        quat[0] = ((long)fifo_data[0] << 24) | ((long)fifo_data[1] << 16) |
            ((long)fifo_data[2] << 8) | fifo_data[3];
        quat[1] = ((long)fifo_data[4] << 24) | ((long)fifo_data[5] << 16) |
            ((long)fifo_data[6] << 8) | fifo_data[7];
        quat[2] = ((long)fifo_data[8] << 24) | ((long)fifo_data[9] << 16) |
            ((long)fifo_data[10] << 8) | fifo_data[11];
        quat[3] = ((long)fifo_data[12] << 24) | ((long)fifo_data[13] << 16) |
            ((long)fifo_data[14] << 8) | fifo_data[15];
        ii += 16;
#ifdef FIFO_CORRUPTION_CHECK
        /* We can detect a corrupted FIFO by monitoring the quaternion data and
         * ensuring that the magnitude is always normalized to one. This
         * shouldn't happen in normal operation, but if an I2C error occurs,
         * the FIFO reads might become misaligned.
         *
         * Let's start by scaling down the quaternion data to avoid long long
         * math.
         */
        quat_q14[0] = quat[0] >> 16;
        quat_q14[1] = quat[1] >> 16;
        quat_q14[2] = quat[2] >> 16;
        quat_q14[3] = quat[3] >> 16;
        quat_mag_sq = quat_q14[0] * quat_q14[0] + quat_q14[1] * quat_q14[1] +
            quat_q14[2] * quat_q14[2] + quat_q14[3] * quat_q14[3];
        if ((quat_mag_sq < QUAT_MAG_SQ_MIN) ||
            (quat_mag_sq > QUAT_MAG_SQ_MAX)) {
            /* Quaternion is outside of the acceptable threshold. */
            mpu_reset_fifo();
            sensors[0] = 0;
            return -1;
        }
        sensors[0] |= INV_WXYZ_QUAT;
#endif
    }

    if (dmp.feature_mask & DMP_FEATURE_SEND_RAW_ACCEL) {
        accel[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
        accel[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
        accel[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
        ii += 6;
        sensors[0] |= INV_XYZ_ACCEL;
    }

    if (dmp.feature_mask & DMP_FEATURE_SEND_ANY_GYRO) {
        gyro[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
        gyro[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
        gyro[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
        ii += 6;
        sensors[0] |= INV_XYZ_GYRO;
    }

    /* Gesture data is at the end of the DMP packet. Parse it and call
     * the gesture callbacks (if registered).
     */
    if (dmp.feature_mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT))
        decode_gesture(fifo_data + ii);

    get_ms(timestamp);
    return 0;
}
我程序执行到第一个if语句的时候就直接返回-1了  这是什么原因
回复 支持 1 反对 0

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2015-9-24
在线时间
11 小时
发表于 2016-4-20 15:01:37 | 显示全部楼层
楼主  我也遇到这个问题,按照你说的方法还是不行啊  崩溃!!!!!!!!!
回复 支持 反对

使用道具 举报

7

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
270
金钱
270
注册时间
2015-12-11
在线时间
42 小时
 楼主| 发表于 2016-4-24 16:20:11 | 显示全部楼层
ivan0621 发表于 2016-4-20 15:01
楼主  我也遇到这个问题,按照你说的方法还是不行啊  崩溃!!!!!!!!!

问题的原因确定一样么? 如果一样应该可以的
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2016-4-30
在线时间
2 小时
发表于 2016-4-30 15:58:44 | 显示全部楼层
int mpu_read_fifo_stream(unsigned short length, unsigned char *data,
    unsigned char *more)
{
    unsigned char tmp[2];
    unsigned short fifo_count;
    if (!st.chip_cfg.dmp_on)
        return -1;
    if (!st.chip_cfg.sensors)
        return -1;

    if (i2c_read(st.hw->addr, st.reg->fifo_count_h, 2, tmp))
        return -1;
    fifo_count = (tmp[0] << 8) | tmp[1];
    if (fifo_count < length) {
        more[0] = 0;
        return -1;
    }
    if (fifo_count > (st.hw->max_fifo >> 1)) {
        /* FIFO is 50% full, better check overflow bit. */
        if (i2c_read(st.hw->addr, st.reg->int_status, 1, tmp))
            return -1;
        if (tmp[0] & BIT_FIFO_OVERFLOW) {
            mpu_reset_fifo();
            return -2;
        }
    }

    if (i2c_read(st.hw->addr, st.reg->fifo_r_w, length, data))
        return -1;
    more[0] = fifo_count / length - 1;
    return 0;
}
是这个  
回复 支持 反对

使用道具 举报

7

主题

57

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
270
金钱
270
注册时间
2015-12-11
在线时间
42 小时
 楼主| 发表于 2016-5-1 13:30:04 | 显示全部楼层
四轴我来了 发表于 2016-4-30 15:58
int mpu_read_fifo_stream(unsigned short length, unsigned char *data,
    unsigned char *more)
{

把if(tmp[0]&BIT_FIFO_OVERFLOW)return -2注释掉,看是否有影响;如果有影响,就表示是FIFO溢出(说明我这个解决方法还是不完全的~),如果没有,就是这个函数内其他部位的原因。
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2019-8-2
在线时间
3 小时
发表于 2020-7-31 22:22:48 | 显示全部楼层
ybchai 发表于 2020-1-16 19:09
我也是,你怎么解决的呀

fifo的数据量要到积累一定数量才能被读取
我卡在这儿是因为读取太快了
所以读取失败
读慢点就好
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 16:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表