[STM32F4] 直流有刷电机控制(电流环,速度环,位置环)

[复制链接]
4538|0
 楼主| zero949079783 发表于 2024-4-6 15:45 | 显示全部楼层 |阅读模式
本帖最后由 zero949079783 于 2024-4-14 13:40 编辑

上位机使用:正点原子ATK_PID硬件:正点原子电机开发板

直流有刷电机 (电流环):链接:https://pan.baidu.com/s/1cpPnogMKNhTAeAOBJlFAxA?pwd=n8ut
提取码:n8ut
直流有刷电机 (速度环):链接:https://pan.baidu.com/s/1bd6SHPedWeDGvbiKfD88Vg?pwd=0vvt
提取码:0vvt
直流有刷电机 (位置环):  
链接:https://pan.baidu.com/s/1Cy3HBHYqmDLjFAGRBZYWVQ?pwd=20dn
提取码:20dn



电流环:
  1. #include "main.h"
  2. #include "math.h"


  3. /*************************************    第二部分    电压电流温度采集    **********************************************/
  4. uint16_t g_adc_val[ADC_CH_NUM];                         /*ADC平均值存放数组*/



  5. PID_TypeDef  g_current_pid;             /* 电流环PID参数结构体 */
  6. /*
  7.     Rt = Rp *exp(B*(1/T1-1/T2))

  8.     Rt 是热敏电阻在T1温度下的阻值;
  9.     Rp是热敏电阻在T2常温下的标称阻值;
  10.     exp是e的n次方,e是自然常数,就是自然对数的底数,近似等于 2.7182818;
  11.     B值是热敏电阻的重要参数,教程中用到的热敏电阻B值为3380;
  12.     这里T1和T2指的是开尔文温度,T2是常温25℃,即(273.15+25)K
  13.     T1就是所求的温度
  14. */

  15. const float Rp = 10000.0f;          /* 10K */
  16. const float T2 = (273.15f + 25.0f); /* T2 */
  17. const float Bx = 3380.0f;           /* B */
  18. const float Ka = 273.15f;

  19. Motor_TypeDef g_motor_data;  /*电机参数变量*/
  20. ENCODE_TypeDef g_encode;     /*编码器参数变量*/

  21. /**
  22. * [url=home.php?mod=space&uid=247401]@brief[/url]       计算温度值
  23. * @param       para: 温度采集对应ADC通道的值(已滤波)
  24. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        计算温度分为两步:
  25.                 1.根据ADC采集到的值计算当前对应的Rt
  26.                 2.根据Rt计算对应的温度值
  27. * @retval      温度值
  28. */
  29. float get_temp(uint16_t para)
  30. {
  31.     float Rt;
  32.     float temp;
  33.    
  34.     /*
  35.         第一步:
  36.         Rt = 3.3 * 4700 / VTEMP - 4700 ,其中VTEMP就是温度检测通道采集回来的电压值,VTEMP = ADC值* 3.3/4096
  37.         由此我们可以计算出当前Rt的值:Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;
  38.     */
  39.    
  40.     Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;       /* 根据当前ADC值计算出Rt的值 */

  41.     /*
  42.         第二步:
  43.         根据当前Rt的值来计算对应温度值:Rt = Rp *exp(B*(1/T1-1/T2))
  44.     */
  45.    
  46.     temp = Rt / Rp;                 /* 解出exp(B*(1/T1-1/T2)) ,即temp = exp(B*(1/T1-1/T2)) */
  47.     temp = log(temp);               /* 解出B*(1/T1-1/T2) ,即temp = B*(1/T1-1/T2) */
  48.     temp /= Bx;                     /* 解出1/T1-1/T2 ,即temp = 1/T1-1/T2 */
  49.     temp += (1.0f / T2);            /* 解出1/T1 ,即temp = 1/T1 */
  50.     temp = 1.0f / (temp);           /* 解出T1 ,即temp = T1 */
  51.     temp -= Ka;                     /* 计算T1对应的摄氏度 */
  52.     return temp;                    /* 返回温度值 */
  53. }

  54. /**
  55. * [url=home.php?mod=space&uid=247401]@brief[/url]       计算ADC的平均值(滤波)
  56. * @param       * p :存放ADC值的指针地址
  57. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        此函数对电压、温度、电流对应的ADC值进行滤波,
  58. *              p[0]-p[2]对应的分别是电压、温度和电流
  59. * @retval      无
  60. */
  61. void calc_adc_val(uint16_t * adcdata)
  62. {
  63.           uint32_t temp[3] = {0,0,0};
  64.                 uint16_t i;
  65.     for(i=0;i<ADC_COLL;i++)         /* 循环ADC_COLL次取值,累加 */
  66.     {
  67.         temp[0] += adcdata[0+i*ADC_CH_NUM];
  68.         temp[1] += adcdata[1+i*ADC_CH_NUM];
  69.         temp[2] += adcdata[2+i*ADC_CH_NUM];
  70.     }
  71.     temp[0] /= ADC_COLL;            /* 取平均值 */
  72.     temp[1] /= ADC_COLL;
  73.     temp[2] /= ADC_COLL;
  74.                
  75.     g_adc_val[0] = temp[0];                 /* 存入电压ADC通道平均值 */
  76.     g_adc_val[1] = temp[1];                 /* 存入温度ADC通道平均值 */
  77.     g_adc_val[2] = temp[2];                 /* 存入电流ADC通道平均值 */               
  78. }
  79. uint8_t current_flag =0;
  80. void get_Motor_value(uint16_t * adcdata)
  81. {
  82.         #define CURRENT_NUM 4
  83.         #define INIT_CURRENT_NUM 5
  84.         float temp_current=0.0;
  85.         static float adc_current = 0;
  86.         static float init_adc_current = 0;
  87.         static uint8_t current_count1 =0,current_count2 =0;
  88.         
  89.         current_count1++;
  90.         calc_adc_val(adcdata);
  91.         adc_current += g_adc_val[2];        /* 取出电流通道对应的ADC值进行累计 */
  92.         
  93.         if(current_count1 >= CURRENT_NUM)/* 累计15次 */
  94.         {
  95.                         adc_current = (float)(adc_current / current_count1);                 /* 取平均值 */
  96.                         if(current_count2 <= INIT_CURRENT_NUM)
  97.                         {
  98.                                 current_count2++;
  99.                                 init_adc_current += adc_current;                         /* 对平均值累计求和 */
  100.                                 if(current_count2 == INIT_CURRENT_NUM)
  101.                                 {
  102.                                         init_adc_current = (float)(init_adc_current/current_count2);        /* 存储初始ADC值 */
  103.                                         current_count2 = INIT_CURRENT_NUM+1;
  104.                                         current_flag =1;
  105.                                        
  106.                                 }
  107.                         }
  108.                         if(current_count2 >= (INIT_CURRENT_NUM+1))
  109.                         {
  110.                                        
  111.                                         temp_current= ((adc_current - init_adc_current) *ADC2CURT);
  112.                                         // g_motor_data.current = temp_current;
  113.                                         FirstOrderRC_LPF(g_motor_data.current,temp_current,0.40);
  114.                                         //g_motor_data.current = (float)((g_motor_data.current * (float)0.60) + ((float)0.40 * temp_current));  /* 一阶低通滤波 */
  115.                                  
  116.                                         if(g_motor_data.current <=20)
  117.                                  {
  118.                                                 g_motor_data.current=0.0;
  119.                                  }
  120.                         }
  121.                 adc_current=0;
  122.                 current_count1=0;
  123.         }
  124. }





  125. /*************************************    第三部分    编码器测速    ****************************************************/
  126. void speed_computer(int32_t encode_now, uint8_t ms)
  127. {
  128.     uint8_t i = 0, j = 0;
  129.     float temp = 0.0;
  130.     static uint8_t sp_count = 0, k = 0;
  131.     static float speed_arr[10] = {0.0};                     /* 存储速度进行滤波运算 */

  132.     if (sp_count == ms)                                     /* 计算一次速度 */
  133.     {
  134.         /* 计算电机转速
  135.            第一步 :计算ms毫秒内计数变化量
  136.            第二步 ;计算1min内计数变化量:g_encode.speed * ((1000 / ms) * 60 ,
  137.            第三步 :除以编码器旋转一圈的计数次数(倍频倍数 * 编码器分辨率)
  138.            第四步 :除以减速比即可得出电机转速
  139.         */
  140.         g_encode.encode_now = encode_now;                                /* 取出编码器当前计数值 */
  141.         g_encode.speed = (g_encode.encode_now - g_encode.encode_old);    /* 计算编码器计数值的变化量 */
  142.         
  143.         speed_arr[k++] = (float)(g_encode.speed * ((1000 / ms) * 60.0) / REDUCTION_RATIO / ROTO_RATIO );    /* 保存电机转速 */
  144.         
  145.         g_encode.encode_old = g_encode.encode_now;          /* 保存当前编码器的值 */

  146.         /* 累计10次速度值,后续进行滤波*/
  147.         if (k == 10)
  148.         {
  149.             for (i = 10; i >= 1; i--)                       /* 冒泡排序*/
  150.             {
  151.                 for (j = 0; j < (i - 1); j++)
  152.                 {
  153.                     if (speed_arr[j] > speed_arr[j + 1])    /* 数值比较 */
  154.                     {
  155.                         temp = speed_arr[j];                /* 数值换位 */
  156.                         speed_arr[j] = speed_arr[j + 1];
  157.                         speed_arr[j + 1] = temp;
  158.                     }
  159.                 }
  160.             }
  161.             
  162.             temp = 0.0;
  163.             
  164.             for (i = 2; i < 8; i++)                         /* 去除两边高低数据 */
  165.             {
  166.                 temp += speed_arr[i];                       /* 将中间数值累加 */
  167.             }
  168.             
  169.             temp = (float)(temp / 6);                       /*求速度平均值*/
  170.             
  171.             /* 一阶低通滤波
  172.              * 公式为:Y(n)= qX(n) + (1-q)Y(n-1)
  173.              * 其中X(n)为本次采样值;Y(n-1)为上次滤波输出值;Y(n)为本次滤波输出值,q为滤波系数
  174.              * q值越小则上一次输出对本次输出影响越大,整体曲线越平稳,但是对于速度变化的响应也会越慢
  175.              */
  176.             g_motor_data.speed = (float)( ((float)0.48 * temp) + (g_motor_data.speed * (float)0.52) );
  177.             k = 0;
  178.         }
  179.         sp_count = 0;
  180.     }
  181.     sp_count ++;
  182. }

  183. uint8_t g_run_flag = 0;

  184. int32_t motor_pwm = 0;
  185. atk_debug_data_rev get_atk_data;


  186. void DCMotor_App(void)
  187. {
  188.         static uint8_t key=0;
  189.         get_atkdebug(&get_atk_data);
  190.         key=key_scan(0);
  191.         if(key == KEY0_PRES)
  192.         {        
  193.                 TurnTogLed(LED1);
  194.                 g_current_pid.SetPoint +=50;
  195.                 g_run_flag = 1;
  196.                 if (g_current_pid.SetPoint == 0)
  197.                 {
  198.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  199.                                 g_motor_data.motor_pwm = 0;
  200.                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);                                  /* 设置电机转速 */
  201.                 }
  202.                 else
  203.                 {
  204.                         DC_Motor_Start(MOTOR_1);
  205.                         if(g_current_pid.SetPoint  >= 250)
  206.                         {
  207.                                 g_current_pid.SetPoint  =250;
  208.                         }
  209.                         atk_debug_send_motorstate(RUN_STATE);           /* 上传电机状态(运行) */
  210.                         //Motor_PWM_Set(g_current_pid.SetPoint,MOTOR_1);
  211.                 }
  212.         }
  213.         else if(key == KEY1_PRES)        {        
  214.                 TurnTogLed(LED1);

  215.                 if (g_current_pid.SetPoint == 0)
  216.                 {
  217.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  218.                                 g_motor_data.motor_pwm = 0;
  219.                                 DC_Motor_Speed(g_motor_data.motor_pwm,MOTOR_1); /* 设置电机转速 */                                 
  220.                 }
  221.                 else
  222.                 {


  223.                 }
  224.         }
  225.         else if(key == KEY2_PRES)
  226.         {

  227.                 DC_Motor_Stop(MOTOR_1);
  228.                 g_run_flag = 0;                                 /* 标记电机停止 */
  229.                 g_motor_data.motor_pwm = 0;
  230.                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);          /* 设置电机转向、速度 */
  231.                 pid_init();
  232.                 atk_debug_send_motorstate(BREAKED_STATE);           /* 上传电机状态(刹车) */
  233.                 atk_debug_send_initdata(TYPE_PID1, (float *)(&g_current_pid.SetPoint), KP, KI, KD);           /* 同步数据到上位机 */
  234.         }
  235. }

  236. void DCMotor_Value(void)
  237. {
  238.         static uint16_t g_time =0;
  239.         int32_t motor_pwm_temp = 0;                                       
  240.         
  241.         if(current_flag == 0 )
  242.                 return;
  243.                                 
  244.                                 
  245.                                 /* 获取编码器值,用于计算速度 */
  246.                                 get_EncodeValue(5);        /* 中位平均值滤除编码器抖动数据,5ms计算一次速度*/
  247.                                 
  248.                                 if(g_time  % 499 ==0)
  249.                                 {                                                                                 
  250.                                        
  251.                                         g_motor_data.volatage  = g_adc_val[0]*ADC2VBUS;               
  252.                                         atk_debug_send_valtage(g_motor_data.volatage );
  253.                                         __NOP();__NOP();__NOP();
  254.                                         g_motor_data.board_temp = get_temp(g_adc_val[1]);
  255.                                         __NOP();__NOP();__NOP();
  256.                                         atk_debug_send_temp(0,get_temp(g_adc_val[1]));
  257.                                         __NOP();__NOP();__NOP();
  258.                                         //g_motor_data.current          = (g_adc_val[2]*ADC2CURT)*0.001;
  259.                                         atk_debug_send_current(g_motor_data.current*0.001,0,0);                        
  260.                                         __NOP();__NOP();__NOP();               
  261.                                         atk_debug_send_speed(g_motor_data.speed);
  262.                                         __NOP();__NOP();__NOP();               
  263. //                                        printf("\r\n******************************\r\n");
  264. //                                        printf("KEY0:增加比较值,KEY1:减小比较值,KEY2:停止电机\r\n\r\n");
  265. //                                        printf("Valtage:%.2fV \r\n",    g_motor_data.volatage);                   /* 打印电压值 */
  266. //                                        printf("Temp:%.2fC \r\n",                    g_motor_data.board_temp   );                  /* 打印温度值 */
  267. //                                        printf("Current:%.2fmA \r\n",   g_motor_data.current); /* 打印电流值 */
  268. //                                        printf("电机速度:%.1f RPM\r\n\r\n",   g_motor_data.speed);               
  269. //                                        printf("\r\n******************************\r\n");
  270.                                 }
  271.                                 else if(g_time % SMAPLSE_PID_SPEED == 0)                /* 电机速度 50ms进行一次pid计算 */
  272.                                 {
  273.                                         if(g_run_flag)
  274.                                         {
  275.                                        
  276.                                                  /* PID计算,输出比较值(占空比) */
  277.                                                 motor_pwm_temp = increment_pid_ctrl (&g_current_pid,g_motor_data.current);
  278.                                                 g_motor_data.motor_pwm = (int32_t)((g_motor_data.motor_pwm * 0.5) + (motor_pwm_temp * 0.5));
  279.                                                 if(g_motor_data.motor_pwm >= 8200)
  280.                                                 {
  281.                                                         g_motor_data.motor_pwm = 8200;
  282.                                                 }
  283.                                                 else if (g_motor_data.motor_pwm <= 0)
  284.                                                 {
  285.                                                         g_motor_data.motor_pwm = 0;
  286.                                                 }
  287.                                        
  288.                                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1); /* 设置电机转速 */
  289.                                         }
  290.                                                 atk_debug_send_wave_data( 1 ,g_motor_data.current);                           /* 选择通道1发送实际电流(波形显示)*/
  291.                                                 atk_debug_send_wave_data( 2 ,g_current_pid.SetPoint);                         /* 选择通道2,发送目标电流(波形显示)*/
  292.                                                 atk_debug_send_wave_data( 3 ,g_motor_data.motor_pwm * 100 / 8400);          /* 选择通道3,发送占空比(波形显示)*/
  293.                                 }

  294.                                 g_time ++;
  295.         
  296. }

  297. void get_EncodeValue(uint8_t  ms)
  298. {
  299.         int encode_now = gtim_get_encode();
  300.         speed_computer(encode_now, ms);
  301. }


  302. PID_TypeDef  g_speed_pid;           /* 速度环PID参数结构体 */

  303. /**
  304. * [url=home.php?mod=space&uid=247401]@brief[/url]       pid初始化
  305. * @param       无
  306. * @retval      无
  307. */
  308. void pid_init(void)
  309. {
  310.         


  311.                 memset(&g_motor_data,0,sizeof(g_motor_data));
  312.                 memset(&g_current_pid,0,sizeof(g_current_pid));
  313.         
  314.     g_current_pid.SetPoint = 0;        /* 设定目标值 */
  315.     g_current_pid.ActualValue = 0.0;    /* 期望输出值 */
  316.     g_current_pid.SumError = 0.0;       /* 积分值 */
  317.     g_current_pid.Error = 0.0;          /* Error[1] */
  318.     g_current_pid.LastError = 0.0;      /* Error[-1] */
  319.     g_current_pid.PrevError = 0.0;      /* Error[-2] */
  320.     g_current_pid.Proportion = KP;      /* 比例常数 Proportional Const */
  321.     g_current_pid.Integral = KI;        /* 积分常数 Integral Const */
  322.     g_current_pid.Derivative = KD;      /* 微分常数 Derivative Const */
  323. }

  324. void DCMotorsample_Init(void)
  325. {
  326.                 pid_init();
  327.                 ADC1CbReg(get_Motor_value);
  328. }


