小伙伴們大家好,好久不更新RT-Thread實戰筆記啦,今天來搞一搞MPU6050,話不多說,淦!
本章源碼獲取
歡迎在“小飛哥嵌入式”公眾號后臺回復“MPU6050”即可獲取本教程源碼
MPU6050簡介
某寶買的,吃灰許久了...
有錢,不想受那鳥氣的,看這個,自己畫一個,對比價格,我勸你買個吧,知道自己行就行了...
典型用法:
可在官網下載最新的芯片手冊和寄存器映射和描述,參看:MPU6050 官網
基本功能:
MPU-60X0是世界上第一款集成 6 軸MotionTracking設備。它集成了3軸MEMS陀螺儀,3軸MEMS加速度計,以及一個可擴展的數字運動處理器 DMP( DigitalMotion Processor),可用I2C接口連接一個第三方的數字傳感器,比如磁力計。擴展之后就可以通過其 I2C或SPI接口輸出一個9軸的信號( SPI接口僅在MPU-6000可用)。MPU-60X0也可以通過其I2C接口連接非慣性的數字傳感器,比如壓力傳感器。
MPU-60X0對陀螺儀和加速度計分別用了三個16位的ADC,將其測量的模擬量轉化為可輸出的數字量。為了精確跟蹤快速和慢速的運動,傳感器的測量范圍都是用戶可控的,陀螺儀可測范圍為±250, ±500, ±1000, ±2000°/秒( dps),加速度計可測范圍為±2, ±4,±8, ±16g。
一個片上1024字節的FIFO,有助于降低系統功耗。和所有設備寄存器之間的通信采用 400kHz的 I2C接口或 1MHz的 SPI接口( SPI僅MPU-6000可用)。對于需要高速傳輸的應用, 對寄存器的讀取和中斷可用 20MHz的SPI。另外,片上還內嵌了一個溫度傳感器和在工作環境下僅有±1%變動的振蕩器。芯片尺寸4×4×0.9mm,采用QFN封裝(無引線方形封裝),可承受最大 10000g的沖擊,并有可編程的低通濾波器。
關于電源, MPU-60X0可支持 VDD范圍 2.5V±5%, 3.0V±5%,或 3.3V±5%。另外MPU-6050還有一個 VLOGIC引腳,用來為 I2C輸出提供邏輯電平。VLOGIC電壓可取1.8±5%或者VDD。
系統結構圖:
通信接口:
MPU-60X0使用 SPI(僅MPU-6000)或 I2C 串行通信至系統處理器接口。與系統處理器通信時,MPU-60X0始終充當從屬設備。LSB的 I2C 從地址的地址由引腳9(AD0)設置(一般接地),本次采用的是IIC的通訊方式,順便學習一下rt-thread的IIC設備驅動。
六軸,代表的是它內置了一個三軸 MEMS 陀螺儀、一個三軸 MEMS 加速度計,一個數字運動處理引擎(DMP)。它還有用于第三方的數字傳感器接口的輔助 I2C 串行接口,比如當輔助 I2C 串行接口連接到一個三軸磁力計,MPU6050 能提供一個完整的九軸融合輸出到其主 I2C 端口。
下圖標明了傳感器的參考坐標系( XYZ組成右手系)以及 3個測量軸和旋轉方向。
旋轉的正向可用右手螺旋定則判斷
數字運動處理器(DMP):
DMP就是MPU6050內部的運動引擎,全稱Digital Motion Processor,直接輸出四元數,可以減輕外圍微處理器的工作負擔且避免了繁瑣的濾波和數據融合。Motion Driver是Invensense針對其運動傳感器的軟件包,并非全部開源,核心的算法部分是針對ARM處理器和MSP430處理器編譯成了靜態鏈接庫,適用于MPU6050、MPU6500、MPU9150、MPU9250等傳感器。
FIFO
MPU-60X0包含一個可通過串行接口訪問的1024字節FIFO寄存器。FIFO配置寄存器決定哪個數據寫入FIFO。可能的選擇包括陀螺儀數據,加速計數據,溫度讀數,輔助傳感器讀數和 FSYNC 輸入。FIFO 計數器跟蹤 FIFO 中包含的有效數據字節數。FIFO寄存器支持突發讀取。中斷功能可用于確定新數據何時可用。
MPU6050的涉及的東西還是很多的,小飛哥也只是簡單了解了一些,小伙伴們可以查看手冊或者百度,很多優秀的介紹,就不再啰嗦啦
rt-thread軟件包使用
硬件連接
小飛哥使用的是ART-PI及ART-PI擴展板(12月份即將開源發布)
使用到的引腳為:
MCU | MPU6050 |
---|---|
3.3V | VCC |
GND | GND |
PI2 | SDA |
PI1 | SCL |
小伙伴們可以還根據自己的MCU及使用到的引腳,模擬的IIC,自己看著選就可以啦
硬件連接OK
軟件編寫
介紹2兩種方式,一種是使用rt-thread平臺軟件包獲取MPU6050的數據,自己解算,另一種就是移植DMP庫進行解算,小飛哥用的是移植的DMP庫來解算的。
- rtt軟件包使用
選擇MPU6050軟件包
然后選擇模擬IIC,可以使用IIC3,也可以使用其他的,和軟件包選用的統一就OK了
設置完成之后,ctrl+S保存即可,軟件包自動就下載添加進來了
接下來編寫讀取函數,直接調用已經封裝好的接口即可
先注冊設備,初始化
i2c_bus=(structmpu6xxx_device*)mpu6xxx_init(MPU6050_I2C_BUS_NAME,MPU6050_ADDR);//初始化MPU6050,測量單位為角速度,加速度while(count++)
mpu6xxx_set_param(i2c_bus,MPU6XXX_ACCEL_RANGE,MPU6XXX_GYRO_RANGE_2000DPS);//陀螺儀范圍配置
mpu6xxx_set_param(i2c_bus,MPU6XXX_ACCEL_RANGE,MPU6XXX_ACCEL_RANGE_2G);//加速度計,一般設置為±2G
mpu6xxx_set_param(i2c_bus,MPU6XXX_SAMPLE_RATE,50);//采樣頻率
mpu6xxx_set_param(i2c_bus,MPU6XXX_DLPF_CONFIG,25);//數字低通濾波器設置,一般為1/2采樣率
然后調用接口:
mpu6xxx_get_gyro(i2c_bus,&gyro);
sprintf(str,"gyro.x=%d
",gyro.x);
rt_kprintf(str);
sprintf(str,"gyro.y=%d
",gyro.y);
rt_kprintf(str);
sprintf(str,"gyro.z=%d
",gyro.z);
rt_kprintf(str);
mpu6xxx_get_accel(i2c_bus,&accel);
sprintf(str,"accel.x=%d
",accel.x);
rt_kprintf(str);
sprintf(str,"accel.y=%d
",accel.y);
rt_kprintf(str);
sprintf(str,"accel.z=%d
",accel.z);
rt_kprintf(str);
運行結果:
來看一下,這兩個函數的內部封裝:
/**
*Thisfunctiongetsthedataofthegyroscope,unit:deg/10s
*Heredeg/10smeans10timeshigherprecisionthandeg/s.
*
*@paramdevthepointerofdevicedriverstructure
*@paramgyrothepointerof3axesstructureforreceivedata
*
*@returnthereadingstatus,RT_EOKreprensentsreadingthedatasuccessfully.
*/
rt_err_tmpu6xxx_get_gyro(structmpu6xxx_device*dev,structmpu6xxx_3axes*gyro)
{
structmpu6xxx_3axestmp;
rt_uint16_tsen;
rt_err_tres;
res=mpu6xxx_get_gyro_raw(dev,&tmp);
if(res!=RT_EOK)
{
returnres;
}
sen=MPU6XXX_GYRO_SEN>>dev->config.gyro_range;
gyro->x=(rt_int32_t)tmp.x*100/sen;
gyro->y=(rt_int32_t)tmp.y*100/sen;
gyro->z=(rt_int32_t)tmp.z*100/sen;
returnRT_EOK;
}
/**
*Thisfunctiongetsthedataoftheaccelerometer,unit:mg
*
*@paramdevthepointerofdevicedriverstructure
*@paramaccelthepointerof3axesstructureforreceivedata
*
*@returnthereadingstatus,RT_EOKreprensentsreadingthedatasuccessfully.
*/
rt_err_tmpu6xxx_get_accel(structmpu6xxx_device*dev,structmpu6xxx_3axes*accel)
{
structmpu6xxx_3axestmp;
rt_uint16_tsen;
rt_err_tres;
res=mpu6xxx_get_accel_raw(dev,&tmp);
if(res!=RT_EOK)
{
returnres;
}
sen=MPU6XXX_ACCEL_SEN>>dev->config.accel_range;
accel->x=(rt_int32_t)tmp.x*1000/sen;
accel->y=(rt_int32_t)tmp.y*1000/sen;
accel->z=(rt_int32_t)tmp.z*1000/sen;
returnRT_EOK;
}
還有獲取磁力計、溫度的接口,就不再一一列舉了,拿到的數據我們可以進行手動解算。
- 移植DMP解算
使用DMP包的話跟rtt的MPU6050的軟件包就沒有很大關系了,只需要IIC接口就可以了
首先把DMP庫文件放到我們的工程中,包含路徑到我們的工程中
然后就需要編寫與DMP庫對接的接口了,下面幾個是需要我們實現的
rt_uint8_tMPU_Write_Len(rt_uint8_taddr,rt_uint8_treg,rt_uint8_tlen,rt_uint8_t*databuf)
{
rt_int8_tres=0;
#ifdefRT_USING_I2C
structrt_i2c_msgmsgs;
rt_uint8_tbuf[50]={0};
#endif
buf[0]=reg;
for(inti=0;i1]=databuf[i];
}
if(i2c_bus->bus->type==RT_Device_Class_I2CBUS)
{
msgs.addr=i2c_bus->i2c_addr;/*slaveaddress*/
msgs.flags=RT_I2C_WR;/*writeflag*/
msgs.buf=buf;/*Senddatapointer*/
msgs.len=len+1;
if(rt_i2c_transfer((structrt_i2c_bus_device*)i2c_bus->bus,&msgs,1)==1)
{
res=RT_EOK;
}
else
{
res=-RT_ERROR;
}
}
}
;i++)>
rt_uint8_tMPU_Read_Len(rt_uint8_taddr,rt_uint8_treg,rt_uint8_tlen,rt_uint8_t*buf)
{
rt_int8_tres=0;
#ifdefRT_USING_I2C
structrt_i2c_msgmsgs[2];
#endif
#ifdefRT_USING_SPI
rt_uint8_ttmp;
#endif
if(i2c_bus->bus->type==RT_Device_Class_I2CBUS)
{
msgs[0].addr=i2c_bus->i2c_addr;/*Slaveaddress*/
msgs[0].flags=RT_I2C_WR;/*Writeflag*/
msgs[0].buf=?/*Slaveregisteraddress*/
msgs[0].len=1;/*Numberofbytessent*/
msgs[1].addr=i2c_bus->i2c_addr;/*Slaveaddress*/
msgs[1].flags=RT_I2C_RD;/*Readflag*/
msgs[1].buf=buf;/*Readdatapointer*/
msgs[1].len=len;/*Numberofbytesread*/
if(rt_i2c_transfer((structrt_i2c_bus_device*)i2c_bus->bus,msgs,2)==2)
{
res=RT_EOK;
}
else
{
res=-RT_ERROR;
}
}
returnres;
}
初始化部分我們改為下面這樣,只注冊IIC設備就行了,其他的配置在DMP中完成:
i2c_bus=(structmpu6xxx_device*)mpu6xxx_init(MPU6050_I2C_BUS_NAME,MPU6050_ADDR);//初始化MPU6050,測量單位為角速度,加速度while(count++)
/*
mpu6xxx_set_param(i2c_bus,MPU6XXX_ACCEL_RANGE,MPU6XXX_GYRO_RANGE_2000DPS);//陀螺儀范圍配置
mpu6xxx_set_param(i2c_bus,MPU6XXX_ACCEL_RANGE,MPU6XXX_ACCEL_RANGE_2G);//加速度計,一般設置為±2G
mpu6xxx_set_param(i2c_bus,MPU6XXX_SAMPLE_RATE,50);//采樣頻率
mpu6xxx_set_param(i2c_bus,MPU6XXX_DLPF_CONFIG,25);//數字低通濾波器設置,一般為1/2采樣率
*/
while(mpu_dmp_init())
{
rt_thread_mdelay(500);
rt_kprintf("
MPU6050Error
");
}
rt_kprintf("
MPU6050OK
");
DMP初始化成功
獲取結算后的數據:
floatpitch,roll,yaw;//歐拉角
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
{
sprintf(str,"pitch=%.1f
",pitch);
rt_kprintf(str);
sprintf(str,"roll=%.1f
",roll);
rt_kprintf(str);
sprintf(str,"yaw=%.1f
",yaw);
rt_kprintf(str);
/*
temp=MPU_Get_Temperature();//得到溫度值
sprintf(str,"temp=%.1f
",temp);
rt_kprintf(str);
MPU_Get_Accelerometer(&aacx,&aacy,&aacz);//得到加速度傳感器數據
MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);//得到陀螺儀數據
*/
}
至此就結束了,使用庫的解算是挺方便的,自己解算其中涉及的計算還是挺麻煩的,本章就不再介紹啦,歡迎做過的小伙伴投稿給我哦!
-
處理器
+關注
關注
68文章
19286瀏覽量
229841 -
軟件包
+關注
關注
0文章
104瀏覽量
11595 -
MPU6050
+關注
關注
39文章
307瀏覽量
71408 -
RT-Thread
+關注
關注
31文章
1289瀏覽量
40129
原文標題:RT-Thread實戰筆記|MPU6050使用詳解及DMP姿態解算
文章出處:【微信號:RTThread,微信公眾號:RTThread物聯網操作系統】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論