目录
一直对串级PID不是很能明白怎么实现,最后找了一些资料学习了一下,在这里分享一下我学习的心得。
一、串级PID的认识
串级PID即是将两个及以上的PID控制器按照串联的方式连接起来,前一个的输出作为后一个的输入两者共同控制目标对象。对于直流电机速度位置闭环控制来说就是外环位置环,内环速度环,两者怎么联系起来呢?有的说法是:外环输入电机旋转的目标圈数,输出为速度;内环输入为速度,输出为PWM增量,这种说法不错但是很容易让人误解。下面谈谈我的看法,输入为电机旋转的目标圈数输出怎么就变成速度了呢,在程序上也没有将圈数转化成速度的处理啊,一般大家都会这样想。但其实这是与后面的PID控制器有关,前一个PID程序输出的其实还是圈数,只是后级PID把它作为速度了,为什么要这样理解呢?举个例子:假如期望圈数为某一个正值,而此时电机编码器传出的值为零,那么误差为期望圈数减去编码器测量值为一正值,这个正值经过PID的计算,计算出的结果就是后级PID的输入,后级PID没有给设定的期望值,它的期望值就是前级PID的输出值,这个输出值经过PID的计算得出的就是电机需要的旋转速度,当然这里给这个输出映射为PWM增量,在实际的程序里面我们会对前级的输出做一个限幅,这个幅值就是期望的速度,我们要让电机按照我们期望的速度旋转起来就必须得给加这样一个限幅。假定现在没有这个限幅,当前级的输出值大于了所期望的速度值那么电机就会超速旋转这样肯定不是我们想要的,那前级的输出值小于所期望的值时那么这个输出值就一定会一直的增加,最后还是出现在了大于所期望速度这种情况。(在这里我们一定要把期望速度设置的在合理范围内)
这个控制框图就是用来控制直流电机速度位置闭环的
二、浅谈PID
PID( Proportional Integral Derivative)控制是最早发展起来的控制策略之一,由于其算法简单、鲁棒性好和可靠性高,被广泛应用于工业过程控制,尤其适用于可建立精确数学模型的确定性控制系统。任何闭环控制系统的首要任务是要稳(稳定)、快(快速)、准(准确)的响应命令。PID调整的主要工作就是如何实现这一任务。增大比例系数P将加快系统的响应,它的作用于输出值较快,但不能很好稳定在一个理想的数值,不良的结果是虽较能有效的克服扰动的影响,但有余差出现,过大的比例系数会使系统有比较大的超调,并产生振荡,使稳定性变坏。积分能在比例的基础上消除余差,它能对稳定后有累积误差的系统进行误差修整,减小稳态误差。微分具有超前作用,对于具有容量滞后的控制通道,引入微分参与控制,在微分项设置得当的情况下,对于提高系统的动态性能指标,有着显著效果,它可以使系统超调量减小,稳定性增加,动态误差减小。
其中:Kp:比例增益,是调适参数;
Ki:积分增益,也是调适参数;
Kd:微分增益,也是调适参数;
e:误差=期望值(SP)- 反馈值(PV);
t:当前时间
1.比例环节
按照比例地放大或缩小偏差信号e(t),偏差一旦产生,控制器立即产生控制作用,以减小偏差。当仅有比例控制时系统输出存在稳态误差。P参数越大比例作用越强,动态响应越快,消除误差的能力越强。但实际系统是有惯性的,控制输出变化后,实际y(t)值变化还需等待一段时间才会缓慢变化。由于实际系统是有惯性的,比例作用不宜太强,比例作用太强会引起系统振荡不稳定。P参数的大小应在以上定量计算的基础上根据系统响应情况,现场调试决定,通常将P参数由大向小调,以能达到最快响应又无超调(或无大的超调)为最佳参数。
2.积分环节
比例作用的输出与误差的大小成正比,误差越大,输出越大,误差越小,输出越小,误差为零,输出为零。由于没有误差时输出为零,因此比例调节不可能完全消除误差,不可能使被控的反馈值达到给定值。必须存在一个稳定的误差,以维持一个稳定的输出,才能使系统的反馈值保持稳定。这就是通常所说的比例作用是有差调节,是有静差的,加强比例作用只能减少静差,不能消除静差(静差:即静态误差,也称稳态误差)。 为了消除静差必须引入积分作用,积分作用可以消除静差,以使被控的y(t)值最后与给定值一致。引进积分作用的目的也就是为了消除静差,使y(t)值达到给定值,并保持一致。 积分作用消除静差的原理是,只要有误差存在,就对误差进行积分,使输出继续增大或减小,一直到误差为零,积分停止,输出不再变化,系统的PV值保持稳定,y(t)值等于u(t)值,达到无差调节的效果。 但由于实际系统是有惯性的,输出变化后,y(t)值不会马上变化,要等待一段时间才缓慢变化,因此积分的快慢必须与实际系统的惯性相匹配,惯性大、积分作用就应该弱,积分时间I就应该大些,反之而然。如果积分作用太强,积分输出变化过快,就会引起积分过头的现象,产生积分超调和振荡。通常I参数也是由大往小调,即积分作用由小往大调,观察系统响应以能达到快速消除误差,达到给定值,又不引起振荡为准。
3.微分环节
不论比例调节作用,还是积分调节作用都是建立在产生误差后才进行调节以消除误差,都是事后调节,因此这种调节对稳态来说是无差的,对动态来说肯定是有差的,因为对于负载变化或给定值变化所产生的扰动,必须等待产生误差以后,然后再来慢慢调节予以消除。但一般的控制系统,不仅对稳定控制有要求,而且对动态指标也有要求,通常都要求负载变化或给定调整等引起扰动后,恢复到稳态的速度要快,因此光有比例和积分调节作用还不能完全满足要求,必须引入微分作用。比例作用和积分作用是事后调节(即发生误差后才进行调节),而微分作用则是事前预防控制,即一发现y(t)有变大或变小的趋势,马上就输出一个阻止其变化的控制信号,以防止出现过冲或超调等。D越大,微分作用越强,D越小,微分作用越弱。系统调试时通常把D从小往大调,具体参数由试验决定。
三、PID分类
1.位置式PID
位置式PID是当前系统的实际位置,与你想要达到的预期位置的偏差,进行PID控制。位置闭环控制就是根据编码器的脉冲累加,测量电机的位置信息,并与目标值进行比较得到一个控制偏差,然后我们对偏差进行比例积分、微分的控制,使偏差趋近于0的一个过程。
位置式离散PID公式
pwm=Kp*e(k)+Ki*e(k)+Kd[e(k)-e[k-1]]
e(k)代表本次偏差
e(k-1)代表上一次偏差
e(k)代表e(k)以及之前的偏差的累计和;其中K为1,2,K
pwm代表输出
2.增量式PID
控制量▲u(k)对应的是近几次位置误差的增量,而不是对应与实际位置的偏差 没有误差累加也就是说,增量式PID中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作。
增量式离散PID公式
ControlVelocity+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
e(k)代表本次偏差
e(k-1)代表上一次偏差,以此类推
ControlVelocity代表增量输出
在我们的速度控制闭环系统里,只使用PI控制
ControlVelocity+=Kp[e(k)-e(k-1)]+Ki*e(k)
总结:增量式算法不需要做累加,控制量增量的确定仅与最近几次偏差采样值有关,计算误差对控制 量计算的影响较小。而位置式算法要用到过去偏差的累加值,容易产生较大的累加误差。
四、串级PID程序
开启了10ms的定时器中断,每10ms进行一次运算,这里巧妙一点是每次运算完后将编码器清零,那么经过10ms后得到编码器数值也就相当于速度了,而且每次对读到的编码器数值进行累计那这样累加值不就是电机已经旋转过的圈数了嘛。先进行位置闭环控制然后将其输出值进行一个限幅,这个限幅的值就是目标速度这样以来就可以保证电机一直以这样一个速度进行旋转了,最后将限幅的结果输入到速度环运算后的结果映射成PWM,这样就可以__HAL_TIM_SetCompare()这个函数来调节电机速度了。位置环用的是位置式PID,速度环用的是增量式PID。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //开启了10ms的定时器中断
{
Encoder=Read_Encoder(); // 读取当前编码器读数,即速度
CurrentPosition+=Encoder; // 编码器读数(速度)积分得到位置
PWM_P=Position_FeedbackControl(TargetCircle, CurrentPosition); //位置闭环控制
PWM_V=PWM_Restrict(PWM_P,TargetVelocity); //对位置环输出进行限幅,使得输出在
目标速度范围内
PWM=Velocity_FeedbackControl(PWM_V, Encoder); //速度闭环控制
SetPWM(PWM); //pwm输入驱动器
__HAL_TIM_CLEAR_IT(&htim4,TIM_IT_UPDATE);
}
定时器编码器模式采用四倍频方式,正向转脉冲数为正向增加,反转为反向减少,但是一般见到0后就从最大值往下减了,这不是希望看到的,我们需要到0后出现负数,为了解决这个问题使用一个技巧就是把编码器读数定义成short类型,这样减到0后就会出现负数了,而且每次读取完成后就进行清零操作。
short Read_Encoder(void)
{ //定时器编码器模式采用四倍频方式,正向转脉冲数为正向增加,反转为反向减少,但是一般见到0后就从最大值往下减了,这不是希望看到的,我们需要到0后出现负数,为了解决这个问题使用一个技巧就是把编码器读数定义成short类型
short Encoder_TIM; //定义编码器读数为short类型
// Encoder_TIM=TIM2->CNT;
Encoder_TIM = (short)(__HAL_TIM_GET_COUNTER(&htim2)); //读取当前编码器的数值
TIM2->CNT=0; //计数器清零
return Encoder_TIM;
}
位置环的PID程序
int Position_FeedbackControl(float Circle, int CurrentPosition)
{
float TargetPosition,Bias, ControlVelocity;
static float Last_bias, Integral_Bias;
TargetPosition=Circle*1040*1.04; //目标位置=目标圈数*1040
//10ms读取一次编码器,电机减速比为20,霍尔编码器精度13,AB双相组合得到4倍频,则转1圈编码器读数
//为20*13*4=1040
//1.04是误差系数,电机本身存在的误差,根据实际情况调整
Bias=TargetPosition-CurrentPosition; //求位置偏差
Integral_Bias+=Bias;
if(Integral_Bias> 970) Integral_Bias= 970; //积分限幅
if(Integral_Bias<-970) Integral_Bias=-970;
ControlVelocity=Position_Kp*Bias+Position_Ki*Integral_Bias+Position_Kd*(Bias-Last_bias);
Last_bias=Bias;
return ControlVelocity;
}
速度环的PID程序
int Velocity_FeedbackControl(int TargetVelocity, int CurrentVelocity)
{
int Bias;
static int ControlVelocity, Last_bias;
Bias=TargetVelocity-CurrentVelocity; //求速度偏差
ControlVelocity+=Velcity_Kp*(Bias-Last_bias)+Velcity_Ki*Bias; //增量式PI控制器
Last_bias=Bias;
return ControlVelocity; //·µ»ØËٶȿØÖÆÖµ
}
设定目标速度,将位置控制器的输出进行限幅。这个是最重要的一步,也是设定电机旋转地目标速度的方式。
int PWM_Restrict(int PWM_P, int TargetVelocity)
{
if(PWM_P>+TargetVelocity)
PWM_P=+TargetVelocity;
else if(PWM_P<-TargetVelocity)
PWM_P=-TargetVelocity;
else
PWM_P=PWM_P;
return PWM_P;
}
五、调参
根据具体的实际情况继续一个个的参数整定,有一个原则就是先调节内环等内环调好了在调节外环,此时外环的Kp设置为1其他的都为0这样来调内环。在这里我找了一个网上别人做的调参动态图可以按照这个方法来调节参数。感觉起来这个图还是比较清楚的。
代码分享:链接:https://pan.baidu.com/s/1Id9ih-RAOg3puBJ5_RXECg
提取码:ig3q