搜索
bottom↓
回复: 1

《DMF407电机控制专题教程_V1.0》第8章 PID算法

[复制链接]

出0入234汤圆

发表于 2022-8-12 18:25:42 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2022-8-12 18:38 编辑

电机开发板:
1)实验平台:正点原子DMF407电机开发板
2)平台购买地址: https://detail.tmall.com/item.htm?&id=677230699323
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/stm32dj/ATK-DMF407.html
4)对正点原子电机开发板感兴趣的同学可以加群讨论: 592929122 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png


第8章 PID算法

本章我们主要来学习PID算法,它是自动控制算法中的经典之作,被广泛应用于温度控制、水位控制、飞行姿态控制等领域。
本章分为如下几个小节:
8.1 自动控制算法
8.2 PID算法入门
8.3 PID算法代码实现


8.1 自动控制系统
在直流有刷电机的基础驱动实验中,如果电机负载不变,我们只要设置固定的占空比(电压),电机的速度就会稳定在目标范围。然而,在实际的应用中,负载可能会发生变化,此时如果还是输出固定的电压,电机的速度就偏离目标范围了,为了解决这个问题,我们需要引入自动控制系统中的闭环控制。接下来我们开始学习自动控制系统的内容。
        1)概念:用自动控制装置,对关键参数进行自动控制,使它在受到外界干扰而偏离正常状态时,能够被自动地调节回到目标范围内。
2)应用场景:电水壶保温系统、大棚温控系统、水位控制系统,等等。
3)分类:自动控制系统分为开环控制系统和闭环控制系统 。
① 开环控制系统
在开环控制系统中,系统输出只受输入的控制,没有反馈回路,控制精度和抑制干扰的特性都比较差。开环控制系统的实例如图8.1.1所示:
image001.png
图8.1.1.开环控制系统实例

图8.1.1中,电风扇风力控制系统就是一个开环控制的系统,我们设置好目标风力之后,控制电路就输出相应的电压(假设是电压控制),此时电机的扇叶转速就被控制在目标范围了。理想状态下,风扇的输出风力确实可以稳定在目标值附近,然而,在实际的使用中,电机会逐渐老化,扇叶上的灰尘也会让负载增大,此时我们所设定目标风力和实际风力可能就存在偏差了。
②闭环控制系统
在闭环控制系统中,引入了反馈回路,利用输出(实际值)和输入(目标值)的偏差,对系统进行控制,避免偏离预定目标。闭环控制系统又称反馈控制系统,它的实例如图8.1.2所示:
image004.jpg
8.1.2 闭环控制系统实例

图8.1.2中,大棚温控系统就是一个闭环控制的系统,我们设置好目标温度之后,温度传感器会采集棚内的实际温度,然后将目标温度和实际温度进行偏差的计算,计算后的结果输入到控制电路中,控制电路进一步控制温控设备进行升温和降温,此时棚内的实际温度就被控制在目标范围了。当实际温度因外部影响偏离目标值时,温度传感器(反馈电路)就能及时的反馈偏差,让系统自动调节温控设备,使得实际温度逐渐回到目标范围。
通过这个实例,大家就可以感受到闭环控制系统的意义所在,如果我们把上述实例中的控制对象变成电机的速度,反馈电路变成编码器测速电路,即可实现电机速度的闭环控制。
8.2 PID算法入门
PID算法是闭环控制系统中常用的算法,PID分别是 Proportion(比例)、Integral(积分)、Differential(微分)的首字母缩写。它是一种结合比例、积分和微分三个环节于一体的闭环控制算法,具体的控制流程如图8.2.1所示:
CEC4CD31-C671-4c09-A436-32CD8D7EBB2B.png
图8.2.1 PID控制流程

图8.2.1中,我们将输入目标值和实际输出值进行偏差的计算,然后把计算结果输入到PID控制算法中,经过比例、积分和微分三个环节的运算,运算后的输出作用于执行器,从而让系统的实际值逐渐靠近目标值。
接下来我们以大棚温控系统为例,来理解PID算法中三个环节的作用。
8.2.1 比例环节( Proportion)
比例环节可以成比例地反应控制系统的偏差信号,即输出与输入偏差成正比,可以用来减小系统的偏差。此环节的公式如下:
image008.png

