MPU6050学习
這個傳感器學起來還是挺費勁的,找的資料都是參差不齊的,最好的學習方法當然是讀datasheet,當然由于都是英文,有人看的頭大,所以我盡量將datasheet作詳細解釋
參考了幾個帖子,大家可以去看看
阿西莫夫電子論壇:http://www.amobbs.com/thread-5581033-1-1.html?_dsign=5c5b5cde
第七實驗室:https://wenku.baidu.com/view/89db87ac7375a417876f8f6b.html
博主ReCclay:https://blog.csdn.net/ReCclay/article/details/82829280
文章目錄
- MPU6050是什么
- 具體特點
- 原理圖和封裝圖
- 傳感器原理
- MPU6050數據
- 數據組成
- 陀螺儀
- 加速度計
- 讀取原始數據
- 關于IIC
- IIC基礎
- MPU6050的IIC讀寫時序
- 1.1單個字節寫
- 1.2單個字節讀
- 2.1 快速寫
- 2.2 快速讀
- *重要寄存器
- 配置寄存器
- 寄存器107-電源管理寄存器1 地址:0x6B
- 寄存器25-陀螺儀采樣率分頻寄存器 地址:0x19
- 寄存器26- 配置寄存器 地址:0x1A
- 寄存器27- 陀螺儀配置寄存器 地址:0x1B
- 寄存器28- 加速度傳感器配置寄存器 地址:0x1C
- 寄存器35-FIFO使能寄存器 地址:0x23
- 讀取數據地址寄存器(只讀)
- 寄存器67to72-陀螺儀數據輸出寄存器 地址:0x43 to 0x48
- 寄存器59to64-加速度傳感器數據輸出寄存器 地址:0x3B to 0x40
- 寄存器65to66-加速度傳感器數據輸出寄存器 地址:0x41 to 0x42
- MPU讀取原始數據程序
- 數據處理和姿態解算
- 官方DMP移植
- 測試
- 姿態解算
datasheet下載(分 產品介紹和 寄存器介紹兩種)
MPU6050是什么
The MPU-60X0 Motion Processing Unit is the world’s first motion processing solution with integrated 9-Axis
sensor fusion using its field-proven and proprietary MotionFusion? engine for handset and tablet
applications, game controllers, motion pointer remote controls, and other consumer devices. The MPU-60X0
has an embedded 3-axis MEMS gyroscope, a 3-axis MEMS accelerometer, and a Digital Motion
Processor? (DMP?) hardware accelerator engine with an auxiliary I2C port that interfaces to 3rd party digital
sensors such as magnetometers. When connected to a 3-axis magnetometer, the MPU-60X0 delivers a
complete 9-axis MotionFusion output to its primary I2C or SPI port (SPI is available on MPU-6000 only).
(引用自datasheet)
具有三軸MEMS陀螺儀(Gyroscope)、三軸MEMS加速度計(Accelerometer)和數字運動處理器(DMP),也可以通過IIC接口接入第三方傳感器如磁力計組成九軸傳感器,利用iic或spi與主機進行通訊
具體特點
- 數字輸出X、Y和Z軸角速率傳感器(陀螺儀),用戶可編程滿刻度范圍為±250、±500、±1000和±2000°/sec。
- 集成16位ADC可同時對陀螺儀進行采樣。
- 數字輸出三軸加速度計,可編程滿刻度范圍為±2g、±4g、±8g和±16g
- 集成16位ADC可在不需要外部設備的情況下對加速度計進行同步采樣。
- 以數字形式輸出 6 軸或 9 軸(需外接磁傳感器)的旋轉矩陣、四元數
(quaternion)、歐拉角格式的融合演算數據(需 DMP 支持)。 - 自帶數字運動處理(DMP: Digital Motion Processing)引擎可減少 MCU 復雜
的融合演算數據、感測器同步化、姿勢感應等的負荷
原理圖和封裝圖
傳感器原理
https://www.cnblogs.com/Jeanco/p/8966407.html
https://wenku.baidu.com/view/89db87ac7375a417876f8f6b.html
傳感器參考坐標系(正向用右手螺旋定律)
MPU6050數據
對于這類傳感器,我們需要了解的分別是它的數據組成和如何讀取數據
數據組成
陀螺儀
陀螺儀直接輸出的是角速度,角速度是指物體在單位時間內轉過的角度大小,對角速度積分可以得到角度。
數字輸出X、Y和Z軸角速率傳感器(陀螺儀),用戶可編程滿刻度范圍為±250、±500、±1000和±2000°/sec。
集成16位ADC可同時對陀螺儀進行采樣。
以上信息可以得到,陀螺儀的量程有±250、±500、±1000和±2000°/sec這四個,同時用16位數據存儲
因為16位數據就是2的十六次方也就是65536,由于最高位在這為符號位,所以相當于-7FFF,即-32767,最大的數是7FFF,即32767。
如果全量程(Full-Scale Range)是±250,對應著32767,也就是一個刻度就是32767/250=131,也就是上面的靈敏度比例因子(Sensitivity Scale Factor)
把從陀螺儀讀出的數字除以131,就可以換算成陀螺儀的角速度數值。
加速度計
加速度計輸出的是傾斜角。
分析方法同以上的陀螺儀,當AFS_SEL=0時,數字-32767對應-2g,32767對應2g。把32767除以2,就可以得到16384, 即靈敏度比例因子。把從加速度計讀出的數字除以16384,就可以換算成加速度的數值。舉個例子,如果我們從加速度計讀到的數字是1000,那么對應的加速度數據是1000/16384=0.49g。g為加速度的單位,重力加速度定義為1g, 等于9.8米每平方秒。
讀取原始數據
數據讀取用的是iic協議
MPU6050有專門講寄存器的datasheet
MPU系統框圖
關于IIC
IIC基礎
IIC協議是一種常見的通訊協議
分軟件IIC和硬件IIC
軟件IIC就是通過GPIO,軟件模擬寄存器的工作方式,硬件(固件)I2C是直接調用內部寄存器進行配置。
這個網絡學習資源一大把,隨便找個看看就行了
貼個教程:https://blog.csdn.net/lingdongtianxia/article/details/81135456
這里給一個51常用的軟件IIC程序
MPU6050的IIC讀寫時序
1.1單個字節寫
步驟:開始信號–>發送地址位+發送一個 R/W 位(0 寫,1 讀)–>等待應答–>發送寄存器地址–>等待應答–>發送數據–>等待應答–>結束信號
代碼
1.2單個字節讀
步驟:開始信號–>發送地址位+發送一個 R/W 位(0 寫,1 讀)–>等待應答–>發送寄存器地址–>等待應答–>開始信號–>發送地址位+發送一個 R/W 位(0 寫,1 讀)–>等待應答–>讀取數據–>不應答–>結束信號
代碼
2.1 快速寫
2.2 快速讀
*重要寄存器
配置寄存器
寄存器107-電源管理寄存器1 地址:0x6B
宏定義
#define PWR_MGMT_1 0x6B //電源管理,典型值:0x00(正常啟用)
詳細介紹:
DEVICE_RESET 位用來控制復位,設置為 1,復位 MPU6050,復位結束后, MPU硬件自動清零該位
SLEEEP 位用于控制 MPU6050 的工作模式,復位后,該位為 1,即進
入了睡眠模式(低功耗),所以我們要清零該位,以進入正常工作模式
TEMP_DIS 用于設置是否使能溫度傳感器,設置為 0,則使能
CLKSEL[2:0] 用于選擇系統時鐘源,選擇關系如表
翻譯以下
| 000 | 內部 8M RC 晶振 |
| 001 | PLL,使用X軸陀螺儀作為參考 |
| 010 | PLL,使用Y軸陀螺儀作為參考 |
| 011 | PLL,使用Z軸陀螺儀作為參考 |
| 100 | PLL,使用外部32.768khz作為參考 |
| 101 | PLL,使用外部19.2Mhz作為參考 |
| 110 | 保留 |
| 111 | 關閉時鐘,保持時序產生電路復位狀態 |
默認是使用內部 8M RC 晶振的,精度不高,所以我們一般選擇 X/Y/Z 軸陀螺作為參考的PLL 作為時鐘源,一般設置 CLKSEL=001 即可
寄存器25-陀螺儀采樣率分頻寄存器 地址:0x19
宏定義
#define SMPLRT_DIV 0x19 //陀螺儀采樣率,典型值:0x07(125Hz)
相關配置:
該寄存器用于設置 MPU6050 的陀螺儀采樣頻率,計算公式為:
采樣頻率 = 陀螺儀輸出頻率 / (1+SMPLRT_DIV)
這里陀螺儀的輸出頻率,是 1Khz 或者 8Khz,與數字低通濾波器( DLPF)的設置有關,當 DLPF_CFG=0/7 的時候,頻率為 8Khz,其他情況是 1Khz。而且 DLPF 濾波頻率一般設置 為采樣率的一半。采樣率,我們假定設置為 125Hz,那么 SMPLRT_DIV=1000/150-1=7
寄存器26- 配置寄存器 地址:0x1A
宏定義
#define CONFIG 0x1A //低通濾波頻率,典型值:0x06(5Hz)
相關配置:
數字低通濾波器( DLPF)的設置位,即: DLPF_CFG[2:0],加速
度計和陀螺儀,都是根據這三個位的配置進行過濾的。 DLPF_CFG 不同配置對應的過濾情況如表:
這里的加速度傳感器,輸出速率( Fs)固定是 1Khz,而角速度傳感器的輸出速率( Fs),
則根據 DLPF_CFG 的配置有所不同。一般我們設置角速度傳感器的帶寬為其采樣率的一半,
如前面所說的,如果設置采樣率為 50Hz,那么帶寬就應該設置為 25Hz,取近似值 20Hz,
就應該設置 DLPF_CFG=100
寄存器27- 陀螺儀配置寄存器 地址:0x1B
宏定義
#define GYRO_CONFIG 0x1B //陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s)
相關配置:
FS_SEL[1:0]這兩個位,用于設置陀螺儀的滿量程范圍:
0,±250° /S
1,±500° /S
2,±1000° /S
3,±2000° /S
我們一般設置為 3,即±2000° /S,因
為陀螺儀的 ADC 為 16 位分辨率,所以得到靈敏度為: 65536/4000=16.4LSB/(° /S)
寄存器28- 加速度傳感器配置寄存器 地址:0x1C
宏定義
#define ACCEL_CONFIG 0x1C //加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)
相關配置:
AFS_SEL[1:0]這兩個位,用于設置加速度傳感器的滿量程范圍:
0, ±2g;
1,±4g;
2,±8g;
3,±16g;
我們一般設置為 0,即±2g,因為加速度傳感器的
ADC 也是 16 位,所以得到靈敏度為: 65536/4=16384LSB/g
寄存器35-FIFO使能寄存器 地址:0x23
宏定義
#define FIFO_EN 0x23
相關配置:
該寄存器用于控制 FIFO 使能,在簡單讀取傳感器數據的時候,可以不用 FIFO,設置
對應位為 0 即可禁止 FIFO,設置為 1,則使能 FIFO
加速度傳感器的 3 個軸,全由 1 個位( ACCEL_FIFO_EN)控制,只要該位置 1,則加速度傳感器的三個通道都開啟 FIFO
讀取數據地址寄存器(只讀)
寄存器67to72-陀螺儀數據輸出寄存器 地址:0x43 to 0x48
宏定義
#define GYRO_XOUT_H 0x43 //陀螺儀X軸高八位數據地址 #define GYRO_XOUT_L 0x44 //陀螺儀X軸低八位數據地址 #define GYRO_YOUT_H 0x45 //陀螺儀Y軸高八位數據地址 #define GYRO_YOUT_L 0x46 //陀螺儀Y軸低八位數據地址 #define GYRO_ZOUT_H 0x47 //陀螺儀Z軸高八位數據地址 #define GYRO_ZOUT_L 0x48 //陀螺儀Z軸低八位數據地址
通過讀取這6個寄存器,就可以讀到陀螺儀 x/y/z 軸的值,比如 x 軸的數據,可以通過讀取
0X43(高 8 位)和 0X44(低 8 位)寄存器得到,其他軸以此類推
寄存器59to64-加速度傳感器數據輸出寄存器 地址:0x3B to 0x40
宏定義
#define ACCEL_XOUT_H 0x3B //加速度計X軸高八位數據地址 #define ACCEL_XOUT_L 0x3C //加速度計X軸低八位數據地址 #define ACCEL_YOUT_H 0x3D //加速度計Y軸高八位數據地址 #define ACCEL_YOUT_L 0x3E //加速度計Y軸低八位數據地址 #define ACCEL_ZOUT_H 0x3F //加速度計Z軸高八位數據地址 #define ACCEL_ZOUT_L 0x40 //加速度計Z軸地八位數據地址
通過讀取這6個寄存器,就可以讀到加速度傳感器 x/y/z 軸的值,比如讀 x 軸的數據,可以通過讀取 0X3B(高 8 位)和0X3C(低8位)寄存器得到,其他軸以此類推
寄存器65to66-加速度傳感器數據輸出寄存器 地址:0x41 to 0x42
宏定義
#define TEMP_OUT_H 0x41 //溫度傳感器高八位數據 #define TEMP_OUT_L 0x42 //溫度傳感器低八位數據溫度傳感器的值,可以通過讀取 0X41(高 8 位)和 0X42(低 8 位)寄存器得到,
溫度換算公式為:
Temperature = 36.53 + regval/340
其中, Temperature 為計算得到的溫度值,單位為℃,regval 為從 0X41 和 0X42 讀到的溫度傳感器值
以上就是寄存器的內容
總結一下所有的
宏定義
MPU讀取原始數據程序
51版
//************************************** //初始化MPU6050 //************************************** void InitMPU6050() {Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠狀態Single_WriteI2C(SMPLRT_DIV, 0x07); //配置陀螺儀采樣率Single_WriteI2C(CONFIG, 0x06); //配置低通濾波頻率Single_WriteI2C(GYRO_CONFIG, 0x18); //配置陀螺儀自檢及測量范圍Single_WriteI2C(ACCEL_CONFIG, 0x01); //配置加速計自檢、測量范圍及高通濾波頻率 } //************************************** //合成數據 //************************************** int GetData(u8 REG_Address) {u8 H,L;H=Single_ReadI2C(REG_Address);L=Single_ReadI2C(REG_Address+1);return (H<<8)+L; //合成數據 } //顯示函數 void Display10BitData(int value,u8 x,u8 y) { u8 i; // value/=64; //轉換為10位數據lcd_printf(dis, value); //轉換數據顯示 // for(i=0;i<6;i++) // { // printf(dis);//發送到串口 // }OLED_ShowString(x,y,dis,16);// DisplayListChar(x,y,dis,4); //啟始列,行,顯示數組,顯示長度 } void main() {delay(500);Config_UARTimer(9600);//串口配置OLED_Init();//oled初始化InitMPU6050();//mpu初始化while(1){OLED_Clear();//清屏Display10BitData(GetData(ACCEL_XOUT_H),0,0); //顯示X軸加速度Display10BitData(GetData(ACCEL_YOUT_H),64,0); //顯示Y軸加速度Display10BitData(GetData(ACCEL_ZOUT_H),0,2); //顯示Z軸加速度Display10BitData(GetData(GYRO_XOUT_H),0,4); //顯示X軸角速度Display10BitData(GetData(GYRO_YOUT_H),64,4); //顯示Y軸角速度Display10BitData(GetData(GYRO_ZOUT_H),0,6); //顯示Z軸角速度}顯示效果
至此,原始數據就已經讀出來了
stm32版程序
數據處理和姿態解算
原始數據于我們來說是毫無用途的,我們要進行轉換,將原始數據轉換成姿態數據
有兩個方法,
一個是通過數學公式,將原始數據計算出姿態數據
第二個是用MPU6050內部的DMP,從這里讀取數據出來
對于我當然是選擇后者了,當然更推薦后者,因為DMP可以對數據進行濾波,同時節省主控芯片的算力
官方DMP移植
官方DMP程序
網上稍微百度一下應該就找到了
這里給一個鏈接提供下載
鏈接:https://pan.baidu.com/s/15eU8zVXgvFWeERb7KjgJNw 密碼:rkw9
這里官方DMP給的是基于msp430的代碼,對于我們要把它改成基于stm32的,本來我是打算自己改的,參照小馬哥的,主要是改一些調用函數的接口,和一些函數的格式
https://www.moore8.com/courses/trainning_playback/1405
但是后來看到了正點原子官方有改過的,還改什么,直接拉過來用了。
接口程序下載
鏈接:https://pan.baidu.com/s/1m9J2JO3xnO2dbyihcfqIxg 密碼:n1gx
由于程序比較多,所以這里就不全都貼出來了
只貼關鍵的代碼
inv_mpu.c
這里將iic接口換成自己的接口,和正點原子的iic程序配套,所以不用動
在這個文件里加了兩個函數,主要也就是用這兩個函數
mpu6050.c
這個文件里就放著我上面說的那些,主要是初始化MPU6050,和獲取原始數據用的
初始化
獲取原始數據-角速度,角加速度,溫度
//得到溫度值(原始值) short MPU_Get_Temperature(void) {u8 buf[2]; short raw;float temp;MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); raw=((u16)buf[0]<<8)|buf[1]; temp=36.53+((double)raw)/340; return temp*100;; } //得到陀螺儀原始值 u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz) {u8 buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);if(res==0){*gx=((u16)buf[0]<<8)|buf[1]; *gy=((u16)buf[2]<<8)|buf[3]; *gz=((u16)buf[4]<<8)|buf[5];} return res;; } //得到加速度原始值 u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az) {u8 buf[6],res; res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);if(res==0){*ax=((u16)buf[0]<<8)|buf[1]; *ay=((u16)buf[2]<<8)|buf[3]; *az=((u16)buf[4]<<8)|buf[5];} return res;; }測試
準備好OLED或者LCD接口代碼
首先,測試OLED正常
第二步,確認串口沒問題
注:不要嫌麻煩,一個模塊一個模塊的確認是最保險的方式
第三步:獲取數據通過串口發出
現在獲得的都是姿態數據了
然后顯示到OLED上
姿態解算
姿態數據得到之后,就是對數據進行處理
總結
- 上一篇: 51单片机常用知识点总结
- 下一篇: stm32之端口复用和重映射