浅谈PID--控制的灵魂之一

目录

一,PID的简介

1,什么是PID

2,为什么要用PID

3,PID的应用

4,PID的功能和分类

二,PID的原理

PID算法的一般形式:

1,连续性状态方程:

2,离散化状态方程:

1)比例部分

2)积分部分

3)微分部分

4)总结

3,PID调参口诀:

1,位置式PID

2,增量式PID

3,串级PID

三,实战项目

四,总结


一,PID的简介

1,什么是PID

PID 控制器以各种形式使用超过了 1 世纪,广泛应用在机械设备、气动设备 和电子设备.在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法

PID,就是“P比例(proportional)、I积分(integral)、D微分(derivative)”,是一种很常见的控制算法。

2,为什么要用PID

1,以温度控制为例子:假设加热控制要加热到500度,没有PID调节的,就是最简单比较通断式,达到温度停止,低于温度加热;
这样的实际温度抖动可能会比较大,加热装置通断电也比较频繁。
如果使用PID,温度到达后不是停止加热,而是温度接近时小功率加热,温度差的很多时,大功率加热,波动幅度小,可靠性好,体验也好。

2,以上一章咱们将的红外循迹来举例子,大家如果是用的八路或九路以上的传感器,可能红外循迹转直角弯是没有问题的(大部分也不行,可能少部分情况下可以),但是如果是5路或者5路以下的循迹,基本上是完全不能循直角弯,大家可以在B站上面找视频,看他们的小车,循迹特别的稳当,而且小车还很快,基本上是要用PID控制的。

3,PID的应用

PID控制算法是一种常用的控制算法,广泛应用于各种自动控制系统中。其主要应用场景包括:

  • 温度控制:PID控制算法可以实现对温度的精确控制,如工业热处理、恒温箱等。
  • 机械控制:PID控制算法可以实现机械系统的精确控制,如电机速度控制、位置控制、压力控制等。
  • 液位控制:PID控制算法可以实现液位的精确控制,如水池液位控制、加油站油罐液位控制等。
  • 流量控制:PID控制算法可以实现对流量的精确控制,如汽轮机进汽量的控制、供水系统控制等。

4,PID的功能和分类

功能:这里我总结了一下PID就是通过负反馈调节,使最终结果达到你的期望值。

分类:位置式PID,增量式PID,串级PID,智能PID等等。

下面我会为大家解释说明位置式PID和增量式PID,串级PID,但后面的智能PID就不说了,本人确实也只是知道名字而已,大家感兴趣就另外了解吧。

二,PID的原理

 P、I、D分别为比例(Proportion)、积分(Integral)、微分(Differential)的简写;将偏差的比例、积分和微分通过线性组合构成控制量,用该控制量对受控对象进行控制,称为PID算法。总之,PID就是对输入偏差进行比例积分微分运算,运算的叠加结果去控制执行机构。在工程实践中,一般P是必须的,所以衍生出来很多的PID控制器,如PI、PD、PID等。

PID算法的一般形式:

输入为r(t),输出为c(t),偏差为e(t),e(t)=r'(t)-c'(t)

1,连续性状态方程:

以PWM控制电机调速为例子:

1,r'(t)是预期PWM值

2,c'(t)是实际PWM值

3,e(t)也就是偏差值就是预期值-实际值

2,离散化状态方程:

Kp部分不变;Ki部分,也就是积分部分,将其转化为累计和;Kd部分,也就是微分部分,转化为前一项的偏差和当前偏差的差;

位置式PID离散表示形式:

增量式PID离散表示形式:

因为串级PID的各个部分的计算就是位置式或增量式,最终结果上是多个之和或之差,所以就没有特定的离散表达形式。

其中: Kp ―― 控制器的比例系数
            Ti ———控制器的积分时间,也称积分系数
            Td ―― 控制器的微分时间,也称微分系数

1)比例部分

作用是对系统瞬间产生的偏差进行快速修正,只有 P 时会有静差 。偏差一旦产生控制器立即产生控制作用, 使控制量向减少偏差的方向变化。

所以比例部分数学表示为:Kp*e(t)

 注意:Kp是比例系数,Kp越大,控制作用越强,则过渡过程越快,控制过程的静态偏差也就越小;但是越大,也越容易产生振荡,破坏系统的稳定性。故而,比例系数 选择必须恰当,才能过渡时间少,静差小而又稳定的效果。  

2)积分部分

作用是消除系统偏差,补偿系统的静差 ,只要存在偏差, 则它的控制作用就不断的增加; 只有在偏差 时, 它的积分才能是一个常数, 控制作用才是一个不会增加的常数。

所以积分部分数学表示为:Ki*(e(t))

       积分环节的调节作用虽然会消除静态误差,但也会降低系统的响应速度,增加系统的超调量。积分常数越大,积分的积累作用越弱, 这时系统在过渡时不会产生振荡;但是增大积分常数 会减慢静态误差的消除过程,消除偏差所需的时间也较长, 但可以减少超调量,提高系统的稳定性。当Ti 较小时, 则积分的作用较强, 这时系统过渡时间中有可能产生振荡, 不过消除偏差所需的时间较短。所以必须根据实际控制的具体要求来确定Ti 。

