华北电力大学计算机控制课程DDC串级回路PID闭环.doc
(27页)
本资源提供全文预览,点击全文预览即可进行全文预览,如果您喜欢下载文档,查找使用更方便哦!
24.9 积分
.课程设计报告名称:过程计算机控制主题: DDC串级回路PID闭环控制系统设计及实时仿真系统:控制班: 学号: 学生姓名: 同组人: 导师:李明阳设计周数:一周一1. 学习和理解使用高级语言(C语言)实现数字PID控制算法模块程序的方法;2. 比较验证理想微分PID和实际微分PID控制算法阶跃响应,加深对上述两种算法各自特征的理解;3. 学习如何使用模拟计算机;4. 学习掌握A/D、D/A转换接口板的使用方法;5. 了解微机中断定时的方法;6. 学习掌握通过A/D、D/A用计算机转换被控对象的动态特性;7. 通过实时仿真实验掌握实时仿真实验DDC编制和调试单回路控制程序。二、实验仪器(1)一台微型计算机,系统软件Windows 98或DOS (不能直接使用I/O能力的NT或XP系统), 内装Turbo C 2.0/3.集成开发环境软件;(2)模拟计算机(XMN-(3)一块通用数据采集控制板(PCL-812PG型)。三、PID离散化理想微分PID该算法的传递函数形式为:采用向后差分法离散上式,差分方程形式为:u[k]=u[k-1] q0*e[2] q1*e[1] q2*e[0];各种系数为:q0=kp*(1 T/Ti Td/T); q1=-kp*(1 2*Td/T); q2=kp*Td/T;实际微分PID该算法的传递函数形式为:采用向后差分法对上式进行离散,写差分方程的形式如下: u[k]=c0*(Δu[k-1]) c1*e[k] c2*e[k-1] c3*e[k-2] u[k-1];各种系数为:c0=Tf/(T Tf);c1=kp*T/(T Tf)*(1 T/Ti Td/T); c2=-kp*T/(T Tf)*(1 2*Td/T); c3=kp*Td/(T Tf);使用模拟计算机中的电容电阻和操作放大器构建硬件二阶惯性环节,搭接二阶惯性链接,模拟被控对象。其传递函数为,硬件电路如下:图中各元件参数如下: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闭环控制系统,为通信做好准备。五、实验结果理想与实践PID上图通过阶跃响应曲线(2)被控对象(实物构建二阶惯性环节)D/A输出约1伏的信号输入模拟被控对象(惯性链接),A/D收集对象的输入信号及其响应D/A输出约2伏的阶跃信号,同时收集输入输出信号。然后,D/A反向输出约2伏负的阶跃信号,同时收集输入输出信号,获得模拟对象的飞升特性曲线。然后,D/A然后反向输出约2伏负的阶跃信号,同时收集输入输出信号,获得模拟对象的飞行特征曲线。在程序中,模拟对象输入信号通过按钮加减。按下H键并按下U键时,D/A输出1伏阶跃信号,按下按钮再次累积阶跃信号。每次按下D键D/A输出的阶跃信号递减1。(3)根据对象单位阶跃响应曲线寻求增益和惯性时间:利用切线法寻求对象的增益和一阶等效的惯性时间:如上图所示,(4)手动切换:(5)设定值r、阶跃响应曲线:程序列表/*---------------头文件定义---------------*/#include#include#include#include/*---------------定义绘图坐标---------------*/#defineox8/*-原点横坐标-------*/#defineoy440/*------原点纵坐标------*/#definexx620/*------x轴顶横坐标--*/#definexy440/*-----x轴顶点纵坐标---*/#definelenx580#defineleny400#defineyx8/*-----y轴顶横坐标----*/#defineyy15/*------y轴顶点纵坐标----*//*-----------------定义绘图区域----------------*/#defineleft20#definetop20#defineright620#definebottom460/*----------------坐标轴注释---------------------*/#definextext1x450#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运算式--------------------------*/loat sjpid(float kp,float tf,float td,float ti,float e[3],float du1,float u1) { int t=1; float u2; float c1=tf/(t+tf); float c2=kp*t*(1+t/ti+td/t)/(t+tf); float c3=-kp*t*(1+2*td/t)/(t+tf); float c4=kp*td/(t+tf); u2=c1*du1+c2*e[0]+c3*e[1]+c4*e[2]+u1; return u2; }/*-------------------------绘图初始化--------------------------*/ void Initial_Sys(void) { int GraphDriver; int GraphMode; detectgraph(&GraphDriver,&GraphMode); initgraph(&GraphDriver,&GraphMode,"C:\\TC201E\\BGI"); cleardevice(); }/*-------------------------绘制坐标系------------------*/ void DrawAxis(void) { int i; 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++) /*-x轴刻度-*/{ 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++) /*-y轴刻度-*/ 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,"The output (Response)"); outtextxy(ytext2x,ytext2y,"U(t)\/V"); }}main() { float kp,ti,td,tf,e[3]={0},ee[3]={0},u[6]={0},au1=0; int r=1,k=1; Initial_Sys(); DrawAxis(); while(k<100) { u[0]=lxpid(1,3.0,10,e,u[1]); e[0]=r; 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[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]。省略部分。ortb(BASE+11,REG); /*软件程序触发*/ for(i=0;i<10000;i++);outportb(BASE+10,channal); /*进行通道设置.选择通道0*/ for(i=0;i<10000;i++);outportb(BASE+9,0); /*设置增益通道增益*/ for(i=0;i<10000;i++); outportb(BASE+12,0); /*触发A/D转换*/ for(i=0;i<10000;i++); do{ /*查询法读PV*/poll=inportb(BASE+5); }while(poll&0x10); hb=inportb(BASE+5); for(i=0;i<10000;i++);lb=inportb(BASE+4); result = lb + ((hb&0x0F)<5) /* make the output real */ pv1=5; else if (pv1<0) pv1=0; temp=(int)(4095*pv1/5.0); hb=temp<<8; lb=temp-(hb<<8);outportb(BASE,1); /*启动DA转换*/ for(i=0;i<10000;i++); outportb(BASE+4,lb); /* low 8 */ for(i=0;i<10000;i++); outportb(BASE+5,hb); /* high 4 */ }/*00----------------------------中断子程序-------------------------*/void interrupt INT_1C(void) { time_counter++; outportb(0x20,0x20); } /*键盘控制*/ int scankey(void) { int key0; /*扫描键盘,判断是否有建按下*/ key0=bioskey(1); /*1:无键按下则返回0 */ if(key0!=0) key0=bioskey(0); /*0:返回按下的键*/ return key0; }/*DelayAction*/ /*tao=(int)(18.2*2) Delay action=2 seconds*/ float DelayAction(float y0) /*软件延迟*/ { float y_out;static float y_old[36]={0}; /*将ad延迟2s作为PV,T=0.2s,于是延迟36步*/int cyc; y_out=y_old[36-1]; for(cyc=1;cyc<36;cyc++) y_old[36-cyc]=y_old[36-cyc-1]; y_old[0]=y0; return y_out; }/*PID 主程序*/ void PIDset(void) /*PID设置*/ { key=scankey(); /*扫描键盘,并将按键存为key*/ if(A_H=='H') /*手动状态*/{ if(key==key_up) Kp+=0.2; else if(key==key_down) Kp-=0.2;else if(key==key_left) Ti-=0.2; else if(key==key_right) Ti+=0.2; else if(key==key_pgup) Td+=0.2; else if(key==key_pgdown) Td-=0.2;else if(key==key_U) /*控制u_m增减*/manu='+'; else if(key==key_D) manu='-'; } if(A_H=='A') /*自动状态*/ { if(key==key_U) /*设定值增减*/sp+=10; if(key==key_D) sp-=10; } if(key==key_E||key==key_ESC) /*退出*/ exit(1); if(key==key_A) /*设为手动*/ A_H='A'; if(key==key_H) /*设为自动*/A_H='H'; if(key==key_I) /*理想PID*/Tf=0; if(key==key_P) /*实际PID*/Tf=Tf0; }/*PID-default:IdealPID*/ float PID(float sp1,float pv1,float Kp1,float Ti1,float Td1,float Tf1,char A_H1,float T1) { float delta_u,u0,e,C1,C2,C3,C4; /*离散化后PID参数 当前时刻,u0为返回值*/static float e1,e2,u1,delta_u1; /*前一时刻的值*/ if(Kp1<0) printf("Kp becomes a negative number,please restart."); else if(Ti1<0) printf("Ti becomes a negative number,please press restart."); else if(Td1<0) printf("Td becomes a negative number,please press restart."); else { C1=Tf1/(T1+Tf1); C2=Kp1*T1*(1+T1/Ti1+Td1/T1)/(T1+Tf1); C3=-Kp1*T1*(1+2*Td1/T1)/(T1+Tf1); C4=Kp1*Td1/(T1+Tf1); /*自动控制*/ if(A_H1=='A') { e=sp1-pv1; delta_u=C1*delta_u1+C2*e+C3*e1+C4*e2; /*delta_u1是delta_u前一时刻的值*/ u0=u1+delta_u; /*当前时刻控制器输出*/ e2=e1; e1=e; delta_u1=delta_u; u1=u0; /*自动时,手操器输出跟踪自动输出*/ error[cj_counter]=sp1-pv1; return u0;}/*手动控制*/ else if(A_H1=='H') { if(manu=='+') /*调节手操器输出*/u+=10; if(manu=='-') u-=10; sp1=pv1; u1=u; sp=pv1; /*sp跟踪pv保证偏差e为0*/ e1=0; e2=0; delta_u1=0; /*将前两时刻的偏差赋值为0*/ error[cj_counter]=sp1-pv1; return u; } } } /*显示与画图*//*初始化 CRT*/ void Initial_Sys(void) { int GraphDriver; int GraphMode; detectgraph(&GraphDriver,&GraphMode); initgraph(&GraphDriver,&GraphMode,"C:\\TC201E\\BGI"); } /*draw basic coordinate axis*/ void axis(void) { int i;Initial_Sys(); setbkcolor(15); /*white0/black15*/ setcolor(9); /*linght blue*/ rectangle(10,20,630,470); /*zone of drawing*/ line(ox,oy,xx,xy); /*axis and arrow*/ line(xx-5,xy-5,xx,xy); line(xx,xy,xx-5,xy+5); line(ox,oy,yx,yy); line(yx-5,yy+5,yx,yy); line(yx+5,yy+5,yx,yy); settextstyle(2,1,5); /*Small font,vert,5 times bigger*/ outtextxy(20,100,"The Output (Response)"); outtextxy(20,40,"U(t)"); settextstyle(2,0,5); /*Small font,horiz,5 times bigger*/ outtextxy(300,455,"Time"); outtextxy(590,455,"t/sec"); setlinestyle(1,0,1); /*dot line,none,width*/ for(i=1;i<4;i++) /*each inport starting position*/ line(ox,oy-100*i,ox+500,oy-100*i); outtextxy(ox-16,oy-100*0,"0"); outtextxy(ox-16,oy-100*1,"1"); outtextxy(ox-16,oy-100*2,"2"); outtextxy(ox-16,oy-100*3,"3"); for(i=1;i<=500/50;i++) /*scale*/ { line(ox+50*i,oy,ox+50*i,oy-400); /*1/T=10,that is 10px=1sec*/ line(ox+50*i-25,oy,ox+50*i-25,oy-10); } setlinestyle(0,0,1); /*real line,none,width*/ outtextxy(ox-4+50,oy+2,"5");outtextxy(ox-8+100,oy+2,"10"); outtextxy(ox-8+150,oy+2,"15"); outtextxy(ox-8+200,oy+2,"20"); outtextxy(ox-8+250,oy+2,"25"); outtextxy(ox-8+300,oy+2,"30"); outtextxy(ox-8+350,oy+2,"35"); outtextxy(ox-8+400,oy+2,"40"); outtextxy(ox-8+450,oy+2,"45"); outtextxy(ox-8+500,oy+2,"50"); } /*line-drawing and notes*/ void Drawline(int cj1,float pv1,float sp1,float u1,float e1) /*画线*/ { static int cj_0=0,cj_1=0,pv_0=0.0,pv_1=0.0,sp_0=0.0,sp_1=0.0,u_0=0.0,u_1=0.0,e_0=0.0,e_1=0.0; cj_1=cj1; /*X coordinate*/ pv_1=(int)(pv1*10); sp_1=(int)(sp1*10); u_1=(int)(u1*10); e_1=(int)(e1*10); setcolor(2); /*green*/ line(ox+cj_0,oy-pv_0,ox+cj_1,oy-pv_1); outtextxy(590,30,"pv"); setcolor(8); /*dark gray*/ line(ox+cj_0,oy-sp_0,ox+cj_1,oy-sp_1); outtextxy(590,45,"sp"); setcolor(3); /*cyan*/ line(ox+cj_0,oy-u_0,ox+cj_1,oy-u_1); outtextxy(590,60,"u"); setcolor(4); /*red*/ line(ox+cj_0,oy-e_0,ox+cj_1,oy-e_1); outtextxy(590,75,"error"); cj_0=cj_1; pv_0=pv_1; sp_0=sp_1; u_0=u_1; e_0=e_1; }. 关 键 词: 控制 计算机 ddc 过程 大学 回路 电力 pid 闭环 华北
天天文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
关于本文
本文标题:华北电力大学过程计算机控制课设DDC串级回路PID闭环.doc
链接地址: https://www.wenku365.com/p-56270545.html