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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

KEA128直立小車源碼

[復制鏈接]
跳轉到指定樓層
樓主
kea128的庫


單片機源程序如下:
  1. #include "headfile.h"

  2. /*系統變量初始化部分*/
  3. void PIDStructurePointerInit(PID_Type_Def *PID_Balance, PID_Type_Def *PID_Speed, PID_Type_Def *PID_Path, PID_Type_Def *PID_Diff ){ //PID初始值給定

  4.   PID_Balance->Kp = 8;
  5.   PID_Balance->Kd = 1.2;
  6.   PID_Balance->out = 0;
  7.   
  8.   PID_Speed->Kp = 10;
  9.   PID_Speed->Ki = 0.05;
  10.   PID_Speed->out   = 0;
  11.   
  12.   PID_Path->Kp = 2.0;
  13.   PID_Path->Kd = 0.0;
  14.   PID_Path->offset = 1.0;
  15.   PID_Path->out    = 0;
  16.   
  17.   PID_Diff->Kp = 15.0;
  18.   PID_Diff->Kd = 2.0;
  19.   PID_Diff->Ki = 0.0;
  20.   
  21.   PID_Diff->offset = 0.35;
  22.   PID_Diff->out    = 0;
  23.   
  24.   for(uint8 n=0; n<10; n++){
  25.    
  26.     PID_Balance->err_k[n] = 0;
  27.     PID_Speed->err_k[n]   = 0;
  28.     PID_Path->err_k[n]    = 0;
  29.     PID_Diff->err_k[n]    = 0;  
  30.     PID_Speed->out_k[n]   = 0;
  31.   };
  32.   
  33. };


  34. void SensorStructurePointerInit(Acc_Type_Def *Acc, Gyro_Type_Def *Gyro, Angle_Type_Def *Angle, Speed_Type_Def *Speed, Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB){ //結構體指針初始化成員

  35.   
  36.   /*Gyro*/  
  37.   Gyro->X_Final=0;
  38.   Gyro->X_Offset=0;
  39.   Gyro->X_Value[0]=0;
  40.   Gyro->X_Value[1]=0;
  41.   Gyro->X_Value[2]=0;

  42.   Gyro->Z_Final=0;
  43.   Gyro->Z_Offset=0;
  44.   Gyro->Z_Value[0]=0;
  45.   Gyro->Z_Value[1]=0;
  46.   Gyro->Z_Value[2]=0;
  47.   
  48.   InductorA->LeftFinal=0;
  49.   InductorA->RightFinal=0;
  50.   InductorA->LeftValue[0]=0;
  51.   InductorA->LeftValue[1]=0;
  52.   InductorA->LeftValue[2]=0;
  53.   
  54.   InductorB->LeftFinal=0;
  55.   InductorB->RightFinal=0;
  56.   InductorB->LeftValue[0]=0;
  57.   InductorB->LeftValue[1]=0;
  58.   InductorB->LeftValue[2]=0;

  59.   //角度目標值  也就是平衡值  沒有轉換成角度值 但是是線性關系。
  60.   Angle->PiontValue = 2300;
  61.   
  62.   //速度目標值  沒有轉換成真實速度  與速度線性關系
  63.   Speed->PiontSpeed = 2000;

  64.   
  65.   Speed->PiontSpeedMax=5000;

  66.   Speed->PiontSpeedMin=1500;

  67.   
  68.   
  69.   
  70.   //此處應照車放在賽道上 電感在導線正上方 最大值 電感離導線最遠點為最小值
  71.   InductorA->LeftMax  = 1200;
  72.   InductorA->LeftMin  = 125;
  73.   InductorA->RightMax = 1200;
  74.   InductorA->RightMin = 125;
  75.   
  76.   
  77.   InductorB->LeftMax = 1200;
  78.   InductorB->LeftMin = 125;
  79.   InductorB->RightMax = 1200;
  80.   InductorB->RightMin = 125;
  81.   

  82.   
  83. };


  84. void CarBalanceSystemInit(Gyro_Type_Def *Gyro){//系統初始化

  85.   
  86.   //uart_init(UART1,9600);

  87.   gpio_init(H2,GPO,1);
  88.   
  89.   //關于ADC管腳接的東西 在headfile.h里有定義
  90.   adc_init(ADC0_SE0);       
  91.   adc_init(ADC0_SE1);       
  92.   adc_init(ADC0_SE2);       
  93.   adc_init(ADC0_SE3);       
  94.   adc_init(ADC0_SE4);       
  95.   adc_init(ADC0_SE5);       
  96.   adc_init(ADC0_SE6);
  97.   adc_init(ADC0_SE7);
  98.   
  99.   adc_init(ADC0_SE8);               
  100.   adc_init(ADC0_SE9);       
  101.   adc_init(ADC0_SE10);       
  102.   adc_init(ADC0_SE11);       
  103.   adc_init(ADC0_SE12);       
  104.   adc_init(ADC0_SE13);       
  105.   adc_init(ADC0_SE14);       
  106.   adc_init(ADC0_SE15);
  107.   

  108.   
  109.   
  110.   OLED_Init();
  111.   
  112.   OLED_ShowString(0,0,"SysInit Finish!");
  113.   OLED_ShowString(0,16,"Car balance2.0V");
  114.   OLED_Refresh_Gram();

  115.   // 使用數字陀螺儀  要初始化IIC
  116.   //IIC_init();
  117.   
  118.   
  119.   //此處陀螺儀中值獲取很重要   不過數字陀螺儀默認就是中值 無需獲取  
  120.   // 如果數字陀螺儀中值為0  那么  此處 直接賦值0即可
  121.   Gyro->Z_Offset = adc_once(ADC0_SE2, ADC_12bit);
  122.   Gyro->X_Offset = adc_once(ADC0_SE3, ADC_12bit);
  123.   
  124.   
  125.   systick_delay_ms(10);

  126.   //左電機
  127.   ftm_pwm_init(ftm2,ftm_ch2,13000,0);       
  128.   ftm_pwm_init(ftm2,ftm_ch3,13000,0);               
  129.   
  130.   //右電機  
  131.   ftm_pwm_init(ftm2,ftm_ch4,13000,0);               
  132.   ftm_pwm_init(ftm2,ftm_ch5,13000,0);       
  133.   

  134.   systick_delay_ms(10);  
  135.   
  136.   //ftm的計數引腳可查看KEA128_port_cfg.h文件內的FTM0_COUNT_PIN與FTM1_COUNT_PIN的宏定義得知
  137.   //一個ftm同一時間只能實現一種功能,如果用于測速就不能用于輸出PWM       
  138.   ///////////////////////////////////////////////////////////////////////////////////////////////
  139.   ftm_count_init(ftm0);   //對E0引腳輸入的脈沖進行計數    E0接編碼器LSB   
  140.   gpio_init(E1,GPI,0);    //用于判斷方向                  C5接編碼器DIR
  141.   port_pull(E1);          //IO上拉
  142.   
  143.   ftm_count_init(ftm1);   //對E7引腳輸入的脈沖進行計數    E7接編碼器LSB
  144.   gpio_init(H6,GPI,0);    //用于判斷方向                  H5接編碼器DIR
  145.   port_pull(H6);          //IO上拉
  146.   //////////////////////////////////////////////////////////////////////////////////////////////


  147.   //定時器中斷
  148.   pit_init(pit0,0x9000);//1.539ms
  149.   
  150.   systick_delay_ms(10);  
  151.   
  152.   

  153. };



  154. //絕對值函數   必須要取地址放入形參
  155. void AbsoluteValue(float *Value, float *Return){
  156.   
  157.   if( (*Value) <0) (*Return) = -1*(*Value);
  158.   else *Value = *Return;
  159. }

  160. /*原始數據獲取部分*/
  161. void GetAccelerationValue(Acc_Type_Def *Acc){ //獲取ACC原始數據
  162.   
  163.   Acc->Z_Value[0] = Acc->Z_Value[1];
  164.   Acc->Z_Value[1] = Acc->Z_Value[2];
  165.   Acc->Z_Value[2] = ACC_Z;//本句是獲取當前加速度  上兩句都是 上次值和上上次值

  166.   //利用多次值進行濾波  參數自行調整看效果
  167.   Acc->Z_Final = 0.33*Acc->Z_Value[2]+0.33*Acc->Z_Value[1]+0.33*Acc->Z_Value[0];
  168.   
  169. };

  170. void GetAngleSpeedValue(Gyro_Type_Def *Gyro){  //獲取Gyro原始數據
  171.   
  172.   Gyro->Z_Value[0] = Gyro->Z_Value[1];
  173.   Gyro->Z_Value[1] = Gyro->Z_Value[2];
  174.   Gyro->Z_Value[2] = GYRO_Z - Gyro->Z_Offset;//如果是數字陀螺儀請給Gyro->Z_Offset賦值  在初始化的時候
  175.   
  176.   Gyro->X_Value[0] = Gyro->X_Value[1]; //前前次
  177.   Gyro->X_Value[1] = Gyro->X_Value[2]; //前次
  178.   Gyro->X_Value[2] = GYRO_X - Gyro->X_Offset; //本次
  179.   
  180.   
  181. };


  182. void GetInductorValue(Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB){ //獲取inductor原始數據
  183.   
  184.   
  185.   InductorA->LeftValue[0] = InductorA->LeftValue[1];
  186.   InductorA->LeftValue[1] = InductorA->LeftValue[2];
  187.   InductorA->LeftValue[2] = L1;//本句是獲取當前電感值  L1在haedfile.h文件中有定義
  188.   
  189.   InductorA->RightValue[0] = InductorA->RightValue[1];
  190.   InductorA->RightValue[1] = InductorA->RightValue[2];
  191.   InductorA->RightValue[2] = L2;//本句是獲取當前電感值  L2在haedfile.h文件中有定義
  192.   
  193.   InductorB->LeftValue[0] = InductorB->LeftValue[1];
  194.   InductorB->LeftValue[1] = InductorB->LeftValue[2];
  195.   InductorB->LeftValue[2] = L3;//本句是獲取當前電感值  L3在haedfile.h文件中有定義

  196.   InductorB->RightValue[0] = InductorB->RightValue[1];
  197.   InductorB->RightValue[1] = InductorB->RightValue[2];
  198.   InductorB->RightValue[2] = L4;//本句是獲取當前電感值  L4在haedfile.h文件中有定義
  199.   
  200.   
  201. };

  202. void GetSpeedValue(Speed_Type_Def *Speed){ //獲取Speed原始數據
  203.   
  204.   
  205.   for(uint8 n=0; n<15 ; n++){  //循環誤差保存
  206.    
  207.     //存儲前14次的值  
  208.     Speed->ActualLiftPulse[n] = Speed->ActualLiftPulse[n+1]; //0~14位賦值
  209.    
  210.     if( n==14 ){ //當前值 15次  最新值
  211.       Speed->ActualLiftPulse[n+1] = ftm_count_get(ftm1)*(-1); //本次 15位賦值  
  212.       
  213.       ftm_count_clean(ftm1);  //清除ftm1計數值  
  214.     }//此處一定要修改好 根據你們實際的硬件  對應好左右輪子  因為編碼器是對著安裝的  那么
  215.     //在車子往前走的時候  左右是相反的  所以要把其中一個負值編碼器變為正的
  216.     //兩個電機存在同樣的問題  都是對著安裝的  
  217.   }
  218.   
  219.   
  220.   
  221.   for(uint8 n=0; n<15 ; n++){  //循環保存
  222.    
  223.     Speed->ActualRightPulse[n] = Speed->ActualRightPulse[n+1]; //0~14位賦值
  224.    
  225.     if( n==14 ){
  226.       Speed->ActualRightPulse[n+1] = ftm_count_get(ftm0);  //本次 15位賦值
  227.       ftm_count_clean(ftm0);  //清除ftm0計數值  
  228.     }
  229.    
  230.   }

  231.   if(gpio_get(H6)) //檢測 ftm1的轉向   H6  E1是針對左右編碼器的  要弄清楚 不要到時候改過以后
  232.     //左邊編碼器的方向  去控制右邊編碼器的 正負號   那就完蛋了
  233.     Speed->ActualLiftPulse[15] = Speed->ActualLiftPulse[15];
  234.   else               
  235.     Speed->ActualLiftPulse[15] = -Speed->ActualLiftPulse[15];            
  236.   
  237.   
  238.   if(gpio_get(E1))  //檢測 ftm0的轉向  
  239.     Speed->ActualRightPulse[15] = Speed->ActualRightPulse[15];
  240.   else               
  241.     Speed->ActualRightPulse[15] = -Speed->ActualRightPulse[15]; //這個負號取決于你車向前走時  編碼器值是否為正      
  242.   
  243. };


  244. void GetButtonStatus(Button_Type_Def *Button){ //Button原始數據獲取
  245.   
  246.   Button->Up[0] = Button->Up[1];
  247.   Button->Up[1] = Button->Up[2];
  248.   Button->Up[2] = Button->Up[3];
  249.   Button->Up[3] = Button->Up[4];
  250.   Button->Up[4] = UP;//第四次是最新的值  按鍵值  在haedfile.h文件中有定義
  251.   
  252.   Button->Down[0] = Button->Down[1];
  253.   Button->Down[1] = Button->Down[2];
  254.   Button->Down[2] = Button->Down[3];
  255.   Button->Down[3] = Button->Down[4];
  256.   Button->Down[4] = DOWN;//第四次是最新的值  按鍵值  在haedfile.h文件中有定義
  257.   
  258.   Button->Life[0] = Button->Life[1];
  259.   Button->Life[1] = Button->Life[2];
  260.   Button->Life[2] = Button->Life[3];
  261.   Button->Life[3] = Button->Life[4];
  262.   Button->Life[4] = LIFE;//第四次是最新的值  按鍵值  在haedfile.h文件中有定義
  263.   
  264.   Button->Right[0] = Button->Right[1];
  265.   Button->Right[1] = Button->Right[2];
  266.   Button->Right[2] = Button->Right[3];
  267.   Button->Right[3] = Button->Right[4];
  268.   Button->Right[4] = RIGHT;//第四次是最新的值  按鍵值  在haedfile.h文件中有定義
  269.   
  270.   Button->Enter[0] = Button->Enter[1];
  271.   Button->Enter[1] = Button->Enter[2];
  272.   Button->Enter[2] = Button->Enter[3];
  273.   Button->Enter[3] = Button->Enter[4];
  274.   Button->Enter[4] = ENTER;//第四次是最新的值  按鍵值  在haedfile.h文件中有定義

  275. };


  276. void GetSwitchStatus(Switch_Type_Def *Switch){ //開關原始數據獲取
  277.   
  278.   Switch->Bm1[0] = Switch->Bm1[1];
  279.   Switch->Bm1[1] = Switch->Bm1[2];
  280.   Switch->Bm1[2] = SW1; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義
  281.   
  282.   Switch->Bm2[0] = Switch->Bm2[1];
  283.   Switch->Bm2[1] = Switch->Bm2[2];
  284.   Switch->Bm2[2] = SW2; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義
  285.   
  286.   Switch->Bm3[0] = Switch->Bm3[1];
  287.   Switch->Bm3[1] = Switch->Bm3[2];
  288.   Switch->Bm3[2] = SW3; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義
  289.   
  290.   Switch->Bm4[0] = Switch->Bm4[1];
  291.   Switch->Bm4[1] = Switch->Bm4[2];
  292.   Switch->Bm4[2] = SW4; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義

  293.   Switch->Bm5[0] = Switch->Bm5[1];
  294.   Switch->Bm5[1] = Switch->Bm5[2];
  295.   Switch->Bm5[2] = SW5; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義
  296.   
  297.   Switch->Bm6[0] = Switch->Bm6[1];
  298.   Switch->Bm6[1] = Switch->Bm6[2];
  299.   Switch->Bm6[2] = SW6; //撥碼開關  第四次是最新的值  在haedfile.h文件中有定義
  300. };

  301. /*原始數據處理部分*/
  302. void GyroHighPassFilter(Gyro_Type_Def *Gyro){ //Gyro濾波

  303.   float K =0.58;//權值濾波  看情況調節
  304.   
  305.   Gyro->Z_Value[2] = K * Gyro->Z_Value[2] +  (1-K) * Gyro->Z_Value[1];
  306.   
  307.   Gyro->Z_Final = Gyro->Z_Value[2];


  308.   Gyro->X_Value[2] = K * Gyro->X_Value[2] +  (1-K) * Gyro->X_Value[1];
  309.   
  310.   Gyro->X_Final = Gyro->X_Value[2];
  311.   

  312.   //權值濾波 去除高頻干擾
  313. };


  314. void AngleHardwareFilter(Angle_Type_Def *Angle){ //角度濾波
  315.   //本函數是直接采集角度的  只有模擬陀螺儀和加速度計進行硬件融合直接解算角度值
  316.   
  317.   Angle->ActualValue[0] = Angle->ActualValue[1];
  318.   Angle->ActualValue[1] = Angle->ActualValue[2];
  319.   Angle->ActualValue[2] = ANGLE; //此處是獲取 最新角度值  
  320.   
  321.   //濾波 Angle->FinalValue為最終值
  322.   Angle->FinalValue = 0.6*Angle->ActualValue[2] + 0.2*Angle->ActualValue[1] + 0.2*Angle->ActualValue[0];
  323.   

  324. };

  325. void AngleSoftwareFilter(Acc_Type_Def *Acc, Gyro_Type_Def *Gyro , Angle_Type_Def *Angle){//角度濾波
  326. //本函數是適用于數字陀螺儀 通過軟件互補融合濾波解算角度  
  327.   
  328.   Acc->Z_Final = 0.9*Acc->Z_Value[2] + 0.05*Acc->Z_Value[1] + 0.05*Acc->Z_Value[0];//權值低通濾波
  329.   
  330.   Gyro->Z_Final = 0.92*Gyro->Z_Value[2] + 0.05*Gyro->Z_Value[1] + 0.03*Gyro->Z_Value[0];//權值低通濾波
  331.   
  332.   //加速度  角速度采集
  333.   
  334.   
  335.   //此處參數需要根據  清華方案里的方法去調節參數  看波形法
  336.   Angle->FinalValue = 0.92*(Angle->FinalValue + 0.05*Gyro->Z_Final) + 0.08*(Acc->Z_Final);//融合濾波

  337.   
  338. };


  339. void InductorSoftwareFilter(Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB, Angle_Type_Def *Angle, Switch_Type_Def *Switch){//電感值歸一濾波

  340.   /*權值濾波 警告無視  */
  341.   InductorA->LeftFinal = 0.8*InductorA->LeftValue[2] + 0.15*InductorA->LeftValue[1] + 0.05*InductorA->LeftValue[0];//-InductorA->LeftMin;
  342.   InductorA->RightFinal = 0.8*InductorA->RightValue[2] + 0.15*InductorA->RightValue[1] + 0.05*InductorA->RightValue[0];//-InductorA->RightMin;
  343.   
  344.   InductorB->LeftFinal = 0.8*InductorB->LeftValue[2] + 0.15*InductorB->LeftValue[1] + 0.05*InductorB->LeftValue[0];
  345.   InductorB->RightFinal = 0.8*InductorB->RightValue[2] + 0.15*InductorB->RightValue[1] + 0.05*InductorB->RightValue[0];




  346.   /*數據歸一化到0~1000*/
  347.   InductorA->LeftFinal  =  1000*( (float)(InductorA->LeftFinal-InductorA->LeftMin)/(InductorA->LeftMax-InductorA->LeftMin) );
  348.   InductorA->RightFinal  = 1000*( (float)(InductorA->RightFinal-InductorA->RightMin)/(InductorA->RightMax-InductorA->RightMin) );
  349.   
  350.   InductorB->LeftFinal  =  1000*( (float)(InductorB->LeftFinal-InductorB->LeftMin)/(InductorB->LeftMax-InductorB->LeftMin) );
  351.   InductorB->RightFinal  = 1000*( (float)(InductorB->RightFinal-InductorB->RightMin)/(InductorB->RightMax-InductorB->RightMin) );
  352.   
  353.   if(InductorA->LeftFinal>999)InductorA->LeftFinal=999;
  354.   if(InductorA->LeftFinal<  0)InductorA->LeftFinal=  0;
  355.   if(InductorA->RightFinal>999)InductorA->RightFinal=999;
  356.   if(InductorA->RightFinal< 0)InductorA->RightFinal=   0;
  357.   
  358.   
  359.   if(InductorB->LeftFinal>999)InductorB->LeftFinal=999;
  360.   if(InductorB->LeftFinal<  0)InductorB->LeftFinal=  0;
  361.   if(InductorB->RightFinal>999)InductorB->RightFinal=999;
  362.   if(InductorB->RightFinal< 0)InductorB->RightFinal=   0;
  363.   
  364.   //電感AB  A 是靠外側的電感  B是靠內側電感    RL就是左右
  365.   
  366.   InductorA->AndValues = InductorA->LeftFinal+InductorA->RightFinal;//電感和值
  367.   
  368.   InductorA->LeftDerivative = InductorA->LeftValue[2] - InductorA->LeftValue[0]; //左點感變化率
  369.   
  370.   InductorA->RightDerivative= InductorA->RightValue[2] - InductorA->RightValue[0];//右電感變化率
  371.   
  372.   InductorB->LeftDerivative = InductorB->LeftValue[2] - InductorB->LeftValue[0];
  373.   
  374. };


  375. void SpeedSoftwareFilter(Speed_Type_Def *Speed){   //速度低通濾波
  376.    
  377.   /*警告無視*/
  378.   Speed->ActualLiftPulse[15]=0.33*Speed->ActualLiftPulse[15] + 0.33*Speed->ActualLiftPulse[14] + 0.33*Speed->ActualLiftPulse[13];
  379.   Speed->ActualRightPulse[15]=0.33*Speed->ActualRightPulse[15] + 0.33*Speed->ActualRightPulse[14] + 0.33*Speed->ActualRightPulse[13];
  380.   // 6 2 2
  381.   
  382.   //實際速度 = R+L
  383.   Speed->ActualSpeed[0] = Speed->ActualSpeed[1];
  384.   Speed->ActualSpeed[1] = Speed->ActualSpeed[2];
  385.   Speed->ActualSpeed[2] =
  386.     (Speed->ActualRightPulse[0]+Speed->ActualLiftPulse[0])+
  387.     (Speed->ActualRightPulse[1]+Speed->ActualLiftPulse[1])+                    
  388.     (Speed->ActualRightPulse[2]+Speed->ActualLiftPulse[2])+
  389.     (Speed->ActualRightPulse[3]+Speed->ActualLiftPulse[3])+
  390.     (Speed->ActualRightPulse[4]+Speed->ActualLiftPulse[4])+
  391.     (Speed->ActualRightPulse[5]+Speed->ActualLiftPulse[5])+
  392.     (Speed->ActualRightPulse[6]+Speed->ActualLiftPulse[6])+
  393.     (Speed->ActualRightPulse[7]+Speed->ActualLiftPulse[7])+
  394.     (Speed->ActualRightPulse[8]+Speed->ActualLiftPulse[8])+
  395.     (Speed->ActualRightPulse[9]+Speed->ActualLiftPulse[9])+
  396.     (Speed->ActualRightPulse[10]+Speed->ActualLiftPulse[10])+
  397.     (Speed->ActualRightPulse[11]+Speed->ActualLiftPulse[11])+
  398.     (Speed->ActualRightPulse[12]+Speed->ActualLiftPulse[12])+
  399.     (Speed->ActualRightPulse[13]+Speed->ActualLiftPulse[13])+
  400.     (Speed->ActualRightPulse[14]+Speed->ActualLiftPulse[14])+
  401.     (Speed->ActualRightPulse[15]+Speed->ActualLiftPulse[15]);
  402.   
  403.   //濾波
  404.   Speed->ActualSpeed[2] = 0.85*Speed->ActualSpeed[2]+0.1*Speed->ActualSpeed[1]+0.05*Speed->ActualSpeed[0];
  405.   //7 2 1
  406.   
  407.   
  408.   //實際差速  = L-R
  409.   Speed->ActualDifferential[0] = Speed->ActualDifferential[1];
  410.   Speed->ActualDifferential[1] = Speed->ActualDifferential[2];
  411.   Speed->ActualDifferential[2] = Speed->ActualLiftPulse[15]-Speed->ActualRightPulse[15];
  412.   Speed->ActualDifferential[2] = 0.8*Speed->ActualDifferential[2]+0.15*Speed->ActualDifferential[1]+0.05*Speed->ActualDifferential[0];
  413.   //實際差速
  414.   
  415.   
  416.   Speed->ActualInstantaneous[0] = Speed->ActualInstantaneous[1];  
  417.   Speed->ActualInstantaneous[1] = Speed->ActualInstantaneous[2];
  418.   Speed->ActualInstantaneous[2] = (Speed->ActualLiftPulse[15]+Speed->ActualRightPulse[15] + (Speed->ActualLiftPulse[14]+Speed->ActualRightPulse[14])) ;
  419.   //瞬時速度計算
  420.   
  421.   Speed->ActualAcceleration = Speed->ActualInstantaneous[2] - Speed->ActualInstantaneous[0];
  422.   //加速度計算
  423.   
  424.   
  425.   
  426. };


  427. void ButtonLowPassFilter(Button_Type_Def *Button){ //按鍵低通濾波
  428.   
  429.   Button->Up_Final = Button->Up[0] || Button->Up[1] || Button->Up[2] || Button->Up[3] || Button->Up[4];
  430.   //有一個1  最終值就是1 全部為0 最終值才為0
  431.   if(Button->Up_Final==1) Button->Up_Final = 0;//取反    以1為有效值
  432.   else Button->Up_Final = 1;
  433.   
  434.   
  435.   Button->Down_Final = Button->Down[0] || Button->Down[1] || Button->Down[2] || Button->Down[3] || Button->Down[4];
  436.   //有一個1  最終值就是1 全部為0 最終值才為0
  437.   if(Button->Down_Final==1) Button->Down_Final = 0;//取反    以1為有效值
  438.   else Button->Down_Final = 1;
  439.   
  440.   
  441.   Button->Life_Final = Button->Life[0] || Button->Life[1] || Button->Life[2] || Button->Life[3] || Button->Life[4];
  442.   //有一個1  最終值就是1 全部為0 最終值才為0
  443.   if(Button->Life_Final==1) Button->Life_Final = 0;//取反    以1為有效值
  444.   else Button->Life_Final = 1;
  445.   
  446.   
  447.   Button->Right_Final = Button->Right[0] || Button->Right[1] || Button->Right[2] || Button->Right[3] || Button->Right[4];
  448.   //有一個1  最終值就是1 全部為0 最終值才為0
  449.   if(Button->Right_Final==1) Button->Right_Final = 0;//取反    以1為有效值
  450.   else Button->Right_Final = 1;
  451.   
  452.   
  453.   Button->Enter_Final = Button->Enter[0] || Button->Enter[1] || Button->Enter[2] || Button->Enter[3] || Button->Enter[4];
  454.   //有一個1  最終值就是1 全部為0 最終值才為0
  455.   if(Button->Enter_Final==1) Button->Enter_Final = 0;//取反    以1為有效值
  456.   else Button->Enter_Final = 1;
  457.   
  458. };

  459. void SwitchLowPassFilter(Switch_Type_Def *Switch){ //開關低通濾波
  460.   
  461.   Switch->Bm1_Final = Switch->Bm1[0] || Switch->Bm1[1] || Switch->Bm1[2];
  462.   if(Switch->Bm1_Final==1) Switch->Bm1_Final = 0;//取反    以1為有效值
  463.   else Switch->Bm1_Final = 1;
  464.   
  465.   Switch->Bm2_Final = Switch->Bm2[0] || Switch->Bm2[1] || Switch->Bm2[2];
  466.   if(Switch->Bm2_Final==1) Switch->Bm2_Final = 0;//取反    以1為有效值
  467.   else Switch->Bm2_Final = 1;
  468.   
  469.   Switch->Bm3_Final = Switch->Bm3[0] || Switch->Bm3[1] || Switch->Bm3[2];
  470.   if(Switch->Bm3_Final==1) Switch->Bm3_Final = 0;//取反    以1為有效值
  471.   else Switch->Bm3_Final = 1;
  472.   
  473.   Switch->Bm4_Final = Switch->Bm4[0] || Switch->Bm4[1] || Switch->Bm4[2];
  474.   if(Switch->Bm4_Final==1) Switch->Bm4_Final = 0;//取反    以1為有效值
  475.   else Switch->Bm4_Final = 1;
  476.   
  477.   Switch->Bm5_Final = Switch->Bm5[0] || Switch->Bm5[1] || Switch->Bm5[2];
  478.   if(Switch->Bm5_Final==1) Switch->Bm5_Final = 0;//取反    以1為有效值
  479.   else Switch->Bm5_Final = 1;
  480.   
  481.   Switch->Bm6_Final = Switch->Bm6[0] || Switch->Bm6[1] || Switch->Bm6[2];
  482.   if(Switch->Bm6_Final==1) Switch->Bm6_Final = 0;//取反    以1為有效值
  483.   else Switch->Bm6_Final = 1;
  484. };


  485. void OutOfControlSignal(Speed_Type_Def *Speed, PID_Type_Def *PID){   //速度失控信號檢測
  486.   
  487.   if( (Speed->ActualSpeed[2]-Speed->ActualSpeed[1]) > 400  &&  Speed->ActualSpeed[2]>10000){
  488.     //加速度過大 車輪空轉

  489.    
  490.     ftm_pwm_duty(ftm2,ftm_ch2,0);
  491.     ftm_pwm_duty(ftm2,ftm_ch3,0);
  492.     ftm_pwm_duty(ftm2,ftm_ch4,0);
  493.     ftm_pwm_duty(ftm2,ftm_ch5,0);
  494. //   
  495.    
  496.    
  497.     while(1){
  498.       
  499. //     led(LED0,LED_ON);  //根據你們的硬件設置報警燈
  500.       
  501.       systick_delay_ms(80);
  502.       
  503. //      led(LED0,LED_OFF);
  504.       
  505.       systick_delay_ms(80);
  506.    
  507.     };

  508.   }

  509. };



  510. /*被控制量處理部分*/
  511. void BalanceFeedbackControl(PID_Type_Def *PID, Angle_Type_Def *Angle, Gyro_Type_Def *Gyro, Ramp_Type_Def *Ramp){ //直立反饋控制
  512.   
  513.   PID->err = (Angle->PiontValue-Angle->FinalValue);//硬件
  514.   //偏差  =  角度目標-角度反饋值
  515.   
  516.   
  517.   PID->out =   1000 + PID->Kp * PID->err + PID->Kd * Gyro->Z_Final;
  518.   //1000是為了給一個PWM中點   Gyro->Z_Final就是 直立的角速度  也就是D控制  PD
  519.   
  520.   //一般情況下  調直立時   先給一個P參數  D給0   就能立起來   如果發現不能立瘋轉  
  521.   //多半是 pid方向相反    把(Angle->PiontValue-Angle->FinalValue)  里面調換下位置  即可
  522.   
  523.   

  524. };


  525. void DirectionFeedbackControl(PID_Type_Def *PID, Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB, Gyro_Type_Def *Gyro, Speed_Type_Def *Speed, Ramp_Type_Def *Ramp){ //方向反饋控制

  526.   
  527.   InductorA->RightFinal = PID->offset*InductorA->RightFinal;  
  528.   InductorA->LeftFinal = (2-PID->offset)*InductorA->LeftFinal;
  529.   //調整零偏
  530.   

  531.   //主要是在用 A電感
  532.   
  533.   PID->err = 10.0*(sqrt(1.0*InductorA->RightFinal)-sqrt(1.0*InductorA->LeftFinal) )/ (InductorA->RightFinal+InductorA->LeftFinal);
  534.   
  535.   
  536.   
  537.    
  538.   if( InductorA->AndValues < 25 && Ramp->Flag[0]!=1) {//丟線找回 且不在坡道
  539.    
  540.     PID->err += 0.55*PID->err_k[6]; //找回強度

  541.   }
  542.   else if( InductorA->AndValues < 50 && Ramp->Flag[0]!=1) {//丟線找回
  543.    
  544.     PID->err += 0.50*PID->err_k[6]; //找回強度
  545.   
  546.   }
  547.   else if( InductorA->AndValues < 75 && Ramp->Flag[0]!=1) {//丟線找回
  548.    
  549.     PID->err += 0.45*PID->err_k[7]; //找回強度
  550.   
  551.   }
  552.   else if( InductorA->AndValues < 100 && Ramp->Flag[0]!=1) {//丟線找回
  553.    
  554.     PID->err += 0.40*PID->err_k[7]; //找回強度
  555.   
  556.   }
  557.   else if( InductorA->AndValues < 125 && Ramp->Flag[0]!=1) {//丟線找回
  558.    
  559.     PID->err += 0.35*PID->err_k[8]; //找回強度
  560.   
  561.   }
  562.   else if( InductorA->AndValues< 150 && Ramp->Flag[0]!=1) {//丟線找回
  563.    
  564.     PID->err += 0.30*PID->err_k[8]; //找回強度
  565.   
  566.   }
  567.   else if( InductorA->AndValues < 175 && Ramp->Flag[0]!=1) {//丟線找回
  568.    
  569.     PID->err += 0.25*PID->err_k[9]; //找回強度9
  570.   
  571.   }
  572.   else if( InductorA->AndValues < 200 && Ramp->Flag[0]!=1) {//丟線找回200
  573.    
  574.     PID->err += 0.2*PID->err_k[9]; //找回強度9
  575.   
  576.   }
  577.   
  578.   if(InductorA->AndValues<150)  PID->err = 0;
  579.   


  580.   PID->out = PID->Kp * PID->err * Speed->ActualInstantaneous[2] + PID->Kd * Gyro->X_Final;
  581.   //轉向PID輸出計算 Gyro->X_Final; 是轉向角速度 也是D控制
  582.   
  583.   
  584.   Speed->PiontDifferential = (int16)(PID->out);  //給定差速環目標值
  585.   //把轉向環  計算出來的輸出值  給差速目標環
  586.   
  587.   for(uint8 n=0; n<9 ; n++){  //循環誤差保存
  588.    
  589.     PID->err_k[n] = PID->err_k[n+1]; //0~8位賦值
  590.    
  591.     if( n==8 )
  592.       PID->err_k[n+1] = PID->err;  //本次 9位賦值
  593.    
  594.   }
  595.   
  596. };


  597. void DifferentialFeedbackControl(PID_Type_Def *PID, Speed_Type_Def *Speed, Gyro_Type_Def *Gyro){//差速反饋控制
  598.      
  599.   //PID->offset只是一個比例分配  PID->offset=2     
  600.   
  601.   int16 SpeedDifferentialValue = PID->offset * Speed->ActualDifferential[2] + (1-PID->offset)*(-0.18*Gyro->X_Final);
  602.   //  得到差速值  是編碼器和   轉向角速度共同決定差速反饋值
  603.   
  604.   
  605.   //Speed->PiontDifferential = 0;
  606.   //差速目標-  差速實際值
  607.   PID->err = ( Speed->PiontDifferential -  SpeedDifferentialValue);

  608.   PID->integral += PID->err;
  609.   
  610.   //積分上下限
  611.   if(PID->integral>50000)PID->integral=50000;
  612.   
  613.   if(PID->integral<-50000)PID->integral=-50000;
  614.   
  615.   if(Speed->ActualSpeed[2]< 50)PID->integral = 0;
  616.   //低速積分清零
  617.   
  618.   PID->out =  PID->Kp * PID->err + PID->Kd * ( SpeedDifferentialValue + PID->err_k[0]);// + PID->Ki * PID->integral;
  619.   //PID計算
  620.   
  621.   for(uint8 n=0; n<9 ; n++){  //循環誤差保存
  622.    
  623.     PID->err_k[n] = PID->err_k[n+1]; //0~8位賦值
  624.    
  625.     if( n==8 )
  626.       PID->err_k[n+1] = PID->err;  //本次 9位賦值
  627.    
  628.   }
  629.   

  630.   PID->err_k[0] = SpeedDifferentialValue;//借用一下PID->err_k[0]咯  存入上次值 差速
  631.   

  632.   //輸出幅度限制   
  633.   if(PID->out>2000)PID->out=2000;//1800
  634.   if(PID->out<-2000)PID->out=-2000;


  635.   
  636. };

  637. void SpeedFeedbackControl(PID_Type_Def *PID, Speed_Type_Def *Speed, Ramp_Type_Def *Ramp, Switch_Type_Def *Switch){ //速度反饋控制
  638.   

  639.   PID->out_k[9] = PID->out;//保存成上一次輸出值
  640.   
  641.   PID->out_k[0] = 0;
  642.   
  643.   
  644.   
  645.   PID->err = Speed->ActualSpeed[2] - Speed->PiontSpeed;
  646.   
  647.   
  648.   PID->integral = PID->err_k[0]+PID->err_k[1]+PID->err_k[2]+PID->err_k[3]+PID->err_k[4]+
  649.   
  650.           PID->err_k[5]+PID->err_k[6]+PID->err_k[7]+PID->err_k[8]+PID->err_k[9]+PID->err;



  651.   PID->out = PID->Kp * PID->err;// + PID->Ki * PID->integral;
  652.   
  653.   PID->out *= 0.05; //縮小速度環輸出
  654.   
  655.   
  656.   if(PID->out >  4800) PID->out= 4800; //后退最低角度4200
  657.   
  658.   if(PID->out < -1800) PID->out= -1800;//前進最低角度-1800

  659.   

  660.   
  661.   for(uint8 n=0; n<9 ; n++){  //循環誤差保存
  662.    
  663.     PID->err_k[n] = PID->err_k[n+1]; //0~8位賦值
  664.    
  665.     if( n==8 )
  666.       PID->err_k[n+1] = PID->err;  //本次 9位賦值
  667.    
  668.   }
  669.   

  670. };

  671. void PWMFeedbackControl(PWM_Type_Def *PWM, PID_Type_Def *PID_Balance, PID_Type_Def *PID_Speed, PID_Type_Def *PID_Path, PID_Type_Def *PID_Diff, Speed_Type_Def *Speed, Switch_Type_Def *Switch){ //PWM疊加反饋控制
  672.   
  673.   float DiffK=1;

  674.    
  675.   PID_Speed->out_k[0] += (PID_Speed->out - PID_Speed->out_k[9]) * 0.0625;//分段成1/16分增量
  676.   
  677.   //PID_Speed->out_k[9]是上次值 //PID_Speed->out是本次值  PID_Speed->out_k[0] 是平滑輸出增量值
  678.   //疊加的時候把   平滑輸出增量值 + 上次的值 得到16個周期內 每4ms周期應給的值
  679.   
  680.   PWM->PiontValue  = (int16)(PID_Balance->out)+ (int16)(PID_Speed->out_k[0] + PID_Speed->out_k[9]) ;
  681.   //把所有環輸出相加
  682.   
  683.   
  684.   PWM->Differential = (int16)(PID_Diff->out);
  685. //差速PWM
  686.   
  687.   
  688.   if(PWM->Differential>0){
  689.    
  690.     PWM->LiftValue = PWM->PiontValue + (DiffK) * PWM->Differential;
  691.   
  692.     PWM->RightValue = PWM->PiontValue - (2-DiffK) * PWM->Differential;      
  693.    
  694.   }
  695.   
  696.   if(PWM->Differential<0){ //差速小于零時  左邊給目標占空比+ 系數*差速
  697.    
  698.     PWM->LiftValue = PWM->PiontValue + (2-DiffK) * PWM->Differential;
  699.   
  700.     PWM->RightValue = PWM->PiontValue - (DiffK) * PWM->Differential;      
  701.    
  702.   }
  703.   
  704.   
  705.   if(PWM->Differential==0){  //差速=0時  左右給一樣的目標占空比
  706.    
  707.     PWM->LiftValue = PWM->PiontValue;
  708.    
  709.     PWM->RightValue = PWM->PiontValue;
  710.   }
  711. };

  712. void ButtonFunctionControl(PID_Type_Def *PID_Balance, PID_Type_Def *PID_Speed, PID_Type_Def *PID_Path, PID_Type_Def *PID_Diff, Angle_Type_Def *Angle, Speed_Type_Def *Speed, Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB, Button_Type_Def *Button, uint8 *Page){ //按鍵功能實現
  713.   //OLED  按鍵 調節PID參數用的   
  714.   
  715.   
  716.   if(Button->Life_Final==1)if(*Page>0)(*Page)--;
  717.   
  718.   if(Button->Right_Final==1)if(*Page<135)(*Page)++;

  719.   //page0
  720.   if(*Page<=5){  //UP  kp
  721.    
  722.     if(Button->Up_Final==1 ){

  723.       if(PID_Balance->Kp<30) PID_Balance->Kp = PID_Balance->Kp+0.01;
  724.     }
  725.         
  726.     if(Button->Down_Final==1 ){

  727.       if(PID_Balance->Kp>0) PID_Balance->Kp = PID_Balance->Kp-0.01;
  728.     }

  729.   }

  730.   if(*Page<=10 && *Page>5){  //UP  kd
  731.    
  732.     if(Button->Up_Final==1){
  733.   
  734.       if(PID_Balance->Kd<30) PID_Balance->Kd = PID_Balance->Kd+0.01;
  735.     }
  736.         
  737.     if(Button->Down_Final==1){
  738.    
  739.       if(PID_Balance->Kd>0) PID_Balance->Kd = PID_Balance->Kd-0.01;
  740.     }
  741.    
  742.   }
  743.   
  744.   if(*Page<=15 && *Page>10){  // angle piont
  745.    
  746.     if(Button->Up_Final==1){
  747.   
  748.       if(Angle->PiontValue<2400) Angle->PiontValue = Angle->PiontValue+1;
  749.     }
  750.         
  751.     if(Button->Down_Final==1){
  752.    
  753.       if(Angle->PiontValue>1600) Angle->PiontValue = Angle->PiontValue-1;
  754.     }
  755.    
  756.   }
  757.    
  758.   if(*Page<=20 && *Page>15){  //speed kp
  759.    
  760.    
  761.     if(Button->Up_Final==1){
  762.    
  763.       if(PID_Speed->Kp<30)PID_Speed->Kp = PID_Speed->Kp+0.1;

  764.     }
  765.       
  766.    
  767.     if(Button->Down_Final==1){      
  768.   
  769.       if(PID_Speed->Kp>0)PID_Speed->Kp = PID_Speed->Kp-0.1;
  770.    
  771.     }
  772.    
  773.    
  774.   }

  775.   if(*Page<=25 && *Page>20){  //speed ki
  776.    
  777.    
  778.     if(Button->Up_Final==1){
  779.   
  780.       if(PID_Speed->Ki<10)PID_Speed->Ki = PID_Speed->Ki+0.001;
  781.     }
  782.         
  783.    
  784.     if(Button->Down_Final==1){  

  785.       if(PID_Speed->Ki>0)PID_Speed->Ki = PID_Speed->Ki-0.001;
  786.     }

  787.    
  788.   }
  789.   
  790.   if(*Page<=30 && *Page>25){  //speeed piont
  791.    
  792.     if(Button->Up_Final==1){
  793.   
  794.       if(Speed->PiontSpeed<10000)Speed->PiontSpeed = Speed->PiontSpeed+10;
  795.     }
  796.         
  797.     if(Button->Down_Final==1){

  798.       if(Speed->PiontSpeed>0)Speed->PiontSpeed = Speed->PiontSpeed-10;
  799.     }
  800.    
  801.    
  802.   }

  803.   
  804.   
  805.   
  806.   //page1
  807.   if(*Page<=35 && *Page>30){  //path kp
  808.    
  809.     if(Button->Up_Final==1){

  810.       if(PID_Path->Kp<30)PID_Path->Kp = PID_Path->Kp+0.01;
  811.     }
  812.         
  813.     if(Button->Down_Final==1 ){

  814.       if(PID_Path->Kp>0)PID_Path->Kp = PID_Path->Kp-0.01;
  815.     }

  816.    
  817.   }
  818.   
  819.   if(*Page<=40 && *Page>35){  //path kd
  820.    
  821.    
  822.     if(Button->Up_Final==1){

  823.       if(PID_Path->Kd<30)PID_Path->Kd = PID_Path->Kd+0.01;
  824.     }
  825.         
  826.     if(Button->Down_Final==1){
  827.    
  828.       if(PID_Path->Kd>0)PID_Path->Kd = PID_Path->Kd-0.01;
  829.     }

  830.   }
  831.   
  832.   if(*Page<=45 && *Page>40){  //path piont
  833.    
  834.    
  835.     if(Button->Up_Final==1){
  836.       
  837.       if(PID_Path->offset<2)PID_Path->offset = PID_Path->offset+0.001;
  838.    
  839.     }
  840.       
  841.     if(Button->Down_Final==1){
  842.    
  843.       if(PID_Path->offset>0)PID_Path->offset = PID_Path->offset-0.001;
  844.    
  845.     }
  846.    
  847.    
  848.   }
  849.   
  850.   if(*Page<=50 && *Page>45){  //diff kp
  851.    
  852.     if(Button->Up_Final==1){

  853.       if(PID_Diff->Kp<30)PID_Diff->Kp = PID_Diff->Kp+0.01;
  854.     }
  855.         
  856.     if(Button->Down_Final==1 ){

  857.       if(PID_Diff->Kp>0)PID_Diff->Kp = PID_Diff->Kp-0.01;
  858.     }

  859.    
  860.   }
  861.   
  862.   if(*Page<=55 && *Page>50){  //diff kd
  863.    
  864.     if(Button->Up_Final==1){

  865.       if(PID_Diff->Kd<30)PID_Diff->Kd = PID_Diff->Kd+0.01;
  866.     }
  867.         
  868.     if(Button->Down_Final==1 ){

  869.       if(PID_Diff->Kd>0)PID_Diff->Kd = PID_Diff->Kd-0.01;
  870.     }

  871.    
  872.   }
  873.    
  874.   if(*Page<=60 && *Page>55){  //diff kd
  875.    
  876.     if(Button->Up_Final==1){

  877.       if(PID_Diff->Ki<30)PID_Diff->Ki = PID_Diff->Ki+0.01;
  878.     }
  879.         
  880.     if(Button->Down_Final==1 ){

  881.       if(PID_Diff->Ki>0)PID_Diff->Ki = PID_Diff->Ki-0.01;
  882.     }

  883.    
  884.   }
  885.   
  886.   if(*Page<=65 && *Page>60){  //diff offset
  887.    
  888.     if(Button->Up_Final==1){

  889.       if(PID_Diff->offset<1)PID_Diff->offset = PID_Diff->offset+0.001;
  890.     }
  891.         
  892.     if(Button->Down_Final==1 ){

  893.       if(PID_Diff->offset>0)PID_Diff->offset = PID_Diff->offset-0.001;
  894.     }

  895.    
  896.   }
  897.   
  898.   

  899.   
  900.   
  901.   //page2
  902.   if(*Page<=70 && *Page>65){ //左電感最大值
  903.    
  904.     if(Button->Up_Final==1 && InductorA->LeftMax < 4000)InductorA->LeftMax ++;
  905.         
  906.    
  907.     if(Button->Down_Final==1 && InductorA->LeftMax > 100)InductorA->LeftMax --;
  908.    
  909.    
  910.   }
  911.   
  912.   if(*Page<=75 && *Page>70){ //左電感最小值
  913.    
  914.    
  915.     if(Button->Up_Final==1 && InductorA->LeftMin < 4000)InductorA->LeftMin ++;
  916.         
  917.    
  918.     if(Button->Down_Final==1 && InductorA->LeftMin > 100)InductorA->LeftMin --;
  919.    
  920.   }
  921.   
  922.   if(*Page<=80 && *Page>75){ //右電感最大值
  923.    
  924.     if(Button->Up_Final==1 && InductorA->RightMax < 4000)InductorA->RightMax ++;
  925.         
  926.    
  927.     if(Button->Down_Final==1 && InductorA->RightMax > 100)InductorA->RightMax --;
  928.    
  929.    
  930.   }
  931.   
  932.   if(*Page<=85 && *Page>80){ //右電感最小值
  933.    
  934.    
  935.     if(Button->Up_Final==1 && InductorA->RightMin< 4000)InductorA->RightMin ++;
  936.         
  937.    
  938.     if(Button->Down_Final==1 && InductorA->RightMin> 100)InductorA->RightMin --;
  939.    
  940.   }
  941.   
  942.   if(*Page<=90 && *Page>85){ //中間電感最大值
  943.    
  944.    
  945.     if(Button->Up_Final==1 && InductorB->LeftMax< 4000)InductorB->LeftMax ++;
  946.         
  947.    
  948.     if(Button->Down_Final==1 && InductorB->LeftMax> 100)InductorB->LeftMax --;
  949.    
  950.   }
  951.   
  952.   if(*Page<=95 && *Page>90){//中間電感最小值
  953.    
  954.    
  955.     if(Button->Up_Final==1 && InductorB->LeftMin< 4000)InductorB->LeftMin ++;
  956.         
  957.    
  958.     if(Button->Down_Final==1 && InductorB->LeftMin> 100)InductorB->LeftMin --;
  959.    
  960.   }
  961.   
  962.   if(*Page<=100 && *Page>95){//最大速度
  963.    
  964.    
  965.     if(Button->Up_Final==1 && Speed->PiontSpeedMax<10000)Speed->PiontSpeedMax ++;
  966.         
  967.    
  968.     if(Button->Down_Final==1 && Speed->PiontSpeedMax >0)Speed->PiontSpeedMax --;
  969.    
  970.   }
  971.   
  972.   if(*Page<=105 && *Page>100){//最小速度
  973.   
  974.     if(Button->Up_Final==1 && Speed->PiontSpeedMin < Speed->PiontSpeedMax)Speed->PiontSpeedMin ++;
  975.         
  976.    
  977.     if(Button->Down_Final==1 && Speed->PiontSpeedMin > 0)Speed->PiontSpeedMin --;
  978.    
  979.    
  980.   }

  981.   
  982. //  
  983. //  //page3
  984. //  if(*Page<=110 && *Page>105){//減速距離
  985. //   
  986. //    if(Button->Up_Final==1 && Speed->SlowDistance < 6000)Speed->SlowDistance ++;
  987. //        
  988. //   
  989. //    if(Button->Down_Final==1 && Speed->SlowDistance > 0)Speed->SlowDistance --;
  990. //  }
  991. //  
  992. //  if(*Page<=115 && *Page>110){//加速距離
  993. //   
  994. //    if(Button->Up_Final==1 && Speed->AccDistance < 6000)Speed->AccDistance ++;
  995. //        
  996. //   
  997. //    if(Button->Down_Final==1 && Speed->AccDistance > 0)Speed->AccDistance --;
  998. //  }
  999. //  
  1000. //  if(*Page<=120 && *Page>115){//錯誤距離
  1001. //   
  1002. //    if(Button->Up_Final==1 && Speed->FaultDistance < 150000)Speed->FaultDistance+=100;
  1003. //        
  1004. //   
  1005. //    if(Button->Down_Final==1 && Speed->FaultDistance > 100)Speed->FaultDistance-=100;
  1006. //  }
  1007.   
  1008. };


  1009. /*輸出量處理部分*/
  1010. void PrintParameterToOLED(PID_Type_Def *PID_Balance, PID_Type_Def *PID_Speed, PID_Type_Def *PID_Path, PID_Type_Def *PID_Diff, Angle_Type_Def *Angle, Speed_Type_Def *Speed , PWM_Type_Def *PWM, Inductor_Type_Def *InductorA, Inductor_Type_Def *InductorB, Curve_Type_Def *Curve, uint8 Page){    //打印參數到OLED上

  1011.   uint8 mode[10];
  1012.   static uint8 Last=0;
  1013.   
  1014.   if(Page<=30){   
  1015.   
  1016.     if(Page<=5) mode[0] = 0;
  1017.     else mode[0] = 1;
  1018.    
  1019.     if(Page<=10 && Page>5) mode[1] =0;
  1020.     else mode[1] = 1;
  1021.    
  1022.     if(Page<=15 && Page>10) mode[2] =0;
  1023.     else mode[2] = 1;
  1024.    
  1025.     if(Page<=20 && Page>15) mode[3] =0;
  1026.     else mode[3] = 1;
  1027.    
  1028.     if(Page<=25 && Page>20) mode[4] =0;
  1029.     else mode[4] = 1;
  1030.    
  1031.     if(Page<=30 && Page>25) mode[5] =0;
  1032.     else mode[5] = 1;
  1033.    
  1034.     if( Last!=1 ){
  1035.       OLED_Fill(0,0,127,63,0);
  1036.       Last = 1;
  1037.     }
  1038.     OLED_ShowString(0,0,"UP P    D         ");
  1039.     OLED_ShowNum(36,0,(int)(PID_Balance->Kp*10),3,12,mode[0]);  
  1040.     OLED_ShowNum(72,0,(int)(PID_Balance->Kd*10),3,12,mode[1]);
  1041.     OLED_ShowString(0,12 ,"AnglePiont        ");
  1042.     OLED_ShowNum(96,12,(int)(Angle->PiontValue),4,12,mode[2]);  
  1043.    
  1044.     OLED_ShowString(0,24 ,"Speed P   I        ");
  1045.     OLED_ShowNum(56,24,(int)(PID_Speed->Kp*10),3,12,mode[3]);  
  1046.     OLED_ShowNum(96,24,(int)(PID_Speed->Ki*1000),3,12,mode[4]);  
  1047.     OLED_ShowString(0,36 ,"SpeedPiont        ");
  1048.     OLED_ShowNum(96,36,(int)(Speed->PiontSpeed),4,12,mode[5]);
  1049.       

  1050.     OLED_ShowNum(32,48,(int)(InductorA->LeftFinal),3,12,0);  
  1051.     OLED_ShowNum(56,48,(int)(InductorA->RightFinal),3,12,0);
  1052.     OLED_ShowNum(86,48,(int)(InductorB->LeftFinal),3,12,0);
  1053.   }  
  1054.   
  1055.   else if(Page>30 && Page<=65){
  1056.    
  1057.     if(Page<=35 && Page>30) mode[0] = 0;
  1058.     else mode[0] = 1;
  1059.    
  1060.     if(Page<=40 && Page>35) mode[1] =0;
  1061.     else mode[1] = 1;
  1062.    
  1063.     if(Page<=45 && Page>40) mode[2] =0;
  1064.     else mode[2] = 1;
  1065.    
  1066.     if(Page<=50 && Page>45) mode[3] =0;
  1067.     else mode[3] = 1;
  1068.    
  1069.     if(Page<=55 && Page>50) mode[4] =0;
  1070.     else mode[4] = 1;
  1071.    
  1072.     if(Page<=60 && Page>55) mode[5] =0;
  1073.     else mode[5] = 1;
  1074.    
  1075.     if(Page<=65 && Page>60) mode[6] =0;
  1076.     else mode[6] = 1;
  1077.    
  1078.    
  1079.    
  1080.     if( Last!=2 ){
  1081.       OLED_Fill(0,0,127,63,0);
  1082.       Last = 2;
  1083.     }
  1084.    
  1085.     OLED_ShowString(0,0,"Path P    D         ");
  1086.     OLED_ShowNum(48,0,(int)(PID_Path->Kp*10),3,12,mode[0]);  
  1087.     OLED_ShowNum(96,0,(int)(PID_Path->Kd*100),3,12,mode[1]);
  1088.     OLED_ShowString(0,12 ,"PathPiont        ");
  1089.     OLED_ShowNum(84,12,(int)(PID_Path->offset*100),3,12,mode[2]);  
  1090.    
  1091.       
  1092.     OLED_ShowString(0,24 ,"Diff P     D        ");
  1093.     OLED_ShowNum(56,24,(int)(PID_Diff->Kp*10),3,12,mode[3]);  
  1094.     OLED_ShowNum(96,24,(int)(PID_Diff->Kd*10),3,12,mode[4]);  
  1095.     OLED_ShowString(0,36 ,"Diff I     S        ");
  1096.     OLED_ShowNum(56,36,(int)(PID_Diff->Ki*10),3,12,mode[5]);
  1097.     OLED_ShowNum(96,36,(int)(PID_Diff->offset*100),3,12,mode[6]); //差速與陀螺儀融合比率
  1098.       
  1099.       

  1100.     OLED_ShowNum(32,48,(int)(InductorA->LeftFinal),3,12,0);  
  1101.     OLED_ShowNum(56,48,(int)(InductorA->RightFinal),3,12,0);
  1102.     OLED_ShowNum(86,48,(int)(InductorB->LeftFinal),3,12,0);
  1103.       
  1104.   }
  1105.   
  1106.   else if(Page>65 && Page<=105){
  1107.    
  1108.     if(Page<=70 && Page>65) mode[0] = 0;
  1109.     else mode[0] = 1;
  1110.    
  1111.     if(Page<=75 && Page>70) mode[1] =0;
  1112.     else mode[1] = 1;
  1113.    
  1114.     if(Page<=80 && Page>75) mode[2] =0;
  1115.     else mode[2] = 1;
  1116.    
  1117.     if(Page<=85 && Page>80) mode[3] =0;
  1118.     else mode[3] = 1;
  1119.    
  1120.     if(Page<=90 && Page>85) mode[4] =0;
  1121.     else mode[4] = 1;
  1122.    
  1123.     if(Page<=95 && Page>90) mode[5] =0;
  1124.     else mode[5] = 1;
  1125.    
  1126.     if(Page<=100 && Page>95) mode[6] =0;
  1127.     else mode[6] = 1;
  1128.    
  1129.     if(Page<=105 && Page>100) mode[7] =0;
  1130.     else mode[7] = 1;
  1131.    
  1132.    
  1133.     if( Last!=3 ){
  1134.       OLED_Fill(0,0,127,63,0);
  1135.       Last = 3;
  1136.     }
  1137.    
  1138.     OLED_ShowString(0,0   ,"LAMAX");
  1139.     OLED_ShowNum(38,0,(int)(InductorA->LeftMax),4,12,mode[0]);
  1140.     OLED_ShowString(68,0  ,"LAMIN");
  1141.     OLED_ShowNum(108,0,(int)(InductorA->LeftMin),3,12,mode[1]);
  1142.    
  1143.    
  1144.     OLED_ShowString(0,12  ,"RAMAX");
  1145.     OLED_ShowNum(38,12,(int)(InductorA->RightMax),4,12,mode[2]);
  1146.     OLED_ShowString(68,12 ,"RAMIN");
  1147.     OLED_ShowNum(108,12,(int)(InductorA->RightMin),3,12,mode[3]);
  1148.    
  1149.    
  1150.    
  1151.     OLED_ShowString(0,24  ,"ZBMAX");
  1152.     OLED_ShowNum(38,24,(int)(InductorB->LeftMax),4,12,mode[4]);
  1153.     OLED_ShowString(68,24 ,"ZBMIN");
  1154.     OLED_ShowNum(108,24,(int)(InductorB->LeftMin),3,12,mode[5]);
  1155.    
  1156.    
  1157.     OLED_ShowString(0,36 ,"SpeedMax");
  1158.     OLED_ShowNum(84,36,(uint32)(Speed->PiontSpeedMax),4,12,mode[6]);
  1159.    
  1160.     OLED_ShowString(0,48 ,"SpeedMin");
  1161.     OLED_ShowNum(84,48,(uint32)(Speed->PiontSpeedMin),4,12,mode[7]);
  1162.    
  1163.   }
  1164.   
  1165.   OLED_Refresh_Gram();

  1166. };



  1167. void MotorControlFlow(PWM_Type_Def *PWM, Ramp_Type_Def *Ramp){ //電機直接控制
  1168.   

  1169.   //如測試線序 在此處 對*PWM賦值 測試完畢再注釋

  1170.   //PWM->LiftValue = 1200;//左輪正傳  往前走
  1171.   //PWM->LiftValue = 1000;
  1172.   //PWM->LiftValue = 800;
  1173.   
  1174.   //PWM->RightValue = 1200;//右輪正傳 往前走
  1175.   //PWM->RightValue = 1000;
  1176.   //PWM->RightValue = 800;

  1177.   //左邊右邊都給 1000的時候 應該是不轉的   
  1178.   
  1179.   if(PWM->LiftValue>(PWMMAX))PWM->LiftValue = (PWMMAX);
  1180.   if(PWM->LiftValue<(PWMMIN))PWM->LiftValue = (PWMMIN);
  1181.   if(PWM->RightValue>(PWMMAX))PWM->RightValue = (PWMMAX);
  1182.   if(PWM->RightValue<(PWMMIN))PWM->RightValue = (PWMMIN);
  1183.   
  1184.   //此處必須先調整好  保證 PWM值是 >1000時  是前進
  1185.   //PWM值< 1000 是后退   而且 兩輪必須一致
  1186.   //能改硬件 就改驅動線  和 電機引線  例如
  1187.   //給同樣都是  1200  左邊電機慢速往前  右邊慢速往后 這時候 調換右電機線
  1188.   //如果出現如下情況  給1200  理論上是 正轉 20%占空比  但出現轉速很快 說明
  1189.   //驅動線序不對   可以在這里調換 通道  或者 直接改線序
  1190.   
  1191.   if(PWM->LiftValue>1000){ //邊輪前進  1000~2000
  1192.      ftm_pwm_duty(ftm2,ftm_ch2,0);
  1193.      ftm_pwm_duty(ftm2,ftm_ch3,PWM->LiftValue-1000);
  1194.   }
  1195.   else if(PWM->LiftValue<1000){ //左輪是后退  0~1000
  1196.      ftm_pwm_duty(ftm2,ftm_ch2,1000-PWM->LiftValue);
  1197.      ftm_pwm_duty(ftm2,ftm_ch3,0);   
  1198.   }  //如果發現 此處給定的是  控制 右輪轉動 則調換下硬件驅動線線序  注意 是兩根兩根的調換  
  1199.    

  1200.   if(PWM->RightValue>1000){ //右輪是前進  1000~2000
  1201.      ftm_pwm_duty(ftm2,ftm_ch4,0);
  1202.      ftm_pwm_duty(ftm2,ftm_ch5,PWM->RightValue-1000);
  1203.   }
  1204.   else if(PWM->RightValue<1000){ //右輪是后退  0~1000
  1205.      ftm_pwm_duty(ftm2,ftm_ch4,1000-PWM->RightValue);
  1206.      ftm_pwm_duty(ftm2,ftm_ch5,0);   
  1207.   }   //如果發現 此處給定的是  控制 左邊輪轉動 則調換下硬件驅動線線序  注意 是兩根兩根的調換   
  1208.   
  1209. };

  1210. uint8 timer3ms = 0, timer4_5ms=0,timer24ms=0 ,timer64ms=0;

  1211. int main(void){
  1212.   
  1213.   //由于本程序閉環較多  調試過程比較繁瑣  建議一開始的時候 屏蔽掉其他環
  1214.   //只調節最基礎的環節  平衡車主要就是對于兩個電機的控制  其中有一個函數
  1215.   //MotorControlFlow函數是直接控制電機的  這個函數需要調試好  其要求就是
  1216.   //占空比0~1000退后   1000~2000向前  通過調換驅動線  和 調換電機線  或者
  1217.   //調換程序中 ch2 3 4 5 的  23順序  45順序來  達到最終的效果  兩個電機
  1218.   //給1000以上是向前走   1000一下向后走  2000往前最快   0往后最快
  1219.   
  1220.   //當電機輸出調整好了以后  再調節編碼器反饋  我們在MotorControlFlow函數里
  1221.   //直接給  PWM->LiftValue = 1200;PWM->RightValue = 1200;  讓兩個電機固定占空比
  1222.   //轉動  這時候 通過IAR在線調試觀察  編碼器測速值 是否正確  是否對應左輪右輪
  1223.   //(左電機轉動對應左編碼器  右電機轉動對應右邊編碼器  不能錯!)
  1224.   //用手阻止一個電機觀察是否是那個電機的編碼器轉速下降  確保 編碼器的方向一致!
  1225.   
  1226.   //編碼器 和 電機調整好以后就方便了很多  接下來就是直立  前提是陀螺儀參數已經整定好
  1227.   //我們調試直立的時候  要把其他環都關閉 方法如下  函數PWMFeedbackControl 是把所有環輸出
  1228.   //整合到電機PWM上的函數 其中  PWM->PiontValue  = (int16)(PID_Balance->out)+ (int16)(PID_Speed->out_k[0] + PID_Speed->out_k[9]) ;
  1229.   //這句話是把  三個環的輸出 疊加在一起  我們只需要保留 直立環  這樣調節直立比較順手
  1230.   //其中還有一個 差速 也要給0  對直立就無影響   
  1231.   
  1232.   //當直立調節完畢后  速度環和直立的融合是比較難的  直立和速度是并環 需要精心調試,也可以
  1233.   //跳過速度環的調試  直接進入轉向環  與差速環    他們之間是串級PID的關系  
  1234.   
  1235.   //如果出現中斷  跑飛 或者  卡住在ADC死循環里  說明堆棧溢出  調整KEA128.ICF文件的  堆棧值 擴大  不超過12K即可
  1236.   


  1237.   
  1238.   get_clk();              //獲取時鐘頻率 必須執行
  1239.   
  1240.   uint8 Page=0;
  1241.   
  1242.   PID_Type_Def  PID_Balance, PID_Speed, PID_Path, PID_Diff;
  1243.   
  1244.   RUN_Type_Def       RUN;
  1245.   Stop_Type_Def      Stop;
  1246.   Ramp_Type_Def      Ramp;
  1247.   Curve_Type_Def     Curve;
  1248.   Acc_Type_Def       Acc;
  1249.   Gyro_Type_Def      Gyro;
  1250.   Angle_Type_Def     Angle;
  1251.   PWM_Type_Def       PWM;
  1252.   Speed_Type_Def     Speed;
  1253.   Button_Type_Def    Button;
  1254.   Switch_Type_Def    Switch;
  1255.   Inductor_Type_Def  InductorA, InductorB;

  1256.   
  1257.   SensorStructurePointerInit( &Acc, &Gyro, &Angle, &Speed, &InductorA, &InductorB );//傳感器參數初始化
  1258.   PIDStructurePointerInit( &PID_Balance, &PID_Speed, &PID_Path, &PID_Diff );//PID參數初始化
  1259.   CarBalanceSystemInit( &Gyro ); //系統初始化  
  1260.   


  1261.   
  1262.   RUN.Flag[4] = 1;//運行出界標志位
  1263.   
  1264.   RUN.Flag[5] = 0;//啟動電機標志位
  1265.   
  1266.   Stop.Flag[0] = 0;//停止線標志位延時啟動標志位
  1267.   
  1268.   Stop.Flag[1] = 0;//停止標志位
  1269.   
  1270.   Ramp.Flag[0] = 0;//接近坡道標志位
  1271.   
  1272.   Ramp.Flag[1] = 0;//上坡道標志位
  1273.   
  1274.   Curve.Flag[1] = 0;//正差速標志位
  1275.   
  1276.   Curve.Flag[2] = 0;//反差速標志位
  1277.   
  1278.   Curve.Flag[3] = 0;//差速數目
  1279.   
  1280.   while(1){

  1281.     if( timer4_5ms  ){
  1282.       
  1283.         gpio_set(H2,1);//
  1284.       
  1285.       GetAccelerationValue( &Acc );  //加速度原始數據采集
  1286.       GetAngleSpeedValue( &Gyro );   //角速度原始數據采集
  1287.       GetSpeedValue( &Speed );       //獲取原始速度數據
  1288.       GetInductorValue( &InductorA, &InductorB );//電感電壓原始數據采集
  1289.       
  1290.       GyroHighPassFilter( &Gyro );  //角速度濾波處理
  1291.       AngleHardwareFilter( &Angle );//角度濾波處理
  1292.       SpeedSoftwareFilter( &Speed );//速度遞歸權值濾波
  1293.       InductorSoftwareFilter( &InductorA, &InductorB, &Angle, &Switch);//電感濾波處理

  1294.       BalanceFeedbackControl( &PID_Balance, &Angle, &Gyro, &Ramp );//平衡度反饋計算
  1295.       DirectionFeedbackControl( &PID_Path, &InductorA, &InductorB, &Gyro, &Speed, &Ramp );//路徑反饋計算
  1296.       DifferentialFeedbackControl( &PID_Diff, &Speed, &Gyro);//差速反饋計算

  1297.       PWMFeedbackControl( &PWM, &PID_Balance, &PID_Speed, &PID_Path, &PID_Diff, &Speed, &Switch );//PWM疊加 直立 方向 速度PWM
  1298.       MotorControlFlow( &PWM, &Ramp ); //電機PWM輸出控制
  1299.       
  1300.         gpio_set(H2,0);//
  1301.       
  1302.       timer4_5ms = 0;//清除時間標志位
  1303.     }
  1304.    
  1305.     //車子跑起來以后就不會執行  因為開銷比較大 影響PID控制周期
  1306.     if( Speed.ActualSpeed[2]<100 && timer24ms && timer4_5ms != 1 ){
  1307.       
  1308.       GetButtonStatus( &Button ); //獲取按鍵狀態
  1309.       ButtonLowPassFilter( &Button );//判斷按鍵狀態
  1310.       
  1311.       
  1312.       ButtonFunctionControl( &PID_Balance, &PID_Speed, &PID_Path, &PID_Diff, &Angle, &Speed, &InductorA, &InductorB, &Button, &Page );//實現按鍵狀態
  1313.       
  1314.       GetSwitchStatus( &Switch ); //獲取開關狀態
  1315.       SwitchLowPassFilter( &Switch );//判斷開關狀態

  1316.       timer24ms = 0;

  1317.     };
  1318.    
  1319.    
  1320.     if(timer64ms && timer4_5ms != 1 ){  
  1321.       
  1322.       if(Speed.ActualSpeed[2]<100)PrintParameterToOLED( &PID_Balance, &PID_Speed, &PID_Path, &PID_Diff, &Angle, &Speed, &PWM, &InductorA, &InductorB, &Curve, Page );
  1323.       //人機交互界面 高速運行不執行
  1324.      
  1325.       SpeedFeedbackControl( &PID_Speed, &Speed, &Ramp, &Switch ); //速度環反饋控制
  1326.       

  1327.        timer64ms = 0;
  1328.     };
  1329.    
  1330.    
  1331.   }
  1332.   
  1333. }




  1334. uint8 count = 0;

  1335. void PIT_CH0_IRQHandler(void)
  1336. {

  1337.   if( count<84 ) count++;
  1338.   else count = 0;
  1339.    
  1340.   
  1341. //  if( count%2==0 ) timer3ms = 1;
  1342.   
  1343.   if( count%3==0 ) timer4_5ms = 1;
  1344.   
  1345.   if( count%16==0 ) timer24ms = 1;
  1346.   
  1347.   if( count%42==0 ) timer64ms=1;

  1348.   
  1349.   PIT_FlAG_CLR(pit0);//清除中斷標志位
  1350.   

  1351.   
  1352. }