3)微分部分

作用是加快调节过程,阻止偏差的变化, 偏差变化的越快, 微分控制器的输出就越大,并能在偏差值变大之前进行修正。微分作用的引入, 将有助于减小超调量, 克服振荡, 使系统趋于稳定, 特别对髙阶系统非常有利, 它加快了系统的跟踪速度。但微分的作用对输入信号的噪声很敏感,对那些噪声较大的系统一般不用微分, 或在微分起作用之前先对输入信号进行滤波。

所以微分部分数学表示为:Kd*(e(k)-e(k-1))

Td 越大时, 则它抑制偏差 变化的作用越强; Td越小时,则它反抗偏差 变化的作用越弱。微分部分显然对系统稳定有很大的作用。适当地选择微分常数Td ,可以使微分作用达到最优。

4)总结

Kp使调节更快,Ki使调节更准,Kd使调节更稳

3,PID调参口诀:

参数整定找最佳, 从小到大顺序查。
                                                       先是比例后积分, 最后再把微分加。
                                                       曲线振荡很频繁, 比例度盘要放大。
                                                       曲线漂浮绕大弯, 比例度盘往小扳。
                                                       曲线偏离回复慢, 积分时间往下降。
                                                       曲线波动周期长, 积分时间再加长。
                                                       曲线振荡频率快, 先把微分降下来。
                                                       动差大来波动慢, 微分时间应加长。
                                                       理想曲线两个波, 前高后低四比一。
                                                       一看二调多分析, 调节质量不会低。


1,位置式PID

当前的输出与过去的所有状态都有关系(积分累加也就是误差累加),并且控制器的输出就是实际的输出结果,一旦控制输出出错,那么整个系统都可能奔溃,并且在整定参数时,要防止过冲现象,需对积分处理部分进行特别处理。这里提一句,只用位置式

初始化部分:

int OUTPUT1=0;//小车的左轮PWM值

int OUTPUT2=0;//小车的右轮PWM值

int PID_xs=0;//小车差速PID控制器的PWM输出值

extern int e;//e就是误差         //作为差速PID控制器的传参输入值

差速PID控制函数部分:

int Position_PID(int Encoder)//差速PID控制器Encoder=e
{
    float Position_KP,Position_KI,Position_KD;//大家自己去设置值
    static float BIAS,PWM,LAST_BIAS,INTEGRAL_BIAS;
    BIAS=Encoder;
    INTEGRAL_BIAS+=BIAS;//i+=j=>i=i+j 
    if(INTEGRAL_BIAS>500)INTEGRAL_BIAS=500;    //限制INTEGRAL_BIAS的值避免太大


    if(INTEGRAL_BIAS<200)INTEGRAL_BIAS=200;    //限制INTEGRAL_BIAS的值避免太小


    PWM=Position_KP*BIAS+Position_KI*INTEGRAL_BIAS+Position_KD*(BIAS-LAST_BIAS);//PID计算公式
    LAST_BIAS=BIAS;
    return PWM;
}  

最终输出部分:

void sc(void)
{

        PID_xs=Position_PID(e);
     OUTPUT1=4000+PID_xs;//直接给PWM
     OUTPUT2=4200-PID_xs;

    TIM_SetCompare2(TIM2,OUTPUT2);
  TIM_SetCompare3(TIM2,OUTPUT1);                                                                    
    
}

2,增量式PID

初始部分一样

差速PID控制函数部分:

int Position_PID(int Encoder)//差速PID控制器Encoder=e
{
    float Position_KP,Position_KI,Position_KD;
    static float BIAS,PWM,LAST_BIAS,LAST_TWO_BIAS;
    BIAS=Encoder;
    INTEGRAL_BIAS+=BIAS;//i+=j=>i=i+j 


    PWM=Position_KP*(BIAS-LAST_BIAS)+Position_KI*(BIAS)+Position_KD*(BIAS-2LAST_BIAS+LAST_TWO_BIAS);//PID计算公式

    LAST_TWO_BIAS=LAST_BIAS;
    LAST_BIAS=BIAS;
    return PWM;
}  

最终输出部分也一样

3,串级PID

初始化部分:

float Kp,Ki,Kd; 

float err;               //此次误差
float last_err;          //上次误差
float err_sum=0;         //误差累加
float err_difference;    //误差的差值
 

float VKp,VKi; 

float filt_velocity;     //滤波后的速度
float last_filt_velocity;//上一次的滤波后的速度
float velocity_sum=0;    //速度的累加

直立环PID控制函数部分:

int vertical_PID_value(float measure,float calcu)
{

    err = measure - calcu;             //误差
    if(err>=-1&&err<=1)
    {err=0;}
    err_sum+=err;                      //误差的累加
    err_difference = err - last_err;   //误差的差值
    last_err = err;                    //此次误差记录为“上次误差”
    
    return Kp*err + Ki*err_sum + Kd*err_difference;
}
 

