首页 > 编程语言 >比传统PID算法更容易实现和调试的增量调速法

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

时间:2024-07-30 14:54:41浏览次数:12  
标签:DevSpeed PID CurDuty else 调速 调试 占空比 转速 bspPwmDutySet

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

在自动控制领域中,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左右轮询一次。

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

标签:DevSpeed,PID,CurDuty,else,调速,调试,占空比,转速,bspPwmDutySet
From: https://blog.csdn.net/weixin_44159326/article/details/140796718

相关文章

  • DRV8301 SPI调试问题(接收一直为0x0000)
    CUBEMX配置uint16_tdrv8301_data_t[1];uint16_tdrv8301_data_t0[1]={0x9000};uint16_tdrv8301_data_t1[1]={0x0000};uint16_tdrv8301_data_r[1];//SPI参数配置函数voidDRV8301_SPI_setting(void){ drv8301_data_t[0]=0x1560; DRV8301_SPI_M1_CS_L; HAL_SPI_......
  • 基于STC8H4K64TL单片机的RTC(即实时时钟)功能调试
    基于STC8H4K64TL单片机的RTC(即实时时钟)功能调试STC8H4K64TL单片机介绍STC8H4K64TL单片机管脚图(48个引脚)STC8H4K64TL单片机串口仿真与串口通信STC8H4K64TL单片机管脚图(32个引脚)STC8H4K64TL单片机管脚图(20个引脚)STC8H系列单片机管脚说明STC8H系列单片机I/O口STC8H......
  • 【C语言】VS实⽤调试技巧
    VS实⽤调试技巧1.什么是bug?2.什么是调试?3.debug和release4.VS调试快捷键4.1环境准备4.2调试快捷键5.监视和内存观察5.1监视5.2内存6.调试举例17.调试举例28.调试举例3:扫雷9.编程常⻅错误归类9.1编译型错误9.2链接型错误9.3运⾏时错误1.什么是bug?......
  • DelphiJNI实际调试
    1:下载DelphiJNI:下载地址https://github.com/aleroot/DelphiJNI,版本比较老,没有找到其他,就用这个吧,如朋友有较新的pas文件,请留言下2:下载jdk,这里下载JDK,这里使用javase-jkd18,也不知道这个版本要不要收费,这里学习用暂时不关新这个。3:编写调用class的代码,DelphiJNI没有demo,看代码云......
  • 学习C语言第十六天(调试、)
    调试第一题    C第二题    A第三题    C第四题    C第五题    Drelease不可以调试第六题        越界访问访问到了i的地址编程题模拟strcpyvoidmy_strcpy(char*arr1,char*arr2){ while(*arr2) { *a......
  • 7.29 调试及admin
    为什么服务不能启动   go模块支持   go程序启动过程   编译完成之后会在制定目录底下生成一个同名文件, 而不是意向中的service文件 没有搞清楚run是什么的,可以直接运行的 go启动和退出      接口是底层的数据结......
  • JSP学生社团管理系统k2120(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文
    系统程序文件列表开题报告内容JSP学生社团管理系统开题报告一、课题背景与意义课题背景随着高等教育的普及和学生综合素质培养的重视,学生社团在高校中扮演着越来越重要的角色。它们不仅是学生锻炼能力、展示才华的平台,也是促进学生交流、丰富校园文化生活的重要途径。然而......
  • JSP学生社团管理系统ja976(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
    系统程序文件列表开题报告内容JSP学生社团管理系统开题报告一、课题背景与意义课题背景随着高校教育改革的深入和学生活动的日益丰富,学生社团作为校园文化的重要载体,其管理和运营面临着诸多挑战。传统的社团管理方式往往依赖于纸质文档和人工操作,不仅效率低下,而且容易出......
  • GLSL教程 第11章:性能优化和调试
    目录11.1GLSL着色器的性能考量11.1.1减少计算复杂度避免不必要的计算使用适当的数据类型优化数学操作11.1.2减少内存访问减少纹理采样次数使用纹理缓存11.1.3优化数据传输减少数据传输量批处理(Batching)11.1.4使用高级渲染技术LevelofDetail(LOD)延迟渲染......
  • 如何使用Visual Studio代码调试django
    我是django开发领域的新人,使用Xcode和相关IDE进行桌面/移动应用程序开发。我必须使用Django,我想知道是否有一个高效的使用VisualStudioCode(或Atom)进行调试的方法。与DjangoIDE相关的任何帮助也会有所帮助。使用VisualStu......