u        -----  输出
Kp        -----  比例系数
e        -----  偏差
我们接下来以大棚温控实例来理解这个公式。假设我们现在需要调节棚内温度为30℃,而实际温度为10℃,此时的偏差e=20,由比例环节的公式可知,当e确定时,Kp越大则输出u越大,也就是温控系统的调节力度越大,这样就可以更快地达到目标温度;而当Kp确定时,偏差e越大则输出u越大。由此可见,在比例环节中,比例系数Kp和偏差e越大则系统消除偏差的时间越短,具体的曲线表现如图8.2.1.1所示:
image010.jpg
图8.2.1.1 比例环节曲线图

        图8.2.1.1中,当Kp的值越大时,其对应的橙色曲线达到目标值的时间就越短,与此同时,橙色曲线出现了一定幅度的超调和振荡,这会使得系统的稳定性下降,因此,我们在设置比例系数的时候,并不是越大越好,而是要兼顾消除偏差的时间以及整个系统的稳定性。
        然而,在实际的应用中,如果仅有比例环节的控制,可能会给系统带来一个问题:静态误差。静态误差是指系统控制过程趋于稳定时,目标值与实测值之间的偏差。我们以大棚温控实例来理解什么是静态误差:
假设我们现在需要调节棚内温度为30℃,而实际温度为25℃,此时偏差e=5,Kp为固定值,如果此时的输出可以让大棚在半个小时之内升温5℃,而外部的温差可以让大棚在半个小时之内降温5℃,也就是说,输出u的作用刚好被外部影响抵消了,这就使得偏差会一直存在,此时的曲线如图8.2.1.2所示:
image012.jpg
图8.2.1.2 存在静态误差

大家可能会想到,我们可以通过增大Kp来增大输出,以此消除偏差。在实际应用中,此方法的局限性很大,因为我们不能确定偏差的大小,它是在实时变化的,如果我们把Kp设置得太大,就会引入超调和振荡,让整个系统的稳定性变差。因此,为了消除静态误差,我们引入了积分环节。
8.2.2 积分环节(Integral)
积分环节可以对偏差e进行积分,只要存在偏差,积分环节就会不断起作用,主要用于消除静态误差,提高系统的无差度。引入积分环节后,比例+积分环节的公式如下:
image014.png

u                -----  输出
e                -----  偏差
∑e          -----  累计偏差
Kp                -----  比例系数
Ki                -----  积分系数
我们依旧以大棚温控实例来理解积分环节的作用。假设现在温控系统的比例环节作用被抵消,存在静态误差5℃,此时偏差存在,积分环节会一直累计偏差,以此增大输出,从而消除静态误差。从上述公式中可以得知,当积分系数Ki或者累计偏差越大时,输出就越大,系统消除静态误差的时间就越短,具体的曲线表现如图8.2.2.1所示:
image016.jpg
图8.2.2.1比例+积分环节曲线图

        图8.2.2.1中,当Ki的值越大时,其对应的橙色曲线达到目标值的时间就越短,与此同时,橙色曲线出现了一定幅度的超调和振荡,这会使得系统的稳定性下降,因此,我们在设置积分系数的时候,并不是越大越好,而是要兼顾消除静态误差的时间以及整个系统的稳定性。
        我们前面有说过,只要系统还存在偏差,积分环节就会不断地累计偏差。当系统偏差为0的时候,说明已经达到目标值,此时的累计偏差不再变化,但是积分环节依旧在发挥作用(此时往往作用最大),这就很容易产生超调的现象了。因此,我们需要引入微分环节,提前减弱输出,抑制超调的发生。
8.2.3 微分环节(Differential)
微分环节可以反应偏差量的变化趋势,根据偏差的变化量提前作出相应控制,减小超调,克服振荡。引入微分环节后,比例+积分+微分环节的公式如下:
image018.png

u_k                  ----------  第k次输出
Kp                ----------  比例系数
Ki                ----------  积分系数
Kd                ----------  微分系数
e_k                ----------  第k次偏差
e_(k-1)        ----------  第k-1次偏差
  ∑_(j=0)^k▒e_j         ----------  累计k次偏差
