其中C代表不灵敏区值;
(2.3)手动/自动双向无扰切换
自动切手动:
系统处于自动时,手操器实时跟踪自动PID调节器的输出,切换瞬间由于手操器内部电路起保持作用,使得切换没有扰动产生,此时对象处于手操器的开环控制,调节器跟踪手操器的输出。
手动切自动:
手动到自动的切换过程主要由计算机软件实现,一方面PID调节器获得手操器输出,同时软件使得算法中的Δu[k-1])、e[k]、e[k-1]、e[k-2]等历史状态清零。
程序中通过设置键盘,使的按下手动键H时,系统处于手动状态,按下自动键A时,系统处于自动状态。
(3)硬件二阶惯性环节搭建
利用模拟计算机中的电容电阻及运算放大器,搭接二阶惯性环节,仿真一个被控对象。
其传递函数为
,硬件电路如下:
图中各元件参数如下:
R3=R2=510K;R1=R4=R5=R6=R7=1M;C1=C2=C=4.7uF;
则可得:
K=(R5/R1)*(R6/R4)=1
T1=T2=R5*C1=R6*C2=1000000*0.0000047=4.7s
所以G(s)=1/(4.7s+1)*(4.7s+1)
搭建好硬件电路后,将PLCD-780插入IPC机箱插槽,用导线将PLCD-780中的A/D、D/A、电源的接线端子与所搭二阶惯性环节的输出、输入端口及机箱上的电源连接,组成一个完整的PID闭环控制系统,为通信做好准备。
(4)PID参数的整定
运用过程控制中PID参数的工程整定方法,运用衰减曲线法对PID参数进行整定。
在matlab中,设置PID参数为Td=0,Ti=
,设置合适的比例带使得对象闭环阶跃响应曲线衰减率为0.9,从而确定PID的整定参数为:
P=0.8
,Ti=1.2tr,Td=0.4tr;
matlab中对象响应曲线为:
由曲线可得PID参数为:
P=0.8
=0.8×5=4,Ti=1.2tr=1.2×10=12,Td=0.4tr=0.4×10=4
(5)实验结果输出
通过在程序中编写相应的绘图模块子程序,在需要画图时调用相应的子程序实现曲线的绘制。
同时在程序中,本小组采用按键实现了PID手自动切换,理想PID与实际PID的切换,以及在手自动状态下由按键改变PID参数,使得调节方式更加的灵活。
3.设计结果
(1)PID阶跃响应曲线
调用程序,向PID模块输入一个阶跃信号,绘出PID阶跃响应曲线如下:
(1.1)理想PID阶跃响应图:
(1.2)实际PID阶跃响应图:
(2)被控对象(惯性环节)阶跃响应曲线
上图通过D/A输出一个1伏左右的信号输入模拟的被控对象(惯性环节),A/D采集对象的输入信号及其响应,再使D/A输出一个幅度为2伏左右的阶跃信号,同时采集输入输出信号。
然后,D/A再反向在输出一个幅度为2伏左右负的阶跃信号,同时采集输入输出信号,得出仿真对象飞升特性曲线。
程序中,通过按键实现模拟对象输入信号的加减。
当按下H按键时,且按下U键时,D/A输出一个1伏阶跃信号,再次按下按键时阶跃信号累加。
每次按下D键时,D/A输出的阶跃信号递减1。
(3)设定值r、控制量u和被控对象输出y的响应曲线:
4.程序清单
/*---------------头文件定义---------------*/
#include
#include
#include
#include
/*---------------定义绘图坐标---------------*/
#defineox8/*-----原点横坐标-------*/
#defineoy440/*------原点纵坐标------*/
#definexx620/*------x轴顶点横坐标--*/
#definexy440/*-----x轴顶点纵坐标---*/
#definelenx580
#defineleny400
#defineyx8/*-----y轴顶点横坐标----*/
#defineyy15/*------y轴顶点纵坐标----*/
/*-----------------定义绘图区域----------------*/
#defineleft20
#definetop20
#defineright620
#definebottom460
/*----------------坐标轴注释---------------------*/
#definextext1x550
#definextext1y450
#defineytext1x10
#defineytext1y60
#definextext2x610
#definextext2y450
#defineytext2x10
#defineytext2y20
/*-------------------------理想PID运算式--------------------------*/
floatlxpid(floatkp,floattd,floatti,floate[3],floatu1)
{
intt=1;
floatu;
floatq0=kp*(1+t/ti+td/t);
floatq1=-kp*(1+2*td/t);
floatq2=kp*td/t;
u=q0*e[0]+q1*e[1]+q2*e[2]+u1;
returnu;
}
/*-------------------------实际PID运算式--------------------------*/
floatsjpid(floatkp,floattf,floattd,floatti,floate[3],floatdu1,floatu1)
{
intt=1,k=1000;
floatu2;
floatc1=tf/(t+tf);
floatc2=kp*t*(1+t/ti+td/t)/(t+tf);
floatc3=-kp*t*(1+2*td/t)/(t+tf);
floatc4=kp*td/(t+tf);
u2=c1*du1+c2*e[0]+c3*e[1]+c4*e[2]+u1;
returnu2;
}
/*-------------------------绘图初始化--------------------------*/
voidInitial_Sys(void)
{
intGraphDriver;
intGraphMode;
detectgraph(&GraphDriver,&GraphMode);
initgraph(&GraphDriver,&GraphMode,"C:
\\TC201E\\BGI");
cleardevice();
}
/*-------------------------绘制坐标系------------------*/
voidDrawAxis(void)
{
inti;
setbkcolor(15);
setcolor(5);
line(ox,oy,xx,xy);/*x_axis*/
line(xx-5,xy-5,xx,xy);
line(xx,xy,xx-5,xy+5);
line(ox,oy,yx,yy);/*y_axis*/
line(yx-5,yy+10,yx,yy);
line(yx+5,yy+10,yx,yy);
for(i=0;i<51;i++)
{
line(ox+10*i,oy,ox+10*i,oy-10);
line(ox+10*i+5,oy,ox+10*i+5,oy-5);
}
for(i=1;i<=8;i++)
line(ox,oy-50*i,ox+10,oy-50*i);
outtextxy(ox+50*0-7,oy+20,"0");
outtextxy(ox+50*1-7,oy+20,"5");
outtextxy(ox+50*2-7,oy+20,"10");
outtextxy(ox+50*3-7,oy+20,"15");
outtextxy(ox+50*4-7,oy+20,"20");
outtextxy(ox+50*5-7,oy+20,"25");
outtextxy(ox+50*6-7,oy+20,"30");
outtextxy(ox+50*7-7,oy+20,"35");
outtextxy(ox+50*8-7,oy+20,"40");
outtextxy(ox+50*9-7,oy+20,"45");
outtextxy(ox+50*10-7,oy+20,"50");
outtextxy(ox-10,oy-50*1,"1");
outtextxy(ox-10,oy-50*2,"2");
outtextxy(ox-10,oy-50*3,"3");
outtextxy(ox-10,oy-50*4,"4");
outtextxy(ox-10,oy-50*5,"5");
outtextxy(ox-10,oy-50*6,"6");
outtextxy(ox-10,oy-50*7,"7");
outtextxy(ox-10,oy-50*8,"8");
settextstyle(SMALL_FONT,HORIZ_DIR,5);
outtextxy(xtext1x,xtext1y,"Time");
outtextxy(xtext2x,xtext2y,"t\/s");
settextstyle(SMALL_FONT,VERT_DIR,5);
outtextxy(ytext1x,ytext1y,"Theoutput(Response)");
outtextxy(ytext2x,ytext2y,"U(t)\/V");
}
main()
{
floatkp,ti,td,tf,e[3]={0},ee[3]={0},u[6]={0},au1=0;
intr=1,k=1;
Initial_Sys();
DrawAxis();
while(k<100)
{
u[0]=lxpid(1,3.0,10,e,u[1]);
e[0]=r;
/*printf("%f\n",u[0]);*/
u[3]=sjpid(1,5,3.0,10,ee,au1,u[4]);
setcolor(5);
line((k-1)*10,130-u[1]*100,k*10,130-u[1]*100);
line(k*10,130-u[1]*100,k*10,130-u[0]*100);
delay(10000);
u[2]=u[1];
u[1]=u[0];
e[2]=e[1];
e[1]=e[0];
ee[0]=r;
setcolor(3);
line((k-1)*10,150-u[4]*100,k*10,150-u[4]*100);
line(k*10,150-u[4]*100,k*10,150-u[3]*100);
delay(10000);
u[5]=u[4];
u[4]=u[3];
ee[2]=ee[1];
ee[1]=ee[0];
au1=u[4]-u[5];
k++;
}
}
/*---------------头文件定义---------------*/
#include"stdio.h"
#include"math.h"
#include"graphics.h"/*forgraphdriverinstalling,onlycanbecalledinTurboC*/
#include"string.h"
#include"dos.h"
#include"bios.h"
#include"conio.h"/*forinterruptprogram头文件定义*/
#include"stdlib.h"
#include"io.h"
/*--------------按键地址区定义--------------------*/
/*statements*/
doublekey_ESC=0x011b;/*definecannotsuitthelengthofbioskey键盘内存定义*/
doublekey_E=0x1265;
doublekey_A=0x1e61;
doublekey_H=0x2368;
doublekey_U=0x1675;
doublekey_D=0x2064;
doublekey_I=0x1769;
doublekey_P=0x1970;
doublekey_up=0x4800;
doublekey_down=0x5000;
doublekey_left=0x4b00;
doublekey_right=0x4d00;
doublekey_pgup=0x4900;
doublekey_pgdown=0x5100;
/*--------------PLCD780基址定义--------------------*/
#defineBASE0x220/*------------PCL812Gneed16addressesinarow,from220Hto3F0H*/
#defineREG0
/*---------------定义绘图坐标---------------*/
#defineox40/*------------原点横坐标-------------*/
#defineoy440/*------------原点纵坐标------------*/
#definexx600/*------------x轴顶点横坐标--------*/
#definexy440/*------------x轴顶点纵坐标--------*/
#defineyx40/*------------y轴顶点横坐标--------*/
#defineyy40/*------------y轴顶点纵坐标---------*/
/*---------------PID参数定义---------------*/
floatKp=1.0;
floatTi=10.0;
floatTd=3.0;
floatTf0=15.0;
floatTf=0;
floatT=0.1;/*---------------采样时间------------*/
floatad,e,pv0;
floatu=0.0;
floatpv=0.0;
floatsp=0.0;
charA_H='H';
charmanu;
intkey=0;
inttime_counter=0;/*timesofinterrupt中断的次数*/
intcj_counter=0;/*samplingcounter采样次数*/
intQ_counter=800;/*采集步长赋初始值*/
intstepdata[800];
intslopedata[800];
interror[800];
/*--------------函数声明-----------------*/
voidinterrupt(*fadd1C)(void);/*中断函数声明*/
voidloop();/*定值采样输出程序声明*/
floatAD(unsignedcharchannal);/*A/D*/
voidDA(floatpv1);/*D/A*/
voidinterruptINT_1C(void);/*8259,resetinterruptcontroller*/
intscankey();
floatDelayAction(floaty0);/*延迟*/
voidPIDset(void);/*pid设置声明*/
floatPID(floatsp1,floatpv1,floatKp1,floatTi1,floatTd1,floatTf1,charA_H1,floatT1);/*pid计算声明*/
floatObject(floatu1,floatT1);/*二阶惯性环节声明*/
voidInitial_Sys(void);/*Initiategraphdisplay*/
voidaxis(void);
voidDrawline(intcj,floatpv1,floatsp1,floatu1,floate1);
/*主函数*/
voidmain(void)
{
inti;
for(i=0;i<500;i++)
{stepdata[i]=10;slopedata[i]=i;error[i]=0;}
/*SetnewINT_1Candsaveold*/
disable();/*屏蔽中断*/
fadd1C=getvect(0x1C);/*1C为定时器控制的软中断,平均一秒发生18.2次,即周期为55ms中断程序,getvect用于取得中断向量入口*/
/*开启中断服务*/
setvect(0x1C,INT_1C);/*设置中断矢量入口*/
enable();
axis();/*画坐标轴*/
loop();/*定时采值输出程序*/
}
/*主函数结束下面为定时采值输出程序*/
voidloop()
{do
{
if((cj_counter*T)<(time_counter/18.2))/*采样次数乘以采样时间小于中断次数除以每分钟中断次数=中断时间*/
{
PIDset();/*Introduction:
Exit-E/ESC,A_H-A/H,Ideal/ParallelPID,sp-U/D由键盘输入设置pid参数*/
u=PID(sp,pv,Kp,Ti,Td,Tf,A_H,T);
/*DA(u);*/
pv=Object(u,T);
/*ad=AD(O);*/
/*pv=DelayAction(u);*/
e=error[cj_counter];
Drawline(cj_counter,pv,sp,u,e);
manu=0;
/*statusbar,atthetopofthescreen--------------howtoexpress%.2f*/
if(Tf==0)
printf("IdealPID,Mode:
%c,sp=%.1f,pv=%2.1f,u=%.1f,error=%.1f,Kp=%.1f,Ti=%.1f,Td=%.1f\t\r",A_H,sp,pv,u,e,Kp,Ti,Td);
elseif(Tf>0)
printf("Parallal,Mode:
%c,sp=%.1f,pv=%