速度环PID控制函数部分:

int velocity_PID_value(int velocity)
{
    float a;                                           //滤波系数(反映滤波程度)
    filt_velocity = a*velocity + (1-a)*last_filt_velocity; //一阶速度滤波
    velocity_sum +=  filt_velocity;                        //速度的累加
    I_xianfu(3000);                                        //累加限幅
    last_filt_velocity = filt_velocity;                    //此次速度记录为“上次速度”

    return VKp*filt_velocity + VKi*velocity_sum;
}   

最终输出部分:

  void shuchu(void)

{

            measure = pitch;                                     //pitch测量值
            calcu = zhongzhi;                                   //roll理论值

            velocity = ( read_encoder2() + read_encoder3() )/2; //速度测量值      
           //PID计算:直立环+速度环
            PWM = vertical_PID_value(measure, calcu) + velocity_PID_value(velocity); 
            PWM_Xianfu(7000,&PWM);      //PWM限幅

}

串级PID本人是以直立平衡小车为例子,上面的pitch就是MPU6050的俯仰角。大家可以去做一个直立平衡小车,这不仅可以大大提高你对PID的理解,更会让你对PID调参的熟练。大家除了用肉眼通过观察小车的状态去调参,还可以用上位机去调参,更方便快速。

三,实战项目

这里我自己写了一个关于PID单环控制的循迹小车,详细代码将放在最后的结尾处。

关键代码部分:

control.c

#include "stm32f10x.h"                  // Device header
#include "control.h"
#include "PWM.h"
#include "xunji.h"
#include "Motor.h"
//位置式PID
int OUTPUT1,OUTPUT2;// OUTPUT 是控制舵机的PWM输出值; OUTPUT1 和OUTPUT2 是控制小车左右轮速度的PWM输出值

int PID_xs=0;//小车差速PID控制器的PWM输出值

extern int e;//e就是误差         

//这里使用定时器的原因就是用定时中断来更新PWM值,使小车按预期目标运行
void TIM3_IRQHandler(void)//TIM3中断服务函数
{
	if(TIM3->SR&0X0001)//定时器每10ms定时中断一次
	{
		TIM3->SR&=~(1<<0);//清除定时器三的计时标志,执行完TIM3中断服务函数里的操作后定时器会重新计时
		PID_xs=PositionPID(e);//将差速PID控制器输出的PWM值赋给PID_xs   
		xianfu_PID();//限幅函数
		sc();//PWM输出函数
	}
		
}

int PositionPID(int Encoder)//差速PID控制器
{
	float Position_KP=500/*快*/,Position_KI=0.65/*准*/,Position_KD=4500/*稳*/;
	static float BIAS,PWM,LAST_BIAS,INTEGRAL_BIAS;
	BIAS=Encoder;
	INTEGRAL_BIAS+=BIAS;//i+=j=>i=i+j 
	if(INTEGRAL_BIAS>500)INTEGRAL_BIAS=500;	//限制INTEGRAL_BIAS的值避免太大
	if(INTEGRAL_BIAS<250)INTEGRAL_BIAS=250;	//限制INTEGRAL_BIAS的值避免太小
	
	PWM=Position_KP*BIAS+Position_KI*INTEGRAL_BIAS+Position_KD*(BIAS-LAST_BIAS);//PID计算公式
	LAST_BIAS=BIAS;
	
	return PWM;
	
}  
void sc(void)
{
	 OUTPUT1=4000+PID_xs;//直接给初始的PWM
	 OUTPUT2=4200-PID_xs;

	TIM_SetCompare2(TIM2,OUTPUT1);//左右两轮的PWM
  TIM_SetCompare3(TIM2,OUTPUT2);                                                                    
	
}

 void xianfu_PID(void)//限幅函数
 {

	
if(OUTPUT1>7200)OUTPUT1=7200;	 
	if(OUTPUT1<0)OUTPUT1=0; 
	 if(OUTPUT2>7200)OUTPUT2=7200;	 
	if(OUTPUT2<0)OUTPUT2=0; 
	 
 }










四,总结

PID是大家学习控制的核心算法,也是大家读我这篇文章了解到的第一个算法,相信大家看到这里,对PID已经有较为熟悉的认知,大家要多去实战,加深自己的理解,大家在本科阶段了解,以及会初步使用PID是非常够了的,如果想要更优秀,不仅要会把PID更广泛的应用,而且也要了解其他的算法,特别是深度学习和神经网络这方面,根据近几年的电赛来看,由开始的PID应用,开始朝向视觉和PID综合发展,所以革命尚未成功,同志仍需努力呀!

下面是我为大家提供得完整的PID单环控制的小车代码。

链接:https://pan.baidu.com/s/1afFMh8jH613rrMmVsnzDRw?pwd=yl66 
提取码:yl66

祝大家学业有成!我们,后会有期!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

暖风醉思人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值