IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> RT-Thread实战笔记|MPU6050使用详解及DMP姿态解算 -> 正文阅读

[嵌入式]RT-Thread实战笔记|MPU6050使用详解及DMP姿态解算

小伙伴们大家好,好久不更新RT-Thread实战笔记啦,今天来搞一搞MPU6050,话不多说,淦!

本章源码获取

欢迎文末留言区或者公众号后台回复“MPU6050”即可获取本教程源码

MPU6050简介

某宝买的,吃灰许久了...

有钱,不想受那鸟气的,看这个,自己画一个,对比价格,我劝你买个吧,知道自己行就行了...

典型用法:

可在官网下载最新的芯片手册和寄存器映射和描述,参看:MPU6050 官网

基本功能:

MPU-60X0是世界上第一款集成 6 轴MotionTracking设备。它集成了3轴MEMS陀螺仪,3轴MEMS加速度计,以及一个可扩展的数字运动处理器 DMP( DigitalMotion Processor),可用I2C接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其 I2C或SPI接口输出一个9轴的信号( SPI接口仅在MPU-6000可用)。 MPU-60X0也可以通过其I2C接口连接非惯性的数字传感器,比如压力传感器。

MPU-60X0对陀螺仪和加速度计分别用了三个16位的ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为±250, ±500, ±1000, ±2000°/秒( dps),加速度计可测范围为±2, ±4,±8, ±16g。

一个片上1024字节的FIFO,有助于降低系统功耗。和所有设备寄存器之间的通信采用 400kHz的 I2C接口或 1MHz的 SPI接口( SPI仅MPU-6000可用)。 对于需要高速传输的应用, 对寄存器的读取和中断可用 20MHz的SPI。另外,片上还内嵌了一个温度传感器和在工作环境下仅有±1%变动的振荡器。芯片尺寸4×4×0.9mm,采用QFN封装(无引线方形封装),可承受最大 10000g的冲击,并有可编程的低通滤波器。

关于电源, MPU-60X0可支持 VDD范围 2.5V±5%, 3.0V±5%,或 3.3V±5%。另外MPU-6050还有一个 VLOGIC引脚,用来为 I2C输出提供逻辑电平。 VLOGIC电压可取1.8±5%或者VDD。

系统结构图:

通信接口:

MPU-60X0使用 SPI(仅MPU-6000)或 I2C 串行通信至系统处理器接口。 与系统处理器通信时,MPU-60X0始终充当从属设备。 LSB的 I2C 从地址的地址由引脚9(AD0)设置(一般接地),本次采用的是IIC的通讯方式,顺便学习一下rt-thread的IIC设备驱动。

六轴,代表的是它内置了一个三轴 MEMS 陀螺仪、一个三轴 MEMS 加速度计,一个数字运动处理引擎(DMP)。它还有用于第三方的数字传感器接口的辅助 I2C 串行接口,比如当辅助 I2C 串行接口连接到一个三轴磁力计,MPU6050 能提供一个完整的九轴融合输出到其主 I2C 端口。

下图标明了传感器的参考坐标系( XYZ组成右手系)以及 3个测量轴和旋转方向。

旋转的正向可用右手螺旋定则判断

数字运动处理器(DMP):

DMP就是MPU6050内部的运动引擎,全称Digital Motion Processor,直接输出四元数,可以减轻外围微处理器的工作负担且避免了繁琐的滤波和数据融合。Motion Driver是Invensense针对其运动传感器的软件包,并非全部开源,核心的算法部分是针对ARM处理器和MSP430处理器编译成了静态链接库,适用于MPU6050、MPU6500、MPU9150、MPU9250等传感器。

FIFO

MPU-60X0包含一个可通过串行接口访问的1024字节FIFO寄存器。 FIFO配置寄存器决定哪个数据写入FIFO。 可能的选择包括陀螺仪数据,加速计数据,温度读数,辅助传感器读数和 FSYNC 输入。 FIFO 计数器跟踪 FIFO 中包含的有效数据字节数。 FIFO寄存器支持突发读取。 中断功能可用于确定新数据何时可用。

MPU6050的涉及的东西还是很多的,小飞哥也只是简单了解了一些,小伙伴们可以查看手册或者百度,很多优秀的介绍,就不再啰嗦啦

rt-thread软件包使用

硬件连接

小飞哥使用的是ART-PI及ART-PI扩展板(12月份即将开源发布)

使用到的引脚为:

MCUMPU6050
3.3VVCC
GNDGND
PI2SDA
PI1SCL

小伙伴们可以还根据自己的MCU及使用到的引脚,模拟的IIC,自己看着选就可以啦

硬件连接OK

软件编写

介绍2两种方式,一种是使用rt-thread平台软件包获取MPU6050的数据,自己解算,另一种就是移植DMP库进行解算,小飞哥用的是移植的DMP库来解算的。

  • rtt软件包使用

