久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4443|回復: 1
打印 上一主題 下一主題
收起左側

四軸四元數的51單片機源程序

[復制鏈接]
跳轉到指定樓層
樓主
分享個四軸四元數的51單片機代碼:



單片機源程序如下:
  1. //四川 綿陽      西南科技大學 信息工程學院 電氣13級 劉其民  
  2. //硬件參數:
  3. //電池:1S/3.7V電池 推薦300-500mAh左右
  4. //電機/槳:720空心杯/59MM槳
  5. //MCU IAP15W4K61S4@28.000MHZ  
  6. //陀螺儀加速度計:MPU-6050
  7. //磁場傳感計:HMC5883L
  8. //無線芯片:NRF24L01
  9. //電機驅動MOS管:AO3400
  10. //MOS管保護用肖特基:BAT54ST
  11. //下載口保護用瞬態抑制二極管:RCLAMP0524P
  12. //機架尺寸:94mm*94mm
  13. //標準PID控制公式:PID=P*e(n)+I*[(e(n)+e(n-1)+...+e(0)]+D*[e(n)-e(n-1)]

  14. //數據定義說明:
  15. //data 51單片機片內RAM最前面128字節RAM 用ACC讀寫,速度最快
  16. //idata 片內RAM最前面256字節的RAM 包括data 用類似指針模式訪問 適合用于指針操作
  17. //pdata 外部擴展RAM的前256字節的RAM
  18. //xdata 外部擴展RAM 用DPTR訪問
  19. #include <STC15W4K60S4.H>
  20. #include <intrins.h>
  21. #include <NRF24L01.H>
  22. #include <MPU6050.H>
  23. #include <math.h>
  24. #include <STC15W4KPWM.H>
  25. void Time0_Init();   //定時器初始化
  26. void update();       //陀螺儀矯正
  27. void Kalman_Filter(float Accel,float Gyro);   //X軸卡爾曼濾波
  28. void Kalman_Filter_Y(float Accel,float Gyro);        //Y軸卡爾曼濾波       
  29. //*************************************自整定PID相關參數************************************************
  30. //unsigned char xdata ERRORPID[512]={0};
  31. //unsigned char xdata ZSYPID[100]={0};
  32. //unsigned long int xdata ALLERROR[100]={0};
  33. //unsigned long int TE=0,TZA=0,ADD=0,THEEND=0,LESTERROR=0;
  34. //float BESTPID=0;
  35. //******************************************************************************************************
  36. unsigned char PID=0;                         //無線串口PID調整延時用
  37. int ich1=0,ich2=0,ich3=0,ich4=0;                                     //無線串口待發送數據
  38. int speed0=0,speed1=0,speed2=0,speed3=0,V=0; //電機控制參數
  39. int PWM0=0,PWM1=0,PWM2=0,PWM3=0;             //電機控制參數
  40. unsigned char TxBuf[20]={0};
  41. unsigned char RxBuf[20]={0};
  42. double g_x=0,g_y=0,g_z=0;                    //陀螺儀靜差消除參數
  43. double PID_x=0,PID_y=0,PID_z=0;              //每根軸PID控制量輸出
  44. //******角度參數****************************************************************************************
  45. double Angle_ax=0,Angle_ay=0,Angle_az=0;    //由加速度計算的傾斜角度
  46. double Angle_gy=0,Angle_gx=0,Angle_gz=0;    //由角速度計算的傾斜角度
  47. double AngleAx=0,AngleAy=0;                 //反三角函數處理后的角度值
  48. double Angle=0,Angley=0;                    //最終傾斜角度
  49. double Anglelate=0,Anglelatey=0,Anglezlate=0;//存儲上一次角度數據
  50. double Ax=0,Ay=0;                            //加入遙控器控制量后的角度
  51. float idata dt=0.008;                              //系統周期
  52. //******卡爾曼濾波參數-X軸******************************************************************************
  53. float data Q_angle=0.001;     //對加速度計的信任度
  54. float data Q_gyro=0.003;      //對陀螺儀的信任度
  55. float data R_angle=0.5;
  56. char  data C_0 = 1;
  57. float data Q_bias, Angle_err;
  58. float data PCt_0, PCt_1, E;
  59. float data K_0, K_1, t_0, t_1;
  60. float data Pdot[4] ={0,0,0,0};
  61. float data PP[2][2] = { { 1, 0 },{ 0, 1 } };
  62. void Kalman_Filter(float Accel,float Gyro)               
  63. {
  64.         Angle+=(Gyro - Q_bias) * dt; //陀螺儀積分角度(測量值-陀螺儀偏差)*dt  
  65. //Angle相當于是系統的預測值
  66.         Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // 先驗估計誤差協方差的微分
  67.         Pdot[1]=- PP[1][1];
  68.         Pdot[2]=- PP[1][1];
  69.         Pdot[3]=  Q_gyro;
  70.         PP[0][0] += Pdot[0] * dt;   // 先驗估計誤差協方差微分的積分
  71.         PP[0][1] += Pdot[1] * dt;   
  72.         PP[1][0] += Pdot[2] * dt;
  73.         PP[1][1] += Pdot[3] * dt;
  74.         Angle_err = Accel - Angle;//估計值與預測值之間的偏差
  75.         PCt_0 = C_0 * PP[0][0];
  76.         PCt_1 = C_0 * PP[1][0];
  77.         E = R_angle + C_0 * PCt_0;
  78.         K_0 = PCt_0 / E;//卡爾曼增益1 用于計算最優估計值
  79.         K_1 = PCt_1 / E;//卡爾曼增益2 用于計算最后估計的偏差
  80.         t_0 = PCt_0;
  81.         t_1 = C_0 * PP[0][1];
  82.         PP[0][0] -= K_0 * t_0;                 //更新協方差矩陣
  83.         PP[0][1] -= K_0 * t_1;
  84.         PP[1][0] -= K_1 * t_0;
  85.         PP[1][1] -= K_1 * t_1;
  86.         Angle        += K_0 * Angle_err;//根據卡爾曼增益1算出最優角度
  87.         Q_bias        += K_1 * Angle_err;//根據卡爾曼增益2算出預測值偏差
  88. }
  89. //******卡爾曼濾波參數-Y軸***************************************************************************
  90.                
  91. float data Q_angley=0.001;  
  92. float data Q_gyroy=0.003;
  93. float data R_angley=0.5;
  94. char  data C_0y = 1;
  95. float idata Q_biasy, Angle_erry;
  96. float idata PCt_0y, PCt_1y, Ey;
  97. float idata K_0y, K_1y, t_0y, t_1y;
  98. float idata Pdoty[4] ={0,0,0,0};
  99. float idata PPy[2][2] = { { 1, 0 },{ 0, 1 } };

  100. void Kalman_Filter_Y(float Accely,float Gyroy)               
  101. {
  102.         Angley+=(Gyroy - Q_biasy) * dt;
  103.         Pdoty[0]=Q_angley - PPy[0][1] - PPy[1][0];
  104.         Pdoty[1]=- PPy[1][1];
  105.         Pdoty[2]=- PPy[1][1];
  106.         Pdoty[3]=Q_gyroy;
  107.         PPy[0][0] += Pdoty[0] * dt;   
  108.         PPy[0][1] += Pdoty[1] * dt;   
  109.         PPy[1][0] += Pdoty[2] * dt;
  110.         PPy[1][1] += Pdoty[3] * dt;
  111.         Angle_erry = Accely - Angley;       
  112.         PCt_0y = C_0y * PPy[0][0];
  113.         PCt_1y = C_0y * PPy[1][0];
  114.         Ey = R_angley + C_0y * PCt_0y;
  115.         K_0y = PCt_0y / Ey;
  116.         K_1y = PCt_1y / Ey;
  117.         t_0y = PCt_0y;
  118.         t_1y = C_0y * PPy[0][1];
  119.         PPy[0][0] -= K_0y * t_0y;               
  120.         PPy[0][1] -= K_0y * t_1y;
  121.         PPy[1][0] -= K_1y * t_0y;
  122.         PPy[1][1] -= K_1y * t_1y;
  123.         Angley        += K_0y * Angle_erry;       
  124.         Q_biasy        += K_1y * Angle_erry;       
  125. }
  126. //************姿態處理和PID**************************************************************************
  127. float idata YP=4.5,YD=115.0,YI=0.05,ERRORX;
  128. float idata XP=4.5,XD=115.0,XI=0.05,ERRORY;
  129. float idata ZP=4.0,ZD=2.0;
  130. void Angle_Calcu(void)
  131. {
  132.         Angle_ax=(GetData(ACCEL_XOUT_H))/8192;  //加速度處理
  133.         Angle_az=(GetData(ACCEL_ZOUT_H))/8192;  //加速度量程 +-4g/S
  134.         Angle_ay=(GetData(ACCEL_YOUT_H))/8192;        //轉換關系8192LSB/g

  135.         Angle_gx=(GetData(GYRO_XOUT_H)-g_x)/65.5;   //陀螺儀處理
  136.         Angle_gy=(GetData(GYRO_YOUT_H)-g_y)/65.5;   //陀螺儀量程 +-500度/S
  137.         Angle_gz=(GetData(GYRO_ZOUT_H)-g_z)/65.5;   //轉換關系65.5LSB/度
  138. //**************X軸指向*******************************************************************************
  139.         AngleAx=atan(Angle_ax/sqrt(Angle_ay*Angle_ay+Angle_az*Angle_az))*180/3.141592657;
  140.   
  141.         Anglelate=Ax;
  142.        
  143.         //Angle=0.95*(Angle-Angle_gy*dt)+0.05*AngleAx;//一階互補濾波       這邊是-Angle_gy
  144.        
  145.         Kalman_Filter(AngleAx,-Angle_gy);       //卡爾曼濾波
  146.        
  147.         Ax=Angle+((float)RxBuf[1]-128)/7;  
  148.         ERRORX+=3*Ax;                 //加強靜差積分強度但是不改變輸出控制量的范圍
  149.         if(ERRORX>1000){ERRORX=1000;}if(ERRORX<-1000){ERRORX=-1000;}
  150.         PID_y=Ax*XP+ERRORX*XI+(Ax-Anglelate)*XD;          
  151.         speed0=0+PID_y,speed2=0-PID_y;
  152. //**************Y軸指向*******************************************************************************
  153.   AngleAy=atan(Angle_ay/sqrt(Angle_ax*Angle_ax+Angle_az*Angle_az))*180/3.141592657;

  154.         Anglelatey=Ay;
  155.        
  156.         //Angley=0.95*(Angley+Angle_gx*dt)+0.05*AngleAy;//一階互補濾波     這邊是+Angle_gx
  157.        
  158.         Kalman_Filter_Y(AngleAy,Angle_gx);      //卡爾曼濾波
  159.        
  160.         Ay=Angley+((float)RxBuf[2]-128)/7-RxBuf[4]/20;           //由于結構問題,油門越大,Y軸加速度計輸出偏差越大,RxBuf[4]補償之
  161.         ERRORY+=3*Ay;                 //加強靜差積分強度但是不改變輸出控制量的范圍
  162.         if(ERRORY>1000){ERRORY=1000;}if(ERRORY<-1000){ERRORY=-1000;}
  163.         PID_x=Ay*YP+ERRORY*YI+(Ay-Anglelatey)*YD;          
  164.         speed3=0+PID_x,speed1=0-PID_x;          
  165. //**************Z軸指向*******************************************************************************
  166.         Angle_gz+=(RxBuf[3]-128)/10;
  167.         PID_z=(Angle_gz)*ZP+(Angle_gz-Anglezlate)*ZD;
  168.         Anglezlate=Angle_gz;
  169.         speed0=speed0+PID_z,speed2=speed2+PID_z;
  170.         speed1=speed1-PID_z,speed3=speed3-PID_z;
  171. //*****************無線串口相關***********************************************************************
  172.         ich1=Ax;
  173.         ich2=Ay;
  174.         ich3=AngleAy;
  175.         ich4=XD;
  176. //**************速度更新******************************************************************************       
  177.         if((1000-RxBuf[4]*4+speed0)>1000)PWM0=1000;
  178.         else if((1000-RxBuf[4]*4+speed0)<0)PWM0=0;
  179.         else PWM0=(1000-RxBuf[4]*4+speed0);

  180.         if((1000-RxBuf[4]*4+speed1)>1000)PWM1=1000;
  181.         else if((1000-RxBuf[4]*4+speed1)<0)PWM1=0;
  182.         else PWM1=(1000-RxBuf[4]*4+speed1);

  183.         if((1000-RxBuf[4]*4+speed2)>1000)PWM2=1000;
  184.         else if((1000-RxBuf[4]*4+speed2)<0)PWM2=0;
  185.         else PWM2=(1000-RxBuf[4]*4+speed2);

  186.         if((1000-RxBuf[4]*4+speed3)>1000)PWM3=1000;
  187.         else if((1000-RxBuf[4]*4+speed3)<0)PWM3=0;
  188.         else PWM3=(1000-RxBuf[4]*4+speed3);
  189.   if(RxBuf[4]>=10)
  190.         {PWM(PWM1,PWM2,PWM0,PWM3);}//1203
  191.         else
  192.         {PWM(1000,1000,1000,1000);}
  193. //******************************************以下注釋內容為PID中D的自動整定模式********************************************
  194.         /*         
  195.         if(RxBuf[4]>60&&THEEND==0)
  196.         {
  197.                 if(Ax<0&&Ay>0)
  198.                 {
  199.                 ERRORPID[TE]=-Ax+Ay;
  200.                 }
  201.                 else if(Ax>0&&Ay<0)
  202.                 {
  203.                 ERRORPID[TE]=Ax-Ay;
  204.                 }       
  205.                 else if(Ax<0&&Ay<0)
  206.                 {
  207.                 ERRORPID[TE]=-Ax-Ay;
  208.                 }       
  209.                 else
  210.                 {
  211.                 ERRORPID[TE]=Ax+Ay;
  212.                 }
  213.                 TE++;
  214.                 if(TE==511)
  215.                 {
  216.                         TE=0;
  217.                         ZSYPID[TZA]=XD;
  218.                         XD++;YD++;
  219.                         for(ADD=0;ADD<=510;ADD++)
  220.                                 {
  221.                              ALLERROR[TZA]+=ERRORPID[ADD];
  222.                                 }
  223.                         TZA++;
  224.                         if(TZA==100)
  225.                         {
  226.                                 THEEND=1;
  227.                                 LESTERROR=ALLERROR[1];
  228.                                 for(TE=1;TE<=99;TE++)
  229.                                 {
  230.                                         if(LESTERROR>=ALLERROR[TE])
  231.                                         {
  232.                                                 LESTERROR=ALLERROR[TE];
  233.                                                 BESTPID=ZSYPID[TE];
  234.                                         }
  235.                                 }
  236.                                 XD=YD=BESTPID;
  237.                         }
  238.                 }
  239.         }       
  240.         */
  241. }
  242. void main()
  243. {
  244. Delay(1000);
  245. PWMGO();
  246. init_NRF24L01();
  247. InitMPU6050();
  248. Time0_Init();
  249. RxBuf[1]=128;
  250. RxBuf[2]=128;
  251. RxBuf[3]=128;
  252. RxBuf[4]=0;
  253.         //SetRX_Mode();
  254. while(1)
  255. {          
  256.                     //以下為無線串口助手發送程序
  257.                                 TxBuf[1]=13; TxBuf[6]=13; TxBuf[11]=15; TxBuf[16]=15;
  258.                           if(ich1<0)         {TxBuf[1]=12; ich1=-ich1;}
  259.                                 if(ich2<0)         {TxBuf[6]=12; ich2=-ich2;}
  260.                                 if(ich3<0)         {TxBuf[11]=12; ich3=-ich3;}
  261.                                 if(ich4<0)         {TxBuf[16]=12; ich4=-ich4;}
  262.                                 TxBuf[2]=ich1/1000;        TxBuf[3]=ich1/100%10; TxBuf[4]=ich1%100/10;        TxBuf[5]=ich1%10;         
  263.                                 TxBuf[7]=ich2/1000;        TxBuf[8]=ich2/100%10; TxBuf[9]=ich2%100/10;        TxBuf[10]=ich2%10;
  264.                                 TxBuf[12]=ich3/1000; TxBuf[13]=ich3/100%10;        TxBuf[14]=ich3%100/10; TxBuf[15]=ich3%10;
  265.                                 TxBuf[17]=ich4/1000; TxBuf[18]=ich4/100%10;        TxBuf[19]=ich4%100/10; TxBuf[0]=ich4%10;
  266.                                 //以上為無線串口助手發送程序
  267.                                 nRF24L01_TxPacket(TxBuf);
  268. ……………………

  269. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
四軸-四元數測試版.rar (197.51 KB, 下載次數: 34)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:99242 發表于 2024-10-17 01:16 | 只看該作者
完全看不懂
回復

使用道具 舉報

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

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品不卡 | 久久久久国产精品 | 91超碰在线 | 午夜精品一区二区三区在线播放 | 亚洲精品在线免费 | 日韩欧美网 | 四虎影视1304t | 欧美国产精品一区二区 | 九色91视频 | 不用播放器看的av | 国产精品日韩欧美一区二区三区 | 亚洲成人在线视频播放 | 久久精品久久久久久 | 精品久久久久久亚洲综合网 | 国产成人在线观看免费 | 一区二区三区久久 | 少妇性l交大片免费一 | www.一区二区三区.com | 国产精品视频久久 | 91精品国产综合久久久久久丝袜 | 一级毛片在线看 | 国产精品久久久久久久久久久免费看 | 亚洲欧美中文日韩在线v日本 | 亚洲视频 欧美视频 | 亚洲日本欧美日韩高观看 | 天天干狠狠干 | 91五月婷蜜桃综合 | 亚洲成年影院 | 成人一区精品 | 99亚洲综合 | 欧美成人免费在线 | 国产不卡一区 | 狠狠操电影 | 日韩欧美在线观看 | av毛片在线 | 国产精品污www一区二区三区 | 国产一区二区三区四区在线观看 | xx视频在线观看 | 成人乱人乱一区二区三区软件 | 日韩成人影院 | 色先锋影音 |