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