选择MPU6050软件包

然后选择模拟IIC,可以使用IIC3,也可以使用其他的,和软件包选用的统一就OK了

设置完成之后,ctrl+S保存即可,软件包自动就下载添加进来了

接下来编写读取函数,直接调用已经封装好的接口即可

先注册设备,初始化

????i2c_bus?=?(struct?mpu6xxx_device?*)mpu6xxx_init(MPU6050_I2C_BUS_NAME,?MPU6050_ADDR);???//初始化MPU6050,测量单位为角速度,加速度????while(count++)

????mpu6xxx_set_param(i2c_bus,?MPU6XXX_ACCEL_RANGE,?MPU6XXX_GYRO_RANGE_2000DPS);??//陀螺仪范围配置
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_ACCEL_RANGE,?MPU6XXX_ACCEL_RANGE_2G);?????//加速度计,一般设置为±2G
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_SAMPLE_RATE,?50);???????????????????????//采样频率
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_DLPF_CONFIG,?25);???????????????????????//数字低通滤波器设置,一般为1/2采样率

然后调用接口:

??????mpu6xxx_get_gyro(i2c_bus,?&gyro);
??????sprintf(str,"gyro.x=%d\r\n",gyro.x);
??????rt_kprintf(str);

??????sprintf(str,"gyro.y=%d\r\n",gyro.y);
??????rt_kprintf(str);

??????sprintf(str,"gyro.z=%d\r\n",gyro.z);
??????rt_kprintf(str);


??????mpu6xxx_get_accel(i2c_bus,&accel);

??????sprintf(str,"accel.x=%d\r\n",accel.x);
??????rt_kprintf(str);
??????sprintf(str,"accel.y=%d\r\n",accel.y);
??????rt_kprintf(str);
??????sprintf(str,"accel.z=%d\r\n",accel.z);
??????rt_kprintf(str);

运行结果:

来看一下,这两个函数的内部封装:

/**
?*?This?function?gets?the?data?of?the?gyroscope,?unit:?deg/10s
?*?Here?deg/10s?means?10?times?higher?precision?than?deg/s.?
?*
?*?@param?dev?the?pointer?of?device?driver?structure
?*?@param?gyro?the?pointer?of?3axes?structure?for?receive?data
?*
?*?@return?the?reading?status,?RT_EOK?reprensents??reading?the?data?successfully.
?*/
rt_err_t?mpu6xxx_get_gyro(struct?mpu6xxx_device?*dev,?struct?mpu6xxx_3axes?*gyro)
{
????struct?mpu6xxx_3axes?tmp;
????rt_uint16_t?sen;
????rt_err_t?res;

????res?=?mpu6xxx_get_gyro_raw(dev,?&tmp);
????if?(res?!=?RT_EOK)
????{
????????return?res;
????}

????sen?=?MPU6XXX_GYRO_SEN?>>?dev->config.gyro_range;

????gyro->x?=?(rt_int32_t)tmp.x?*?100?/?sen;
????gyro->y?=?(rt_int32_t)tmp.y?*?100?/?sen;
????gyro->z?=?(rt_int32_t)tmp.z?*?100?/?sen;

????return?RT_EOK;
}
/**
?*?This?function?gets?the?data?of?the?accelerometer,?unit:?mg
?*
?*?@param?dev?the?pointer?of?device?driver?structure
?*?@param?accel?the?pointer?of?3axes?structure?for?receive?data
?*
?*?@return?the?reading?status,?RT_EOK?reprensents??reading?the?data?successfully.
?*/
rt_err_t?mpu6xxx_get_accel(struct?mpu6xxx_device?*dev,?struct?mpu6xxx_3axes?*accel)
{
????struct?mpu6xxx_3axes?tmp;
????rt_uint16_t?sen;
????rt_err_t?res;

????res?=?mpu6xxx_get_accel_raw(dev,?&tmp);
????if?(res?!=?RT_EOK)
????{
????????return?res;
????}

????sen?=?MPU6XXX_ACCEL_SEN?>>?dev->config.accel_range;

????accel->x?=?(rt_int32_t)tmp.x?*?1000?/?sen;
????accel->y?=?(rt_int32_t)tmp.y?*?1000?/?sen;
????accel->z?=?(rt_int32_t)tmp.z?*?1000?/?sen;

????return?RT_EOK;
}

还有获取磁力计、温度的接口,就不再一一列举了,拿到的数据我们可以进行手动解算。

  • 移植DMP解算

使用DMP包的话跟rtt的MPU6050的软件包就没有很大关系了,只需要IIC接口就可以了

首先把DMP库文件放到我们的工程中,包含路径到我们的工程中

然后就需要编写与DMP库对接的接口了,下面几个是需要我们实现的

