MPU6050是什么?
它是由3轴陀螺仪、3轴加速度传感器组成的6轴运动处理芯片,还可以通过一个预留IIC接口外接磁力传感器(如GY-282磁罗盘),其它型号还有:MPU6000、MPU9150、MPU9250等。
我们常用它来给系统输入欧拉角。

关于欧拉角:

如下图:
α是 x 轴与交点线的夹角 β 是 z 轴与 Z 轴的夹角, γ 是交点线与 X 轴的夹角。
很可惜地,对于夹角的顺序和标记,夹角的两个轴的指定,并没有任何常规。 科学家对此从未达成共识。每当用到欧拉角时,我们必须明确的表示出夹角的顺序,指定其参考轴。
实际上,有许多方法可以设定两个坐标系 的相对取向。欧拉角方法只是其中的一种。此外,不同的作者会用不同组合的欧拉角来描述,或用不同的名字表示同样的欧拉角。因此,使用欧拉角前,必须先做好明确的定义。

硬件快速搭建:
通信接口:IIC
电源:2.4-3.4V

典型电路:

管脚说明:

第8脚 VLOGIC一般直接接电源即可。(接不同电压就是指其IO口电压,如此脚接1.8V,则其IO口逻辑电压即为1.8V)
第9脚 是IIC地址选择,接低:地址为0x68,接高:地址为0x69;
与MCU的连接电路(STM32为例):

特点参数:

