PID积分项优化与C语言实现


前言

本文将讲述PID算法中积分项的优化,对于已经理解普通PID算法控制原理并想继续深入了解PID的你有一定的帮助。
PID算法相比一般的位式控制算法有了很大的改进,普通的PID在合适的参数整合下也能起到很好的控制作用。
本文PID中积分项的优化只是锦上添花。


以下是本篇文章的正文内容

一、简述PID的积分

在学习积分项优化之前要清楚知道积分的作用。
(1)积分是过去所有偏差的和,在系统中起到的作用是消除静差。
(2)积分系数太大导致稳定后出现超调,积分系数太小导致稳定后系统波动。
(3)积分项并非无穷大,可能小于0,可能等于0
(4)要最大化积分的作用,主要是调整好积分系数
积分优化的目的是让积分不要起到干扰作用。

二、积分分离

1.内容讲解

所谓的积分分离就是在系统偏差较大时不采用积分。
在系统刚开始趋向稳定时,这段时间偏差很大导致积分很大。那么当系统接近稳定时由于积分项很大就会出现超调和较大的震荡,积分起到干扰作用,这时我们可以选择不要积分。

2.C语言实现

C语言实现过程非常简单,设定偏差上限值,当偏差绝对值大于上限时然让积分项输出为0。下面举个例子。

if( abs(ek) > EK_MAX )
	index = 0;
else
	index = 1;
out = kp*ek + index*ki*sk + kd*(ek-ek_1);

三、抗积分饱和

1.内容讲解

饱和是指PID输出值out超过了最大值,我们知道硬件的实际输出不可能无穷大,所以即便out超过最大值,最终我们还是会让out等于最大值。当out出现单方向饱和时,积分的单方向偏差会累积到很大,这时如果突然要系统反偏,由于积分单方向累积较大,那么积分对于系统起到干扰作用。
举个例子,正方向最大速度旋转的电机,突然要让它反方向旋转,由于积分正方向偏差大,如果积分不进行抗饱和系统反应速度会很慢。
所以我们需要在out饱和时不要将饱和方向的偏差加入到积分项中,只将与饱和方向相反的偏差加入积分项中。

2.C语言实现

在积分分离基础上加入抗积分饱和

if(pid.out > OUT_MAX)
{
    
    
	if( abs(pid.ek) > EK_MAX ) //积分分离
		index = 0;
	else
	{
    
    
		index = 1;
	   	if(pid.ek < 0) //积分只累积负值
			pid.sk += pid.ek;
	}
}
else if(pid.out < OUT_MIN)
{
    
    
	if( abs(pid.err) > EK_MAX ) //积分分离
		index = 0;
	else
	{
    
    
		index = 1;
        if(pid.ek > 0) //积分只累积正值
       		pid.sk += pid.ek;
	}
}
else //不出现饱和时
{
    
    
	if( abs(pid.ek) > EK_MAX ) //积分分离
    	index = 0;
	else
	{
    
    
		index = 1;
        pid.sk += pid.ek;
    }
}

四、变积分

1.内容讲解

上述的积分分离是在偏差达到最大值时不要积分,那么偏差在没有达到最大值但又比较大时可以适当虚弱积分的作用。作用与积分分离一样,防止系统接近稳定由于积分项很大出现超调和较大的震荡。

2.C语言实现

在上述代码基础上加入变积分

扫描二维码关注公众号,回复: 12427672 查看本文章
if(pid.out > OUT_MAX)
{
    
    
	if( abs(pid.ek) > EK_MAX ) //积分分离
		index = 0;
	else
	{
    
    
		if(EK_MID < abs(pid.ek) < EK_MAX) //变积分
			index = 0.5;
		else
			index = 1;
	   	if(pid.ek < 0) //积分只累积负值
			pid.sk += pid.ek;
	}
}
else if(pid.out < OUT_MIN)
{
    
    
	if( abs(pid.err) > EK_MAX ) //积分分离
		index = 0;
	else
	{
    
    
		if(EK_MID < abs(pid.ek) < EK_MAX) //变积分
			index = 0.5;
		else
			index = 1;
        if(pid.ek > 0) //积分只累积正值
       		pid.sk += pid.ek;
	}
}
else //不出现饱和时
{
    
    
	if( abs(pid.ek) > EK_MAX ) //积分分离
    	index = 0;
    else if(EK_MID < abs(pid.ek) < EK_MAX) //变积分
		index = 0.5;
	else
		index = 1;
		
    pid.sk += pid.ek;
}

结语

那么以上就是本篇文章的所有内容了。
本文如果有什么不对的或者需要改进的地方欢迎指出。

猜你喜欢

转载自blog.csdn.net/qq_46554815/article/details/113337303