打印
[应用相关]

单轴25GA370直流电机增量式PID旋转控制(L298N驱动)

[复制链接]
1514|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Brand2|  楼主 | 2016-9-21 21:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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****/


沙发
lsdavid| | 2016-9-22 09:30 | 只看该作者
我有一个问题想请教一下,程序中你为什么用double类型?ARM Cortex-M2, Cortex-M4 不是不支持double吗?我认为那些变量用float就够了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

157

主题

824

帖子

2

粉丝