卡爾曼濾波源碼
以stm32f103rct6為例
測試串口通信數據
MPU數據進行處理
檢測X軸加速度,Y軸角速度
參考網上例程
單片機源程序如下:
- #include "stm32f10x.h"
- #include <stdio.h>
- #include "delay.h"
- #include "sys.h"
- #include "Usart.h"
- #include "MPU6050.h"
- //******角度參數************
- float Gyro_y; //Y軸陀螺儀數據暫存
- float Angle_gy; //由角速度計算的傾斜角度
- float Accel_x; //X軸加速度值暫存
- float Angle_ax; //由加速度計算的傾斜角度
- float Angle; //最終測量角度
- void TIM2_Configuration(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定義一個定時器結構體變量
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定時器2
-
- TIM_TimeBaseStructure.TIM_Period = (10000 - 1); //計數100次,因為從0開始,所以減1
- TIM_TimeBaseStructure.TIM_Prescaler = (72 - 1); //時鐘72分頻,因為0不分頻,所以減1
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 使用的采樣頻率之間的分頻比例
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定時器2
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除定時器2中斷標志位
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //打開定時器2中斷
- TIM_Cmd(TIM2, ENABLE); //計數器使能,開始計數
- }
- void NVIC_Configuration(void)
- {
- NVIC_InitTypeDef NVIC_InitStructure;
-
- NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- /********************注冊定時器2中斷處理函數***********************/
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- /******************注冊串口1中斷服務函數************************/
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//配置串口中斷
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//占先式優先級設置為0
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //副優先級設置為0
- NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;//中斷禁止
- NVIC_Init(&NVIC_InitStructure);//中斷初始化
- }
- /*************卡爾曼濾波*********************************/
- void Kalman_Filter(float Accel,float Gyro)
- {
-
- static const float Q_angle=0.001;
- static const float Q_gyro=0.003;
- static const float R_angle=0.5;
- static const float dt=0.01; //dt為kalman濾波器采樣時間;
- static const char C_0 = 1;
- static float Q_bias, Angle_err;
- static float PCt_0, PCt_1, E;
- static float K_0, K_1, t_0, t_1;
- static float Pdot[4] ={0,0,0,0};
- static float PP[2][2] = { { 1, 0 },{ 0, 1 } };
-
- Angle+=(Gyro - Q_bias) * dt; //先驗估計
- Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先驗估計誤差協方差的微分
- Pdot[1]= -PP[1][1];
- Pdot[2]= -PP[1][1];
- Pdot[3]=Q_gyro;
-
- PP[0][0] += Pdot[0] * dt; // Pk-先驗估計誤差協方差微分的積分
- PP[0][1] += Pdot[1] * dt; // =先驗估計誤差協方差
- PP[1][0] += Pdot[2] * dt;
- PP[1][1] += Pdot[3] * dt;
-
- Angle_err = Accel - Angle; //zk-先驗估計
-
- PCt_0 = C_0 * PP[0][0];
- PCt_1 = C_0 * PP[1][0];
-
- E = R_angle + C_0 * PCt_0;
-
- K_0 = PCt_0 / E;
- K_1 = PCt_1 / E;
-
- t_0 = PCt_0;
- t_1 = C_0 * PP[0][1];
- PP[0][0] -= K_0 * t_0; //后驗估計誤差協方差
- PP[0][1] -= K_0 * t_1;
- PP[1][0] -= K_1 * t_0;
- PP[1][1] -= K_1 * t_1;
-
- Angle += K_0 * Angle_err; //后驗估計
- Q_bias += K_1 * Angle_err; //后驗估計
- Gyro_y = Gyro - Q_bias; //輸出值(后驗估計)的微分=角速度
- }
- void Angle_Calculate(void)
- {
- static uint8_t DataBuffer[2]; //數據緩存
- /****************************加速度****************************************/
- I2C_ReadBuffer(DataBuffer, ACCEL_XOUT_H, 2);
- Accel_x = (short)((DataBuffer[0]<<8)+DataBuffer[1]); //讀取X軸加速度
- Angle_ax = (Accel_x +220) /16384; //去除零點偏移,計算得到角度(弧度)
- Angle_ax = Angle_ax*1.2*180/3.14; //弧度轉換為度,
- /****************************角速度****************************************/
- I2C_ReadBuffer(DataBuffer, GYRO_YOUT_H, 2);
- Gyro_y = (short)((DataBuffer[0]<<8)+DataBuffer[1]); //靜止時角速度Y軸輸出為-18左右
- Gyro_y = (Gyro_y + 18)/16.4; //去除零點偏移,計算角速度值
- // Angle_gy = Angle_gy + Gyro_y*0.01; //角速度積分得到傾斜角度.
- /***************************卡爾曼濾波+角度融合*************************************/
- Kalman_Filter(Angle_ax,Gyro_y); //卡爾曼濾波計算傾角
- /*******************************互補濾波******************************************/
- /*補償原理是取當前傾角和加速度獲
- 得傾角差值進行放大,然后與陀螺
- 儀角速度疊加后再積分,從而使傾
- 角最跟蹤為加速度獲得的角度0.5
- 為放大倍數,可調節補償度;
- 0.01為系統周期10ms
- */
- // Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/
-
- }
- int main(void)
- {
- Stm32_Clock_Init(6);//系統時鐘設置為外部晶振,9倍頻
- delay_init(72);//系統SysTick初始化
- Usart_Configuration();
- TIM2_Configuration();
- NVIC_Configuration();
- I2C_Congiguration();
- MPU6050_Init();
- while (1)
- {
- printf("%f %f ",Angle,Gyro_y);
- USART1_Send_Enter();
- delay_ms(100);
- }
- }
- /****************定時器2中斷服務函數***************************************/
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
- {
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- Angle_Calculate();
- }
- }
復制代碼
所有資料51hei提供下載:
卡爾曼濾波.rar
(427.33 KB, 下載次數: 68)
2018-5-6 01:19 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|