速度环:
  1. #include "main.h"
  2. #include "math.h"


  3. /*************************************    第二部分    电压电流温度采集    **********************************************/
  4. uint16_t g_adc_val[ADC_CH_NUM];                         /*ADC平均值存放数组*/


  5. PID_TypeDef  g_speed_pid;     /*速度环PID参数结构体*/

  6. /*
  7.     Rt = Rp *exp(B*(1/T1-1/T2))

  8.     Rt 是热敏电阻在T1温度下的阻值;
  9.     Rp是热敏电阻在T2常温下的标称阻值;
  10.     exp是e的n次方,e是自然常数,就是自然对数的底数,近似等于 2.7182818;
  11.     B值是热敏电阻的重要参数,教程中用到的热敏电阻B值为3380;
  12.     这里T1和T2指的是开尔文温度,T2是常温25℃,即(273.15+25)K
  13.     T1就是所求的温度
  14. */

  15. const float Rp = 10000.0f;          /* 10K */
  16. const float T2 = (273.15f + 25.0f); /* T2 */
  17. const float Bx = 3380.0f;           /* B */
  18. const float Ka = 273.15f;

  19. Motor_TypeDef g_motor_data;  /*电机参数变量*/
  20. ENCODE_TypeDef g_encode;     /*编码器参数变量*/

  21. /**
  22. * [url=home.php?mod=space&uid=247401]@brief[/url]       计算温度值
  23. * @param       para: 温度采集对应ADC通道的值(已滤波)
  24. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        计算温度分为两步:
  25.                 1.根据ADC采集到的值计算当前对应的Rt
  26.                 2.根据Rt计算对应的温度值
  27. * @retval      温度值
  28. */
  29. float get_temp(uint16_t para)
  30. {
  31.     float Rt;
  32.     float temp;
  33.    
  34.     /*
  35.         第一步:
  36.         Rt = 3.3 * 4700 / VTEMP - 4700 ,其中VTEMP就是温度检测通道采集回来的电压值,VTEMP = ADC值* 3.3/4096
  37.         由此我们可以计算出当前Rt的值:Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;
  38.     */
  39.    
  40.     Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;       /* 根据当前ADC值计算出Rt的值 */

  41.     /*
  42.         第二步:
  43.         根据当前Rt的值来计算对应温度值:Rt = Rp *exp(B*(1/T1-1/T2))
  44.     */
  45.    
  46.     temp = Rt / Rp;                 /* 解出exp(B*(1/T1-1/T2)) ,即temp = exp(B*(1/T1-1/T2)) */
  47.     temp = log(temp);               /* 解出B*(1/T1-1/T2) ,即temp = B*(1/T1-1/T2) */
  48.     temp /= Bx;                     /* 解出1/T1-1/T2 ,即temp = 1/T1-1/T2 */
  49.     temp += (1.0f / T2);            /* 解出1/T1 ,即temp = 1/T1 */
  50.     temp = 1.0f / (temp);           /* 解出T1 ,即temp = T1 */
  51.     temp -= Ka;                     /* 计算T1对应的摄氏度 */
  52.     return temp;                    /* 返回温度值 */
  53. }

  54. /**
  55. * [url=home.php?mod=space&uid=247401]@brief[/url]       计算ADC的平均值(滤波)
  56. * @param       * p :存放ADC值的指针地址
  57. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        此函数对电压、温度、电流对应的ADC值进行滤波,
  58. *              p[0]-p[2]对应的分别是电压、温度和电流
  59. * @retval      无
  60. */
  61. void calc_adc_val(uint16_t * adcdata)
  62. {
  63.           uint32_t temp[3] = {0,0,0};
  64.                 uint16_t i;
  65.     for(i=0;i<ADC_COLL;i++)         /* 循环ADC_COLL次取值,累加 */
  66.     {
  67.         temp[0] += adcdata[0+i*ADC_CH_NUM];
  68.         temp[1] += adcdata[1+i*ADC_CH_NUM];
  69.         temp[2] += adcdata[2+i*ADC_CH_NUM];
  70.     }
  71.     temp[0] /= ADC_COLL;            /* 取平均值 */
  72.     temp[1] /= ADC_COLL;
  73.     temp[2] /= ADC_COLL;
  74.                
  75.     g_adc_val[0] = temp[0];                 /* 存入电压ADC通道平均值 */
  76.     g_adc_val[1] = temp[1];                 /* 存入温度ADC通道平均值 */
  77.     g_adc_val[2] = temp[2];                 /* 存入电流ADC通道平均值 */               
  78. }

  79. void get_Motor_value(uint16_t * adcdata)
  80. {
  81.         calc_adc_val(adcdata);
  82.         
  83. }





  84. /*************************************    第三部分    编码器测速    ****************************************************/
  85. void speed_computer(int32_t encode_now, uint8_t ms)
  86. {
  87.     uint8_t i = 0, j = 0;
  88.     float temp = 0.0;
  89.     static uint8_t sp_count = 0, k = 0;
  90.     static float speed_arr[10] = {0.0};                     /* 存储速度进行滤波运算 */

  91.     if (sp_count == ms)                                     /* 计算一次速度 */
  92.     {
  93.         /* 计算电机转速
  94.            第一步 :计算ms毫秒内计数变化量
  95.            第二步 ;计算1min内计数变化量:g_encode.speed * ((1000 / ms) * 60 ,
  96.            第三步 :除以编码器旋转一圈的计数次数(倍频倍数 * 编码器分辨率)
  97.            第四步 :除以减速比即可得出电机转速
  98.         */
  99.         g_encode.encode_now = encode_now;                                /* 取出编码器当前计数值 */
  100.         g_encode.speed = (g_encode.encode_now - g_encode.encode_old);    /* 计算编码器计数值的变化量 */
  101.         
  102.         speed_arr[k++] = (float)(g_encode.speed * ((1000 / ms) * 60.0) / REDUCTION_RATIO / ROTO_RATIO );    /* 保存电机转速 */
  103.         
  104.         g_encode.encode_old = g_encode.encode_now;          /* 保存当前编码器的值 */

  105.         /* 累计10次速度值,后续进行滤波*/
  106.         if (k == 10)
  107.         {
  108.             for (i = 10; i >= 1; i--)                       /* 冒泡排序*/
  109.             {
  110.                 for (j = 0; j < (i - 1); j++)
  111.                 {
  112.                     if (speed_arr[j] > speed_arr[j + 1])    /* 数值比较 */
  113.                     {
  114.                         temp = speed_arr[j];                /* 数值换位 */
  115.                         speed_arr[j] = speed_arr[j + 1];
  116.                         speed_arr[j + 1] = temp;
  117.                     }
  118.                 }
  119.             }
  120.             
  121.             temp = 0.0;
  122.             
  123.             for (i = 2; i < 8; i++)                         /* 去除两边高低数据 */
  124.             {
  125.                 temp += speed_arr[i];                       /* 将中间数值累加 */
  126.             }
  127.             
  128.             temp = (float)(temp / 6);                       /*求速度平均值*/
  129.             
  130.             /* 一阶低通滤波
  131.              * 公式为:Y(n)= qX(n) + (1-q)Y(n-1)
  132.              * 其中X(n)为本次采样值;Y(n-1)为上次滤波输出值;Y(n)为本次滤波输出值,q为滤波系数
  133.              * q值越小则上一次输出对本次输出影响越大,整体曲线越平稳,但是对于速度变化的响应也会越慢
  134.              */
  135.             g_motor_data.speed = (float)( ((float)0.48 * temp) + (g_motor_data.speed * (float)0.52) );
  136.             k = 0;
  137.         }
  138.         sp_count = 0;
  139.     }
  140.     sp_count ++;
  141. }

  142. uint8_t g_run_flag = 0;

  143. int32_t motor_pwm = 0;

  144. void DCMotor_App(void)
  145. {
  146.         static uint8_t key=0;
  147.         key=key_scan(0);
  148.         if(key == KEY0_PRES)
  149.         {        
  150.                 TurnTogLed(LED1);
  151.                 g_speed_pid.SetPoint +=30;
  152.                 g_run_flag = 1;
  153.                 if (g_speed_pid.SetPoint == 0)
  154.                 {
  155.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  156.                                 g_motor_data.motor_pwm = 0;
  157.                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);                                  /* 设置电机转速 */
  158.                 }
  159.                 else
  160.                 {
  161.                         DC_Motor_Start(MOTOR_1);
  162.                         if(g_speed_pid.SetPoint  >= 300)
  163.                         {
  164.                                 g_speed_pid.SetPoint  =300;
  165.                         }
  166.                         atk_debug_send_motorstate(RUN_STATE);           /* 上传电机状态(运行) */
  167.                         DC_Motor_Speed(g_speed_pid.SetPoint,MOTOR_1); /* 设置电机转速 */

  168.                 }
  169.         }
  170.         else if(key == KEY1_PRES)        {        
  171.                 TurnTogLed(LED1);
  172.                 g_speed_pid.SetPoint -= 30;

  173.                 g_run_flag = 1;
  174.                 if (g_speed_pid.SetPoint == 0)
  175.                 {
  176.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  177.                                 g_motor_data.motor_pwm = 0;
  178.                                 DC_Motor_Speed(g_motor_data.motor_pwm,MOTOR_1); /* 设置电机转速 */                                 
  179.                 }
  180.                 else
  181.                 {
  182.                         DC_Motor_Start(MOTOR_1);
  183.                         if(g_speed_pid.SetPoint  <= -300)
  184.                         {
  185.                                 g_speed_pid.SetPoint  =-300;
  186.                         }
  187.                         DC_Motor_Speed(g_speed_pid.SetPoint,MOTOR_1); /* 设置电机转速 */

  188.                         atk_debug_send_motorstate(RUN_STATE);           /* 上传电机状态(运行) */
  189.                 }
  190.         }
  191.         else if(key == KEY2_PRES)
  192.         {
  193.                 DC_Motor_Stop(MOTOR_1);
  194.                 g_run_flag = 0;                                 /* 标记电机停止 */
  195.                 g_motor_data.motor_pwm = 0;
  196.                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);          /* 设置电机转向、速度 */
  197.                 g_speed_pid.SetPoint = 0;
  198.                 pid_init();
  199.                 atk_debug_send_motorstate(BREAKED_STATE);           /* 上传电机状态(刹车) */
  200.                 atk_debug_send_initdata(TYPE_PID1, (float *)(&g_speed_pid.SetPoint), KP, KI, KD);           /* 同步数据到上位机 */
  201.         }
  202. }

  203. void DCMotor_Value(void)
  204. {
  205.         static uint16_t init_adc_val = 0;
  206.         static uint16_t g_time =0;
  207.         static uint8_t num = 0;
  208.         if(num < 2)
  209.         {
  210.                 num ++;
  211.                 atk_debug_send_motorcode(DC_MOTOR);         /* 上传电机类型(直流有刷电机) */
  212.     atk_debug_send_motorstate(IDLE_STATE);      /* 上传电机状态(空闲) */
  213.                 init_adc_val = g_adc_val[2];
  214.                 init_adc_val += g_adc_val[2];       /* 现在的值和上一次存储的值相加 */
  215.     init_adc_val /= 2;  
  216.         }else
  217.         {                                                        
  218.                                 
  219.                                 
  220.                                 
  221.                                 /* 获取编码器值,用于计算速度 */
  222.                                 get_EncodeValue(5);        /* 中位平均值滤除编码器抖动数据,5ms计算一次速度*/
  223.                                 
  224.                                 if(g_time  % 1000 ==0)
  225.                                 {                                                                                 
  226.                                        
  227.                                         __NOP();__NOP();__NOP();
  228.                                         g_motor_data.board_temp = get_temp(g_adc_val[1]);
  229.                                             
  230. //                                                        
  231.                                         printf("\r\n******************************\r\n");
  232.                                         printf("KEY0:增加比较值,KEY1:减小比较值,KEY2:停止电机\r\n\r\n");
  233.                                         printf("Valtage:%.2fV \r\n",    g_motor_data.volatage);                   /* 打印电压值 */
  234.                                         printf("Temp:%.2fC \r\n",                    g_motor_data.board_temp   );                  /* 打印温度值 */
  235.                                         printf("Current:%.2fmA \r\n",   g_motor_data.current); /* 打印电流值 */
  236.                                         printf("电机速度:%.1f RPM\r\n\r\n",   g_motor_data.speed);               
  237.                                         printf("\r\n******************************\r\n");
  238.                                 }
  239.                                 else if(g_time %300 == 0)
  240.                                 {
  241.                                         atk_debug_send_temp(0,get_temp(g_adc_val[1]));
  242.                                 }
  243.                                 else if(g_time %200 == 0)
  244.                                 {
  245.                                         g_motor_data.volatage  = g_adc_val[0]*ADC2VBUS;               
  246.                                         atk_debug_send_valtage(g_motor_data.volatage );
  247.                                 }
  248.                                 else if(g_time % SMAPLSE_PID_SPEED == 0)                /* 电机速度 50ms进行一次pid计算 */
  249.                                 {
  250.                                         atk_debug_send_speed(g_motor_data.speed);
  251.                                         if(g_run_flag)
  252.                                         {
  253.                                        
  254.                                                  /* PID计算,输出比较值(占空比) */
  255.                                                 g_motor_data.motor_pwm = increment_pid_ctrl (&g_speed_pid,g_motor_data.speed);
  256.                                                 
  257.                                                 if(g_motor_data.motor_pwm >= 8200)
  258.                                                 {
  259.                                                         g_motor_data.motor_pwm = 8200;
  260.                                                 }
  261.                                                 else if (g_motor_data.motor_pwm <= -8200)
  262.                                                 {
  263.                                                         g_motor_data.motor_pwm = -8200;
  264.                                                 }
  265.                                        
  266.                                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1); /* 设置电机转速 */
  267.                                         }
  268.                                                 atk_debug_send_wave_data( 1 ,g_motor_data.speed);                           /* 选择通道1,发送实际速度(波形显示)*/
  269.                                                 atk_debug_send_wave_data( 2 ,g_speed_pid.SetPoint);                         /* 选择通道2,发送目标速度(波形显示)*/
  270.                                                 atk_debug_send_wave_data( 3 ,g_motor_data.motor_pwm * 100 / 8400);          /* 选择通道3,发送占空比(波形显示)*/
  271.                                 }
  272.                                 else if(g_time % 20 == 0)
  273.                                 {
  274.                                         g_motor_data.current          = (abs(g_adc_val[2]-init_adc_val)*ADC2CURT)*0.001;
  275.                                         atk_debug_send_current(g_motor_data.current,0,0);                                       
  276.                                 }
  277.                                 g_time ++;
  278.         }
  279. }

  280. void get_EncodeValue(uint8_t  ms)
  281. {
  282.         int encode_now = gtim_get_encode();
  283.         speed_computer(encode_now, ms);
  284. }


  285. PID_TypeDef  g_speed_pid;           /* 速度环PID参数结构体 */

  286. /**
  287. * [url=home.php?mod=space&uid=247401]@brief[/url]       pid初始化
  288. * @param       无
  289. * @retval      无
  290. */
  291. void pid_init(void)
  292. {
  293.         
  294.                 memset(&g_motor_data,0,sizeof(g_motor_data));
  295.                 memset(&g_speed_pid,0,sizeof(g_speed_pid));
  296.         
  297.                 /* 初始化速度环PID参数 */
  298.     g_speed_pid.SetPoint = 0;       /* 设定目标值 */
  299.     g_speed_pid.ActualValue = 0.0;  /* 期望输出值 */
  300.     g_speed_pid.SumError = 0.0;     /* 积分值 */
  301.     g_speed_pid.Error = 0.0;        /* Error[1] */
  302.     g_speed_pid.LastError = 0.0;    /* Error[-1] */
  303.     g_speed_pid.PrevError = 0.0;    /* Error[-2] */
  304.     g_speed_pid.Proportion = KP;    /* 比例常数 Proportional Const */
  305.     g_speed_pid.Integral = KI;      /* 积分常数 Integral Const */
  306.     g_speed_pid.Derivative = KD;    /* 微分常数 Derivative Const */
  307.         
  308.                 atk_debug_send_wave_data( 1 ,g_motor_data.speed);                           /* 选择通道1,发送实际速度(波形显示)*/
  309.                 atk_debug_send_wave_data( 2 ,g_speed_pid.SetPoint);                         /* 选择通道2,发送目标速度(波形显示)*/
  310.                 atk_debug_send_wave_data( 3 ,g_motor_data.motor_pwm * 100 / 8400);          /* 选择通道3,发送占空比(波形显示)*/
  311. }

  312. void DCMotorsample_Init(void)
  313. {
  314.                 pid_init();
  315.                 ADC1CbReg(get_Motor_value);
  316. }

