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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

KEA128電磁智能車程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:388667 發表于 2018-8-21 20:12 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. #include "headfile.h"
  2. #include "KEA128_uart.h"
  3. #include "KEA128_qiu.h"
  4. #include "filter.h"
  5. #include "All_Init.h"
  6. #define Speed_set 0
  7. #define zhong 2250

  8. struct PID_Typedef  //PID結構體
  9. {
  10.     float P;
  11.     float I;
  12.     float D;
  13.     int Error;
  14.     int PreError;
  15.     int PreDError;//
  16.     int d_error;
  17.     int dd_error;
  18.     int Output;
  19.     int target;
  20.     int measure;
  21. }PID_Typedef;
  22. float Kp,Kd,Ks;
  23. extern uint16 val_get_L;//左側電感電壓值  PTA8
  24. extern uint16 val_get_R;//右側電感電壓值  PTA7
  25. extern uint16 aveL,aveR;
  26. extern float val_dev_to_one,val_sum_to_one,aveL_to_one,aveR_to_one;
  27. //extern uint16 val_get_M;
  28. extern uint8 time_flag,dir_time;
  29. extern uint8 read_bianmaqi;
  30. uint8 * itoa(int32 num);
  31. uint16 SpeedSumL,SpeedSumR;
  32. uint16 SpeedL,SpeedR;
  33. uint16 uart_cnt=0;
  34. uint16 sum_cnt;

  35. double Speed_L;
  36. double Speed_R;
  37. float ActualErr=0.0;                             
  38. float   Err_L;                                          
  39. float   Err_N;
  40. float   Error=0.0;
  41. void speedout();

  42. //void differential();
  43. void ReadBianMaQi();
  44. void Ad_deal();
  45. void MOTOR_PID(struct PID_Typedef *PID,int target,int measure);
  46. void PID_init();//pid參數賦值


  47. struct PID_Typedef  Left;
  48. struct PID_Typedef  Right;


  49. int main(void)
  50. {  
  51.    get_clk();              //獲取時鐘頻率 必須執行
  52.    ALL_Init();
  53.    PID_init();
  54.    pit_init_ms(pit0,1);                    //初始化pit0 周期設置為10ms
  55.    set_irq_priority(PIT_CH0_IRQn,1);        //設置pit0優先級
  56.    enable_irq(PIT_CH0_IRQn);                        //開啟pit0中斷
  57.    EnableInterrupts;        

  58.     for(;;)
  59.     {   
  60.         ReadBianMaQi();//讀取脈沖10讀取一次,


  61.         speedout();    //40ms進行一次控速
  62.         if(time_flag==50)
  63.         {
  64.             time_flag=0;
  65.             //uart_cnt++;                  
  66.             //if(uart_cnt>=10)
  67.             //{
  68.                 //uart_cnt=0;



  69.             //}
  70.         }
  71.     }        
  72. }

  73. void ReadBianMaQi()
  74. {
  75.   if(read_bianmaqi>=10)
  76.   {//10ms讀取一次編碼器

  77.     read_bianmaqi=0;

  78.     adc_get();
  79.     filter1();
  80.     adc_to_one();
  81.     Ad_deal();
  82.     SpeedL = ftm_count_get(ftm1);//讀取脈沖
  83.     ftm_count_clean(ftm1);//清除寄存器
  84.     SpeedR = ftm_count_get(ftm0);//讀取脈沖1
  85.     ftm_count_clean(ftm0);//清楚寄存器

  86.     SpeedSumL +=SpeedL;
  87.     SpeedSumR +=SpeedR;
  88.     SpeedL=0;
  89.     SpeedR=0;
  90.   }

  91. }

  92. void speedout()
  93. {  

  94.   if(sum_cnt>=40)
  95.   {//40ms進行一次速度控制
  96.     sum_cnt=0;


  97.     Left.measure=SpeedSumL;
  98.     Right.measure=SpeedSumR;
  99.     SpeedSumL =0;
  100.     SpeedSumR =0;

  101.    // Left.target=200;
  102.    // Right.target=200;

  103.      if( ActualErr>0)//在一定的范圍內才加差速
  104.   {

  105.      Right.target=Speed_set-ActualErr*Ks;
  106.      Left.target=Speed_set+ActualErr;
  107.    }
  108.     else
  109.     {
  110.        Left.target=Speed_set+ActualErr*Ks;
  111.        Right.target=Speed_set-ActualErr;
  112.     }
  113.    if(Left.target > 700)          //限幅防止輸出過大
  114.         Left.target= 700;
  115.     if(Left.target <-700)          //限幅防止輸出過大
  116.         Left.target=-700;
  117.     if(Right.target > 700)
  118.         Right.target= 700;
  119.     if(Right.target <-700)  
  120.         Right.target=-700;  
  121. //   MOTOR_PID(&Left,Left.target,Left.measure);
  122. //   MOTOR_PID(&Right,Right.target,Right.measure);
  123. //    Left.target=200;
  124. //    Right.target=200;
  125.    Left.Output=Left.target;
  126.    Right.Output=Right.target;

  127.    if(Left.Output>=900)//限上值 但是在這里不管下限 在計算里面管
  128.         Left.Output = 900;
  129.     else if(Left.Output<=-900)
  130.         Left.Output =-900;

  131.     if(Right.Output>=900)//限上值 但是在這里不管下限 在計算里面管
  132.           Right.Output = 900;
  133.     else if(Right.Output<=-900)
  134.            Right.Output =-900;

  135.   if(Left.Output>=0)
  136.     {
  137.       Left.Output=(uint16)Left.Output+0;
  138.       ftm_pwm_duty(ftm2,ftm_ch2,0);
  139.       ftm_pwm_duty(ftm2,ftm_ch3,Left.Output);
  140.     }  
  141.     else
  142.     {
  143.      Left.Output=(uint16)(-Left.Output)+0;
  144.      ftm_pwm_duty(ftm2,ftm_ch3,0);
  145.      ftm_pwm_duty(ftm2,ftm_ch2,Left.Output);
  146.     }

  147.     if(Right.Output>=0)
  148.     {
  149.       Right.Output=(uint16)Right.Output+0;
  150.       ftm_pwm_duty(ftm2,ftm_ch0,0);
  151.       ftm_pwm_duty(ftm2,ftm_ch1,Right.Output);
  152.     }
  153.     else
  154.     {
  155.       Right.Output=(uint16)(-Right.Output)+0;
  156.       ftm_pwm_duty(ftm2,ftm_ch1,0);
  157.       ftm_pwm_duty(ftm2,ftm_ch0,Right.Output);
  158.     }

  159.     /*ftm_pwm_duty(ftm2,ftm_ch0,Left.Output);       //,設置占空比,,右電機正轉,,在系統配置中已經將PWMIO口改成C0C1C2C3
  160.     ftm_pwm_duty(ftm2,ftm_ch1,0);      
  161.     ftm_pwm_duty(ftm2,ftm_ch2,0);      //左電機正轉
  162.     ftm_pwm_duty(ftm2,ftm_ch3,Right.Output); */

  163.     uart_cnt++;                  
  164.     if(uart_cnt>=25)
  165.     {//4*25=1000  1秒輸出一次上位機,方便觀察
  166.       uart_cnt=0;
  167.       uart_putstr(uart2,"L編碼器目標");
  168.       uart_putstr(uart2,itoa(Left.target));
  169.       uart_putstr(uart2,"\t");

  170.       uart_putstr(uart2,"R編碼器目標");
  171.       uart_putstr(uart2,itoa(Right.target));
  172.       uart_putstr(uart2,"\n");

  173.       uart_putstr(uart2,"L編碼器速度");
  174.       uart_putstr(uart2,itoa(Left.measure));
  175.       uart_putstr(uart2,"\t");

  176.       uart_putstr(uart2,"R編碼器速度");
  177.       uart_putstr(uart2,itoa(Right.measure));
  178.       uart_putstr(uart2,"\n");

  179.       uart_putstr(uart2,"左邊感量");
  180.       uart_putstr(uart2,itoa(aveL));
  181.       uart_putstr(uart2,"\t");

  182.       uart_putstr(uart2,"右邊感量");
  183.       uart_putstr(uart2,itoa(aveR));
  184.       uart_putstr(uart2,"\n");

  185.       uart_putstr(uart2,"LDuty");
  186.       uart_putstr(uart2,itoa(Left.Output));
  187.       uart_putstr(uart2,"\t\t");

  188.       uart_putstr(uart2,"RDuty");
  189.       uart_putstr(uart2,itoa(Right.Output));
  190.       uart_putstr(uart2,"\n");
  191.     }
  192.   }
  193. }

  194. //整數轉換為字符串(輸入整數,返回字符串地址)
  195. uint8 * itoa(int32 num)
  196. {
  197.   int32 i=0,isNegative=0;
  198.   static uint8 s[15];                                                           //必須是全局變量或者是靜態變量

  199.   //如果是負數,先轉為正數
  200.   if((isNegative=num) < 0) num = -num;

  201.   //從個位開始變為字符,直到最高位,最后應該反轉
  202.   do
  203.   {
  204.     s[i++] = num%10 + '0';
  205.     num /= 10;
  206.   }while(num > 0);

  207.   //如果是負數,補上負號
  208.   if(isNegative < 0) s[i++] = '-';

  209.   //最后加上字符串結束符
  210.   s[i] = '\0';

  211.   /******翻轉字符串******/
  212.   //p指向s的頭部
  213.   uint8 *p = s;

  214.   //q指向s的尾部
  215.   uint8 *q = s;
  216.   while(*q) ++q;
  217.   q--;

  218.   //交換移動指針,直到p和q交叉
  219.   uint8 temp;
  220.   while(q > p)
  221.   {
  222.     temp = *p;
  223.     *p++ = *q;
  224.     *q-- = temp;
  225.   }

  226.   return s;
  227. }

  228. /*pid 調電機*/
  229. /*****差速函數******/
  230. /*void differential()
  231. {
  232.   int chasu=0;


  233.   errorL=aveL-zhong;
  234.   errorR=aveR-zhong;

  235.   tempL=errorL*100;
  236.   tempL=tempL/zhong;

  237.   tempR=errorR*100;
  238.   tempR=tempR/zhong;

  239.   Right.target=(int)(speed_set-error*speed_set/100);
  240.   Left.target=(int)(speed_set-error*speed_set/100);
  241. */

  242. /* if( ActualErr>0)//在一定的范圍內才加差速
  243.   {

  244.       Right.target=(int)speed_set+ ActualErr;
  245.       Left.target=(int)speed_set-ActualErr*Ks;
  246.    }
  247.     else
  248.     {
  249.        Right.target=(int)speed_set-ActualErr;
  250.        Left.target=(int)speed_set+ ActualErr*Ks;
  251.     }
  252.    if( Left.target> 700)          //限幅防止輸出過大
  253.          Left.target= 700;
  254.     if( Left.target <-700)          //限幅防止輸出過大
  255.          Left.target=-700;
  256.     if( Right.target > 700)
  257.          Right.target= 700;
  258.     if( Right.target <-700)  
  259.          Right.target=-700;

  260.   //給各自的target賦值
  261. }*/

  262. /******電機PID部分程序**********/
  263. /*增量式 pid ,慢慢調 */
  264. void MOTOR_PID(struct PID_Typedef *PID,int target,int measure)    //target目標期望值,measure目標測量值,輸出占空比改變量
  265. {
  266.     PID->Error=target - measure;    //計算偏差。        
  267.     PID->d_error = PID->Error - PID->PreError;               //偏差計算(比例)
  268.     PID->dd_error = PID->d_error - PID-> PreDError;       //偏差計算(微分)
  269.     PID->PreError = PID->Error;                  //存儲當前偏差
  270.     PID->PreDError = PID->d_error;

  271.     if ((PID->Error > -5) && (PID->Error <5))        // 設置調節死區 編碼器返回的值跟目標值在小誤差范圍內不調節 防止超調過度起反作用
  272.     {
  273.         ; // 不執行PID調節
  274.     }
  275.     else
  276.    {

  277.      PID->Output+= ((PID->P* PID->d_error) + (PID->I * PID->Error) + (PID->D * PID->dd_error));
  278.     }
  279.     if(PID->Output>=900)//限上值 但是在這里不管下限 在計算里面管
  280.         PID->Output = 900;
  281.     else if(PID->Output<=0)
  282.       PID->Output =0;
  283. }

  284. void Ad_deal()
  285. {
  286.     float IncrementErr;
  287.     Error=val_dev_to_one*100/pow(val_sum_to_one,1.5);  //水平電感偏差         
  288.     if(Error>=100)
  289.       Error=100;
  290.     if(Error<=-100)
  291.       Error=-100;
  292. //    Error=(sqrt(AD3)-sqrt(AD1))/(AD1+AD3)*3800;
  293.     /****************增量式PD****************/
  294.     IncrementErr=Kp*(Error-Err_N)+Kd*(Error-2*Err_N+Err_L);   //增量式PD
  295.     ActualErr+=IncrementErr;                                  //
  296.     Err_L=Err_N;                                              //
  297.     Err_N=Error;


  298. //    Lost_Err();                                 //防丟線程序
  299.     /*****************兩輪差速效果*****************/
  300.     if(Error<=0)                                              //計算兩輪差速效果
  301.       Error=-Error;                                           //
  302.     Ks=Error/10;                                              //
  303.     if(Ks>1.3)                                                //
  304.       Ks=1.3;    //0.78                                       //增大后內輪減速明顯
  305. }


  306. void PID_init()
  307. {
  308.     Left.P = 0.4;    //左輪P
  309.     Left.I = 0.28;     //左輪I
  310.     Left.D = 0;    //

  311.     Right.P = 0.4;   //右輪P
  312.     Right.I = 0.28;    //右輪I
  313.     Right.D = 0;   //右輪D

  314.     /* 電感差速  */

  315.     Error=0.0;
  316.     Err_N=0.0;
  317.     Err_L=0.0;         
  318.     Kp=5.0;           
  319.     Kd=20.0;     
  320.   /*左右輪差速效果*/
  321.     Ks=0.0;                     //在arithmetic.c中賦值Error/10
  322. }
復制代碼
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜a√| 高清18麻豆| 国产性生活一级片 | av毛片| 狠狠狠色丁香婷婷综合久久五月 | 国产成人免费在线 | 欧美成人猛片aaaaaaa | 中文字幕 欧美 日韩 | 亚洲一二三区免费 | 一区二区三区在线免费看 | 久久久久亚洲精品国产 | 在线免费观看亚洲 | 亚洲协和影视 | 日韩不卡一区二区三区 | 99伊人 | 精品免费国产一区二区三区四区介绍 | 91看片网 | 精久久久 | 亚洲在线一区二区 | 免费毛片网站 | 精品国产一区二区久久 | 欧美精品日韩精品国产精品 | 伊人久久一区二区 | 激情欧美一区二区三区 | 久久一二 | 黄色一级电影免费观看 | 一区二区三区网站 | 91丨九色丨国产在线 | 精品一区av | 久久久精品一区 | 精品国产一区二区三区性色 | 国产一区二区三区免费视频 | 久久久久久久av | 精品日韩一区二区 | 国产精品区一区二区三 | 亚洲免费在线 | 亚洲成人播放器 | 国产线视频精品免费观看视频 | 亚洲视频中文字幕 | 999精品视频| 在线一区 |