MPU6050的初始化

mpu6050是运动处理传感器,它集成了3轴陀螺仪,3轴加速度计以及dmp,其中的dmp是一个可通过iic接口扩展的数字运动处理器。
对于dmp可以用 invensense 公司提供的资料库,使mpu6050可以解算出姿态,通过iic接口直接输出陀螺仪和加速度数据融合后的四元数,减轻了处理器的负荷,非常适合简单的开发应用。但是,使用dmp的这种硬件解算也存在问题,有时会无法读出数据,因此,在四轴的应用中通常都会采用软件解算,常见的姿态解算方法有:非线性互补滤波算法,卡尔曼滤波算法,mahony互补滤波算法(可参见crazypony的开源项目)。
mpu6050通过iic协议与处理器进行通信。我使用stm32时通常采用软件模拟iic的方式。
寄存器的查阅 mpu6050的所有寄存器都可以在官方文档“mpu-6000 and mpu-6050 register map and descriptions”中找到,平时使用中最为重要的有以下几种:电源管理寄存器1和2、陀螺仪配置寄存器、陀螺仪采样率分频寄存器、加速度传感器配置寄存器、配置寄存器。
以电源管理寄存器为例:
寄存器地址:0x6b(hex)或107(十进制)。
表格后面的几位bit7~bit0代表八位二进制,给该寄存器赋值就是改变这几位的值。各个位代表的意义可看表下方的说明:如device_reset :when set to 1, this bit resets all internal registers to their default values.the bit automatically clears to 0 once the reset is done.表明device_reset被置1时芯片就会将所有内部寄存器复位。
-
驱动程序 对mpu6050的初始化驱动就是通过iic的协议,对mpu6050的寄存器进行初始化配置,我选择配置的有:
设置电源管理寄存器1(0x6b),复位mpu6050 (下面举例)
设置陀螺仪配置寄存器(0x1b),将量程设置为 2000dps
设置加速度计配置寄存器(0x1c),将量程设置为 2g
设置采样频率分频器(0x19),将采样率设置为50hz
设置中断使能寄存器(0x38),关闭中断
设置电源管理寄存器2(0x6c),使加速度陀螺仪都工作
//以下函数通过iic协议,修改mpu6050的电源管理寄存器,实现复位
//其中的(iic_……)函数为iic通信函数,可从名字中了解大致功能,具体应用可参见iic通信协议的内容
char mpu_reset()
{
iic_start();
iic_send_byte((0x68《《1)|0); //发送器件地址+写命令
if(iic_wait_ack())
{
iic_stop();
return 1;
}
iic_send_byte(0x6b); //写寄存器地址,选择电源管理寄存器1
iic_wait_ack();
iic_send_byte(0x80); //发送数据(1000 0000)第七位为1,复位
if(iic_wait_ack())
{
iic_stop();
return 1;
}
iic_stop();
return 0;
}
按照相同的方法对其余的寄存器进行配置之后,mpu6050就可以正常工作了。接下来的任务就是不断读取它的数据,计算出芯片的姿态了。。。
读取原始数据
使用iic协议读取以上寄存器的值,每个轴的值由16位二进制表示(0–65535),以x轴为例:accel_xout[15:8]、accel_xout[7:0]分别为x轴加速度的高八位和低八位,每次读取八位再将它们拼起来即可。
ax=( (unsigned int)buffer[0]《《8 ) | buffer[1];
此时就获得了mpu6050输出的adc值了,它是以lsb为单位的,而不是以实际值的 g 为单位,它对应的实际值与你在初始化的时候设置的量程有关。比如说我们设置的量程是+-2g,那对应的灵敏度=65536/4 lsb/g , 那么实际的加速度值=adc的值lsb / 16384 lsb/g
通过这些我们就可以得到原始数据了,顺便附上初始化mpu6050源代码:
itstructure);
gpio_initstructure.gpio_pin = gpio_pin_11;
gpio_initstructure.gpio_speed = gpio_speed_50mhz; gpio_initstructure.gpio_mode = gpio_mode_out_od; gpio_init(gpiob, &gpio_initstructure);
if(single_read(mpu6050_addr,who_am_i)==0x68) {
single_write(mpu6050_addr,pwr_mgmt_1, 0x00);
//电源管理1,解除休眠状态,时钟为内部8mhz
single_write(mpu6050_addr,smplrt_div, 0x07);//采样速率125hz single_write(mpu6050_addr,config,0x06);
//不使能fsync,不使用外同步采样速率;dlpf_cfg[2~0],设置任意轴是否通过dlpf,
//典型值:0x06(5hz)低通滤波器带宽5hz,
//对加速度和陀螺仪都有效,输出频率为1khz,决定smplrt_div的频率基准
single_write(mpu6050_addr,gyro_config, 0x08);//不自测,量程设置500°/s /*?gyro 量程单位系数
+-250 deg/s 131 lsb/deg/s 初始化hex 0x00 +-500 deg/s 65.5 lsb/deg/s 0x08 +-1000 deg/s 32.8 lsb/deg/s 0x10 +-2000 deg/s 16.4 lsb/deg/s 0x18 */
single_write(mpu6050_addr,accel_config, 0x00);//不自测,量程设置2g
/* accle any axe
+-2 g 16384 lsb/g +-4 g 8192 lsb/g +-8 g 4096 lsb/g +-16 g 2048 lsb/g
*/
return 0; } return 1; }
//******读取mpu6050数据**************************************** //**************************************
//读取mpu6050内部数据,两个字节,合成数据 //************************************** s16
getdata(u8
reg_address)
//返回值为有符号的整形,16位 {
s16 h=0,l=0;
h = single_read(mpu6050_addr,reg_address); //先读高字节,再读低字节
l = single_read(mpu6050_addr,reg_address+1); return
(h《《8)+l;
//合成数据,为有符号整形数 }
//-------------加速度部分解算角度------------------
s32 read_acc(void) {
s32 accel_x; //mpo6050读出的x轴加速度 s32 accel_z; //mpu6050读出的z轴加速度 //-------------加速度部分解算------------------
/*使用是加速度轴x轴正向朝向小车行径方向,y轴陀螺仪的正向 逆时针方向。 加速度计的量程范围见配置 不自测,量程设置4g scal系数为8192 accle any axe
+-2 g 16384 lsb/g +-4 g 8192 lsb/g +-8 g 4096 lsb/g +-16 g 2048 lsb/g */
accel_x = getdata(accel_xout_h); //从mpu6050读取x轴加速度 accel_z = getdata(accel_zout_h); //从mpu6050读取z轴加速度
if(accel_x》0) {
angle_accel = atan2((float)accel_x,(float)accel_z)*(180/3.14159265);//反正切计算rad
/* atan2(y,x)是表示x-y平面上所对应的(x,y)坐标的角度, 它的值域范围是(-pi,pi) 用数学表示就是:atan2(y,x)=arg(y/x)-pi 当y《0时,其值为负,
当y》0时,其值为正。 atan2*180/pi可以计算出角度值 */
}
else {
s32 read_gyro_y; s32 angle_gyro; //-------角速度解算-------------------------
//角速度量程见配置 本处使用1000 deg/s。scal系数为32.8 lsb /*?gyro 量程单位系数
+-250 deg/s 131 lsb/deg/s offset 44.38188277*2 +-500 deg/s 65.5 lsb/deg/s offset 44.38188277 +-1000 deg/s 32.8 lsb/deg/s ok offset 44.38188277/2 +-2000 deg/s 16.4 lsb/deg/s offset 44.38188277/4 */
read_gyro_y= getdata(gyro_yout_h)+gyro_y_offset; //静止时角速度y轴输出 //gyro_y_offset计算方法gyro静止时候n多个数据的算术均值
angle_gyro= -read_gyro_y/65.5; //去除零点偏移,计算角速度值,负号为方向处理 //angle_gyro测量值的单位是 deg/s.测量的物理量是角速度。 return angle_gyro; }
angle_accel
=
atan2((float)accel_z,(float)accel_x)*(180/3.14159265)-90;//反正切计算 angle_accel = -angle_accel; }
//angle_accel物理量单位是角度 deg! return angle_accel; }
//陀螺仪计算y轴的角速度 s32 read_gry(void) {

远程支持如何提高效率?并发远程控制多台主机还不卡顿
Cable Modem 开启有线宽带教程
联合电子车载应用软件一站式解决方案 USP2.0 软件开发平台
一步步重新演绎汽车驾驶新体验
Avago发布光学传感器片上系统(SOC) ADNS-270
MPU6050的初始化
AMD又一次抢先卡位B450芯片组,华擎已准备了四款B450芯片组
单身汪”福利来啦!未来可以找个机器人做女友了
使用Arduino计算直流电压的方式
门禁系统设计中被忽视问题细谈分析
谷歌实力招揽AI人才
平尚贴片电阻不断提高智能产品的质量及性能
LCD液晶显示屏的闪屏问题
R&S FSVR实时频谱分析仪的性能特性应用优势
可控硅电子时间继电器
详解投影仪自动对焦镜头马达驱动原理
曝阿里巴巴计划收购韵达至少10%的股份 将是阿里对大型快递企业的第五笔投资
什么是HBM3 为什么HBM很重要
郭台铭带领富士康转型工业互联网 苹果业绩迎来“晴雨表”
P50能否延续P40的成功 或将搭载麒麟9000+鸿蒙OS