找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 8388|回復(fù): 4
收起左側(cè)

平衡車卡爾曼濾波源碼,6軸MPU6050+互補(bǔ)濾波

  [復(fù)制鏈接]
ID:321526 發(fā)表于 2018-5-3 19:45 | 顯示全部樓層 |閱讀模式
卡爾曼濾波單片機(jī)源程序如下:
  1.                                                                   
  2. /***********************************************************************
  3. // 兩輪自平衡車最終版控制程序(6軸MPU6050+互補(bǔ)濾波+PWM電機(jī))
  4. // 單片機(jī)STC12C5A60S2
  5. // 晶振:20M
  6. ***********************************************************************/

  7. #include <REG52.H>       
  8. #include <math.h>     
  9. #include <stdio.h>   
  10. #include <INTRINS.H>

  11. typedef unsigned char  uchar;
  12. typedef unsigned short ushort;
  13. typedef unsigned int   uint;

  14. //******功能模塊頭文件*******

  15. #include "DELAY.H"                    //延時(shí)頭文件
  16. #include "STC_ISP.H"            //程序燒錄頭文件
  17. #include "SET_SERIAL.H"                //串口頭文件
  18. #include "SET_PWM.H"                //PWM頭文件
  19. #include "MOTOR.H"                        //電機(jī)控制頭文件
  20. #include "MPU6050.H"                //MPU6050頭文件



  21. //******角度參數(shù)************

  22. float Gyro_y;        //Y軸陀螺儀數(shù)據(jù)暫存
  23. float Angle_gy;      //由角速度計(jì)算的傾斜角度
  24. float Accel_x;             //X軸加速度值暫存
  25. float Angle_ax;      //由加速度計(jì)算的傾斜角度
  26. float Angle;         //小車最終傾斜角度
  27. uchar value;                 //角度正負(fù)極性標(biāo)記       

  28. //******PWM參數(shù)*************

  29. int   speed_mr;                 //右電機(jī)轉(zhuǎn)速
  30. int   speed_ml;                 //左電機(jī)轉(zhuǎn)速
  31. int   PWM_R;         //右輪PWM值計(jì)算
  32. int   PWM_L;         //左輪PWM值計(jì)算
  33. float PWM;           //綜合PWM計(jì)算
  34. float PWMI;                         //PWM積分值

  35. //******電機(jī)參數(shù)*************

  36. float speed_r_l;        //電機(jī)轉(zhuǎn)速
  37. float speed;        //電機(jī)轉(zhuǎn)速濾波
  38. float position;            //位移

  39. //******藍(lán)牙遙控參數(shù)*************
  40. uchar remote_char;
  41. char  turn_need;
  42. char  speed_need;

  43. //*********************************************************
  44. //定時(shí)器100Hz數(shù)據(jù)更新中斷
  45. //*********************************************************

  46. void Init_Timer1(void)        //10毫秒@20MHz,100Hz刷新頻率
  47. {
  48.         AUXR &= 0xBF;                //定時(shí)器時(shí)鐘12T模式
  49.         TMOD &= 0x0F;                //設(shè)置定時(shí)器模式
  50.         TMOD |= 0x10;                //設(shè)置定時(shí)器模式
  51.         TL1 = 0xE5;                    //設(shè)置定時(shí)初值
  52.         TH1 = 0xBE;                    //設(shè)置定時(shí)初值
  53.         TF1 = 0;                    //清除TF1標(biāo)志
  54.         TR1 = 1;                    //定時(shí)器1開始計(jì)時(shí)
  55. }



  56. //*********************************************************
  57. //中斷控制初始化
  58. //*********************************************************

  59. void Init_Interr(void)         
  60. {
  61.         EA = 1;     //開總中斷
  62.     EX0 = 1;    //開外部中斷INT0
  63.     EX1 = 1;    //開外部中斷INT1
  64.     IT0 = 1;    //下降沿觸發(fā)
  65.     IT1 = 1;    //下降沿觸發(fā)
  66.         ET1 = 1;    //開定時(shí)器1中斷
  67. }



  68. //******卡爾曼參數(shù)************
  69.                
  70. float code Q_angle=0.001;  
  71. float code Q_gyro=0.003;
  72. float code R_angle=0.5;
  73. float code dt=0.01;                          //dt為kalman濾波器采樣時(shí)間;
  74. char  code C_0 = 1;
  75. float xdata Q_bias, Angle_err;
  76. float xdata PCt_0, PCt_1, E;
  77. float xdata K_0, K_1, t_0, t_1;
  78. float xdata Pdot[4] ={0,0,0,0};
  79. float xdata PP[2][2] = { { 1, 0 },{ 0, 1 } };


  80. //*********************************************************
  81. // 卡爾曼濾波
  82. //*********************************************************

  83. //Kalman濾波,20MHz的處理時(shí)間約0.77ms;

  84. void Kalman_Filter(float Accel,float Gyro)               
  85. {
  86.         Angle+=(Gyro - Q_bias) * dt; //先驗(yàn)估計(jì)

  87.        
  88.         Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先驗(yàn)估計(jì)誤差協(xié)方差的微分

  89.         Pdot[1]=- PP[1][1];
  90.         Pdot[2]=- PP[1][1];
  91.         Pdot[3]=Q_gyro;
  92.        
  93.         PP[0][0] += Pdot[0] * dt;   // Pk-先驗(yàn)估計(jì)誤差協(xié)方差微分的積分
  94.         PP[0][1] += Pdot[1] * dt;   // =先驗(yàn)估計(jì)誤差協(xié)方差
  95.         PP[1][0] += Pdot[2] * dt;
  96.         PP[1][1] += Pdot[3] * dt;
  97.                
  98.         Angle_err = Accel - Angle;        //zk-先驗(yàn)估計(jì)
  99.        
  100.         PCt_0 = C_0 * PP[0][0];
  101.         PCt_1 = C_0 * PP[1][0];
  102.        
  103.         E = R_angle + C_0 * PCt_0;
  104.        
  105.         K_0 = PCt_0 / E;
  106.         K_1 = PCt_1 / E;
  107.        
  108.         t_0 = PCt_0;
  109.         t_1 = C_0 * PP[0][1];

  110.         PP[0][0] -= K_0 * t_0;                 //后驗(yàn)估計(jì)誤差協(xié)方差
  111.         PP[0][1] -= K_0 * t_1;
  112.         PP[1][0] -= K_1 * t_0;
  113.         PP[1][1] -= K_1 * t_1;
  114.                
  115.         Angle        += K_0 * Angle_err;         //后驗(yàn)估計(jì)
  116.         Q_bias        += K_1 * Angle_err;         //后驗(yàn)估計(jì)
  117.         Gyro_y   = Gyro - Q_bias;         //輸出值(后驗(yàn)估計(jì))的微分=角速度

  118. }



  119. //*********************************************************
  120. // 傾角計(jì)算(卡爾曼融合)
  121. //*********************************************************

  122. void Angle_Calcu(void)         
  123. {
  124.         //------加速度--------------------------

  125.         //范圍為2g時(shí),換算關(guān)系:16384 LSB/g
  126.         //角度較小時(shí),x=sinx得到角度(弧度), deg = rad*180/3.14
  127.         //因?yàn)閤>=sinx,故乘以1.3適當(dāng)放大

  128.         Accel_x  = GetData(ACCEL_XOUT_H);          //讀取X軸加速度
  129.         Angle_ax = (Accel_x - 1100) /16384;   //去除零點(diǎn)偏移,計(jì)算得到角度(弧度)
  130.         Angle_ax = Angle_ax*1.2*180/3.14;     //弧度轉(zhuǎn)換為度,


  131.     //-------角速度-------------------------

  132.         //范圍為2000deg/s時(shí),換算關(guān)系:16.4 LSB/(deg/s)

  133.         Gyro_y = GetData(GYRO_YOUT_H);              //靜止時(shí)角速度Y軸輸出為-30左右
  134.         Gyro_y = -(Gyro_y + 30)/16.4;         //去除零點(diǎn)偏移,計(jì)算角速度值,負(fù)號為方向處理
  135.         //Angle_gy = Angle_gy + Gyro_y*0.01;  //角速度積分得到傾斜角度.       

  136.        
  137.         //-------卡爾曼濾波融合-----------------------

  138.         Kalman_Filter(Angle_ax,Gyro_y);       //卡爾曼濾波計(jì)算傾角


  139.         /*//-------互補(bǔ)濾波-----------------------

  140.         //補(bǔ)償原理是取當(dāng)前傾角和加速度獲得傾角差值進(jìn)行放大,然后與
  141.     //陀螺儀角速度疊加后再積分,從而使傾角最跟蹤為加速度獲得的角度
  142.         //0.5為放大倍數(shù),可調(diào)節(jié)補(bǔ)償度;0.01為系統(tǒng)周期10ms       
  143.                
  144.         Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/
  145.                                                                                                                           
  146. }  



  147. //*********************************************************
  148. //電機(jī)轉(zhuǎn)速和位移值計(jì)算
  149. //*********************************************************

  150. void Psn_Calcu(void)         
  151. {
  152.        
  153.         speed_r_l =(speed_mr + speed_ml)*0.5;
  154.         speed *= 0.7;                                  //車輪速度濾波
  155.         speed += speed_r_l*0.3;       
  156.         position += speed;                          //積分得到位移
  157.         position += speed_need;
  158.         if(position<-6000) position = -6000;
  159.         if(position> 6000) position =  6000;

  160.          
  161. }


  162. static float code Kp  = 9.0;       //PID參數(shù)
  163. static float code Kd  = 2.6;            //PID參數(shù)
  164. static float code Kpn = 0.01;      //PID參數(shù)
  165. static float code Ksp = 2.0;            //PID參數(shù)

  166. //*********************************************************
  167. //電機(jī)PWM值計(jì)算
  168. //*********************************************************

  169. void PWM_Calcu(void)         
  170. {
  171.    
  172.         if(Angle<-40||Angle>40)               //角度過大,關(guān)閉電機(jī)
  173.         {  
  174.           CCAP0H = 0;
  175.       CCAP1H = 0;
  176.           return;
  177.         }
  178.         PWM  = Kp*Angle + Kd*Gyro_y;          //PID:角速度和角度
  179.         PWM += Kpn*position + Ksp*speed;      //PID:速度和位置
  180.         PWM_R = PWM + turn_need;
  181.         PWM_L = PWM - turn_need;
  182.         PWM_Motor(PWM_L,PWM_R);
  183.          
  184. }




  185. //*********************************************************
  186. //手機(jī)藍(lán)牙遙控
  187. //*********************************************************

  188. void Bluetooth_Remote(void)         
  189. {

  190.         remote_char = receive_char();                                   //接收藍(lán)牙串口數(shù)據(jù)

  191.         if(remote_char ==0x02) speed_need = -80;           //前進(jìn)
  192.         else if(remote_char ==0x01) speed_need = 80;   //后退
  193.              else speed_need = 0;                                           //不動(dòng)

  194.     if(remote_char ==0x03) turn_need = 15;                   //左轉(zhuǎn)
  195.         else if(remote_char ==0x04) turn_need = -15;   //右轉(zhuǎn)
  196.              else turn_need = 0;                                           //不轉(zhuǎn)
  197.          
  198. }


  199. /*=================================================================================*/

  200. //*********************************************************
  201. //main
  202. //*********************************************************
  203. void main()
  204. {

  205.         delaynms(500);           //上電延時(shí)
  206.         Init_PWM();               //PWM初始化
  207.     Init_Timer0();     //初始化定時(shí)器0,作為PWM時(shí)鐘源
  208.         Init_Timer1();     //初始化定時(shí)器1
  209.         Init_Interr();     //中斷初始化
  210.         Init_Motor();           //電機(jī)控制初始化
  211.         Init_BRT();                   //串口初始化(獨(dú)立波特率)
  212.         InitMPU6050();     //初始化MPU6050
  213.         delaynms(500);           

  214.         while(1)
  215.         {
  216.           
  217.          Bluetooth_Remote();

  218.         }
  219. }


  220. /*=================================================================================*/

  221. //********timer1中斷***********************

  222. void Timer1_Update(void) interrupt 3
  223. {
  224.   
  225.    TL1 = 0xE5;                    //設(shè)置定時(shí)初值10MS
  226.    TH1 = 0xBE;
  227.    
  228.    //STC_ISP();                    //程序下載
  229.    Angle_Calcu();                  //傾角計(jì)算
  230.    Psn_Calcu();                    //電機(jī)位移計(jì)算
  231.    PWM_Calcu();                    //計(jì)算PWM值
  232.    
  233.    speed_mr = speed_ml = 0;         

  234. }


  235. //********右電機(jī)中斷***********************

  236. void INT_L(void) interrupt 0
  237. {

  238.    if(SPDL == 1)  { speed_ml++; }                 //左電機(jī)前進(jìn)
  239.    else                      { speed_ml--; }                 //左電機(jī)后退
  240.    LED = ~LED;

  241. }


  242. //********左電機(jī)中斷***********************

  243. ……………………

  244. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
MPU6050_Kalman_PWM_remote.rar (56.26 KB, 下載次數(shù): 256)


回復(fù)

使用道具 舉報(bào)

ID:471390 發(fā)表于 2019-5-24 09:26 | 顯示全部樓層
強(qiáng),剛好需要
回復(fù)

使用道具 舉報(bào)

ID:471390 發(fā)表于 2019-5-24 09:26 | 顯示全部樓層
剛好需要,謝謝大佬
回復(fù)

使用道具 舉報(bào)

ID:622782 發(fā)表于 2021-6-12 06:39 | 顯示全部樓層
太棒了,正需要這個(gè)。頂禮膜拜中~
回復(fù)

使用道具 舉報(bào)

ID:81918 發(fā)表于 2024-1-6 14:00 | 顯示全部樓層

太棒了,正需要這個(gè)。頂禮膜拜中~
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表