找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1799|回复: 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. }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表