① 以数字形式输出 6 轴或 9 轴(需外接磁传感器)的旋转矩阵、四元数 ( 、欧拉角格式 (Euler Angle 的融合演算数据(需 DMP 支持)
② 具有 131 LSBs/ LSBs/°°/sec 敏感度与全格感测范围为± 250 、± 500 、± 1000 与± 2000 °°/sec的 3 轴角速度感测器 陀螺仪
③ 集成可程序控制,范围为± 2g 、± 4g 、± 8g 和± 16g 的 3 轴加速度传感器
④ 移除加速器与陀螺仪轴间敏感度,降低设定给予的影响与感测器的飘移
⑤ 自带数字运 动处理 (DMP: Digital Motion 引擎可减少 MCU 复杂的融合演算数据、感测器同步化、姿势感应等的负荷
⑥ 内建运作时间偏差与磁力感测器校正演算技术,免除了客户须另外进行校正的需求
⑦ 自带一个数字温度传感器
⑧ 带数字输入同步引脚 (Sync 支持视频电子影相稳定技术与 GPS
⑨ 可程序控制的中断 ( interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、 high G 中断、零动作感应、触击感应、摇动感应功能
⑩ VDD 供电电压为 2.5V 5% 、 3.0V 5% 、 3.3V 5% VLOGIC 可低至 1.8V 5%
⑪ 陀螺仪工作电流: 5mA ,陀螺仪待机电流 5uA ;加速器工作电流 500uA ,加速器省电模式电流: 40uA@10Hz
⑫ 自带 1024 字节 FIFO ,有助于降低系统功耗
⑬ 高达 400Khz 的 IIC 通信接口
⑭ 超小封装尺寸: 4x4x0.9mm QFN

MPU6050程序快速开发:

程序开发步骤:
MPU6050的初始化:

1、初始化IIC接口;
2、设置角速度传感器、加速度传感器的量程范围;
3、设置其它参数,如:配置中断、设置AUX IIC接口、设置FIFO、设置陀螺仪采样率、设置数字滤波器等。
4、设置系统时钟;
5、使能角速度、加速度传感器;
这些设置都是通过配置MPU6050内部寄存器设置的,具体步骤可参考正点原子关于MPU6050章节的介绍;

下面是正点原子STM32的MPU6050初始化代码:

u8 MPU_Init(void)
{ u8 res;GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//先使能外设IO PORTA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;    // 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //IO口速度为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);                     //根据设定参数初始化GPIOAGPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO!!!MPU_AD0_CTRL=0;           //控制MPU6050的AD0脚为低电平,从机地址为:0X68MPU_IIC_Init();//初始化IIC总线MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050delay_ms(100);MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);    //唤醒MPU6050 MPU_Set_Gyro_Fsr(3);                    //陀螺仪传感器,±2000dpsMPU_Set_Accel_Fsr(0);                  //加速度传感器,±2gMPU_Set_Rate(50);                       //设置采样率50HzMPU_Write_Byte(MPU_INT_EN_REG,0X00); //关闭所有中断MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭MPU_Write_Byte(MPU_FIFO_EN_REG,0X00); //关闭FIFOMPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效res=MPU_Read_Byte(MPU_DEVICE_ID_REG);if(res==MPU_ADDR)//器件ID正确{MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);   //设置CLKSEL,PLL X轴为参考MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作MPU_Set_Rate(50);                       //设置采样率为50Hz}else return 1;return 0;
}
//设置MPU6050陀螺仪传感器满量程范围
//fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
//返回值:0,设置成功
//    其他,设置失败
u8 MPU_Set_Gyro_Fsr(u8 fsr)
{return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
}
//设置MPU6050加速度传感器满量程范围
//fsr:0,±2g;1,±4g;2,±8g;3,±16g
//返回值:0,设置成功
//    其他,设置失败
u8 MPU_Set_Accel_Fsr(u8 fsr)
{return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
}
//设置MPU6050的数字低通滤波器
//lpf:数字低通滤波频率(Hz)
//返回值:0,设置成功
//    其他,设置失败
u8 MPU_Set_LPF(u16 lpf)
{u8 data=0;if(lpf>=188)data=1;else if(lpf>=98)data=2;else if(lpf>=42)data=3;else if(lpf>=20)data=4;else if(lpf>=10)data=5;else data=6; return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器
}
//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//    其他,设置失败
u8 MPU_Set_Rate(u16 rate)
{u8 data;if(rate>1000)rate=1000;if(rate<4)rate=4;data=1000/rate-1;data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);  //设置数字低通滤波器return MPU_Set_LPF(rate/2);  //自动设置LPF为采样率的一半
}//得到温度值
//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{u8 buf[2]; short raw;float temp;MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); raw=((u16)buf[0]<<8)|buf[1];  temp=36.53+((double)raw)/340;  return temp*100;;
}
//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{u8 buf[6],res;  res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);if(res==0){*gx=((u16)buf[0]<<8)|buf[1];  *gy=((u16)buf[2]<<8)|buf[3];  *gz=((u16)buf[4]<<8)|buf[5];}   return res;;
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
//返回值:0,成功
//    其他,错误代码
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{u8 buf[6],res;  res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);if(res==0){*ax=((u16)buf[0]<<8)|buf[1];  *ay=((u16)buf[2]<<8)|buf[3];  *az=((u16)buf[4]<<8)|buf[5];}  return res;;
}
//IIC连续写
//addr:器件地址
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{u8 i; MPU_IIC_Start(); MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令  if(MPU_IIC_Wait_Ack())  //等待应答{MPU_IIC_Stop();       return 1;      }MPU_IIC_Send_Byte(reg);    //写寄存器地址MPU_IIC_Wait_Ack();     //等待应答for(i=0;i<len;i++){MPU_IIC_Send_Byte(buf[i]);   //发送数据if(MPU_IIC_Wait_Ack())        //等待ACK{MPU_IIC_Stop();  return 1;       }      }    MPU_IIC_Stop();     return 0;
}
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{ MPU_IIC_Start(); MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令   if(MPU_IIC_Wait_Ack())  //等待应答{MPU_IIC_Stop();       return 1;      }MPU_IIC_Send_Byte(reg);    //写寄存器地址MPU_IIC_Wait_Ack();     //等待应答MPU_IIC_Start();MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令    MPU_IIC_Wait_Ack();     //等待应答 while(len){if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK else *buf=MPU_IIC_Read_Byte(1);      //读数据,发送ACK  len--;buf++; }    MPU_IIC_Stop();    //产生一个停止条件 return 0;
}
//IIC写一个字节
//reg:寄存器地址
//data:数据
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Byte(u8 reg,u8 data)
{ MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令   if(MPU_IIC_Wait_Ack())  //等待应答{MPU_IIC_Stop();       return 1;      }MPU_IIC_Send_Byte(reg);    //写寄存器地址MPU_IIC_Wait_Ack();     //等待应答 MPU_IIC_Send_Byte(data);//发送数据if(MPU_IIC_Wait_Ack()) //等待ACK{MPU_IIC_Stop();  return 1;       }       MPU_IIC_Stop();     return 0;
}
//IIC读一个字节
//reg:寄存器地址
//返回值:读到的数据
u8 MPU_Read_Byte(u8 reg)
{u8 res;MPU_IIC_Start(); MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 MPU_IIC_Wait_Ack();     //等待应答 MPU_IIC_Send_Byte(reg);  //写寄存器地址MPU_IIC_Wait_Ack();     //等待应答MPU_IIC_Start();MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令    MPU_IIC_Wait_Ack();     //等待应答 res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK MPU_IIC_Stop();          //产生一个停止条件 return res;
}

经过上面的设置,即可读出MPU6050 的加速度传感器角速度传感器的原始数据。不过这些原始数据对于希望获取姿态数据的情况时用处不大,我们期望得到的是欧拉角:航向角 yaw 、横滚角 roll 、俯仰角 pitch。要得到欧拉角数据,就得利用我们的原始数据,进行姿态融合解算,这个比较复杂,幸而MPU6050 自带了数字运动处理器,即 DMP 。它可以将内部角度、陀螺等传感器进行融合计算,输出一个四元数,然后我们再通过计算公式将四元数转换为欧拉角。
使用MPU6050内置DMP可大大简化驱动代码设计,MCU将不需要进行姿态解算,可降低MCU负担。
MPU6050的DMP输出的四元数是q30格式,就是浮点数放大了2的30次方,在具体换算成欧拉角之前,需先将其转换为浮点数,也就是除以2的30次方即可,也就是:“欧拉角=MPU6050输出的四元数 / 2^30(1073741824)”;下面给出正点原子的代码:

#define q30  1073741824.0fq0=quat[0] / q30; //q30 格式转换为浮点数
q1=quat[1] / q30;
q2=quat[2] / q30;
q3=quat[3] / q30;
//计算得到俯仰角、横滚角、航向角:
pitch=asin( 2 * q1 * q3 + 2 * q0* q2)* 57.3; 俯仰角
roll =atan2(2 * q2 * q3 + 2 * q0 * q1, 2 * q1 * q1 2 * q2* q2 + 1)* 57.3; 横滚角
yaw=atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1 q2*q2 q3*q3) * 57.3; 航向角
//公式中的57.3是弧度抓换为角度,即180/ π,这样得到的结果就是以度(°)为单位的。(关于为什么这样计算的数学推导这里不做深究)

上述中的q0、q1、q2、q3,如何获得?它是MPU6050官方给出的一套C代码驱动库中完成的,实际开发中,需要将其移植到项目工程中,具体移植还是可以直接参考正点原子,其实主要就是要用它的两个.c文件:“inv_mpu.c和inv_mpu_dmp_motion_driver.c”。移植完成后,即可直接调用函数接口,正点原子写出了两个函数可完成最终的欧拉角获取:
使用DMP前要先初始化MPU6050的DMP,下面是代码:
(这是已经移植好MPU6050官方驱动库文件的情况下)

//mpu6050,dmp初始化
//返回值:0,正常
//    其他,失败
u8 mpu_dmp_init(void)
{u8 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);//设置FIFOif(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);  //使能DMPif(res)return 9;}else return 10;return 0;
}

