二. 踩坑分享
在進行姿態解算分享之前,先分享一個踩坑經歷。一般來說MPU6050的ID讀出為0x68,淘寶上買到的模塊,基本上都是這個。但是我使用的是自己畫的PCB,手動焊接的,在讀取ID的時候,一直為0x98,但是認知中要為0x68才是對的,這個時候就會懷疑是不是自己的程序或者焊接的問題了。但好在后面讀取六軸數據,姿態解算后得到的角度基本是正確的(折騰了一天了,才發現)。這是個坑,大家可以注意一下。
三. 姿態解算
所謂姿態解算就是通過六軸的數據,來求解物體的三個角度: roll , pitch , yaw。
1. 通過加速度求解
先看一下加速度求解角度的表達式(通過加速度是無法求解yaw的)。atan(acc_y / acc_x)和sqrt(acc_y*acc_y + acc_z * acc_z)不就是上篇中Cordic算法求解的值嗎,都不需要使用的其他的計算。
roll = atan(acc_y / acc_x); pitch = atan(acc_x / (sqrt(acc_y*acc_y + acc_z * acc_z)));
2. 通過角速度求解
通過角速度的求解就更簡單了,只需要將當前角度加上(角速度×dt)就可以。角速度求解的時候會有些問題,在靜態的時候,角速度會有零漂,這個時候角度誤差會越來越大。
3. 融合
可以看到有上面的兩種方法求解角度,可以單獨使用,但是可能會不太準確,精度要求不高的場合可以只使用加速度求解。在精度要求比較高的場合下,需要使用這兩種方法求解,然后再將求得的結果進行融合。常用的方法有: 卡爾曼濾波、一階互補濾波、二階互補濾波。
一階互補濾波,如下,簡單粗暴。要想濾波效果好的話,可以試試卡爾曼濾波。
roll = a * acc_roll + (1 - a) *gyro_roll;
以上只是一種比較常規的求解方法,追求高精度的話,可以使用四元數的方法進行求解(復雜度大大增加)。
四. 代碼實現
代碼都是現成的,在之前的文章中已經寫好了,這里做的工作就是將這些模塊組合在一起。
1. 模塊接口
輸入請求,輸出應答和三個角度,角度值擴大了2^16倍。
module IMU( input clk, //27M input rst_n, input imu_req, output imu_ack, output signed[31:0] roll, output signed[31:0] pitch, output signed[31:0] yaw, output IICSCL, /*IIC 時鐘輸出*/ inout IICSDA /*IIC 數據線*/ );
2. 狀態機
這里使用到了兩個Cordic模塊,第一個模塊先計算出roll和sqrt(acc_y*acc_y + acc_z * acc_z)的值,然后第二個模塊通過acc_x和sqrt(acc_y*acc_y + acc_z * acc_z)的值 計算出 pitch的角度。最后對數據經過了一個簡單的FIR濾波。
always@(*) begin case(state) S_IDLE: if( imu_req == 1'b1) next_state <= S_READ_MPU6050; ? ? ? else ? ? ? ? ? next_state <= S_IDLE; ? S_READ_MPU6050: ? ? ? if( mpu6050_ack == 1'b1 ) ? ? ? ? ? next_state <= S_Cordic; ? ? ? else ? ? ? ? ? next_state <= S_READ_MPU6050; ? S_Cordic: ? ? ? if( cordic_ack == 1'b1) ? ? ? ? ? next_state <= S_Cordic2; ? ? ? else ? ? ? ? ? next_state <= S_Cordic; ? S_Cordic2: ? ? ? if( cordic2_ack == 1'b1) ? ? ? ? ? next_state <= S_FILTER; ? ? ? else ? ? ? ? ? next_state <= S_Cordic2; ? S_FILTER: ? ? ? if( fir_filter_ack == 1'b1) ? ? ? ? ? next_state <= S_ACK; ? ? ? else ? ? ? ? ? next_state <= S_FILTER; ? S_ACK: ? ? ? next_state <= S_IDLE; ? default: ? ? next_state <= S_IDLE; ? endcase end
3. 融合
這里的融合,暫時沒有做,只對加速度求解的角度進行了一個濾波處理,后面會根據需要再進行更新。
FIR_Filter FIR_Filter_HP( .clk ( clk ), .rst_n ( rst_n ), .fir_filter_req ( fir_filter_req ), .fir_filter_ack ( fir_filter_ack ), .filter_data_in ( theta ), .filter_data_out ( acc_roll ) ); FIR_Filter FIR_Filter_HP2( .clk ( clk ), .rst_n ( rst_n ), .fir_filter_req ( fir_filter_req ), .fir_filter_ack ( ), .filter_data_in ( theta2 ), .filter_data_out ( acc_pitch ) );
模塊已上板測試,解算出來的角度沒有問題(可能精度不是那么完美,濾波與融合那里需要下點功夫)。
審核編輯:劉清
-
FPGA
+關注
關注
1630文章
21797瀏覽量
606021 -
CORDIC算法
+關注
關注
0文章
17瀏覽量
9759 -
MPU6050
+關注
關注
39文章
307瀏覽量
71665 -
姿態解算
+關注
關注
0文章
49瀏覽量
8303
原文標題:FPGA實現MPU6050姿態解算
文章出處:【微信號:FPGA研究院,微信公眾號:FPGA研究院】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論