比传统PID算法更容易实现和调试的增量调速法

当你接到一个控制任务,比如需要控制电机的转速,并支持动态快速调整转速,电机的转速可以实时获取。然后开始网上一顿搜索,搜索结果大致如下所述。

在自动控制领域中,PID 控制算法是一种非常常见且有效的控制算法,用于实现闭环控制系统中的精确控制。PID 控制器由三个组成部分构成:比例 (P)、积分 (I) 和微分 (D)。每个部分都有其特定的功能,共同作用于系统的输出以达到期望的设定值。

PID 控制算法的基本公式如下:

其中:

( u(t) ) 表示控制器的输出。

( e(t) ) 表示误差信号,即设定值与实际值之间的差值。

( K_p ) 是比例增益。

( K_i ) 是积分增益。

( K_d ) 是微分增益。

各组成部分的作用

1.比例项 (P):

        •比例项直接与误差成正比。

        •它可以快速响应误差的变化。

        •比例项的系数 ( K_p ) 影响系统的响应速度和稳定性。

2.积分项 (I):

        •积分项随着时间累积误差。

        •它有助于消除静态误差(即当系统稳定时仍存在的误差)。

        •积分项的系数 ( K_i ) 影响系统的最终精度。

3.微分项 (D):

        •微分项考虑误差的变化率。

        •它可以预测未来的误差变化趋势,并提前做出调整。

        •微分项的系数 ( K_d ) 影响系统的动态性能,尤其是抗扰动的能力。

看完上述理论公式是否有点不知所措?要实际使用要怎么实现呢?多年前我曾经按照上述公式,写过代码并调试,但实际工程使用效果并不理想(很容易过冲,也就是加速时电机转速容易超过设定转速),参数比较难确定,而且如果换了电机需要重调参数。(这里也可能是我没有找到调试的最优方案,感兴趣的同学可以深入研究,评论区交流)

言归正传,后来又有幸接触到一个项目需要控制电机转速,就换了设计思路,大致流程是:

Step1 获取到当前的实时转速和当前设置的PWM占空比(一般调节速度使用PWM)

Step2 比较当前转速和目标转速的大小,如当前转速小于目标转速则进入加速流程。反之则进入减速流程

加速流程:

计算当前转速和目标转速相差的绝对值,根据不同的绝对值区间,再当前占空比数值上调大不同数值。

减速流程:

计算当前转速和目标转速相差的绝对值,根据不同的绝对值区间,再当前占空比数值上调小不同数值。

以下是调速的核心代码片段,工程实测可用,而且调速比较平滑,前提是需要以最快速度轮询。

注,以下duty取值范围是0~10000,需要换算到占空比的0%~100%

{

       //轮询所有需要调节的电机通道

 for(i=0;i<PWM_MAX_CHN_NUM;i++)            

{

            {               

                uint16_t CurDuty;      //当前占空比

//等待获取当前实际转速

                while(Bsp_WheelSpeedGet(i, &RpmList[i]) == FALSE);   

                CurDuty = HalPwmDutyGet(i);              

                {

                    uint16_t CurDuty;       

                    uint16_t DevSpeed;                        

                  //CarWeelSpeedList是各通道目标转速

                    if(RpmList[i] <= CarWeelSpeedList[i])//加速状态

                    {

                        DevSpeed = CarWeelSpeedList[i] - RpmList[i]

//速度调节完成

                        if(DevSpeed < CAR_DEV_BUT_OK_SPEED)                                                      {                           

                            continue;

                        }                   

                     //根据速度差距采取不同的速度调整策略

                        if(DevSpeed <= 100)          

                        {

                            bspPwmDutySet(i,CurDuty+1);

                        }

                        else if(DevSpeed <= 500)

                        {

                            bspPwmDutySet(i,CurDuty+10);

                        }

                        else if(DevSpeed <= 1000)

                        {

                            bspPwmDutySet(i,CurDuty+100);

                        }

                        else if(DevSpeed <= 2000)

                        {

                            bspPwmDutySet(i,CurDuty+200);

                        }

                        else

                        {

                            bspPwmDutySet(i,CurDuty+300);

                        }

                    }

                    else //加速过快导致速度超过目标速度 或 减速

                    {                       

                        DevSpeed = RpmList[i] - CarWeelSpeedList[i];     //速度调节完成

                        if((DevSpeed < CAR_DEV_BUT_OK_SPEED)   || (CurDuty == 0))

                        {

                             //目标速度为0

                            if(CarWeelSpeedList[i] == 0)                                                               

                             {

                                bspPwmDutySet(i,0);

                            }                           

                            continue;

                        }                       

                        if(DevSpeed <= 120)

                        {

                          if(CurDuty)

{

                             bspPwmDutySet(i,CurDuty-1);    

}

//此处有可能让占空比为0

                            if(CarWeelSpeedList[i] == 0)//目标速度为0

                            {

                                bspPwmDutySet(i,0);

                            }                         

                        }

                        else if(DevSpeed <= 500)      //速度差距较小

                        {

                            if(CurDuty > 10)

                            {

                                bspPwmDutySet(i,CurDuty-10);

                            }

                        }

                        else if(DevSpeed <= 1000)

                        {

                            if(CurDuty > 100)

                            {

                                bspPwmDutySet(i,CurDuty-100);

                            }

                            else

                            {

                                bspPwmDutySet(i,(CurDuty >> 1)+10);

                            }

                        }

                        else    //速度差距较大

                        {

                            if(CurDuty > 300)

                            {

                                bspPwmDutySet(i,CurDuty-300);

                            }

                            else if(CurDuty > 200)

                            {

                                bspPwmDutySet(i,CurDuty-200);

                            }

                            else if(CurDuty > 100)

                            {

                                bspPwmDutySet(i,CurDuty-100);

                            }

                            else if(CurDuty > 50)

                            {

                                bspPwmDutySet(i,CurDuty-50);

                            }

                            else

                            {

                                if(CurDuty > 10)

                                {

                                    bspPwmDutySet(i,CurDuty-10);

                                }

                                else

                                {

                                    bspPwmDutySet(i,(CurDuty >> 1)+1);

                                }

                            }

                        }                     

                    }                                          

                }               

            }

        }

}

以上代码中,前提条件是系统任务不能太重,上叙流程需要以每10ms左右轮询一次。

【创作不易,欢迎转载,转载请注明出处】

如果大家对相关文章感兴趣,可以关注公众号“嵌入式毛哥”,持续分享嵌入式干货,不限于疑难故障分析解决、算法共享、开发设计思想等,志在帮助更多人在嵌入式行业发光发热。

  • 25
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式毛哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值