復制代碼

所有資料51hei提供下載:
KEA128直立.zip (4.71 MB, 下載次數: 37)


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

使用道具 舉報

沙發
ID:105146 發表于 2018-7-2 21:02 | 只看該作者
首先感謝分享!參考一下
回復

使用道具 舉報

板凳
ID:105146 發表于 2018-7-2 21:29 | 只看該作者
編譯出錯啊~提示缺少一些文件
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产第二页 | 日日夜夜免费精品视频 | 成人一区二 | 亚洲午夜视频 | 日韩精品一 | 国产精品国产三级国产aⅴ无密码 | 99久久婷婷国产综合精品电影 | 97视频在线观看网站 | 亚洲成av人片在线观看 | 亚洲综合精品 | 亚洲午夜视频 | 久久久.com | 欧美日韩专区 | 精品在线一区 | 久草网址| 久久综合香蕉 | 国产成在线观看免费视频 | 国产精品久久久久久久久久 | 日本午夜视频 | 亚洲永久免费观看 | 综合久久av| 九九色综合 | 草草视频在线免费观看 | 欧美不卡视频一区发布 | 久久精品色欧美aⅴ一区二区 | 毛片网络 | 免费一区二区三区 | 成人一区二区电影 | 久久精品视频99 | 本地毛片| 久久久精| 精品国产乱码久久久久久蜜臀 | 91大神在线看 | 午夜视频网 | 久久久久久国产精品免费免费狐狸 | 亚洲欧美在线一区 | 色综合区 | 国产欧美日韩综合精品一区二区 | 亚洲a毛片 | 99久久精品免费看国产小宝寻花 | 亚洲毛片在线 |