前言

上一篇,给大家介绍了平衡小车的硬件资源及其小车底层硬件介绍篇

平衡小车学习教程1——硬件资源及其小车底层硬件介绍篇

这篇来教大家如何快速的使用MPU6050自带的DMP库读取陀螺仪数据,读取翻滚角(Roll)、俯仰角(Pitch)、航向角(Yaw)这三个角的数据。

而我们平衡小车的直立环

就是通过读取Roll角的数据

根据Roll角的变化,通过PID算法,得到实际值和期望值,从而得到所计算出的值传递给PWM。从而使小车达到直立状态。

所以,如何使用单片机读取陀螺仪的数据就是一个非常重要的点

本篇文章的教程采用的是STM32单片机,读取这三个角


一、认识MPU6050


1、基础认识

MPU6050,一般是下面这个小模块,通常来说,分为6脚和8脚的,6脚和8脚的区别

就是8脚的有一个XDA和一个XCL接口,这两个接口可以外接磁力计。下图就是8脚的MPU6050。


2、引脚介绍

由于MPU6050是IIC通信的,所以要使用IIC通信初始化MPU6050,读取其内部的寄存器,从而获取小车的实时状态。

所以其重要的两个引脚就是SCL引脚和SDA引脚

此外,MPU6050还有一个中断引脚INT,可以配置寄存器,让其产生中断,读取陀螺仪数据可放在中断内部进行。

引脚 引脚介绍
VCC 3.3V/5V电源输入
GND 接地
SDA IIC通信数据线
SCL IIC通信时钟线
XDA IIC外接通信数据线
XCL IIC外接通信时钟线
AD0 IIC从机设置引脚(悬空或接GND时为0x68 / 接高电平为0x69 )
INT MPU6050中断引脚

二、移植方法

在这里不深究MPU6050的内部寄存器的原理,这里其实我也没弄明白

大家可以先从实操出发,首先知道如何快速使用,其实太过深究其内部原理也没太大意义,后面想深入研究也是没问题的。

所以这里我将会带着大家一步一步的如何快速移植MPU6050其内部自带的DMP库,如何使用自带的数字运动处理器(DMP库)读取完整的 6轴或9 轴姿态融合演算数据。


1、什么是DMP

我们可以通过IIC通信读取MPU6050其内部的寄存器,从而得到加速度传感器数据或者角速度传感器数据

但是我们做平衡小车,不是要这六个数据,而是欧拉角,即Roll、Pitch、Yaw角这三个角度

要得到欧拉角,其实要进行姿态解算,自己来姿态解算有点困难,但是使用DMP就不一样了,使用DMP,可以将原始数据直接转换为四元数输出,得到四元数之后,就可以很方便的计算出欧拉角,从而得到Roll、Pitch、Yaw角。

2、如何移植DMP


下载原子的百度网盘资料

正点原子MPU6050资料下载

  1. 首先点击上方链接,点进去之后把这个资料下载下来

  2. 然后下载下来捏 旧资料–>程序源码–>随便选一个压缩包文件解压

我这里选择(库函数版本,适合MiniSTM32开发板)扩展实验16 ATK-MPU6050六轴传感器实验


移植对应文件添加进我们自己的工程当中

  1. 这个工程里,我们需要的就是啥捏,需要的就只是

六轴传感器模块ATK-MPU6050资料(旧资料)\2,程序源码\移植\(库函数版本,适合MiniSTM32开发板)扩展实验16 ATK-MPU6050六轴传感器实验\HARDWARE

这个文件夹里的MPU6050文件夹

  1. 复制这整个文件到自己的工程文件夹里,然后在Keil里添加相应的文件,如何在keil里添加对应文件我就不多说了

然后,大家可以看见,最终我们需要的文件就是mpuiic.c

mpu6050.c

inv_mpu.c

inv_mpu_dmp_motion_driver.c

,将这四个文件添加进Keil里的驱动文件中,最终效果如下图

  1. 然后捏修改自己板子对应的引脚或者使用杜邦线来连接6050
  2. 然后Keil里项目文件如下图所示
    就是这四个文件,我们需要的就是这四个文件

3、移植注意事项

1、mpuiic.c

mpuiic.h


第一个要注意的地方,修改初始化引脚

找到

	void MPU_IIC_Init(void)

可以看到这是MPU6050对应的SCL和SDA的初始化引脚,MPU6050是使用IIC通信来获得欧拉角的

所以我们要对这个IO进行修改

下方是源文件中的初始化

我们根据PCB中引出的GPIO,进行修改,由于我们板载引脚是

