PID算法
对于PID算法一本书也讲不完,再说我也不懂,这里只是现学现卖简单介绍一下,其中不明或错误之处欢迎指出,PID顾名思义……往下看吧(对于很多公式我只想说:不明觉厉!)
<备注:虽然我没有用拉氏变换讲PID,但微积分的概念是必须了解的,忘记的话不用看高数,翻一翻高中数学书就行了,里面确实有讲到>
(备注:下面很多公式等号左边的都没有写,不懂自己百度)
PID算法在数字计算机系统下是不能直接使用的,需要采用离散化方法,采用数字式PID,在PID中积分微分和比例是这样计算的:
比例项就是这一刻的误差乘以一个常数所得项
积分项就是(这一刻的误差*采样周期)+(上一刻的误差*采样周期)+(上上一刻的误差*采样周期)+……+(初始误差值*采样周期)求和所得项
微分项就是(这一刻的误差减去上一刻的误差)/周期所得项
在实际应用中并非向上面写的那样,这里只是帮助理解,用的时候要知道变通
位置式PID
先看一个比较容易理解的PID算法,位置式PID控制算法,
位置式PID控制算法中离散表达式如下:
至于上面式子中的字母含义我还是不说了吧,用心看会懂的,从左到右依次是比例项,积分项,微分项,T为采样周期(就是传感器获得相邻两次数据之间的时间差),error就是想要得到的量和实际得到的量之间的差值,Kp,Ki,Kd就是所谓的PID参数,k,j,∑什么的就不要解释了吧,位置式PID控制算法的缺点是:由于采用全量输出,所以每次输出都与过去输出有关,计算时要对误差error累加,如果传感器出现故障偏差,计算得到的输出控制量可能出现执行机构的大幅变化,这种情况容易造成事故,为避免这种情况发生,实际应用中以增量式PID算法居多
增量式PID
增量式PID控制算法,当执行机构需要的是控制量的增量时(如步进电机的驱动),应采用增量式PID控制,既然是增量控制,那么其表达式很容易通过上面的位置式PID表达式可以推导出来:
对上面式子,希望不会有人做出对Ki项的疑问
显然这种方式不需要累加,控制增量之与最近的状态有关,误动作影响小,容易获得比较好的控制效果,看完了PID的基本概念,下面分析一个实例,陀螺仪和加速计的数据融合问题
附上2011年飞思卡尔官网给出的参考方案:陀螺仪和加速计的数据融合角度计算方案
ARDUINO 代码
-
void CarVoltageGet(void) {
-
long lnDeltaValue;
-
ADC_GetValue16(g_nCarVoltage);
-
/*读取加速度值,减去零偏数值*/
-
lnDeltaValue = (int)CV_ACCE_VAL;
-
lnDeltaValue = lnDeltaValue - (int)CV_ACCE_OFFSET;
-
g_nCarAcceVal = (int)lnDeltaValue;
-
/*将加速度计角度归一化*/
-
g_nCarAcceVal = mult_r(g_nCarAcceVal, CV_ACCE_ANGLE_RATIO);
-
/*读取陀螺仪数值,减去零偏数值*/
-
g_nCarGyroVal = (int)CV_GYRO_VAL;
-
g_nCarGyroVal = (int)(g_nCarGyroVal - CV_GYRO_ZERO);
-
/*归一化*/
-
g_nCarGyroVal = mult_r(g_nCarGyroVal, CAR_GYRO_RATIO_INT);
-
/*
-
*使用一个长整型数字(g_lnCarAngleSigma)进行积分,
-
*对于数值通过右移10位(相当于除以1024)得到最终的角度值
-
*/
-
g_nCarAngle = (int)(g_lnCarAngleSigma >> 10);
-
lnDeltaValue = g_nCarAcceVal - g_nCarAngle;
-
lnDeltaValue = lnDeltaValue * CAR_ACCE_RATIO;
-
g_lnCarAngleSigma += (g_nCarGyroVal + lnDeltaValue);
-
}
利用加速度计所获得的角度信息θg与陀螺仪积分后的角度θ进行比较,将比较的误差信号经过比例Tg 放大之后,与陀螺仪输出的角速度信号叠加之后再进行积分,从框图中可以看出,对于加速度计给定的角度θg,经过比例、积分环节之后产生的角度θ必然最终等于θg。
由于加速度计获得的角度信息不会存在积累误差,所以最终将输出角度θ中的积累误差消除了加速度计所产生的角度信息θg中会叠加很强的有车模运动加速度噪声信号,为了避免该信号对于θ的影响,因此比例系数Tg应该非常小
这样,加速度的噪声信号经过比例、积分后,在输出角度信息中就会非常小了
由于存在积分环节,所以无论比例Tg多么小,最终输出角度θ必然与加速度计测量的角度θg相等,只是这个调节过程会随着Tg的减小而延长
为了避免输出角度跟着θg过长,可以采取以下两个方面的措施:
(1)仔细调整陀螺仪的放大电路,使得它的零点偏置尽量接近于设定值,并且稳定
(2)在控制电路和程序运行的开始,尽量保持车模处于直立状态,这样一开始就使得输出角度θ与gθ 相等,此后,加速度计的输出只是消除积分的偏移,输出角度不会出现很大的偏差
积分分离PID
PID之所以经久不衰,因为PID实用性很强可以千变万化来适应不同的需求,我认为很多时候并不需要高深的理论,技术上的灵活应用比一堆让人头疼的数学公式更有价值,小李飞刀独步武林大概就是这个道理,说到小李探花,这几天正是花开好时节,学校里的海棠、樱花看上去都挺好,不过桃花最,额……为什么陶渊明写的是桃花源记,而不是樱花海棠花呢?
还有腾格尔的歌演……又闲扯了,在普通PID算法中积分环节在启动、结束等大幅增减设定时,短时间内输出会有很大偏差,会造成PID运算的积分积累,甚至引起较大的振荡,这在实际应用中是不允许的。
那么解决这种问题的一个思路就是将积分项分离开,即当被控量与设定值偏差较大时,取消积分作用,以免积分作用使系统稳定性降低;当被控量接近给定值时再引入积分控制,以便消除静差,提高控制精度;具体步骤如下:
(1)由实际情况,人为设定阀值(不知道什么是阀值?我也不知道这是谁取的名字)
(2)当误差大于阀值时采用PD控制
(3)当误差小于阀值时采用PID控制
其算法表达式如下:
其中β为积分项开关系数,即当误差大于阀值时β为0,小于阀值时β为1(阀值就是这个意思)
首先帮大家解决一下什么是PID调节,为什么就要这样的疑惑。
PID是比例,积分,微分的英文单词的首字母的简称。
下面举个例子说明一下PID,让大家有个感官的认识,。
一个人闭眼走路,假设他知道自己离目的地有100米远,那么他就可以以每秒一米一步这样的速度走向目的地,100米刚刚好是100步,这是一个非常理想化的现象。假设他不知道目的地有多远,目的地可能是1000米也有可能是10000米,他用每秒每步3米得速度向前,很不巧的是这个目的地在80米处,他走了26步时刚刚好差2米,走27步有刚刚好又多出1米,这就是所谓的稳态误差,如果这个人知道目的地在大概15米处得地方,开始这个人以每秒一米一步的速度,走完一步然后目测一下离目的地还有多远,结果发现还剩下大概14米,显然一米一步太慢,因此这个人决定每秒大于一米一步走,得出一条式子,
y=Kp*e(t)
其中y为下一次要每步要走的距离,e(t) 为目测距离,也就是偏差,换句话说就是自己走了的距离跟要走的距离也就是目的地的误差,Kp就是一个常数,假设我们把Kp设置为0.5,
y=Kp*e(t)可以得出y=7;也就是说那个人下一步要以每秒7米得速度走,重复上述的过程,,7+1共走了8米,然后目测一下距离15米处还有多远,还有7米得误差,所以下一步要走3.5米,然后在重复,发现最后会出现一个稳态的误差,也就是多走一步会超出目的地,少走一步又没到目的地。当然这个上述的例子情况非常特殊,大家可能觉得最后那些误差可以忽略,但是实际应用中,肯定没有人走路的那么特殊,按照这种线性比例下去最后得到的误差会非常大,所以就引入了一个积分的概念,积分的数学几何定义是在区间[a, b]里连续的非负曲线与直线x=a,x=b围成的图形的面积。从积分的定义可以得到一个函数
其中Ti为积分时间,e(t)就是误差了。Y就是输出,它是个不定积分,事实上把它融入到上述人走路的例子它是个定积分,从0 到t时刻的误差的对时间的积分,也就是说误差曲线e(t)与时间轴围成的面积,积分时间Ti是一个常量,也就是说是自己规定大小,很明显,由上式得y为e(t)与t所围成的图形的面积的除以Ti的值,Ti越大y越小,Ti越小y越大,大了系统会动荡,所以要慢慢调节系数。
下面是关于积分跟比例的专业阐述:
比例(P)控制
比例控制是一种最简单的控制方式。其控制器的输出与输入误差信号成比例关系。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。
积分(I)控制
在积分控制中,控制器的输出与输入误差信号的积分成正比关系。对一个自动控制系统,如果在进入稳态后存在稳态误差,则称这个控制系统是有稳态误差的或简称有差系统(System with Steady-state Error)。
为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。
因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。
微分调节就是偏差值的变化率。例如,如果输入偏差值线性变化,则在调节器输出侧叠加一个恒定的调节量。大部分控制系统不需要调节微分时间。因为只有时间滞后的系统才需要附加这个参数。如果画蛇添足加上这个参数反而会使系统的控制受到影响。
举个例子,人去调节窝炉的温度,慢慢调节旋钮,使得温度慢慢变大,要使得温度达到某个固定值,人可以慢慢调节,边看温度边调节,如果开始离这个这目标温度远就快速旋旋钮(比例效果),到最后要使得温度误差小就微调(积分效果),然后实际上温度是有一个惯性在那里,开始你以很快速度调节旋钮的时候温度不会突变,不会一下子就达到稳定值,它慢慢增加到最后,但是不是每个人都是这么有经验,当他看到温度值离目标温度还差这么远,又加快旋转旋钮,最终结果导致实际温度跟目标温度差别非常远,微调也跟本没法调整,最后导致系统的不稳定,但是如果这个人很有经验,他事先知道这个温度是有惯性的,开始它快速旋转旋钮看温度上升率非常高,也就是温度变化非常快,他就放慢旋转速度了,最后结果是准确的把温度调整到最佳(微分效果)。
人可以是这样子,但是计算机可不会这样调节,那么就要通过一个PID得到一个输出值来调节了。
下面是一段关于微分的专业阐述:
控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。 自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳。其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。这就是说,在控制器中仅引入 “比例”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能 够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在 调节过程中的动态特性。
综上所述得到一个一条公式,这个就是模拟PID
下面是关于应用,增量式PID算法。其实PID的算法可以做很深,但没必要,一般入门级的算法已经在很多场合够用了,这里之所以选用增量式PID算法(另外还有位置式PID等等),因为增量式PID算法运算量少,非常适合单片机的应用。
显然要想给单片机运算,就必须是数字量,而上述的PID是模拟PID,我们要将他数字化,离散化。
目前大部分矿用电机车都是采用串电阻调速,该方法虽然比较成熟,但是有大量的能源消耗在电阻上,造成能源的极大浪费,本文研究一种基于直流斩波的调速控制器,该方法节采用全控型开关器件,其优点是系统频带宽,响应速度快,动态抗干扰能力强。矿用电机车直流斩波调速控制器的硬件部分主要分为主电路与控制电路两部分,首先对主电路进行设计,然后对斩波器功率开关管IGBT进行选型。最后再对控制电路进行设计,其中控制电路是以ATmega16单片机为主控芯片,控制电路包括电源电路、采样电路、调速电路、M57962L驱动电路、欠压保护电路、过流保护电路、复位电路、报警电路以及扩展电路等。
其中积分在上面说到的,他的几何意义就是求e(t)与时间轴t围成的图形的面积,将这个面积分成T等分 ,T=0到T=1跟e(t)围成的面积加上T=1到T=2跟e(t)围成的面积一直累加……直到T-1到T跟e(t)围成的面积刚好就是整个e(t)与t时间轴围成的面积,刚刚好是e(t)对t的积分,如果T无限大,那么就可以分割成无限个小图形那么这个图形的面积就可以用T[e(1)+e(2)+………+e(T-1)+e(T)]来代替积分效果,而这个T等分就是AD在整个时间轴t中采样的点,显然越快的AD在相同的时间t里面采样的点越多,换句话说就是T更接近无限大。因此积分可以用累和代替。
下面为积分的专业的解释
定义
设函数f(x)在[a,b]上有界,在[a,b]中任意插入若干个分点
a=x0<x1<...<xn-1<xn=b
把区间[a,b]分成n个小区间
[x0,x1],...[xn-1,xn]。
在每个小区间[xi-1,xi]上任取一点ξi(xi-1≤ξi≤xi),作函数值f(ξi)与小区间长度的乘积f(ξi)△xi,并作出和
如果不论对[a,b]怎样分法,也不论在小区间上的点ξi怎样取法,只要当区间的长度趋于零时,和S总趋于确定的极限I,
这时我们称这个极限I为函数f(x)在区间[a,b]上的定积分, 记作
微分用差分代替,先说明一下微分的几何意义
我们可以想象把上图中的f(x)换成e(t),x轴换成t轴,把△x换成△t,当△t非常小的时候曲线MN等价于直线MN,△y就等于dy,所以
可以用Td*[e(t)-e(t-1)]/ △t,同样△t就是采样时间~越小越好。
因此模拟PID离散化得到在k-1时刻的输出
因此得到一个增量
其中的T为采样时间
,如果计算机控制系统采用恒定的采样周期T,一旦确定A、B、C(系数的选取是PID的关键这里不做讨论)
增量式PID控制算法与位置式PID算法相比,计算量小得多,因此在实际中得到广泛的应用。
位置式PID控制算法也可以通过增量式控制算法推出递推计算公式:
就是目前在计算机控制中广泛应用的数字递推PID控制算法。
下面是程序
typedef struct PID
{
intSetPoint; //设定目标 DesiredValue
longSumError; //误差累计
doubleProportion; //比例常数Proportional Const
doubleIntegral; //积分常数 IntegralConst
doubleDerivative; //微分常数Derivative Const
intLastError; //Error[-1]
intPrevError; //Error[-2]
} PID;
static PID sPID;
static PID *sptr = &sPID;
/*====================================================================
InitializePID Structure PID参数初始化
===================================================================*/
void IncPIDInit(void)
{
sptr->SumError= 0;
sptr->LastError= 0; //Error[-1]
sptr->PrevError= 0; //Error[-2]
sptr->Proportion= 0; //比例常数Proportional Const
sptr->Integral= 0; //积分常数IntegralConst
sptr->Derivative= 0; //微分常数Derivative Const
sptr->SetPoint= 0;
}
/*==================================================================== 增量式PID计算部分
====================================================================*/
int IncPIDCalc(int NextPoint)
{
registerint iError, iIncpid; //当前误差
iError= sptr->SetPoint - NextPoint; //增量计算
iIncpid= sptr->Proportion * iError //E[k]项
-sptr->Integral * sptr->LastError //E[k-1]项
+sptr->Derivative * sptr->PrevError; //E[k-2]项
//存储误差,用于下次计算
sptr->PrevError= sptr->LastError;
sptr->LastError= iError;
//返回增量值
return(iIncpid);
}
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
推荐B站看清翔的51单片机课程,其中会讲很多C语言的基础知识,个人感觉挺好的,不过就是一节课时间太长了...