| 
 
| 本帖最后由 Brand2 于 2016-9-21 21:31 编辑 
 例程名称: YSF1_HAL_MOTOR-045. 单轴25GA370直流电机增量式PID旋转控制(L298N驱动)
 *
 ******************************************************************************
 * 说明:
 * 本例程配套硬石stm32开发板YS-F1Pro使用。
 *
 * 淘宝:
 * 论坛:硬石电子社区
 * 版权归硬石嵌入式开发团队所有,请勿商用。
 ******************************************************************************
 */
 
 【1】例程简介
 【2】跳线帽情况
 【3】操作及现象
 /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
 
 main.c文件内容
 
 /* 私有类型定义 --------------------------------------------------------------*///定义PID结构体typedef struct{   __IO int      SetPoint;                                 //设定目标 Desired Value   __IO double   Proportion;                               //比例常数 Proportional Const   __IO double   Integral;                                 //积分常数 Integral Const   __IO double   Derivative;                               //微分常数 Derivative Const   __IO int      LastError;                                //Error[-1]   __IO int      PrevError;                                //Error[-2]}PID;/* 私有宏定义 ----------------------------------------------------------------*//*************************************///定义PID相关宏// 这三个参数设定对电机运行影响非常大/*************************************/#define  P_DATA      3.2                                 //P参数#define  I_DATA      1.1                                //I参数#define  D_DATA      -0.15                              //D参数/* 私有变量 ------------------------------------------------------------------*/__IO uint16_t time_count=0;        // 时间计数,每1ms增加一(与滴定时器频率有关)__IO uint32_t CaptureNumber=0;     // 输入捕获数__IO uint8_t  start_flag=0;__IO double encoder_speed=0;static PID sPID;static PID *sptr = &sPID;int main(void){  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */  HAL_Init();  /* 配置系统时钟 */  SystemClock_Config();  KEY_GPIO_Init();  MX_DEBUG_USART_Init();  IncPIDInit();  ENCODER_TIMx_Init();  HAL_TIM_Base_Start(&htimx_ENCODER);  /* 高级控制定时器初始化并配置PWM输出功能 */  L298N_TIMx_Init();  /* 启动定时器 */  HAL_TIM_Base_Start(&htimx_L298N);  HAL_TIM_IC_Start_IT(&htimx_ENCODER,ENCODER_TIM_CHANNELx);  /* 启动定时器通道和互补通道PWM输出 */  L298N_DCMOTOR_Contrl(1,2,0);  start_flag=1;  printf("增量式PID算法控制电机旋转\n");  /* 无限循环 */  while (1)  {    if(KEY1_StateRead()==KEY_DOWN)  // 增速    {      /* 设置目标速度 */      sptr->SetPoint =50;    }    if(KEY2_StateRead()==KEY_DOWN)  // 减速    {      /* 设置目标速度 */      sptr->SetPoint =300;    }  }}void HAL_SYSTICK_Callback(void){  if(start_flag) // 等待脉冲输出后才开始计时  {    time_count++;         // 每1ms自动增一    if(time_count==200)    {      __IO uint32_t count;      __IO int para;      __IO double cal;      /* 得到编码器计数值,数值越大说明速度越大 */      count=CaptureNumber;      CaptureNumber=0;    // 清零,从零开始计数      /* 计数得到增量式PID的增量数值 */      para=IncPIDCalc(count);      /* 根据增量数值调整当前电机速度 */      if((para<-3)||(para>3)) // 不做 PID 调整,避免误差较小时频繁调节引起震荡。      {        PWM_Duty +=para;      }      if(PWM_Duty>899)PWM_Duty=899;      // 11:编码器线数(转速一圈输出脉冲数)      // 34:电机减数比,内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比      cal=sptr->SetPoint;      printf("\n设定目标速度 -> 编码器在%ds时间计数%d个脉冲\n",time_count,sptr->SetPoint);      printf("                相当于实际目标速度为:%0.2f圈/s\n",cal*(1000/time_count)/11/34);      cal=count;      printf("当前电机速度-> 编码器在%ds时间计数%d个脉冲\n",time_count,count);      printf("                相当于当前实际速度为:%0.2f圈/s\n",cal*(1000/time_count)/11/34);      printf("增量式PID算法计数结果值:%d   设置新的占空比为:%d\n",para,PWM_Duty);      L298N_DCMOTOR_Contrl(1,2,PWM_Duty);      time_count=0;    }  }}/**************PID参数初始化********************************/void IncPIDInit(void){    sptr->LastError=0;            //Error[-1]    sptr->PrevError=0;            //Error[-2]    sptr->Proportion=P_DATA;      //比例常数 Proportional Const    sptr->Integral=I_DATA;        //积分常数  Integral Const    sptr->Derivative=D_DATA;      //微分常数 Derivative Const    sptr->SetPoint=100;           //设定目标Desired Value}/********************增量式PID控制设计************************************/int IncPIDCalc(int NextPoint){  int iError,iIncpid;                                 //当前误差  iError=sptr->SetPoint-NextPoint;                    //增量计算  iIncpid=(sptr->Proportion * iError)                 //E[k]项              -(sptr->Integral * sptr->LastError)     //E[k-1]项              +(sptr->Derivative * sptr->PrevError);  //E[k-2]项  sptr->PrevError=sptr->LastError;                    //存储误差,用于下次计算  sptr->LastError=iError;  return(iIncpid);                                    //返回增量值}/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
 
 
 | 
 |