摘要
MPU6050是InvenSense公司推出的全球首款整合性6軸運動處理組件碌奉,內(nèi)部整合了3軸陀螺儀和3軸加速度傳感器。在制作自平衡小車和四軸六軸時需要用來做姿態(tài)的監(jiān)控键畴。
本文核心記錄使用arduino uno開發(fā)板獲取
MPU6050三軸數(shù)據(jù)的基本操作
硬件接線
MPU6050模塊使用的數(shù)據(jù)接口協(xié)議是I2C總線協(xié)議芋绸,在arduino中使用Wire類庫來實現(xiàn)MPU6050的訪問。
接線方式:
? ? //VCC--5V
? ? //GND--GND
? ? //SCL--A5
? ? //SDA--A4
? ? //AD0-- (AD0引腳為地址選擇引腳梁沧,懸空或者接GND,硬件地址為0x68呈枉,接VCC/高電平硬件地址為0x69)
? ? //INT-- (中斷引腳趁尼,如果用到可以接中端口,此處不接)
需要使用到的Wire庫方法
1.wire.begin();/wire.begin(address);不帶參數(shù)為以主機模式進入總線模式猖辫,帶參數(shù)為以從機模式進入總線酥泞。
2.Wire.beginTransmission(address);開啟對應器件的傳輸。
3. Wire.write(address); //指定操作寄存器的地址啃憎。
4.Wire.write(0); //寫入一個字節(jié)的數(shù)據(jù)0芝囤。
5.Wire.requestFrom(address, n, true);//向器件請求2個字節(jié)的數(shù)據(jù),特別說明辛萍,此處地址為器件地址悯姊。請求返回的數(shù)據(jù)存儲到緩沖區(qū)buffer中
6.Wire.endTransmission(true); //結(jié)束傳輸,釋放總線
7.Wire.available();//返回總線緩沖區(qū)有效數(shù)據(jù)字節(jié)數(shù)贩毕;
8.Wire.read();//從緩沖區(qū)buffer中讀取數(shù)據(jù)悯许,一次讀取一個字節(jié)
示例1.從MPU6050中讀數(shù)據(jù)
Wire.beginTransmission(0x68); //開啟MPU6050的傳輸
Wire.write(0x3F); //指定需要讀取數(shù)據(jù)的寄存器地址
Wire.requestFrom(0x68, 2, true); //向器件發(fā)出2個字節(jié)數(shù)據(jù)的請求
Wire.endTransmission(true); //結(jié)束傳輸,釋放總線
while ((Wire.available() < 2));//等待2字節(jié)數(shù)據(jù)存入緩沖區(qū)辉阶。
int val = Wire.read() << 8 | Wire.read();
示例2.向MPU6050中寫數(shù)據(jù)
Wire.beginTransmission(0x68); //開啟MPU6050的傳輸
Wire.write(0x6B); //指定寄存器地址
Wire.write(0); //寫入一個字節(jié)的數(shù)據(jù)
Wire.endTransmission(true); //結(jié)束傳輸釋放總線
MPU6050模塊的訪問
1.? ? 啟動器件:在對MPU6050進行各項操作前先壕,需要先啟動該器件,具體操作就是向它的0x6B寫入一個字節(jié)的數(shù)據(jù)0谆甜。
//向0x6B寫入一個字節(jié)的數(shù)據(jù)0垃僚,啟動器件
void MPU_START(void)
{
Wire.beginTransmission(0x68); //開啟MPU6050的傳輸
Wire.write(0x6B); //指定寄存器地址
Wire.write(0); //寫入一個字節(jié)的數(shù)據(jù)0
Wire.endTransmission(true); //結(jié)束傳輸釋放總線
}
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); //結(jié)束傳輸,釋放總線
}
//加速度倍率更新配置
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); //結(jié)束傳輸罕袋,釋放總線
}
3.? ? ? 數(shù)據(jù)獲取和換算:加速度角速度和溫度數(shù)據(jù)均為16位數(shù)據(jù)改淑,寄存器地址如下:
0x3B碍岔,加速度計的X軸分量ACCEL_X
0x3D,加速度計的Y軸分量ACCEL_Y
0x3F溅固,加速度計的Z軸分量ACCEL_Z
0x41付秕,當前溫度TEMP
0x43,繞X軸旋轉(zhuǎn)的角速度GYRO_X
0x45侍郭,繞Y軸旋轉(zhuǎn)的角速度GYRO_Y
0x47询吴,繞Z軸旋轉(zhuǎn)的角速度GYRO_Z
從寄存器讀取到的數(shù)據(jù)為2個字節(jié)的對應的數(shù)據(jù)分量,需要將獲取的數(shù)據(jù)分量換算成相應的加速度和角速度亮元。
換算方法:實際數(shù)值=對應數(shù)據(jù)分量/32768*倍率
假設(shè)猛计,角速度和加速度倍率配置均默認為0,則角速度倍率±250度/s爆捞,加速度倍率為±2g奉瘤。
則X軸角速度和加速度分別為gyr_x=GYRO_X/32768*250
acc_x=ACCEL_X/32768*2g;
g為當?shù)刂亓铀俣龋?.8m/s^2;
其中:MPU6050寄存器詳細說明可以查詢產(chǎn)品的數(shù)據(jù)手冊煮甥。
完整實例代碼:
// 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 <Wire.h>
// 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寫入一個字節(jié)的數(shù)據(jù)0双霍,啟動器件
void MPU_START(void)
{
? ? Wire.beginTransmission(0x68); //開啟MPU6050的傳輸
? ? Wire.write(0x6B); //指定寄存器地址
? ? Wire.write(0); //寫入一個字節(jié)的數(shù)據(jù)
? ? Wire.endTransmission(true); //結(jié)束傳輸砚偶,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); //結(jié)束傳輸,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); //結(jié)束傳輸洒闸,true表示釋放總線
}
//獲取MPU數(shù)據(jù)
void Get_Value(void)
{
? ? //獲取各個軸分量數(shù)據(jù)
? ? 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();
? ? }
? ? //數(shù)據(jù)換算
? ? 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);
}