控制策略学习记录

PID:比例积分微分-难点在于控制器参数的设定

https://www.arduino.cn/thread-12813-1-1.html(通俗的解释)

采样周期:采样周期越小,越能反映模拟量的变化情况,但是过小会增加CPU的运算工作量,而且相邻的两次采样差值机会没有变化;

阶跃响应:在某个时间点发送突变;

1.比例控制  (有偏差的时候使用)

闭环系统中调节困难的主要原因是系统的延迟作用,比例系数过小是的调节速度太慢,比例系数过大的话会使得震荡次数增加,调调节时间增加,动态性变差,造成闭环系统不稳定;

数字化的表示:

2.积分控制(稳定后有误差的时候使用)

目的:消除静态误差(稳态误差:系统达到稳定后还是存在一定的误差),提高控制精度

积分项和当前的误差值和过去的历次误差值的累加值值成正比,因此积分作用本身具有严重的滞后特性;

3.微分控制(监控变化趋势,超前调节)

误差的微分就是误差的变化率,误差变化越快,微分绝对值越大,控制器输出量的微分部分与误差的微分成正比,反映了被控制量变化的趋势;

数字量:

直流电机为例子分析:rin(t)是电机转速的预定值,rout(t)是电机转速的实际值

偏差:Kp*err(k)=rin(k)-rout(k)    T是采样间隔

积分环节:(加和的形式)err(k)+err(k+1).......

微分环节:(斜率的形式)[err(k)-err(k-1)]/T

PID实现算法:位置型;(参考资料来源:https://wenku.baidu.com/view/827c5423647d27284a735105.html



struct pid{
	float SetSpeed;
	float ActualSpeed;
	float err;
	float err_last;
	float Kp,Ki,Kd;
	float voltage;
	float intergral;
}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.intergral=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.intergral+=pid.err;//积分就是求和
    //关键的公式体现:位置式
	pid.voltage=pid.Kp*pid.err+pid.Ki*pid.intergral+pid.Kd*(pid.err-pid.err_last);
    //增量式
    //incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err
    //-2*pid.err_next+pid.err_last);
    //pid.ActualSpeed+=incrementSpeed;
    //pid.err_last=pid.err_next;
	pid.err_last=pid.err;
	pid.ActualSpeed=pid.voltage*1.0;//?????什么意思
	return pid.ActualSpeed;
}

int main(){
	printf("system begin \n");
	PID_init();
	init_count=0;
	while(count<1000)
	{
		float speed=PID_realize(200.0);
		printf("%f\n",speed);
		count++;
	}
}

积分分离的控制算法

为什么要积分分离??答:普通PID中,引入积分环节的目的是为了消除静态误差,提高控制的精度。但是在启动,结束或大幅度增减设定的时候,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应极限控制量,从而引起较大的超调甚至震荡;因为这个原因,引入积分分离的概念。

基本思路:当被控量与设定的值偏差较大时,取消积分的作用,当被控制量接近给定的值时,引入积分控制,以消除静态差,提高精度。

关键部分代码如下:

if(abs(pid.err)>200)
{
	index=0;
}
else{
	index=1;
	pid.integral+=pid.err;
}
pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);//index是关键

猜你喜欢

转载自blog.csdn.net/runkui8905/article/details/81975682