PID算法整理

在工业应用中,PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,

我们看一个生活例子,冬天洗热水澡,需要先放掉一段时间的冷水,因为水管里有一段冷水,热水器也需要一个加热过程,等过了这段时间之后水温有些接近目标值后,开始调节水龙头来调节冷、热水之间的比例及出水量,之后再慢慢的微调,在洗浴过程中感觉温度不合适,再一点点的调节。这个过程,其实就是PID算法过程。我们之所以微调,是因为水温的变化速度与我调节的速度不相匹配,存在一个滞后效应,我们需要调节一点点,等一下再感觉一下温度,不够再调节一点点,再感觉,这个过程就叫PID算法,也可以说,滞后效应是引入PID的原因。负反馈系统,都有滞后效应。

如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。

当被控对象结构和参数不能完全掌握,或不到精确数学模型时,控制理论其它技术难以采用时,系统控制器结构和参数必须依靠经验和现场调试来确定,这时应用PID控制技术最为方便。即当我们不完全了解一个系统和被控对象﹐或不能有效测量手段来获系统参数时,最适合用PID控制技术。

什么是PID?

  • PID,即比例Proportion积分Integral微分Derivative三个单词的缩写。
  • 闭环自动控制技术是基于反馈的概念以减少不确定性,在闭环自动控制原理中,我们把它叫做“PID控制器”。
  • 即P是比例系数,I是积分系数、D是微分系数(介绍顺序是PDI)
  • t是时间,各个量都是随时间而变化的
  • 该系统由模拟 PID 控制器(控制器本身就是比例、积分、微分三个环节的加和)和被控对象组成。
  • 上面框图中, i(t) 是给定值,o (t) 是系统的实际输出值,给定值实际输出值构成控制偏差e(t) = i(t) o(t).
    • e(t) 作为 PID 控制的输入, u(t)作为 PID 控制器的输出和被控对象的输入。 公式随后给出
    • PID得到的是要增加多少量或减少多少量
    • 比例系数P
    • 比例系数就是用在穿过(0,0)这个坐标点直线的放大倍数k,k越大,直线的斜率越大,所以是用在y = k * x中的,其中的k就是比例系数p,大家都简称为kp,所以就变成了y = Kp * x。

      如果说是使用比例进行调节。

      则当前第1次调节时执行器对应的输出值为U1 = Kp * ( curentValue1 - totalValue1 )。

      第2次调节时执行器对应的输出值为U2 = Kp * ( currentValue2 - totalValue2 )。 

    • 这就是比例系数P的应用,也就是大家说的比例调节。

    •          比例调节就是根据当前的值与目标值的差值,乘以了一个Kp的系数,来得到一个输出值,这输出值直接影响了下次当前值的变化。如果只有比例调节的话,系统会震荡的比较厉害。比如你的汽车现在运行的速度是60km/h,现在你想通过你的执行器去控制这个汽车达到恒定的50km/h,如果你只用kp进行比例调节话。U = Kp * ( 60 - 50 ),假设Kp取值为1,此时得到U执行器的输出值是10,结果当你执行器输出后,坐在车上的你瞬间发现汽车一下变成了35Km/h,此时U2 = Kp * (35 - 50),此时得到U执行器的输出值是-15,结果当你执行器输出后,发现汽车变成了55Km/h,由于惯性和不可预知的误差因素,你的汽车始终无法达到恒定的50km/h。始终在晃动,相信如果你在车上,你一定吐的很厉害。所以光有比例系数进行调节,在有些场合是没有办法将系统调稳定的。

    • 为了减缓震荡的厉害,如果一个系数P不够,再来一个系数微分D。

    • 微分系数D

    • 注意微分,实际上是对误差进行微分。

    • 加入误差1是err(1)。误差2是err(2)。则误差err的微分是 (err2 - err1)。乘上微分系数D,大家叫做Kd,则当执行器第1次调节后有了第1次的误差,第2次调节后有了第2次的误差,则结合P系数。就有了PD结合,根据每次调节时,误差的值的经验推算,你就能选取出D的系数。

    • 。假如误差是越来越小的,那么微分后( (err2 - err1))肯定是一个负值。负值在乘以了一个D系数 加上了比例调节的值后肯定值要比单纯使用比例调节的值要小,所以就启到了阻尼的作用。有了阻尼的作用就会使得系统区域稳定。PD结合的公式经过上面的分析后为

      U(t) = Kp * err(t) + Kd * d(err(t))/dt(模拟公式)(下文介绍离散化公式)

    • BUT以热水为例。假如有个人把我们的加热装置带到了非常冷的地方,开始烧水了。需要烧到50℃。

      在P的作用下,水温慢慢升高。直到升高到45℃时,他发现了一个不好的事情:天气太冷,水散热的速度,和P控制的加热的速度相等了。 
      这可怎么办?

      P兄这样想:我和目标已经很近了,只需要轻轻加热就可以了。 
      D兄这样想:加热和散热相等,温度没有波动,我好像不用调整什么。

      于是,水温永远地停留在45℃,永远到不了50℃。

      作为一个人,根据常识,我们知道,应该进一步增加加热的功率。可是增加多少该如何计算呢? 
      前辈科学家们想到的方法是真的巧妙。

      设置一个积分量。只要偏差存在,就不断地对偏差进行积分(累加),并反应在调节力度上。

      这样一来,即使45℃和50℃相差不太大,但是随着时间的推移,只要没达到目标温度,这个积分量就不断增加。系统就会慢慢意识到:还没有到达目标温度,该增加功率啦! 
      到了目标温度后,假设温度没有波动,积分值就不会再变动。这时,加热功率仍然等于散热功率。但是,温度是稳稳的50℃。 

    • 积分系数I

      积分,实际上是对误差的积分,也就是误差的无限和。kI的值越大,积分时乘的系数就越大,积分效果越明显。

      所以,I的作用就是,减小静态情况下的误差,让受控物理量尽可能接近目标值。

      I在使用时还有个问题:需要设定积分限制。防止在刚开始加热时,就把积分量积得太大,难以控制。

    • 小结

    • 1.PID控制其实是对偏差的控制过程;

      2.如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。

      3.积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。

      4.而微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。

    •  三种比较简单的PID控制算法,分别是:增量式算法,位置式算法,微分先行。 这三种PID算法虽然简单,但各有特点,基本上能满足一般控制的大多数要求。

      假设采样时间间隔为T,则在k时刻:

      1.输入量为

      2.输出量为

      3.偏差量为 

        从而公式如下:

       kp是比例系数,Ti是时间和,TD是微分系数

       下面将对PID连续系统离散化,从而方便在处理器上实现。

                  假设采样间隔为T,则在第K个T时刻:

      偏差= 

      积分环节用加和的形式表示,即 

      微分环节用斜率的形式表示,即

      PID算法离散化后的式子: 

       则可表示成为:

      其中式中:

      比例数Kp:

      控制器的输出与输入偏差值成比例关系。系统一旦出现偏差,比例调节立即产生调节作用以减少偏差。特点:过程简单快速、比例作用大,可以加快调节,减小误差;但是使系统稳定性下降,造成不稳定,有余差。

      积分数Ki:

      积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。

      微分数Kd:

      微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。

      PID的基本离散表示形式如上。目前的这种表述形式属于位置型PID,另外一种表述方式为增量式PID,由上述表达式可以轻易得到:

      那么:

      上式就是离散化PID的增量式表示方式,由公式可以看出,增量式的表达结果和最近三次的偏差有关,这样就大大提高了系统的稳定性。需要注意的是最终的输出结果应该为:

      输出量  =u(k)=增量调节

