关于MPU6050学习的一些总结之三MPU6050程序解读
關(guān)于MPU6050學(xué)習(xí)的一些總結(jié)之三MPU6050程序解讀
- 前言
- MPU6050.h
- 初始化函數(shù)
- 獲取數(shù)據(jù)
- 數(shù)據(jù)處理(計(jì)算零偏)
- 結(jié)語(yǔ)
前言
經(jīng)過(guò)兩天的整理終于可以嘗試解讀MPU6050程序了,話不多說(shuō)直接看程序。
MPU6050.h
在讀頭文件之前還有個(gè)小知識(shí)點(diǎn)在第一節(jié)遺忘了,現(xiàn)在補(bǔ)上。那就是在MPU6050內(nèi)部用來(lái)存儲(chǔ)自身地址的寄存器,它的名字也很形象叫WHO_AM_I。
可以看出這個(gè)寄存器是只讀寄存器,只有Bit1-Bit6存放六位只讀數(shù)據(jù)。分別是110 100,地址的第7位由引腳AD0的高低電平?jīng)Q定。下面直接看MPU6050的頭文件。
初始化函數(shù)
u8 mpu6050_buffer[14]; //iic讀取后存放數(shù)據(jù) struct _sensor sensor; u8 InitMPU6050(void) {u8 date;date = Single_Write(MPU6050_ADDRESS, PWR_MGMT_1, 0x00); //解除休眠狀態(tài)date += Single_Write(MPU6050_ADDRESS, SMPLRT_DIV, 0x07);date += Single_Write(MPU6050_ADDRESS, CONFIGL, 0x03);date += Single_Write(MPU6050_ADDRESS, GYRO_CONFIG, 0x10);date += Single_Write(MPU6050_ADDRESS, ACCEL_CONFIG, 0x09);//+-4Greturn date; }Single_Write();函數(shù)在第二節(jié)已經(jīng)介紹過(guò),因此初始化函數(shù)主要對(duì)寄存器寫入字節(jié)數(shù)據(jù)。查閱相關(guān)寄存器可知:
1.對(duì)于電源管理寄存器1寫入0x00,即SLEEP=0:喚醒MPU6050;TEMP_DIS=0,使能溫度傳感器;CLKSEL=0,采用內(nèi)部8MHz時(shí)鐘作為時(shí)鐘源。
2.對(duì)于采樣分頻寄存器寫入0x07,即SMPLRT_DIV=7;
3.對(duì)于配置寄存器寫入0x03,即低通濾波器參數(shù)DLPF_CFG=3,查表得陀螺儀輸出頻率Fs=1KHz。根據(jù)公式:采樣頻率=陀螺儀輸出頻率/(1+SMPLRT_DIV)
計(jì)算得到采樣頻率為1KHz/(1+7)=125Hz。
4.對(duì)于陀螺儀配置寄存器寫入0x10,查表可知不觸發(fā)自檢,滿量程為±1000°/s。
5.對(duì)于加速度計(jì)配置寄存器寫入0x09,查表可知不觸發(fā)自檢,滿量程為±4g,另外根據(jù)表可知,高通濾波器的截止頻率為5Hz.
獲取數(shù)據(jù)
//**************************實(shí)現(xiàn)函數(shù)******************************************** //將iic讀取到得數(shù)據(jù)分拆,放入相應(yīng)寄存器,更新MPU6050_Last //****************************************************************************** void MPU6050_Read(void) {mpu6050_buffer[0]=Single_Read(MPU6050_ADDRESS, 0x3B);mpu6050_buffer[1]=Single_Read(MPU6050_ADDRESS, 0x3C);mpu6050_buffer[2]=Single_Read(MPU6050_ADDRESS, 0x3D);mpu6050_buffer[3]=Single_Read(MPU6050_ADDRESS, 0x3E);mpu6050_buffer[4]=Single_Read(MPU6050_ADDRESS, 0x3F);mpu6050_buffer[5]=Single_Read(MPU6050_ADDRESS, 0x40);mpu6050_buffer[8]=Single_Read(MPU6050_ADDRESS, 0x43);mpu6050_buffer[9]=Single_Read(MPU6050_ADDRESS, 0x44);mpu6050_buffer[10]=Single_Read(MPU6050_ADDRESS, 0x45);mpu6050_buffer[11]=Single_Read(MPU6050_ADDRESS, 0x46);mpu6050_buffer[12]=Single_Read(MPU6050_ADDRESS, 0x47);mpu6050_buffer[13]=Single_Read(MPU6050_ADDRESS, 0x48);}由高到低依次讀取加速度計(jì)和陀螺儀三個(gè)軸的數(shù)據(jù)存放到數(shù)組內(nèi)。在看下一段代碼之前,還需要看幾個(gè)宏定義以便更加容易地理解函數(shù)。
#define RtA 57.324841 //弧度到角度 #define AtR 0.0174533 //角度轉(zhuǎn)弧度 #define Acc_G 0.0011963 //±4g 8g/65536 #define Gyro_G 0.03051756 //±1000°/s 2000/65536 #define Gyro_Gr 0.0005426 // °每秒轉(zhuǎn)化為rad/s在這里,RtA表示弧度轉(zhuǎn)角度的換算即180/pi180/pi180/pi;AtR表示角度轉(zhuǎn)弧度的換算即pi/180pi/180pi/180;Acc_G表示加速度計(jì)靈敏度的倒數(shù)即AccG=1/(65536/8)Acc_G=1/(65536/8)\quadAccG?=1/(65536/8);
同理GyroG=1/(65536/2000)Gyro_G=1/(65536/2000)GyroG?=1/(65536/2000);將單位°/s轉(zhuǎn)化為rad/s后對(duì)應(yīng)的便是Gyro_Gr。
由于傳感器傳回的數(shù)據(jù)為16位數(shù)字量,對(duì)于加速度計(jì)將16位數(shù)字量num.acc轉(zhuǎn)化為模擬量的公式為:num.acc?ACCGnum.acc*ACC_Gnum.acc?ACCG?。對(duì)于陀螺儀將16位數(shù)字量num.Gyro轉(zhuǎn)化為模擬量的公式為:num.Gyro?GyroG,單位為°/s,num.Gyro?Gyro.Gr,單位為rad/snum.Gyro*Gyro_G,單位為°/s,num.Gyro*Gyro.Gr,單位為rad/snum.Gyro?GyroG?,單位為°/s,num.Gyro?Gyro.Gr,單位為rad/s。
數(shù)據(jù)處理(計(jì)算零偏)
void MPU6050_Dataanl(void) {MPU6050_Read();sensor.acc.origin.x = ((((int16_t)mpu6050_buffer[0]) << 8) | mpu6050_buffer[1]) - sensor.acc.quiet.x;//將加速度計(jì)x軸的高位和低位測(cè)量值整合到一起,并減去漂移量。sensor.acc.origin.y = ((((int16_t)mpu6050_buffer[2]) << 8) | mpu6050_buffer[3]) - sensor.acc.quiet.y;//將加速度計(jì)y軸的高位和低位測(cè)量值整合到一起,并減去漂移量。sensor.acc.origin.z = ((((int16_t)mpu6050_buffer[4]) << 8) | mpu6050_buffer[5]);//將加速度計(jì)z軸的高位和低位測(cè)量值整合到一起,并減去漂移量。sensor.gyro.origin.x = ((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]);//將陀螺儀x軸的高位和低位測(cè)量值整合到一起。sensor.gyro.origin.y = ((((int16_t)mpu6050_buffer[10]) << 8)| mpu6050_buffer[11]);//將陀螺儀y軸的高位和低位測(cè)量值整合到一起。sensor.gyro.origin.z = ((((int16_t)mpu6050_buffer[12]) << 8)| mpu6050_buffer[13]);//將陀螺儀z軸的高位和低位測(cè)量值整合到一起。sensor.gyro.radian.x = sensor.gyro.origin.x * Gyro_Gr - sensor.gyro.quiet.x * Gyro_Gr;//數(shù)字量轉(zhuǎn)換成模擬量,單位是rad/ssensor.gyro.radian.y = sensor.gyro.origin.y * Gyro_Gr - sensor.gyro.quiet.y * Gyro_Gr;//數(shù)字量轉(zhuǎn)換成模擬量,單位是rad/ssensor.gyro.radian.z = sensor.gyro.origin.z * Gyro_Gr - sensor.gyro.quiet.z * Gyro_Gr;//數(shù)字量轉(zhuǎn)換成模擬量,單位是rad/s // The calibration of acc // if(flag.calibratingA)//加速度計(jì)初始數(shù)據(jù)校準(zhǔn),記錄零偏{static int32_t tempax=0,tempay=0,tempaz=0;static uint8_t cnt_a=0;if(cnt_a==0){sensor.acc.quiet.x = 0;sensor.acc.quiet.y = 0;sensor.acc.quiet.z = 0;tempax = 0;tempay = 0;tempaz = 0;cnt_a = 1;}tempax+= sensor.acc.origin.x;tempay+= sensor.acc.origin.y;tempaz+= sensor.acc.origin.z;if(cnt_a==200){sensor.acc.quiet.x = tempax/cnt_a;sensor.acc.quiet.y = tempay/cnt_a;sensor.acc.quiet.z = tempaz/cnt_a;cnt_a = 0;flag.calibratingA = 0;EE_SAVE_ACC_OFFSET();//保存數(shù)據(jù)return;}cnt_a++; } }這里面的flag.calibratingA通過(guò)翻看其他文件大概了解到是用來(lái)校準(zhǔn)加速度計(jì)的,在遙控的程序中有用到(具體怎么實(shí)現(xiàn)的還沒(méi)有看懂),大致就是通過(guò)遙控命令來(lái)使flag.calibratingA=1,我猜想是在起飛前為了校準(zhǔn)加速度計(jì)通過(guò)人為遙控來(lái)測(cè)量零偏。接下來(lái)就是讀取200次加速度計(jì)在靜止?fàn)顟B(tài)下的測(cè)量值取平均數(shù)來(lái)定義零偏,通過(guò)EE_SAVE_ACC_OFFSET();函數(shù)保存到EEPROM中。
/*====================================================================================================*/ /*====================================================================================================* **函數(shù) : Gyro_OFFSET **功能 : 陀螺儀靜態(tài)采集 **輸入 : None **輸出 : None **備注 : None **====================================================================================================*/ /*====================================================================================================*/ void Gyro_OFFSET(void) {uint16_t cnt_g = 0;int32_t tempgx = GYRO_GATHER;int32_t tempgy = GYRO_GATHER;int32_t tempgz = GYRO_GATHER;int16_t gx_last=0,gy_last=0,gz_last=0;sensor.gyro.quiet.x=0;sensor.gyro.quiet.y=0;sensor.gyro.quiet.z=0;while(tempgx>=GYRO_GATHER || tempgy>=GYRO_GATHER || tempgz>= GYRO_GATHER) //此循環(huán)是確保四軸處于完全靜止?fàn)顟B(tài){tempgx=0;tempgy=0;tempgz=0;cnt_g=30;while(cnt_g--){MPU6050_Read();sensor.gyro.origin.x = ((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]);sensor.gyro.origin.y = ((((int16_t)mpu6050_buffer[10]) << 8)| mpu6050_buffer[11]);sensor.gyro.origin.z = ((((int16_t)mpu6050_buffer[12]) << 8)| mpu6050_buffer[13]);tempgx += absu16(sensor.gyro.origin.x - gx_last);tempgy += absu16(sensor.gyro.origin.y - gy_last);tempgz += absu16(sensor.gyro.origin.z - gz_last);gx_last = sensor.gyro.origin.x;gy_last = sensor.gyro.origin.y;gz_last = sensor.gyro.origin.z;} }tempgx=0;tempgy=0;tempgz=0;cnt_g=2000;while(cnt_g--) //此循環(huán)進(jìn)行陀螺儀標(biāo)定,前提是四軸已經(jīng)處于完全靜止?fàn)顟B(tài){MPU6050_Read();sensor.gyro.origin.x = ((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]);sensor.gyro.origin.y = ((((int16_t)mpu6050_buffer[10]) << 8)| mpu6050_buffer[11]);sensor.gyro.origin.z = ((((int16_t)mpu6050_buffer[12]) << 8)| mpu6050_buffer[13]);tempgx += sensor.gyro.origin.x;tempgy += sensor.gyro.origin.y;tempgz += sensor.gyro.origin.z;}sensor.gyro.quiet.x = tempgx/2000;sensor.gyro.quiet.y = tempgy/2000;sensor.gyro.quiet.z = tempgz/2000; }這里GYRO_GATHER是宏定義設(shè)定好的值為100。具體怎么得到的不太清楚,就理解成設(shè)定的一個(gè)標(biāo)準(zhǔn)吧。第一個(gè)while循環(huán)是用來(lái)確保四軸處于完全靜止?fàn)顟B(tài),大致流程就是采集30次陀螺儀測(cè)量值數(shù)據(jù),并且將每?jī)蓚€(gè)相鄰的數(shù)據(jù)做差后進(jìn)行累加,三個(gè)軸在采集30次數(shù)據(jù)后累加得到的數(shù)據(jù)都小于100(GYRO_GATHER)的話,說(shuō)明陀螺儀處于靜止?fàn)顟B(tài)。那么,就可以進(jìn)行接下來(lái)零偏的計(jì)算了。本次程序是采集2000次數(shù)據(jù)求取平均值作為陀螺儀的零偏量。
結(jié)語(yǔ)
通過(guò)三篇文章已經(jīng)全部完成了MPU6050模塊的學(xué)習(xí),包括寄存器的使用,通過(guò)IIC協(xié)議來(lái)讀寫數(shù)據(jù),對(duì)數(shù)據(jù)處理得到真實(shí)值和傳感器的零偏。接下來(lái),我打算繼續(xù)去了解這些數(shù)據(jù)又是怎樣獲取四軸飛行器的姿態(tài)以及實(shí)現(xiàn)對(duì)四軸飛行器的控制呢?
總結(jié)
以上是生活随笔為你收集整理的关于MPU6050学习的一些总结之三MPU6050程序解读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 解决办法:Call stored pro
- 下一篇: 示波器电源测试交流耦合的陷阱