我们依旧以大棚温控实例来理解微分环节的作用。假设温控系统目标温度为30℃,在上午八点的时候存在偏差15℃,经过一段时间的调节,到了上午九点,此时偏差已经缩小到5℃,偏差的变化量= 九点的偏差(第k次)-八点的偏差(第k-1次)= -10,结合上述公式可知,此时微分环节会削弱比例和积分环节的作用,减小输出以抑制超调。
至此,PID算法三个环节的作用已经介绍完,我们最终得到了PID算法的一个公式:

        该公式是PID离散公式之一,除了离散公式之外,PID还有连续的公式,但是因为连续的公式不利于机器计算,我们这里不做介绍。大家需要注意,在实际的应用中,并不是每一个系统都需要PID的三个环节参与控制的,有的系统只需要比例环节或积分环节就可以控制得很好,除此之外,每一个系统的PID系数并不是通用的,这需要根据实际的情况去设置。
8.2.4 PID算法离散公式
1)位置式PID公式

u_k                  ----------  第k次输出
Kp                ----------  比例系数
Ki                ----------  积分系数
Kd                ----------  微分系数
e_k                ----------  第k次偏差
e_(k-1)        ----------  第k-1次偏差
  ∑_(j=0)^k▒e_j         ----------  累计k次偏差
我们在上一小节中得到的PID离散公式称为位置式或全量式PID公式,该公式的计算需要全部控制量参与,它的每一次输出都和过去的状态有关。
2)增量式PID公式
通过位置式的PID公式,我们只需两步即可推导出增量式PID公式:
第一步,将 k = k-1代入位置式PID公式,得:
image029.png

第二步,由u_k  -u_(k-1)  得:
image033.png

至此,增量式 PID方式就推导完了。从公式中可以看出,增量式 PID 的计算并不需要一直累计偏差,它的输出与近三次的偏差有很大关系。
注意:增量式PID公式输出的只是控制量的增量。我们以一个实例来理解这句话:假设电机实际转速为50RPM,现在我们要让它加速到60RPM,如果采用的是位置式PID,系统将直接输出60RPM对应的控制量(占空比);如果采用的是增量式PID,系统将输出提速10RPM对应的控制量(占空比),此时我们还需要加上上次(50RPM)的输出。
介绍完PID的两个离散化公式,接下来我们比较一下这两个PID公式的不同点,具体如表8.2.4.1所示:
DFDB9227-3759-48e8-8BBC-265ED6E8B9A4.png
表8.2.4.1两种PID公式对比

3)两种PID公式的优缺点
① 位置式:
优点:位置式 PID 是一种非递推式算法,带有积分作用,适用于不带积分部件的对象。
缺点:全量计算,计算错误影响很大;需要对偏差进行累加,运算量大。
② 增量式:
优点:只输出增量,计算错误影响小;不需要累计偏差,运算量少,实时性相对较好。
缺点:积分截断效应大,有稳态误差。
8.3 积分饱和问题
在位置式PID中,如果系统长时间无法达到目标值,累计偏差(积分)就会变得很大,此时系统的响应就很慢了。我们以一个实例来分析这个问题:
假设某个电机能达到的最大速度为300RPM,而我们设置了目标速度为350RPM,这明显是一个不合理的目标值,此时PID控制系统的曲线如图8.3.1所示:
image035.jpg
图8.3.1不合理目标值

        图8.3.1中,由于系统长时间无法达到目标值,累计偏差(积分)会变得越来越大,逐渐达到深度饱和的状态,此时我们再设置一个合理范围的目标速度(例如200RPM),系统就没有办法在短时间内响应了。
        为了避免位置式PID中可能出现的积分饱和问题,可采取以下措施:
        ① 优化PID曲线,系统越快达到目标值,累计的偏差就越小;
        ② 限制目标值调节范围,规避可以预见的偏差;
        ③ 进行积分限幅,在调整好PID系数之后,根据实际系统来选择限幅范围。
8.4 PID算法代码实现
        1)控制量相关的结构体
