1. 簡(jiǎn)介
MPU6050 是 InvenSense 公司推出的整合性 6 軸運(yùn)動(dòng)處理組件,其內(nèi)部整合了 3 軸陀螺儀和 3 軸加速度傳感器,并且含有一個(gè)IIC 接口, 可用于連接外部磁力傳感器,并利用自帶的數(shù)字運(yùn)動(dòng)處理器(DMP: Digital Motion Processor) 硬件加速引擎,通過(guò)主 IIC 接口,向應(yīng)用端輸出完整的 9 軸融合演算數(shù)據(jù)。
InvenSense 公司提供了一套基于DMP的運(yùn)動(dòng)處理驅(qū)動(dòng)庫(kù),可大大降低單片機(jī)對(duì)動(dòng)處理運(yùn)算的負(fù)荷,同時(shí)也大大降低了編程難度。該模塊廣泛運(yùn)用于飛控、計(jì)步等電子產(chǎn)品中。
1.1 模塊原理圖
1.2 引腳說(shuō)明
序號(hào) | 引腳 | 說(shuō)明 |
---|---|---|
1 | VCC | 3.3V/5V |
2 | GND | 地線 |
3 | SCL | 作為從機(jī)時(shí) IIC 時(shí)鐘線 |
4 | SDA | 作為從機(jī)時(shí) IIC 數(shù)據(jù)線 |
5 | XDA | 作為主機(jī)時(shí) IIC 數(shù)據(jù)線 |
6 | XCL | 作為主機(jī)時(shí) IIC 時(shí)鐘線 |
7 | AD0 | 作為從機(jī)時(shí) IIC 地址 |
8 | INT | 中斷輸出引腳 |
XDA和XCL是在MPU6050作為主機(jī)時(shí)的信號(hào)線,在與單片機(jī)的IIC通信中,MPU6050作為從機(jī),所以用不到
AD0 是從 IIC 接口(接 MCU)的地址控制引腳,該引腳控制IIC 地址的最低位。由原理圖可知,AD0 接了 GND,所以 MPU6050 的 IIC 地址默認(rèn)為:0X68
INT也用不到,當(dāng)模塊需要輸出數(shù)據(jù)時(shí),可以通過(guò)該引腳給單片機(jī)中斷信號(hào),一般都不需要
1.3 接線方式
單片機(jī) —— MPU6050
5V <——> VCC
GND <——> GND
Px.x <——> SCL
Px.x <——> SDA
2. IIC通信
如果你學(xué)過(guò)一段時(shí)間單片機(jī),你或多或少會(huì)聽(tīng)說(shuō)過(guò)IIC通信(也寫(xiě)作I2C,通常讀作:I方C),這是硬件開(kāi)發(fā)里很常見(jiàn)、很常用的一種通信協(xié)議。
其實(shí)協(xié)議并不是聽(tīng)上去的那么高不可攀,它終究是人為定義的一個(gè)標(biāo)準(zhǔn)而已,我們只需遵循這個(gè)標(biāo)準(zhǔn)就可以了。
這里面的協(xié)議層會(huì)涉及到時(shí)序,如果你還不是“老司機(jī)”,暫且可以放下不去專研,因?yàn)檫@些都會(huì)被封裝為函數(shù),使用格式也非常固定,完全不必?fù)?dān)心。比如通信中最頻繁的 讀寫(xiě)操作 ,會(huì)被封裝成 IIC讀/寫(xiě)函數(shù) ,而讀寫(xiě)只能算是最基礎(chǔ)的操作,還可以利用它進(jìn)一步封裝成各種設(shè)置函數(shù)和數(shù)據(jù)采集函數(shù)。
2.1 IIC介紹
I2C(Inter-Integrated Circuit)總線是由 PHILIPS 公司開(kāi)發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。是微電子通信控制領(lǐng)域廣泛采用的一種總線標(biāo)準(zhǔn)。它是 同步通信的一種特殊形式,具有接口線少,控制方式簡(jiǎn)單, 器件封裝形式小,通信速率較高等優(yōu)點(diǎn)。 I2C 總線 只有 兩根雙向信號(hào)線 。一根是 數(shù)據(jù)線 SDA ,另一根是 時(shí)鐘線 SCL 。由于其管腳少,硬件實(shí)現(xiàn)簡(jiǎn)單,可擴(kuò)展性強(qiáng)等特點(diǎn),因此被廣泛的使用在各大集成芯片內(nèi)。
2.2 例程講解
開(kāi)發(fā)資料中的例程代碼雖然很多,但最后在main函數(shù)里對(duì)MPU6050操作的只有兩個(gè)函數(shù),其他函數(shù)大多作為這兩個(gè)函數(shù)的內(nèi)容。其實(shí),對(duì)于這種不小的工程項(xiàng)目,我們往往會(huì)寫(xiě)成多個(gè)文件,方便查看和使用,這就涉及到了工程項(xiàng)目的管理,后續(xù)可能還會(huì)出一篇教程 (>﹏<)
// 初始化MPU6050
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); // #define PWR_MGMT_1 0x6B
Single_WriteI2C(SMPLRT_DIV, 0x07); // #define SMPLRT_DIV 0x19
Single_WriteI2C(CONFIG, 0x06); // #define CONFIG 0x1A
Single_WriteI2C(GYRO_CONFIG, 0x18); // #define GYRO_CONFIG 0x1B
Single_WriteI2C(ACCEL_CONFIG, 0x01);// #define ACCEL_CONFIG 0x1C
}
// 合成數(shù)據(jù)
int GetData(uchar REG_Address)
{
uchar H,L;
H=Single_ReadI2C(REG_Address); // 相應(yīng)寄存器地址
L=Single_ReadI2C(REG_Address+1);
return ((H<<8)+L);
}
InitMPU6050 可以初始化模塊,函數(shù)里對(duì)MPU6050的各個(gè)寄存器寫(xiě)入?yún)?shù),從而實(shí)現(xiàn)初始化的功能,如果你想了解寄存器內(nèi)部的配置原理,可以根據(jù)寄存器地址找到它的數(shù)據(jù)手冊(cè)上對(duì)應(yīng)的說(shuō)明
GetData 可以返回采集的數(shù)據(jù),值得注意的是這里得到數(shù)據(jù)不是角度,還需要進(jìn)一步融合數(shù)據(jù)才能解算出姿態(tài)角
3. 姿態(tài)解算
3.1 歐拉角
歐拉角是最直觀的一種姿態(tài)描述方式,所以在談到姿態(tài)時(shí),我們往往會(huì)使用歐拉角表達(dá)
一個(gè)坐標(biāo)系到另一個(gè)坐標(biāo)系的變換,可以通過(guò)繞不同坐標(biāo)軸的3次連續(xù)轉(zhuǎn)動(dòng)來(lái)實(shí)現(xiàn)。這三次的轉(zhuǎn)動(dòng)角度統(tǒng)一稱之為歐拉角
-
偏航角(Yaw)
機(jī)體系x軸投影到水平面與參考系x軸的夾角,順時(shí)針旋轉(zhuǎn)為正。 -
俯仰角(Pitch)
機(jī)體系x軸與水平面的夾角,抬頭為正。 -
橫滾角(Roll)
機(jī)體坐標(biāo)系z(mì)軸與通過(guò)機(jī)體系x軸的鉛垂面間的夾角,機(jī)體右旋為正。
3.2 解算方法
上面得到數(shù)據(jù)只是10位原始數(shù)據(jù),我們需要把原始數(shù)據(jù)融合成與姿態(tài)有關(guān)的
歐拉角
這里有兩種方法:
第一種是自己添加濾波算法,常用的有一階互補(bǔ)濾波、二階互補(bǔ)濾波和卡爾曼濾波等
第二種是直接使用MPU6050內(nèi)部的DMP
DMP 是什么意思? DMP 就是指 MPU6050 內(nèi)部集成的處理單元,可以直接運(yùn)算出四元數(shù)和姿態(tài),而不再需要另外進(jìn)行數(shù)學(xué)運(yùn)算。DMP 的使用大大簡(jiǎn)化了四軸的代碼設(shè)計(jì)。DMP 是數(shù)字運(yùn)動(dòng)處理器的縮寫(xiě),顧名思義 mpu6050 并不單單是一款傳感器,其內(nèi)部還包含了可以獨(dú)立完成姿態(tài)解算算法的處理單元。如在設(shè)計(jì)中使用 DMP 來(lái)實(shí)現(xiàn)傳感器融合算法優(yōu)勢(shì)很明顯。首先,invensense 官方提供的姿態(tài)解算算法應(yīng)該比像我們自己寫(xiě)的要可靠得多。其次,由 DMP 實(shí)現(xiàn)姿態(tài)解算算法將單片機(jī)從算法處理的壓力中解放出來(lái),單片機(jī)所要做的是等待DMP 解算完成后產(chǎn)生的外部中斷,在外部中斷里去讀取姿態(tài)解算的結(jié)果。這樣單片機(jī)有大量的時(shí)間來(lái)處理其他任務(wù),提高了系統(tǒng)的實(shí)時(shí)性
經(jīng)過(guò) DMP 你就可以得到四元數(shù),四元數(shù)就是 4 個(gè)數(shù),可以表征姿態(tài),經(jīng)過(guò)幾個(gè)數(shù)學(xué)公式之后就可以得出姿態(tài),姿態(tài)包括 pitch,roll,yaw
下面介紹的是第一種方法的一階互補(bǔ)濾波,因?yàn)?1單片機(jī)對(duì)DMP的幾個(gè)庫(kù)函數(shù)不太兼容,或許后面會(huì)嘗試解決并出教程 ╮(╯_╰)╭ ,而第一種算法網(wǎng)上有不少案例,實(shí)際使用上,兩種方法對(duì)于初學(xué)者的難度都差不多
3.3 一階互補(bǔ)濾波
需要注意的是,以下代碼只能得到俯仰和滾轉(zhuǎn)的數(shù)據(jù),偏航角(Yaw)由于偏差太大沒(méi)有輸出值
以下代碼不是完整的,還需要使用開(kāi)發(fā)資料中的例程
//*******************************************************************************************************
//主程序
//*******************************************************************************************************
void main()
{
unsigned int time; // 保存定時(shí)器計(jì)數(shù)值
float halfT; // 每次采樣的時(shí)間
int Ax,Ay,Az,Gx,Gy,Gz; // 加速度計(jì)和陀螺儀的原始數(shù)據(jù)
unsigned long Gravity;
float AngleX1,AngleY1,AngleZ1,AngleX2,AngleY2,AngleZ2=0,dx,dy,dz;
float Filter;
Filter=0.8; //互補(bǔ)濾波系數(shù)
delay(500); //上電延時(shí)
init_uart();
InitMPU6050(); 初始化MPU6050
delay(150);
while(1)
{
Ax=GetData(ACCEL_XOUT_H);
Ay=GetData(ACCEL_YOUT_H);
Az=GetData(ACCEL_ZOUT_H);
Gx=GetData(GYRO_XOUT_H);
Gy=GetData(GYRO_YOUT_H);
Gz=GetData(GYRO_ZOUT_H);
TR0 = 0;
time = (TH0<<8)|TL0;
halfT = (time/1000000.)*(12/11.0592);
// Display10BitData((int)(halfT*1000000)); //顯示采樣時(shí)間
TH0 = 0;
TL0 = 0;
TR0 = 1;
Gravity=sqrt((float)Ax*Ax+(float)Ay*Ay+(float)Az*Az); //Ax*Ax+Ay*Ay+Az*Az
AngleX1=acos((float)Ax/Gravity)*180.0/3.14-90;;
AngleY1=acos((float)Ay/Gravity)*180.0/3.14-90;
AngleZ1=acos((float)Az/Gravity)*180.0/3.14;
dy=halfT*Gx/-16.4; //陀螺儀測(cè)的轉(zhuǎn)角y
dx=halfT*Gy/16.4; //陀螺儀測(cè)的轉(zhuǎn)角x
dz=halfT*Gz/16.4; //陀螺儀測(cè)的轉(zhuǎn)角z
//x和y軸數(shù)據(jù)是融合加速度計(jì)和陀螺儀數(shù)據(jù), z軸只采用陀螺儀數(shù)據(jù)
AngleX2=Filter*(AngleX2+dx)+(1-Filter)*AngleX1;
AngleY2=Filter*(AngleY2+dy)+(1-Filter)*AngleY1;
// z軸數(shù)據(jù)有兩種方式,一種是只使用陀螺儀的數(shù)據(jù),舍棄z軸加速度(z軸零飄嚴(yán)重):
AngleZ2=AngleZ2+dz; // 注意MPU6050必須芯片正面朝上
SeriPushSend(0x20);SeriPushSend('X'); SeriPushSend(':');
Display10BitData((int)AngleX2); //顯示X軸角度
SeriPushSend(0x20);SeriPushSend('Y'); SeriPushSend(':');
Display10BitData((int)AngleY2); //顯示Y軸角度
SeriPushSend(0x20);SeriPushSend('Z'); SeriPushSend(':');
Display10BitData((int)AngleZ2); //顯示Z軸角度
SeriPushSend(0x0d);
SeriPushSend(0x0a);//換行,回車
delay(500); // 控制采樣頻率
}
}
4. 串口通信
4.1 概念
串行通訊是指僅用一根接收線和一根發(fā)送線就能將數(shù)據(jù)以位進(jìn)行傳輸?shù)囊环N通訊方式。盡管串行通訊的比按字節(jié)傳輸?shù)牟⑿型ㄐ怕谴诳梢栽趦H僅使用兩根線的情況下就能實(shí)現(xiàn)數(shù)據(jù)的傳輸
典型的串口通信使用3根線完成,分別是地線、發(fā)送、接收。由于串口通信是異步的,所以端口能夠在一根線上發(fā)送數(shù)據(jù)同時(shí)在另一根線上接收數(shù)據(jù)。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶的校驗(yàn)。對(duì)于兩個(gè)需要進(jìn)行串口通信的端口,這些參數(shù)必須匹配,這也是能夠?qū)崿F(xiàn)串口通訊的前提
我們使用的STC89C516RD+內(nèi)部集成有一個(gè)串行通信口,使用時(shí)只需配置波特率、工作方式和中斷開(kāi)關(guān),因?yàn)檫@塊內(nèi)容比較吃單片機(jī)前面的中斷和定時(shí)器的基礎(chǔ),所以沒(méi)掌握也無(wú)須擔(dān)心,這些都有比較固定的初始化模板,直接使用例程提供的函數(shù)即可
4.2 串口顯示姿態(tài)角
代碼下載到單片機(jī)內(nèi)之后,使用串口助手顯示數(shù)據(jù)
4.3 接線圖
上電時(shí),MPU6050的綠色電源指示燈亮起,程序下載完成后,串口模塊會(huì)有LED一直閃爍,表示串口通信正在工作文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-633172.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-633172.html
到了這里,關(guān)于單片機(jī)開(kāi)發(fā)教程3——串口發(fā)送MPU6050姿態(tài)角的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!