基于STM32F103C8T6的HAL库版本的MPU6050dmp库使用心得

原创出处:STM32系列(HAL库)——F103C8T6通过MPU6050+DMP姿态解算读取角度及温度_mpu6050 读取温度-CSDN博客

        本帖纯属记录自己的学习心得体会,首先先列出原创文章,本文章内容都是基于使用这个代码的时候遇到的一些问题,非常感谢这位大佬,我觉得他的代码,对我这制作平衡小车起到了非常大的帮助

        近期学习计划是小项目与FreeRTOS并行学习,在近段时间,我做出来了属于自己的平衡小车,虽然平衡性能不像其他大佬那样一动不动,代码也是一步一步得跟着例程来,但是我是个飞舞,即使是这样感觉做出了也很不容易了,而且我自己的也可以做到平衡了,已经很满足了(大佬勿喷,这纯属是菜鸟专属的自娱自乐)

问题1:dmp库是什么?

        dmp库最开始我都没有听说过,都不知道这是个啥玩意,最开始使用MPU6050,我学习的都是如何根据IIC协议读出三轴的加速度与角速度,而不是我们更需要的俯仰角(pitch),偏航角(yaw),横滚角(roll)

        dmp库是官方自己写出来的一些库函数,可以通过使用dmp库读出三轴角速度,加速度,以及俯仰角(pitch),偏航角(yaw),横滚角(roll),虽然yaw,roll,pitch可以通过根据三轴的角速度,三轴的加速度经过一系列数学运算得出来,但是误差很大,所以一般都是通过dmp库读出yaw,roll,pitch这三个角

问题2:如何使用dmp库?

两种方法:一种是直接去官方下载,但是官方的dmp库并不是基于STM32的,而是MSP430的,还需要经过一系列的修改才能使用,在我自己看来,这种方法非常耗时,网上的方法百花齐放,却没有找到一个我觉得OK的

另一种就是去找现成的,最顶头的那篇原创文章正是我需要的,所以如果需要的,可以直接去原创处下载,我觉得非常好用,只需要根据实际情况的MPU6050连接方式,修改对应的宏定义就好,甚至还免去了我们STM32的IIC通信接口,也不需要我们手写IIC通信协议,因为原创的dmp库是基于软件IIC的,只需要随便找两个IO口就可以使用

#define GPIO_PORT_IIC     GPIOB                       /* GPIO端口 */
#define RCC_IIC_ENABLE    __HAL_RCC_GPIOB_CLK_ENABLE()       /* GPIO端口时钟 */
#define IIC_SCL_PIN       GPIO_PIN_4                 /* 连接到SCL时钟线的GPIO */
#define IIC_SDA_PIN       GPIO_PIN_3                 /* 连接到SDA数据线的GPIO */

问题3:我自己遇到的一些问题以及解决方法

1.程序卡死,一般都是卡死在mpu_dmp_init()这里

        我第一次使用是完全用不了的,就是无报错,但是运行起来啥现象也没有,怀疑是卡死在HardWare了,然后自己通过之前学习的Keil的调试方法,一步一步找,找到了卡死的原因:卡在了HAL_Delay这里,发现处了IIC底层通信协议的延时函数是自己写的,其他的(总共有两处)都是调用了HAL_Delay,至于为什么在这里会卡死,目前我自己还不明白,于是自己修改成了之前在学习51单片机的时候,跟着江科大黄老师写的万能延时函数,用此来代替HAL_Delay,然后自己又重新试了一下,发现可以使用了,当时非常开心!!

两处修改,一处是在MPU6050.h文件,另一个是在inv_mpu_dmp_motion_driver.h文件

#define delay_ms				My_Delay

2. MPU6050的dmp加载可以通过,但是读出的数据都是0或者无法持续读(只读一次数据,后面就没反应了)

uint8_t mpu_dmp_init(void)
{
    uint8_t res=0;
    MPU_IIC_Init(); 	//初始化IIC总线
    if(mpu_init()==0)	//初始化MPU6050
    {
        res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置所需要的传感器
        if(res)return 1;
        res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置FIFO
        if(res)return 2;
        res=mpu_set_sample_rate(DEFAULT_MPU_HZ);	//设置采样率
        if(res)return 3;
        res=dmp_load_motion_driver_firmware();		//加载dmp固件
        if(res)return 4;
        res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
        if(res)return 5;
        res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|	//设置dmp功能
                               DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
                               DMP_FEATURE_GYRO_CAL);
        if(res)return 6;
        res=dmp_set_fifo_rate(DEFAULT_MPU_HZ);	//设置DMP输出速率(最大不超过200Hz)
        if(res)return 7;
        res=run_self_test();		//自检
        if(res)return 8;
        res=mpu_set_dmp_state(1);	//使能DMP
        if(res)return 9;
    } else return 10;
    return 0;
}

上面的就是我印象最深刻的地方,可以发现,dmp库的加载只要有一步出错了,后面的都不会加载,而是直接推出了,我们可以通过查看该函数的返回值,查看究竟是哪一步出错了,从而进一步排查错误

MPUSingle = mpu_dmp_init();		
if(MPUSingle == 0) OLED_ShowString(0, 0, "MPU_OK:", 12, 0);
else OLED_ShowString(0, 0, "MPU_Err:", 12, 0);

而且我们进一步观察函数,发现只有当它返回值是0的时候,dmp库才会被正确加载,只要返回值不是0,就说明dmp加载必然出错了

可能性1:暂时不明

我自己出现的问题是一直返回10,就说明连最基础的mpu_init()都出错了。mpu_init的作用是向MPU6050写一系列数据,除非是地址出错了,否则就是通信协议时序有问题

最后发现问题出在这里,连续写数据的时候出错了,写数据的时候SDA应答有问题

 if(MPU_IIC_Wait_Ack())		//等待ACK
{
    MPU_IIC_Stop();
    return 1;
}

但是到最后我发现,源码的通信协议时序是完全没问题的,这就说明,有可能是其他硬件与其发送了冲突吧,到最后我发现是自己的HC-SR04超声波模块的初始化有问题

void HC_SR04_Start(void)
{
  HAL_GPIO_WritePin(HCSR04_TrigPort, HCSR04_TrigPin, GPIO_PIN_SET);
  Delay_us(13);
  HAL_GPIO_WritePin(HCSR04_TrigPort, HCSR04_TrigPin, GPIO_PIN_RESET);
}

去掉了超声波模块的初始化,就没问题了,至于是为什么,我现在还没有弄明白,不过超声波模块本就是附加品,对平衡小车功能影响不大,去掉也无所谓

可能性2:MPU6050初始化的时候没有水平放置

这个我自己是注意到的,不过看到很多人都会被这个问题困扰着,所以在这里再提一嘴

总结:

最好在dmp初始化函数加上调试函数,这样可以帮助我们更快锁定错误源头

PID:

PID我自己学的不怎么样,经过这个项目后,只能说是略有心得,而且PID有很多大佬讲的都非常不错,我这就不提了,这里想提醒的就是,PID的运算最好放在MPU6050的INT中断函数里面,并且PID的执行间隔一定要快(从而映射到MPU6050的采样率),最好是10ms或者5ms进行一次PID运算,也就是10ms或者5msMPU6050采样一次,同时我也学到了较好地写法,如下:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(mpu_dmp_get_data(&Pitch, &Roll, &Yaw) == 0)
  {
    if(GPIO_Pin == GPIO_PIN_5)
    {
      PID_Control();
    }
  }
}

在运行PID之前先来个if判断,判断是否采样成功,如果采样成功,马上进行一次PID运算

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值