有了PID的离散化公式之后,我们实现PID算法的代码是非常简单的,这里先回顾一下两个PID公式所涉及到的所有控制量:
u_k          、∆u_k ----  期望输出值(计算后的输出)
Kp                ----------  比例系数
Ki                ----------  积分系数
Kd                ----------  微分系数
e_k                ----------  第k次偏差
e_(k-1)        ----------  第k-1次偏差
e_(k-2)        ----------  第k-2次偏差
  ∑_(j=0)^k▒e_j          --------  累计偏差
        在代码中,我们可以通过一个结构体来管理这些控制量,具体定义如下:
typedef struct
{
    __IO float  SetPoint;                         /* 目标值 */
    __IO float  ActualValue;             /* 期望输出值 */
    __IO float  SumError;                    /* 偏差累计 */
    __IO float  Proportion;                  /* 比例系数 P */
    __IO float  Integral;                    /* 积分系数 I */
    __IO float  Derivative;                  /* 微分系数 D */
    __IO float  Error;                       /* Error[1],第k次偏差 */
    __IO float  LastError;                   /* Error[-1],第k-1次偏差 */
    __IO float  PrevError;                   /* Error[-2],第k-2次偏差 */
} PID_TypeDef;
这个结构体当中的每一个成员所代表的控制量在注释中已经很清楚,这里就不再介绍。值得注意的是,该结构体中多了一个目标值的控制量,它将会用于偏差的计算。
2)PID算法代码
PID算法的代码实现本质上就是对于两个离散公式的应用,我们先看位置式PID代码:
/*
* @brief       pid闭环控制
* @param       *PID:PID结构体变量地址
* @param       Feedback_value:当前实际值
* @retval      期望输出值
*/
int32_t increment_pid_ctrl(PID_TypeDef *PID,float Feedback_value)
{
    PID->Error = (float)(PID->SetPoint - Feedback_value);         /* 计算偏差 */
    PID->SumError += PID->Error;                                                         /* 累计偏差 */
    PID->ActualValue = (PID->Proportion * PID->Error)        /* 比例环节 */
                       + (PID->Integral * PID->SumError)        /* 积分环节 */
       + (PID->Derivative * (PID->Error - PID->LastError)); /* 微分环节 */
    PID->LastError = PID->Error;                                 /* 存储偏差,用于下次计算 */
    return ((int32_t)(PID->ActualValue));        /* 返回计算后输出的数值 */
}
increment_pid_ctrl函数用来进行位置式PID的控制,该函数的2个形参:*PID传入PID控制量相关的结构体地址;Feedback_value传入当前系统的实际值,用于计算偏差。在函数中,我们先计算本次偏差Error,然后把偏差累计,存入SumError成员当中,接着根据位置式的公式进行三个环节的计算,计算后的期望输出存入ActualValue成员当中,然后存储本次偏差,最后返回期望输出值。
接着我们看增量式PID代码:
/*
* @brief       pid闭环控制
* @param       *PID:PID结构体变量地址
* @param       Feedback_value:当前实际值
* @retval      期望输出值
*/
int32_t increment_pid_ctrl(PID_TypeDef *PID,float Feedback_value)
{
PID->Error = (float)(PID->SetPoint - Feedback_value);         /* 计算偏差 */

PID->ActualValue +=
/* 比例环节 */
(PID->Proportion * (PID->Error - PID->LastError))  
/* 积分环节 */                        
+ (PID->Integral * PID->Error)         
/* 微分环节 */
+ (PID->Derivative * (PID->Error - 2 * PID->LastError + PID->PrevError));

PID->PrevError = PID->LastError;                      /* 存储偏差,用于下次计算 */
PID->LastError = PID->Error;
return ((int32_t)(PID->ActualValue));        /* 返回计算后输出的数值 */
}
增量式PID的代码实现和位置式是非常类似的,所以我们在实际的代码实现中,可以通过一个宏定义来切换这两种不同的算法,值得注意的是,增量式PID输出的是调节量,所以计算期望输出值ActualValue的时候是自增运算,这一点和位置式PID是不一样的。


阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入54汤圆

发表于 2022-9-29 16:26:51 | 显示全部楼层
好文章,看完撸一发
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 07:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表