将公式代码化:              

   pid.voltage = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * (pid.err - pid.err_last);

代码转载:

#include<stdio.h>
struct _pid {
	float SetSpeed; //定义设定值
	float ActualSpeed; //定义实际值
	float err; //定义偏差值
	float err_last; //定义上一个偏差值
	float Kp, Ki, Kd; //定义比例、积分、微分系数
	float voltage; //定义电压值(控制执行器的变量)
	float integral; //定义积分值
}pid;
void PID_init() {
	printf("PID_init begin \n");
	pid.SetSpeed = 0.0;
	pid.ActualSpeed = 0.0;
	pid.err = 0.0;
	pid.err_last = 0.0;
	pid.voltage = 0.0;
	pid.integral = 0.0;
	pid.Kp = 0.2;
	pid.Ki = 0.015;
	pid.Kd = 0.2;
	printf("PID_init end \n");
}
float PID_realize(float speed) {
	pid.SetSpeed = speed;
	pid.err = pid.SetSpeed - pid.ActualSpeed;
	pid.integral += pid.err;
	pid.voltage = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * (pid.err - pid.err_last);
	pid.err_last = pid.err;
	pid.ActualSpeed = pid.voltage * 1.0;
	return pid.ActualSpeed;
}
int main() {
	printf("System begin \n");
	PID_init();
	int count = 0;
	while (count < 1000)
	{
		float speed = PID_realize(200.0);
		printf("%f\n", speed);
		count++;
	}
	return 0;
}

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值