位置环:
  1. #include "main.h"
  2. #include "math.h"


  3. /*************************************    第二部分    电压电流温度采集    **********************************************/
  4. uint16_t g_adc_val[ADC_CH_NUM];                         /*ADC平均值存放数组*/



  5. PID_TypeDef  g_location_pid;             /*位置环PID参数结构体*/

  6. /*
  7.     Rt = Rp *exp(B*(1/T1-1/T2))

  8.     Rt 是热敏电阻在T1温度下的阻值;
  9.     Rp是热敏电阻在T2常温下的标称阻值;
  10.     exp是e的n次方,e是自然常数,就是自然对数的底数,近似等于 2.7182818;
  11.     B值是热敏电阻的重要参数,教程中用到的热敏电阻B值为3380;
  12.     这里T1和T2指的是开尔文温度,T2是常温25℃,即(273.15+25)K
  13.     T1就是所求的温度
  14. */

  15. const float Rp = 10000.0f;          /* 10K */
  16. const float T2 = (273.15f + 25.0f); /* T2 */
  17. const float Bx = 3380.0f;           /* B */
  18. const float Ka = 273.15f;

  19. Motor_TypeDef g_motor_data;  /*电机参数变量*/
  20. ENCODE_TypeDef g_encode;     /*编码器参数变量*/

  21. /**
  22. * [url=home.php?mod=space&uid=247401]@brief[/url]       计算温度值
  23. * @param       para: 温度采集对应ADC通道的值(已滤波)
  24. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        计算温度分为两步:
  25.                 1.根据ADC采集到的值计算当前对应的Rt
  26.                 2.根据Rt计算对应的温度值
  27. * @retval      温度值
  28. */
  29. float get_temp(uint16_t para)
  30. {
  31.     float Rt;
  32.     float temp;
  33.    
  34.     /*
  35.         第一步:
  36.         Rt = 3.3 * 4700 / VTEMP - 4700 ,其中VTEMP就是温度检测通道采集回来的电压值,VTEMP = ADC值* 3.3/4096
  37.         由此我们可以计算出当前Rt的值:Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;
  38.     */
  39.    
  40.     Rt = 3.3f * 4700.0f / (para * 3.3f / 4096.0f ) - 4700.0f;       /* 根据当前ADC值计算出Rt的值 */

  41.     /*
  42.         第二步:
  43.         根据当前Rt的值来计算对应温度值:Rt = Rp *exp(B*(1/T1-1/T2))
  44.     */
  45.    
  46.     temp = Rt / Rp;                 /* 解出exp(B*(1/T1-1/T2)) ,即temp = exp(B*(1/T1-1/T2)) */
  47.     temp = log(temp);               /* 解出B*(1/T1-1/T2) ,即temp = B*(1/T1-1/T2) */
  48.     temp /= Bx;                     /* 解出1/T1-1/T2 ,即temp = 1/T1-1/T2 */
  49.     temp += (1.0f / T2);            /* 解出1/T1 ,即temp = 1/T1 */
  50.     temp = 1.0f / (temp);           /* 解出T1 ,即temp = T1 */
  51.     temp -= Ka;                     /* 计算T1对应的摄氏度 */
  52.     return temp;                    /* 返回温度值 */
  53. }

  54. /**
  55. * @brief       计算ADC的平均值(滤波)
  56. * @param       * p :存放ADC值的指针地址
  57. * [url=home.php?mod=space&uid=536309]@NOTE[/url]        此函数对电压、温度、电流对应的ADC值进行滤波,
  58. *              p[0]-p[2]对应的分别是电压、温度和电流
  59. * @retval      无
  60. */
  61. void calc_adc_val(uint16_t * adcdata)
  62. {
  63.           uint32_t temp[3] = {0,0,0};
  64.                 uint16_t i;
  65.     for(i=0;i<ADC_COLL;i++)         /* 循环ADC_COLL次取值,累加 */
  66.     {
  67.         temp[0] += adcdata[0+i*ADC_CH_NUM];
  68.         temp[1] += adcdata[1+i*ADC_CH_NUM];
  69.         temp[2] += adcdata[2+i*ADC_CH_NUM];
  70.     }
  71.     temp[0] /= ADC_COLL;            /* 取平均值 */
  72.     temp[1] /= ADC_COLL;
  73.     temp[2] /= ADC_COLL;
  74.                
  75.     g_adc_val[0] = temp[0];                 /* 存入电压ADC通道平均值 */
  76.     g_adc_val[1] = temp[1];                 /* 存入温度ADC通道平均值 */
  77.     g_adc_val[2] = temp[2];                 /* 存入电流ADC通道平均值 */               
  78. }

  79. void get_Motor_value(uint16_t * adcdata)
  80. {
  81.         calc_adc_val(adcdata);
  82.         
  83. }





  84. /*************************************    第三部分    编码器测速    ****************************************************/
  85. void speed_computer(int32_t encode_now, uint8_t ms)
  86. {
  87.     uint8_t i = 0, j = 0;
  88.     float temp = 0.0;
  89.     static uint8_t sp_count = 0, k = 0;
  90.     static float speed_arr[10] = {0.0};                     /* 存储速度进行滤波运算 */

  91.     if (sp_count == ms)                                     /* 计算一次速度 */
  92.     {
  93.         /* 计算电机转速
  94.            第一步 :计算ms毫秒内计数变化量
  95.            第二步 ;计算1min内计数变化量:g_encode.speed * ((1000 / ms) * 60 ,
  96.            第三步 :除以编码器旋转一圈的计数次数(倍频倍数 * 编码器分辨率)
  97.            第四步 :除以减速比即可得出电机转速
  98.         */
  99.         g_encode.encode_now = encode_now;                                /* 取出编码器当前计数值 */
  100.         g_encode.speed = (g_encode.encode_now - g_encode.encode_old);    /* 计算编码器计数值的变化量 */
  101.         
  102.         speed_arr[k++] = (float)(g_encode.speed * ((1000 / ms) * 60.0) / REDUCTION_RATIO / ROTO_RATIO );    /* 保存电机转速 */
  103.         
  104.         g_encode.encode_old = g_encode.encode_now;          /* 保存当前编码器的值 */

  105.         /* 累计10次速度值,后续进行滤波*/
  106.         if (k == 10)
  107.         {
  108.             for (i = 10; i >= 1; i--)                       /* 冒泡排序*/
  109.             {
  110.                 for (j = 0; j < (i - 1); j++)
  111.                 {
  112.                     if (speed_arr[j] > speed_arr[j + 1])    /* 数值比较 */
  113.                     {
  114.                         temp = speed_arr[j];                /* 数值换位 */
  115.                         speed_arr[j] = speed_arr[j + 1];
  116.                         speed_arr[j + 1] = temp;
  117.                     }
  118.                 }
  119.             }
  120.             
  121.             temp = 0.0;
  122.             
  123.             for (i = 2; i < 8; i++)                         /* 去除两边高低数据 */
  124.             {
  125.                 temp += speed_arr[i];                       /* 将中间数值累加 */
  126.             }
  127.             
  128.             temp = (float)(temp / 6);                       /*求速度平均值*/
  129.             
  130.             /* 一阶低通滤波
  131.              * 公式为:Y(n)= qX(n) + (1-q)Y(n-1)
  132.              * 其中X(n)为本次采样值;Y(n-1)为上次滤波输出值;Y(n)为本次滤波输出值,q为滤波系数
  133.              * q值越小则上一次输出对本次输出影响越大,整体曲线越平稳,但是对于速度变化的响应也会越慢
  134.              */
  135.             g_motor_data.speed = (float)( ((float)0.48 * temp) + (g_motor_data.speed * (float)0.52) );
  136.             k = 0;
  137.         }
  138.         sp_count = 0;
  139.     }
  140.     sp_count ++;
  141. }

  142. uint8_t g_run_flag = 0;

  143. int32_t motor_pwm = 0;

  144. void DCMotor_App(void)
  145. {
  146.         static uint8_t key=0;
  147.         key=key_scan(0);
  148.         if(key == KEY0_PRES)
  149.         {        
  150.                 TurnTogLed(LED1);
  151.                 g_location_pid.SetPoint +=1320;        /* 正转一圈,电机旋转圈数 = 计数值变化量 / 44 / 30 */
  152.                 g_run_flag = 1;
  153.                 if (g_location_pid.SetPoint == 0)
  154.                 {
  155.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  156.                                 g_motor_data.motor_pwm = 0;
  157.                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);                                  /* 设置电机转速 */
  158.                 }
  159.                 else
  160.                 {
  161.                         DC_Motor_Start(MOTOR_1);
  162.                         if(g_location_pid.SetPoint  >= 6600)
  163.                         {
  164.                                 g_location_pid.SetPoint  =6600;
  165.                         }
  166.                         atk_debug_send_motorstate(RUN_STATE);           /* 上传电机状态(运行) */
  167.                         DC_Motor_Speed(g_location_pid.SetPoint,MOTOR_1); /* 设置电机转速 */

  168.                 }
  169.         }
  170.         else if(key == KEY1_PRES)        {        
  171.                 TurnTogLed(LED1);
  172.                 g_location_pid.SetPoint -= 1320;        /* 正转一圈,电机旋转圈数 = 计数值变化量 / 44 / 30 */

  173.                 g_run_flag = 1;
  174.                 if (g_location_pid.SetPoint == 0)
  175.                 {
  176.                                 DC_Motor_Stop(MOTOR_1);           /* 停止则立刻响应 */                        
  177.                                 g_motor_data.motor_pwm = 0;
  178.                                 DC_Motor_Speed(g_motor_data.motor_pwm,MOTOR_1); /* 设置电机转速 */                                 
  179.                 }
  180.                 else
  181.                 {
  182.                         DC_Motor_Start(MOTOR_1);
  183.                         if(g_location_pid.SetPoint  <= -6600)
  184.                         {
  185.                                 g_location_pid.SetPoint  =-6600;
  186.                         }
  187.                         DC_Motor_Speed(g_location_pid.SetPoint,MOTOR_1); /* 设置电机转速 */

  188.                         atk_debug_send_motorstate(RUN_STATE);           /* 上传电机状态(运行) */
  189.                 }
  190.         }
  191.         else if(key == KEY2_PRES)
  192.         {
  193.                 DC_Motor_Stop(MOTOR_1);
  194.                 g_run_flag = 0;                                 /* 标记电机停止 */
  195.                 g_motor_data.motor_pwm = 0;
  196.                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);          /* 设置电机转向、速度 */
  197.                 g_location_pid.SetPoint = 0;
  198.                 pid_init();
  199.                 atk_debug_send_motorstate(BREAKED_STATE);           /* 上传电机状态(刹车) */
  200.                 atk_debug_send_initdata(TYPE_PID1, (float *)(&g_location_pid.SetPoint), KP, KI, KD);           /* 同步数据到上位机 */
  201.         }
  202. }

  203. void DCMotor_Value(void)
  204. {
  205.         int32_t motor_pwm_temp = 0;
  206.         static uint16_t init_adc_val = 0;
  207.         static uint16_t g_time =0;
  208.         static uint8_t num = 0;
  209.         if(num < 2)
  210.         {
  211.                 num ++;
  212.                 atk_debug_send_motorcode(DC_MOTOR);         /* 上传电机类型(直流有刷电机) */
  213.     atk_debug_send_motorstate(IDLE_STATE);      /* 上传电机状态(空闲) */
  214.                 init_adc_val = g_adc_val[2];
  215.                 init_adc_val += g_adc_val[2];       /* 现在的值和上一次存储的值相加 */
  216.     init_adc_val /= 2;  
  217.         }else
  218.         {                                                        
  219.                                 
  220.                                 

  221.                                 /* 获取编码器值,用于计算速度 */
  222.                                 get_EncodeValue(5);        /* 中位平均值滤除编码器抖动数据,5ms计算一次速度*/
  223.                                 
  224.                                 if(g_time  % 1000 ==0)
  225.                                 {                                                                                 
  226.                                        
  227.                                         g_motor_data.volatage  = g_adc_val[0]*ADC2VBUS;               
  228.                                         atk_debug_send_valtage(g_motor_data.volatage );
  229.                                         __NOP();__NOP();__NOP();
  230.                                         g_motor_data.board_temp = get_temp(g_adc_val[1]);
  231.                                         atk_debug_send_temp(0,g_motor_data.board_temp);  
  232.                                         __NOP();__NOP();__NOP();
  233.                                        
  234.                                         g_motor_data.current          = (abs(g_adc_val[2]-init_adc_val)*ADC2CURT)*0.001;
  235.                                         atk_debug_send_current(g_motor_data.current,0,0);                        
  236.                                         __NOP();__NOP();__NOP();
  237.                                        
  238. //                                        printf("\r\n******************************\r\n");
  239. //                                        printf("KEY0:增加比较值,KEY1:减小比较值,KEY2:停止电机\r\n\r\n");
  240. //                                        printf("Valtage:%.2fV \r\n",    g_motor_data.volatage);                   /* 打印电压值 */
  241. //                                        printf("Temp:%.2fC \r\n",                    g_motor_data.board_temp   );                  /* 打印温度值 */
  242. //                                        printf("Current:%.2fmA \r\n",   g_motor_data.current); /* 打印电流值 */
  243. //                                        printf("电机速度:%.1f RPM\r\n\r\n",   g_motor_data.speed);               
  244. //                                        printf("\r\n******************************\r\n");
  245.                                 }

  246.                                 else if(g_time % SMAPLSE_PID_SPEED == 0)                /* 电机速度 50ms进行一次pid计算 */
  247.                                 {
  248.                                         if(g_run_flag == 1)
  249.                                         {
  250.                                                 /* PID计算,输出比较值(占空比),再进行一阶低通滤波 */
  251.                                                 motor_pwm_temp = increment_pid_ctrl(&g_location_pid,g_motor_data.location);
  252.                                                 g_motor_data.motor_pwm = (int32_t)((g_motor_data.motor_pwm * 0.5) + (motor_pwm_temp * 0.5));
  253.                                                  if (g_motor_data.motor_pwm >= 3000)                     /* 限制占空比 */
  254.                                                 {
  255.                                                                 g_motor_data.motor_pwm = 3000;
  256.                                                 }
  257.                                                 else if (g_motor_data.motor_pwm <= -3000)
  258.                                                 {
  259.                                                                 g_motor_data.motor_pwm = -3000;
  260.                                                 }
  261.                                                 atk_debug_send_wave_data( 1 ,g_motor_data.location);                                        /* 选择通道1,发送实际位置(波形显示)*/
  262.             atk_debug_send_wave_data( 2 ,g_location_pid.SetPoint);                                      /* 选择通道2,发送目标位置(波形显示)*/
  263.                                                 
  264.                                                 Motor_PWM_Set(g_motor_data.motor_pwm,MOTOR_1);
  265.                                         }
  266.                                 }

  267.                                 g_time ++;
  268.         }
  269. }

  270. void get_EncodeValue(uint8_t  ms)
  271. {
  272.         int encode_now = gtim_get_encode();
  273.         
  274.   g_motor_data.location = encode_now;                             /* 获取当前计数总值,用于位置闭环控制 */     
  275.         speed_computer(encode_now, ms);
  276. }


  277. /**
  278. * @brief       pid初始化
  279. * @param       无
  280. * @retval      无
  281. */
  282. void pid_init(void)
  283. {
  284.         
  285.                 memset(&g_motor_data,0,sizeof(g_motor_data));
  286.                 memset(&g_location_pid,0,sizeof(g_location_pid));
  287.         
  288.     g_location_pid.SetPoint = 0.0;       /* 设定目标值 */
  289.     g_location_pid.ActualValue = 0.0;    /* 期望输出值 */
  290.     g_location_pid.SumError = 0.0;       /* 积分值 */
  291.     g_location_pid.Error = 0.0;          /* Error[1] */
  292.     g_location_pid.LastError = 0.0;      /* Error[-1] */
  293.     g_location_pid.PrevError = 0.0;      /* Error[-2] */
  294.     g_location_pid.Proportion = KP;      /* 比例常数 Proportional Const */
  295.     g_location_pid.Integral = KI;        /* 积分常数 Integral Const */
  296.     g_location_pid.Derivative = KD;      /* 微分常数 Derivative Const */
  297.         
  298.                 atk_debug_send_wave_data( 1 ,g_motor_data.speed);                           /* 选择通道1,发送实际速度(波形显示)*/
  299.                 atk_debug_send_wave_data( 2 ,g_location_pid.SetPoint);                         /* 选择通道2,发送目标速度(波形显示)*/
  300.                 atk_debug_send_wave_data( 3 ,g_motor_data.motor_pwm * 100 / 8400);          /* 选择通道3,发送占空比(波形显示)*/
  301. }

  302. void DCMotorsample_Init(void)
  303. {
  304.                 pid_init();
  305.                 ADC1CbReg(get_Motor_value);
  306. }





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

本版积分规则

33

主题

91

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部