rt_uint8_t?MPU_Write_Len(rt_uint8_t?addr,rt_uint8_t?reg,rt_uint8_t?len,rt_uint8_t?*databuf)
{
????rt_int8_t?res?=?0;
#ifdef?RT_USING_I2C
????struct?rt_i2c_msg?msgs;
????rt_uint8_t?buf[50]?=?{0};
#endif
????buf[0]?=?reg;

????for(int?i?=?0;i<len;i++)
????{
????????buf[i+1]=databuf[i];
????}

????if?(i2c_bus->bus->type?==?RT_Device_Class_I2CBUS)
????{
????????msgs.addr??=?i2c_bus->i2c_addr;????/*?slave?address?*/
????????msgs.flags?=?RT_I2C_WR;????????/*?write?flag?*/
????????msgs.buf???=?buf;??????????????/*?Send?data?pointer?*/
????????msgs.len???=?len+1;

????????if?(rt_i2c_transfer((struct?rt_i2c_bus_device?*)i2c_bus->bus,?&msgs,?1)?==?1)
????????{
????????????res?=?RT_EOK;
????????}
????????else
????????{
????????????res?=?-RT_ERROR;
????????}
????}
}

rt_uint8_t?MPU_Read_Len(rt_uint8_t?addr,rt_uint8_t?reg,rt_uint8_t?len,rt_uint8_t?*buf)
{
????rt_int8_t?res?=?0;
#ifdef?RT_USING_I2C
????struct?rt_i2c_msg?msgs[2];
#endif
#ifdef?RT_USING_SPI
????rt_uint8_t?tmp;
#endif
????if?(i2c_bus->bus->type?==?RT_Device_Class_I2CBUS)
????{
????????msgs[0].addr??=?i2c_bus->i2c_addr;????/*?Slave?address?*/
????????msgs[0].flags?=?RT_I2C_WR;????????/*?Write?flag?*/
????????msgs[0].buf???=?&reg;?????????????/*?Slave?register?address?*/
????????msgs[0].len???=?1;????????????????/*?Number?of?bytes?sent?*/

????????msgs[1].addr??=?i2c_bus->i2c_addr;????/*?Slave?address?*/
????????msgs[1].flags?=?RT_I2C_RD;????????/*?Read?flag?*/
????????msgs[1].buf???=?buf;??????????????/*?Read?data?pointer?*/
????????msgs[1].len???=?len;??????????????/*?Number?of?bytes?read?*/

????????if?(rt_i2c_transfer((struct?rt_i2c_bus_device?*)i2c_bus->bus,?msgs,?2)?==?2)
????????{
????????????res?=?RT_EOK;
????????}
????????else
????????{
????????????res?=?-RT_ERROR;
????????}
????}

????return?res;
}

初始化部分我们改为下面这样,只注册IIC设备就行了,其他的配置在DMP中完成:

????i2c_bus?=?(struct?mpu6xxx_device?*)mpu6xxx_init(MPU6050_I2C_BUS_NAME,?MPU6050_ADDR);???//初始化MPU6050,测量单位为角速度,加速度????while(count++)

/*
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_ACCEL_RANGE,?MPU6XXX_GYRO_RANGE_2000DPS);??//陀螺仪范围配置
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_ACCEL_RANGE,?MPU6XXX_ACCEL_RANGE_2G);?????//加速度计,一般设置为±2G
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_SAMPLE_RATE,?50);???????????????????????//采样频率
????mpu6xxx_set_param(i2c_bus,?MPU6XXX_DLPF_CONFIG,?25);???????????????????????//数字低通滤波器设置,一般为1/2采样率
*/

????while(mpu_dmp_init())
????{
????????rt_thread_mdelay(500);
????????rt_kprintf("\r\nMPU6050?Error\r\n");
????}
????rt_kprintf("\r\nMPU6050?OK\r\n");

DMP初始化成功

获取结算后的数据:

????float?pitch,roll,yaw;???????????//欧拉角

????if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
????{
??????sprintf(str,"pitch=%.1f\r\n",pitch);
????????rt_kprintf(str);

????????sprintf(str,"roll=%.1f\r\n",roll);
????????rt_kprintf(str);

????????sprintf(str,"yaw=%.1f\r\n",yaw);
????????rt_kprintf(str);


/*
????????temp=MPU_Get_Temperature();??????????//得到温度值

????????sprintf(str,"temp=%.1f\r\n",temp);
????????rt_kprintf(str);

????????MPU_Get_Accelerometer(&aacx,&aacy,&aacz);???//得到加速度传感器数据
????????MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);????//得到陀螺仪数据
*/
???}

至此就结束了,使用库的解算是挺方便的,自己解算其中涉及的计算还是挺麻烦的,本章就不再介绍啦,欢迎做过的小伙伴投稿给我哦

资料获取

欢迎添加小飞哥好友,一起交流问题与经验,回复加群即可加入“高质量开发者”群

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:27:35  更:2021-11-28 11:28:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:52:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码