摘要
MPU6050是InvenSense公司推出的全球首款整合性6轴运动处理组件,内部整合了3轴陀螺仪和3轴加速度传感器。在制作自平衡小车和四轴六轴时需要用来做姿态的监控。
本文核心记录使用arduino uno开发板获取
MPU6050三轴数据的基本操作
硬件接线
MPU6050模块使用的数据接口协议是I2C总线协议,在arduino中使用Wire类库来实现MPU6050的访问。
接线方式:
//VCC--5V
//GND--GND
//SCL--A5
//SDA--A4
//AD0-- (AD0引脚为地址选择引脚,悬空或者接GND,硬件地址为0x68,接VCC/高电平硬件地址为0x69)
//INT-- (中断引脚,如果用到可以接中端口,此处不接)
需要使用到的Wire库方法
1.wire.begin();/wire.begin(address);不带参数为以主机模式进入总线模式,带参数为以从机模式进入总线。
2.Wire.beginTransmission(address);开启对应器件的传输。
3. Wire.write(address); //指定操作寄存器的地址。
4.Wire.write(0); //写入一个字节的数据0。
5.Wire.requestFrom(address, n, true);//向器件请求2个字节的数据,特别说明,此处地址为器件地址。请求返回的数据存储到缓冲区buffer中
6.Wire.endTransmission(true); //结束传输,释放总线
7.Wire.available();//返回总线缓冲区有效数据字节数;
8.Wire.read();//从缓冲区buffer中读取数据,一次读取一个字节
示例1.从MPU6050中读数据
Wire.beginTransmission(0x68); //开启MPU6050的传输
Wire.write(0x3F); //指定需要读取数据的寄存器地址
Wire.requestFrom(0x68, 2, true); //向器件发出2个字节数据的请求
Wire.endTransmission(true); //结束传输,释放总线
while ((Wire.available() < 2));//等待2字节数据存入缓冲区。
int val = Wire.read() << 8 | Wire.read();
示例2.向MPU6050中写数据
Wire.beginTransmission(0x68); //开启MPU6050的传输
Wire.write(0x6B); //指定寄存器地址
Wire.write(0); //写入一个字节的数据
Wire.endTransmission(true); //结束传输释放总线
MPU6050模块的访问
1. 启动器件:在对MPU6050进行各项操作前,需要先启动该器件,具体操作就是向它的0x6B写入一个字节的数据0。
//向0x6B写入一个字节的数据0,启动器件
void MPU_START(void)
{
Wire.beginTransmission(0x68); //开启MPU6050的传输
Wire.write(0x6B); //指定寄存器地址
Wire.write(0); //写入一个字节的数据0
Wire.endTransmission(true); //结束传输释放总线
}
2. 配置MPU6050的倍率:默认加速度倍率±2g,默认角速度±250度/s。寄存器0x1B和0x1C两个寄存器的bit4+bit3分别用来配置角速度倍率和加速度倍率,用f表示倍率。
//角速度倍率更新配置
void GYRO_COFIG(unsigned int f)
{
Wire.beginTransmission(0x68); //开启MPU-6050的传输
Wire.write(0x1B); //角速度倍率寄存器的地址
Wire.requestFrom(0x68, 1, true); //请求读出原配置
unsigned char acc_conf = Wire.read();//原配置读出
acc_conf = ((acc_conf & 0xE7) | (f << 3));//倍率配置更新
Wire.write(acc_conf);更新倍率写入
Wire.endTransmission(true); //结束传输,释放总线
}
//加速度倍率更新配置
void ACCEL_COFIG(unsigned int f)
{
Wire.beginTransmission(0x68); //开启MPU-6050的传输
Wire.write(0x1C); //加速度倍率寄存器的地址
Wire.requestFrom(0x68, 1, true); //请求读出原配置
unsigned char acc_conf = Wire.read();//原配置读出
acc_conf = ((acc_conf & 0xE7) | (f << 3));//倍率配置更新
Wire.write(acc_conf);更新倍率写入
Wire.endTransmission(true); //结束传输,释放总线
}
3. 数据获取和换算:加速度角速度和温度数据均为16位数据,寄存器地址如下:
0x3B,加速度计的X轴分量ACCEL_X
0x3D,加速度计的Y轴分量ACCEL_Y
0x3F,加速度计的Z轴分量ACCEL_Z
0x41,当前温度TEMP
0x43,绕X轴旋转的角速度GYRO_X
0x45,绕Y轴旋转的角速度GYRO_Y
0x47,绕Z轴旋转的角速度GYRO_Z
从寄存器读取到的数据为2个字节的对应的数据分量,需要将获取的数据分量换算成相应的加速度和角速度。
换算方法:实际数值=对应数据分量/32768*倍率
假设,角速度和加速度倍率配置均默认为0,则角速度倍率±250度/s,加速度倍率为±2g。
则X轴角速度和加速度分别为gyr_x=GYRO_X/32768*250
acc_x=ACCEL_X/32768*2g;
g为当地重力加速度,取9.8m/s^2;
其中:MPU6050寄存器详细说明可以查询产品的数据手册。
完整实例代码:
// Visual Micro is in vMicro>General>Tutorial Mode
//
/*
Name: MPU6050_TestDemo.ino
Created:2020/3/18 星期三 20:17:09
Author: SilenceJerui
*/
/*
接线方式:
//MPU6050--UNO
//VCC--5V
//GND--GND
//SCL--A5
//SDA--A4
//AD0-- (AD0引脚为地址选择引脚,悬空或者接GND,硬件地址为0x68,接VCC/高电平硬件地址为0x69)
//INT-- (中断引脚,如果用到可以接中端口,此处不接)
*/
#include
// Define User Types below here or use a .h file
//
#define ACCEL_CONFIG 1
#define GYRO_CONFIG 1
#define G 9.8
float val_seven[7];
// Define Function Prototypes that use User Types below here or use a .h file
//
// Define Functions below here or use other .ino or cpp files
//向0x6B写入一个字节的数据0,启动器件
void MPU_START(void)
{
Wire.beginTransmission(0x68); //开启MPU6050的传输
Wire.write(0x6B); //指定寄存器地址
Wire.write(0); //写入一个字节的数据
Wire.endTransmission(true); //结束传输,true表示释放总线
}
//配置角速度倍率
void GYRO_CONFIG_SET(int f)
{
Wire.beginTransmission(0x68); //开启MPU-6050的传输
Wire.write(0x1B); //角速度倍率寄存器的地址
Wire.requestFrom(0x68, 1, true); //先读出原配置
unsigned char acc_conf = Wire.read();
acc_conf = ((acc_conf & 0xE7) | (f << 3));
Wire.write(acc_conf);
Wire.endTransmission(true); //结束传输,true表示释放总线
}
//配置加速度倍率
void ACCEL_CONFIG_SET(int f)
{
Wire.beginTransmission(0x68); //开启MPU-6050的传输
Wire.write(0x1C); //加速度倍率寄存器的地址
Wire.requestFrom(0x68, 1, true); //先读出原配置
unsigned char acc_conf = Wire.read();
acc_conf = ((acc_conf & 0xE7) | (f << 3));
Wire.write(acc_conf);
Wire.endTransmission(true); //结束传输,true表示释放总线
}
//获取MPU数据
void Get_Value(void)
{
//获取各个轴分量数据
Wire.beginTransmission(0x68); //开启MPU-6050的传输
Wire.write(0x3B);
Wire.requestFrom(0x68, 7 * 2, true);
Wire.endTransmission(true);
for (long i = 0; i < 7; ++i)
{
val_seven[i] = Wire.read() << 8 | Wire.read();
}
//数据换算
val_seven[0] = (float)(val_seven[0] / 32768 * (2 ^ ACCEL_CONFIG) * G);//acc_x
val_seven[1] = (float)(val_seven[1] / 32768 * (2 ^ ACCEL_CONFIG) * G);//acc_y
val_seven[2] = (float)(val_seven[2] / 32768 * (2 ^ ACCEL_CONFIG) * G);//acc_z
val_seven[4] = (float)(val_seven[4] / 32768 * (2 ^ GYRO_CONFIG) * 250);//gyr_x
val_seven[5] = (float)(val_seven[5] / 32768 * (2 ^ GYRO_CONFIG) * 250);//gyr_y
val_seven[6] = (float)(val_seven[6] / 32768 * (2 ^ GYRO_CONFIG) * 250);//gyr_z
}
// The setup() function runs once each time the micro-controller starts
void setup()
{
Serial.begin(9600);
Wire.begin();//以主机模式开启总线
MPU_START();//启动MPU6050
GYRO_CONFIG_SET(0);//配置器件角速度倍率
ACCEL_CONFIG_SET(0);//配置器件加速度倍率
}
// Add the main program code into the continuous loop() function
void loop()
{
Get_Value();
Serial.print("acc_x:");
Serial.print('\t');
Serial.println(val_seven[0]);
Serial.print("acc_y:");
Serial.print('\t');
Serial.println(val_seven[1]);
Serial.print("acc_z:");
Serial.print('\t');
Serial.println(val_seven[2]);
Serial.print("gyr_x:");
Serial.print('\t');
Serial.println(val_seven[4]);
Serial.print("gyr_y:");
Serial.print('\t');
Serial.println(val_seven[5]);
Serial.print("gyr_z:");
Serial.print('\t');
Serial.println(val_seven[6]);
delay(500);
}