毕业设计2- MPU6050传感器调试记录(STM32CubeMX+STM32F103C8T6)
文章目錄
- 一、前情提要
- 二、STM32CubeMX配置
- 三、寄存器介紹
- 四、Keil代碼介紹
- 總結
本次調試的傳感器是正點原子的MPU6050(三軸陀螺儀+三軸加速度)。因為我的畢設中并不要求解算出歐拉角,只是用來反映風電機組(demo)的振動情況即可。為了簡化, 所以我只使用了三軸加速度計,但是在這篇介紹中,采用了硬件I2C來讀取了硬件傳感器原始數據,并對這些數據進行了 卡爾曼濾波。
一、前情提要
這部分的問題是我在剛接觸這個傳感器的幾個問題,通過自己查閱資料有了個大致的了解。因此在這里想分享一下。感謝各位大佬們的分享,讓我不斷地可以學習。
我看了1個博客和1個小破站上的視頻,感覺博主和UP主講的很好
小破站視頻: https://www.bilibili.com/video/BV1sL411F7fu?spm_id_from=333.337.search-card.all.click
知乎博客: https://zhuanlan.zhihu.com/p/195683958
代碼參考視頻: https://www.bilibili.com/video/BV1qf4y1r73k?spm_id_from=333.337.search-card.all.click
這些問題也是我自己的理解,僅供參考,有不正確之處,歡迎大家指出,我的郵箱:2802433362@qq.com
1.你能解釋一下這種N軸IMU常見的一些概念嗎?
(1)笛卡爾坐標系:
在下面實際中的這張圖好像跟上面的不太一樣啊,其實我們旋轉一下就好了,我說這個的目的是在姿態解算的時候,我們經常會旋轉坐標系,注意XYZ軸的位置關系千萬不要搞混了,有時候我自己也是多旋轉就亂了,所以可以借助右手坐標系來幫助我們理解。
(2)歐拉角:我們常說的歐拉角指的是ROLL(橫滾角)、偏航角(Yaw)、俯仰角(Pitch)。具體的大家可以根據下面的模型來進行理解。知乎博主“碼農愛學習”寫的真的不錯,簡單易懂,很適合我們這種小白。“https://zhuanlan.zhihu.com/p/195683958”,我敢我再寫下去也是照搬人家的東西,博主概括的真的很全。
(3)四元素:他是表示旋轉的另一種方式,可以與歐拉角進行轉化,具體的話可以參考CSDN的另外一個博主的文章:https://blog.csdn.net/xiaoma_bk/article/details/79082629
(4)陀螺儀傳感器:這個是涉及到很多物理方面的東西,我們可以簡單的認為它可以X、Y、Z軸的角速度。
(5)加速度計傳感器:測量的是X、Y、Z的加速度。
(6)磁力計傳感器:測量的3軸磁場強度(這個目前我也不是很熟,后面要慢慢用起來的)
2. 我在網上查閱的資料看到有3軸、6軸、9軸、10軸傳感器你能解釋一下有什么區別嗎?
(1) 3軸傳感器是指3軸陀螺儀。 它測量的是3個軸(XYZ)的角速度,其實通過這三個數據也能進行姿態解算得到三個歐拉角(俯仰角、橫滾角、偏航角),因此他也是可以獨立工作的,出現了市面上常見的3軸傳感器。但是這個傳感器存在的問題是:
(a)因為它的計算方式的角度=角速度*dt,大家學過高數和大學物理,當dt很小時,我們可以把物體看成勻速運動,但是這樣造成的問題是不太符合實際情況,我們只是假設這樣子,會有較大的累積誤差;
(b)之前看那個博主說,只使用3軸陀螺儀會出現相位差的問題(這部分我不是很懂,后面需要去補充一些知識)。
偉大的前輩們也知道這個問題,所以一個神奇的想法就產生了,能不能用兩個傳感器,相互校正一下,然后取個平均啥的(傳感器融合當然沒這么簡單,此處只是舉個栗子),應該能精確很多吧。但是從兩個角度來做效果應該更好,因為再加一個3軸陀螺儀,就沒多大必要(此處我也不知道解釋比較好,就是那種本來這個誤差就大,換個角度去測量會更好,而不是疊羅漢。),于是6軸加速度就產生了。
(2)6軸傳感器是指3軸陀螺儀+3軸加速度計。 3軸加速度計測量的就是XYZ軸上的加速度g的一個分量。當這個坐標系很正的時候,三軸的數值應該為aacx=0g、aacy=0g、aacz=1*g,其中9為重力加速度,9.8m/s2。當這個傳感器有一個傾斜的話,g在x軸和y軸上就會有個分量,有可能就變成了aacx=0.3g、aacy=0.2g、aacz=0.7g,我們其實可以根據這些數據得到三個歐拉角,所有單獨用加速度計也可以進行姿態結算,但是如果單獨用的話我們是無法解算出偏航的角的。可以參考下面的推導公式,我們通過傳感器得到的是ax、ay、az但是我們通過推導發現y沒了(p代表pitch俯仰角、r表示raw橫滾角、y表示yaw偏航角),數學就是這么神奇,哈哈,想不到吧,所以3軸加速度計只能解算出pitch角和raw角,所以6軸傳感器的yaw(偏航角會一直漂移),而pitch(俯仰角)和raw(橫滾角)通過數據融合算法可以得到較為穩定的值。,目前常用的數據融合算法是DMP和卡爾曼濾波。卡爾曼濾波不得不說是一個很神奇的東西,此處強烈感謝卡爾曼前輩能研究出這么優秀又通用的算法。
(3)9軸傳感器是指3軸陀螺儀+3軸加速度計+3軸磁力計。加3軸磁力計的目的大家可能可以猜到的啦,可以把偏航角也給校準了,這樣可以得到較為穩定的3個歐拉角(或者穩定的四元組),具體的解算過程大家可以參考上面推薦的知乎博客,大佬寫的真的不錯,當然小破站上的小哥哥的那個視頻講的也很清楚,再次感謝大佬們。我這次沒有選用類似MPU9250的9軸傳感器,一是因為我并不需要進行姿態計算,二是因為我的整個系統存在電機和鋼軸,會對磁力計的校準影響很大,不能起到相應的效果。因此大家在使用的時候應該主要有磁場校準影響的情況。
9軸傳感器不是已經很完美了嗎?可以完全把姿態計算出來,10軸傳感器又是啥哩
(4)10軸傳感器是指3軸陀螺儀+3軸加速度計+3軸磁力計+1個氣壓計,這個可以把氣壓高度計算出來,我認為這個是錦上添花的作用。 ,當然存在即是合理,自然有它的應用場景。
3. 網上說的DMP算法和卡爾曼濾波你能簡要說一下他們是什么嗎?
(1)對于DMP算法:可以參考知乎博主“碼農愛學習”的這篇文章:https://zhuanlan.zhihu.com/p/165156300
復制他的一段話:DMP就是MPU6050內部的運動引擎,全稱Digital Motion Processor,直接輸出四元數,可以減輕外圍微處理器的工作負擔且避免了繁瑣的濾波和數據融合。 就我們使用的諸如MPU6050、MPU9250等來說,DMP是硬件融合,就是商家已經做了硬件的嵌入,我們只需要調用相應的驅動庫即可,這樣可以很方便的,具體的一些驅動程序可以參考正點原子的驅動程序。
(2)對于卡爾曼濾波算法: 利用加速度計采集的3軸加速度計進行姿態融合成的pitch、roll作為觀測值, 利用陀螺儀采集的3軸角度值進行的姿態融合成的pitch,yaw,raw作為測量值。所以利用卡爾曼濾波可以實現pitch(俯仰角)、roll(橫滾角)的穩定輸出。
(3)下面還是引用知乎博主“碼農愛學習”中的內容:這部分其實反映的是卡爾曼濾波的思想,K其實指的是卡爾曼增益,這部分我們可以這樣理解:每個傳感器都可以進行姿態解算,得到自己的三個歐拉角,而我們希望把這些融合(直接取平均的方式顯然太low)了。因為每個傳感器都有自己的優缺點,我們應該把每個傳感器的優點利用起來會使結果更加地準確,因此前輩們提取了每個傳感器權重不同的方法來進行融合,至于這個權重到底是多少,卡爾曼老先生在自己的論文中有明確的推導(卡爾曼濾波最經典的那5個方程:2個預測方程,3個更新方程)。此處不再多做介紹,大家如果對卡爾曼濾波原理什么的想要有更深的了解,可以自行搜索,后面我也會自己出一期我自己對卡爾曼濾波的理解。
二、STM32CubeMX配置
有了上面的一些基礎概念和了解,我們下面開始配置STM32CubeMX
(1) 在“SYS”設置為“SW”調試模式;
(2)我們在“RCC”中選擇外部晶振模式;
(3) 因為MPU6050采用的通信協議是I2C,而我們又想采用硬件I2C去開發,所以必須進行勾選。
(4)因為我們想把數據打印到電腦的“串口調試助手”,所以我們需要開一路串口,波特率為115200;
(5)我們下面配置時鐘樹;
(6)將這個工程存放在文件夾中,整個目錄最好不要有中文,因為后面自動生成代碼的時候并不能直接打開,不過問題也不大,需要自己去相關文件夾中的找到工程文件打開;
(7)我們勾選一下我們希望生成文件的配置。
到此為止,我們的配置就已經完成了。
三、寄存器介紹
對于傳感器而言,寄存器是很重要的東西,所以我們想要使用一個傳感器,一定要清楚他的寄存器怎樣配置,數據存儲在哪個寄存器中
(其實我在學習的時候也不喜歡看手冊,但是咱們都是搞這個的,datasheet肯定要看的,后面我們能形成屬于自己的一套看datasheet的流程和經驗,會很舒服的)。我這里只是介紹一下我再這次調試中用到的寄存器,具體的每一個比特位到底表示什么大家自己查手冊就好了。
四、Keil代碼介紹
這部分是參考小破站上的視頻講解:https://www.bilibili.com/video/BV1qf4y1r73k?spm_id_from=333.337.search-card.all.click(俺是妥妥自己搬運工具人,同時加上自己的一點理解)。關于我們應該對I2C通信有個簡單的了解吧(不了解的話,小破綻也有很多資源,我比較推薦的是創客學院的武老師的講解)。對于I2C設備,都有一個自己的設備地址,我們首先要做的知道設備地址。
(1)首先我們進行多串口重映像,在“usart.h”文件中添加以下代碼;
#include "stdarg.h" #include "string.h" #include "stdio.h"(2)在“usart.c”文件中添加下面的代碼;
#define TXBUF_SIZE_MAX 100 void usart2_printf(const char *format, ...) {va_list args;uint32_t length;uint8_t txbuf[TXBUF_SIZE_MAX] = {0};va_start(args, format);length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args);va_end(args);HAL_UART_Transmit(&huart2, (uint8_t *)txbuf, length, HAL_MAX_DELAY);memset(txbuf, 0, TXBUF_SIZE_MAX); }(3)對于類似樹莓派的Linux系統中我們可以通過I2C查詢的指令即可實現,當然,STM32也有相應的程序可以查看:
for (uint8_t i=0; i<255;i++) {if(HAL_I2C_IsDeviceReady(&hi2c1, i ,1, 1000) == HAL_OK) //尋找設備地址,I2C原裝函數 { usart2_printf("%d\r\n",i);break;}. }我們在串口中可以看到返回值,我返回的是208,轉換成16進制數據為0xD0,所以我們的I2C設備地址為0xD0。
(4)下面我們在“main.c”文件中 添加宏定義:
(5)進行MPU6050初始化,配置一些寄存器;
void MPU6050_Init(void ) {/*HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);第1個參數為I2C操作句柄第2個參數為從機設備地址第3個參數為從機寄存器地址第4個參數為從機寄存器地址長度第5個參數為發送的數據的起始地址第6個參數為傳輸數據的大小第7個參數為操作超時時間 */uint8_t check,Data;// check device ID WHO_AM_I//檢查設備ID HAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR,WHO_AM_I_REG,1,&check ,1,1000);if(check == 104) //if the device is present,寄存器地址默認0x68{//power management register 0x6B we should write all 0's to wake the sensor up//電源管理寄存器,我們應該在0x6B中寫入所有0來喚醒傳感器Data = 0;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR ,PWR_MGMT_1_REG ,1,&Data ,1,1000);//Set DATA RATE of 1KHz by writing SMPLRT_DIV register//通過寫入SMPLRT_DIV寄存器設置1KHz的數據速率Data = 0x07;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR ,SMPLRT_DIV_REG ,1 ,&Data,1,1000);// Set accelerometer configuration in ACCEL_CONFIG Register// XA_ST=0,YA_ST=0,ZA_ST=0, FS_SEL=0 ->±2g//在加速度寄存器中修改配置Data = 0x00;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &Data, 1, 1000);// Set Gyroscopic configuration in GYRO_CONFIG Register// XG_ST=0,YG_ST=0, FS_SEL=0 ->± 250 °/s//修改重力加速計配置Data = 0x00;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR, GYRO_CONFIG_REG, 1, &Data, 1, 1000);} }(6)進行數據讀取函數:加速度數據讀取、陀螺儀數據讀取、溫度數據讀取;
//************************************加速度傳感器讀取*************************************// void MPU6050_Read_Accel(void) {uint8_t Rec_Data[6];//Read 6 BYTES of data starting from ACCEL_XOUT_H registerHAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR ,ACCEL_XOUT_H_REG ,1,Rec_Data ,6,1000);Accel_X_RAW = (int16_t )(Rec_Data [0] <<8 | Rec_Data [1]);Accel_Y_RAW = (int16_t )(Rec_Data [2] <<8 | Rec_Data [3]);Accel_Z_RAW = (int16_t )(Rec_Data [4] <<8 | Rec_Data [5]);Ax = Accel_X_RAW/16384.0;Ay = Accel_Y_RAW/16384.0;Az = Accel_Z_RAW/16384.0; } //*********************************陀螺儀數據讀取*****************************************// void MPU6050_Read_Gyro(void ) {uint8_t Rec_Data[6];// Read 6 BYTES of data staring from GYRO_XOUT_H registerHAL_I2C_Mem_Read (&hi2c1, MPU6050_ADDR ,GYRO_XOUT_H_REG ,1,Rec_Data ,6 ,1000);Gyro_X_RAW = (int16_t )(Rec_Data [0] << 8 | Rec_Data [1]);Gyro_Y_RAW = (int16_t )(Rec_Data [2] << 8 | Rec_Data [3]);Gyro_Z_RAW = (int16_t )(Rec_Data [4] << 8 | Rec_Data [5]);Gx = Gyro_X_RAW/131.0;Gy = Gyro_Y_RAW/131.0;Gz = Gyro_Z_RAW/131.0; } //***********************************芯片溫度讀取************************************// void MPU6050_Read_Temp(void ) {uint8_t Rec_Data[2];HAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR ,TEMP_OUT_H_REG ,1 ,Rec_Data ,2 ,1000);Temp_RAW = (int16_t )(Rec_Data [0]<<8)|Rec_Data [1];Temp = 36.53 + (Temp_RAW )/340; }(7) 在主函數中調用這些函數即可;
(8)我們將這些代碼編譯,燒錄到我們單片機中即可。
總結
通過本次實驗,我學會了:
(1)了解了陀螺儀進行姿態計算的原理;
(2)大致了解卡爾曼濾波的基本過程,同時怎么樣將卡爾曼應用到卡爾曼濾波;
(3)通過單片機實現了MPU6050原始數據的讀取。
后面還需要學習的:
(1)陀螺儀、加速度計、磁力計他們的工作原理是什么,誤差到底來自于那些方面;
(2)利用這些原始數據進行姿態解算的具體怎么操作;
(3)在草稿本上認真推導姿態解算的過程,并把它記錄下來。
總結
以上是生活随笔為你收集整理的毕业设计2- MPU6050传感器调试记录(STM32CubeMX+STM32F103C8T6)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32 磁场传感器HMC5883
- 下一篇: bim 水利枢纽 运维_BIM——运维专