引脚 对应GPIO
AD0 GND
INT PB5
SCL PB4
SDA PB3

做出以下修改

// 初始化IIC  SCL PB4	SDA PB3
void MPU_IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 先使能外设IO PORTC时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  // 使能AFIO 复用时钟
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 失能JTAG调试端口  这样PB3 pB4 就是作为一个普通的IO口使用

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4; // 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	   // 推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	   // IO口速度为50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);				   // 根据设定参数初始化GPIO

	GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4); // PB3 PB4 输出高
}

至于为什么在初始化的过程中会失能JTAG呢?


可以看引脚对应的功能,PB3和PB4是JTAG试端口,我们需要失能JTAG端口才可以把这两个IO当作GPIO使用


第二个要注意的地方,修改SCL和SDA的宏定义

打开mpuiic.h

文件

可以看到这里定义了很多宏定义,这是源程序


第一个IO设置是啥意思呢?


我们知道IIC通信中,SDA是数据线,肯定是有输入和输出的,这里的IO方向设置,就是设置SDA的输入模式和输出模式,大家可以看库函数手册,如下图,这是对应的引脚数高八位的端口的寄存器 端口配置高寄存器(GPIOx_CRH) (x=A..E)

我们先根据源程序,分析一下,首先他使用的是
SCL-->PC12


SDA-->PC11


IO方向,就是对端口的寄存器进行操作,所以

#define MPU_SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}

这一句前面就是重新清零PC11的端口模式位,后面就是再把PC11的端口寄存器的第15-12位设置为1000


这个图好理解了叭,总结能力满分

我们做出以下修改

#define MPU_SDA_IN()              \
    {                             \
        GPIOB->CRL &= 0XFFFF0FFF; \
        GPIOB->CRL |= 8 << 12;    \
    }
#define MPU_SDA_OUT()             \
    {                             \
        GPIOB->CRL &= 0XFFFF0FFF; \
        GPIOB->CRL |= 3 << 12;    \
    }

// IO操作函数
#define MPU_IIC_SCL PBout(4) // SCL
#define MPU_IIC_SDA PBout(3) // SDA
#define MPU_READ_SDA PBin(3) // 输入SDA

2、查看一下,自己移植的正点原子的代码,有没有用到INT引脚

如果用到了INT引脚,一般是中断读取欧拉角,肯定初始化了IO,把那部分去掉,我们并没有使用到INT引脚(使用的是主程序中循环读取

)

他初始化的IO可能会导致程序错误

所以还请注释掉,保证后面操作的正确性


4.在主程序中初始化MPU6050

1、在主程序中初始化MPU6050

    delay_ms(500); // 延时0.5s 使MPU6050初始化稳定
	MPU_Init();    // 初始化MPU6050
	mpu_dmp_init();


2、在主程序中不断获取DMP处理后的数据

  while( mpu_dmp_get_data(&pitch, &roll, &yaw)!=0 ){}//返回值:0,正常	//    其他,失败1
  u1_printf("\n\r pitch=%0.2f roll=%0.2f yaw=%0.2f \n\r", pitch, roll, yaw);
复制


3、连接串口查看角度变化

一般要等个几秒钟,等待MPU6050初始化成功!

然后使用串口查看数据

可以看到,读取数据成功,三个角都成功的被读取,我们的目的实现


四、Roll、Pitch、Yaw角的区分

1、手动旋转MPU6050进行区分

这个呢,大家可以根据自己读取到的角度进行区分,把MPU6050进行旋转,查看角度的变化

左右就是偏航角(沿X轴)
上下就是俯仰角(沿Z轴)
左侧右侧偏就是翻滚角(沿Y轴)

大家可以去找大佬讲的,网上有很多资料的

2、使用vofa+控件进行区分(未实现)

本来想用vofa+,来直观的显示一下角度的变换的,可是没搞出来,这个控件不知道咋玩,等啥时候弄出来了补上


五、总结

这一篇主要是软件篇,教大家如何移植并且读取到MPU6050的数据,毕竟平衡小车的所有都是基于角度来实现直立的,这是软件篇的第一步。

大家在学会这个之后,就可以快速移植官方文件,得到自己想要的功能

文章还是有很多没有讲的很清楚的地方,我也是粗略的将移植步骤交给大家,有一些原理还是不够深入

希望大家,还是要先了解原理,再深入,再做项目,在项目中二次深入理解

好啦,下一节将会给大家带来
小车的底层驱动的软件篇——小车底层驱动(电机、编码器)

大家可以再次期待一下下,嘿嘿,加油加油!

原文作者:CSDN 藕粉-