如此,通过“u8 mpu_dmp_init(void)”这个函数即可获取MPU6050的FIFO输出的四元数,但我们还要经过上述的换算,才能得到欧拉角,函数代码如下:

//得到dmp处理后的数据(注意,本函数需要比较多堆栈,局部变量有点多)
//pitch:俯仰角 精度:0.1°   范围:-90.0° <---> +90.0°
//roll:横滚角  精度:0.1°   范围:-180.0°<---> +180.0°
//yaw:航向角   精度:0.1°   范围:-180.0°<---> +180.0°
//返回值:0,正常
//    其他,失败
u8 mpu_dmp_get_data(float *pitch,float *roll,float *yaw)
{float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;unsigned long sensor_timestamp;short gyro[3], accel[3], sensors;unsigned char more;long quat[4]; if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1;     /* Gyro and accel data are written to the FIFO by the DMP in chip frame and hardware units.* This behavior is convenient because it keeps the gyro and accel outputs of dmp_read_fifo and mpu_read_fifo consistent.**//*if (sensors & INV_XYZ_GYRO )send_packet(PACKET_TYPE_GYRO, gyro);if (sensors & INV_XYZ_ACCEL)send_packet(PACKET_TYPE_ACCEL, accel); *//* Unlike gyro and accel, quaternions are written to the FIFO in the body frame, q30.* The orientation is set by the scalar passed to dmp_set_orientation during initialization. **/if(sensors&INV_WXYZ_QUAT) {q0 = quat[0] / q30;   //q30格式转换为浮点数q1 = quat[1] / q30;q2 = quat[2] / q30;q3 = quat[3] / q30; //计算得到俯仰角/横滚角/航向角*pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3;    // pitch*roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3;   // roll*yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;   //yaw}else return 2;return 0;
}

至此,我们即得到了MPU6050的三个欧拉角:pitch、roll、yaw。

关于GY282电子罗盘:

它使用了6050的寄存器,并联在6050的内部的数据总线上了,而并非直接在系统总线上通过sda和scl读取,系统能够直接寻址。

MPU6050快速开发使用相关推荐

  1. java 对比两个表的字段的差异_Joolun小程序商城 2.2.2版本上线了——Java微信快速开发平台...

    Joolun是一款基于spring-boot的微信快速开发平台,目前拥有公众号基础版和小程序商城版两个版本.Joolun采用目前流行的前后端分离技术所写,是一款高效.易用的java微信开发框架平台,二 ...

  2. jeecgboot前端开发_一款基于代码生成器的Java快速开发平台【jeecg-boot】

    原标题:一款基于代码生成器的Java快速开发平台[jeecg-boot] 今天给大家介绍一个后台脚手架框架:jeecg-boot 来看看官方怎么介绍的. 一款基于代码生成器的Java快速开发平台!全新 ...

  3. 【转】 Android快速开发系列 10个常用工具类 -- 不错

    原文网址:http://blog.csdn.net/lmj623565791/article/details/38965311 转载请标明出处:http://blog.csdn.net/lmj6235 ...

  4. 快速开发一个PHP扩展

    快速开发一个PHP扩展 作者:heiyeluren 时间:2008-12-5 博客:http://blog.csdn.net/heiyeshuwu 本文通过非常快速的方式讲解了如何制作一个PHP 5. ...

  5. 快速 开发平台 架构_快速介绍清洁架构

    快速 开发平台 架构 by Daniel Deutsch 由Daniel Deutsch 快速介绍清洁架构 (A quick introduction to clean architecture) I ...

  6. 度量快速开发平台端口映射的介绍

    度量快速开发平台在客户中部署的时候,可能会想内网与外网用户同时使用.一般情况下,服务端都是部署在内网的,那外网用户要访问,就可能用到端口映射的功能.端口映射基本都是在路由器上进行. 下面就是几个常用的 ...

  7. 利用UltimateAndroid框架进行快速开发

    UltimateAndroid是一套集成了许多现有优秀的Android开源类库并将之组合成一个整体的Android快速开发框架.框架目前主要包含的功能有View Injection,ORM,异步网络请 ...

  8. Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台项目

    项目介绍 Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台 基于 Layui 的后台管理系统模板,扩展 Layui 原生 U ...

  9. java项目_JNPF快速开发平台-简单快速高效开发java项目

    ◆JNPF快速开发平台 JNPF快速开发平台采用前后端分离技术.采用B/S架构开发,形成一站式开发多端(APP+PC)使用. 使用JNPF开发平台可以简单.快速.高效的构建各种类型java项目. ◆J ...

最新文章

  1. Linux下设置进程使用指定核的CPU
  2. Redlock——Redis集群分布式锁
  3. cocos2dx - Lua 语言
  4. python取中间值的函数_tensorflow实现在函数中用tf.Print输出中间值
  5. 路径中斜杠/、点斜杠./、点点斜杠../的区别
  6. 第22天:如何使用OpenAI Gym和Universe构建AI游戏机器人
  7. Unity面试题精选(6)
  8. redis缓存穿透、缓存雪崩、缓存击穿详解
  9. php并发访问排队_使用xdebug对php做性能分析调优
  10. [济南考勤机专题]考勤机类型(五)打卡考勤机
  11. 一文读懂POE交换机和普通交换机的区别
  12. js使用双层for循环实现倒三角形、正三角形
  13. pytorch+yolov3(4)
  14. Machine Learning 机器学习基本概念
  15. 将图片(HDC)打印出来
  16. 四.链式法则及高阶导数
  17. 透视变换(perspective transformation)
  18. 博弈论(初级)——数学知识(C++)
  19. canvas制作圆型印章
  20. 常用的几种设计模式详解

热门文章

  1. 新联邦业务数据湖为颠覆大数据应用铺路
  2. java基于springboot框架实现的环保网站垃圾分类系统实战项目
  3. IT宅男的福音!15个编程类的游戏,编程游戏两不误!
  4. 不留痕迹的清除部分history历史命令记录
  5. 微信小程序跳转报错errMsg: “navigateTo:fail webview count limit exceed“
  6. 基于python的灰色预测模型
  7. 基于PHP+MySQL汽车展览会网站的设计与实现
  8. Python - 海龟图
  9. SpringCloud Module依赖程序包找不到问题解决方法
  10. 《大教堂与集市》读书笔记