DDC单回路PID闭环控制系统的设计及实时仿真课程设计.doc_第1页
DDC单回路PID闭环控制系统的设计及实时仿真课程设计.doc_第2页
DDC单回路PID闭环控制系统的设计及实时仿真课程设计.doc_第3页
DDC单回路PID闭环控制系统的设计及实时仿真课程设计.doc_第4页
DDC单回路PID闭环控制系统的设计及实时仿真课程设计.doc_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

课程设计(综合实验)报告( 2011- 2012 年度第 二学期)名 称: 过程计算机控制系统 题 目:ddc单回路pid闭环控制系统的设计及实时仿真院 系: 控制与计算机工程学院 班 级: 自动0905 学 号: 学生姓名: 指导教师: 朱耀春 设计周数: 一周 成 绩: 日期:2012 年 6 月 20 日 课程设计报告一、 课程设计的目的与要求1.设计目的在计算机控制系统课程学习的基础上,加强学生的实际动手能力,通过对ddc直接数字闭环控制的仿真加深对课程内容的理解。2.设计要求本次课程设计通过多人合作完成ddc直接数字闭环控制的仿真设计,学会a/d、d/a转换模块的使用。通过手动编写pid运算式掌握数字pid控制器的设计与整定的方法,并做出模拟计算机对象飞升特性曲线,熟练掌握ddc单回路控制程序编制及调试方法。二、 设计正文1.设计思想 本课程设计利用turboc2.1开发环境,通过手动编写c语言程序完成pid控制器的设计,a/d、d/a转换,绘出pid阶跃响应曲线与被控对象动态特性曲线。整个设计程序模块包含了pid配置模块,plcd-780定时采样、定时输出模块,pid手/自动切换模块(按键控制)及绘图显示模块。设计中,通过设定合理的pid 参数,控制plcd-780完成模拟计算机所搭接二阶惯性环节数据的采集,并通过绘图程序获得对象阶跃响应曲线。 2. 设计步骤(1)前期准备工作 (1.1)配备微型计算机一台,系统软件windows 98或dos (不使用无直接i/o能力的nt或xp系统), 内装turbo c 2.0/3.0集成开发环境软件;(1.2)配备模拟计算机一台(xmn-1型), 通用数据采集控制板一块(plcd-780型);(1.3)复习turboc2.0并参照说明书学习plcd-780的使用(2) pid的设计(2.1)pid的离散化理想微分pid算法的传递函数形式为:采用向后差分法对上式进行离散,得出其差分方程形式为:uk=uk-1+q0*e2+q1*e1+q2*e0;其中各项系数为:q0=kp*(1+t/ti+td/t); q1=-kp*(1+2*td/t); q2=kp*td/t;实际微分pid算法的传递函数形式为:采用向后差分法对上式进行离散化,写成差分方程的形式为: uk=c0*(uk-1)+c1*ek+c2*ek-1+c3*ek-2+uk-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); (2.2)数字pid算法的改进积分分离算法积分分离算法通过控制pid输入偏差e达到优化目的,当偏差较大时停止积分作用,只有当偏差较小时才投入积分,算法如下表示:当|e(k)|时,采用pd控制; 当|e(k)|c时,|e(k)|=|e(k)|; 当|e(k)|c时,|e(k)|=0 其中c代表不灵敏区值;(2.3) 手动/自动双向无扰切换自动切手动:系统处于自动时,手操器实时跟踪自动pid调节器的输出,切换瞬间由于手操器内部电路起保持作用,使得切换没有扰动产生,此时对象处于手操器的开环控制,调节器跟踪手操器的输出。手动切自动:手动到自动的切换过程主要由计算机软件实现,一方面pid调节器获得手操器输出,同时软件使得算法中的uk-1)、ek、ek-1、ek-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.85=4,ti=1.2tr=1.210=12 ,td=0.4tr=0.410=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 /*-定义绘图坐标-*/ #define ox 8 /*-原点横坐标-*/ #define oy 440 /*-原点纵坐标-*/ #define xx 620 /*-x轴顶点横坐标-*/ #define xy 440 /*-x轴顶点纵坐标-*/ #define lenx 580 #define leny 400 #define yx 8 /*-y轴顶点横坐标-*/ #define yy 15 /*-y轴顶点纵坐标-*/ /*-定义绘图区域-*/ #define left 20 #define top 20 #define right 620 #define bottom 460 /*-坐标轴注释-*/ #define xtext1x 550 #define xtext1y 450 #define ytext1x 10 #define ytext1y 60 #define xtext2x 610 #define xtext2y 450 #define ytext2x 10 #define ytext2y 20/*-理想pid运算式-*/float lxpid(float kp,float td,float ti,float e3,float u1) int t=1; float u; float q0=kp*(1+t/ti+td/t); float q1=-kp*(1+2*td/t); float q2=kp*td/t; u=q0*e0+q1*e1+q2*e2+u1; return u; /*-实际pid运算式-*/float sjpid(float kp,float tf,float td,float ti,float e3,float du1,float u1) int t=1,k=1000; 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*e0+c3*e1+c4*e2+u1; return u2; /*-绘图初始化-*/void initial_sys(void) int graphdriver; int graphmode; detectgraph(&graphdriver,&graphmode); initgraph(&graphdriver,&graphmode,c:tc201ebgi); 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;i51;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,the output (response); outtextxy(ytext2x,ytext2y,u(t)/v);main() float kp,ti,td,tf,e3=0,ee3=0,u6=0,au1=0; int r=1,k=1; initial_sys(); drawaxis(); while(k100) u0=lxpid(1,3.0,10,e,u1); e0=r; /*printf(%fn,u0);*/ u3=sjpid(1,5,3.0,10,ee,au1,u4); setcolor(5); line(k-1)*10,130-u1*100,k*10,130-u1*100); line(k*10,130-u1*100,k*10,130-u0*100); delay(10000); u2=u1; u1=u0; e2=e1; e1=e0; ee0=r; setcolor(3); line(k-1)*10,150-u4*100,k*10,150-u4*100); line(k*10,150-u4*100,k*10,150-u3*100); delay(10000); u5=u4; u4=u3; ee2=ee1; ee1=ee0; au1=u4-u5; k+;/*-头文件定义-*/#include stdio.h#include math.h#include graphics.h/*for graph driver installing,only can be called in turbo c*/#include string.h#include dos.h#include bios.h#include conio.h/*for interrupt program 头文件定义* /#include stdlib.h#include io.h/*-按键地址区定义-*/*statements*/double key_esc=0x011b;/*define can not suit the length of bioskey 键盘内存定义*/double key_e=0x1265;double key_a=0x1e61;double key_h=0x2368;double key_u=0x1675;double key_d=0x2064;double key_i=0x1769;double key_p=0x1970;double key_up=0x4800;double key_down=0x5000;double key_left=0x4b00;double key_right=0x4d00;double key_pgup=0x4900;double key_pgdown=0x5100;/*-plcd780基址定义-*/#define base 0x220/*-pcl812g need 16 addresses in a row,from 220h to 3f0h*/#define reg 0/*-定义绘图坐标-*/#define ox 40/*-原点横坐标-*/#define oy 440 /*-原点纵坐标-*/#define xx 600/*-x轴顶点横坐标-*/#define xy 440/*-x轴顶点纵坐标-*/#define yx 40/*-y轴顶点横坐标-*/#define yy 40/*-y轴顶点纵坐标-*/*-pid参数定义-*/float kp=1.0;float ti=10.0;float td=3.0;float tf0=15.0;float tf=0; float t=0.1; /*-采样时间-*/float ad,e,pv0;float u=0.0;float pv=0.0;float sp=0.0;char a_h=h;char manu;int key=0;int time_counter=0;/*times of interrupt中断的次数*/int cj_counter=0;/*sampling counter采样次数*/int q_counter=800;/* 采集步长 赋初始值*/int stepdata800;int slopedata800;int error800;/*-函数声明 -*/void interrupt (*fadd1c)(void); /*中断函数声明*/void loop(); /*定值采样输出程序声明*/float ad(unsigned char channal);/*a/d*/void da(float pv1);/*d/a*/void interrupt int_1c(void);/*8259,reset interrupt controller*/int scankey();float delayaction(float y0); /*延迟*/void pidset(void);/*pid设置声明*/float pid(float sp1,float pv1,float kp1,float ti1,float td1,float tf1,char a_h1,float t1);/*pid计算声明*/float object(float u1,float t1); /*二阶惯性环节声明*/void initial_sys(void);/*initiate graph display*/void axis(void);void drawline(int cj,float pv1,float sp1,float u1,float e1);/*主函数*/void main(void)int i;for(i=0;i500;i+)stepdatai=10;slopedatai=i;errori=0; /* set new int_1c and save old */disable(); /*屏蔽中断*/fadd1c=getvect(0x1c);/*1c为定时器控制的软中断,平均一秒发生18.2次,即周期为55ms 中断程序,getvect用于取得中断向量入口*/* 开启中断服务*/setvect(0x1c,int_1c);/*设置中断矢量入口*/enable();axis(); /*画坐标轴*/loop(); /*定时采值输出程序*/*主函数结束 下面为定时采值输出程序*/void loop() doif(cj_counter*t)0)printf(parallal,mode:%c,sp=%.1f,pv=%2.1f,u=%.1f,error=%.1f,kp=%.1f,ti=%.1f,td=%.1ftr,a_h,sp,pv,u,e,kp,ti,td);else printf(tttf got a wrong value! please exit and restart this program.r);cj_counter+;while(cj_counter500);disable();/* 恢复中断*/setvect(0x1c,fadd1c);enable();/*d/a conversion program,0 to 4095 - 0to +5*/float ad(unsigned char channal)float result=0;int i;unsigned char hb=0,lb=0,ok=0x10;/*12bit ad/high 4 bits and low 8 bits*/outportb(base+11,reg);/*软件程序触发*/delay(10); /*here,delay(int ms) is used long before,and we just need some time for hardware working*/outportb(base+10,channal);/*进行通道设置.选择通道0*/delay(10);outportb(base+9,1); /*设置增益通道增益*/delay(10);outportb(base+12,0);/*触发a/d转换*/delay(10); dook=inportb(base+5);while(ok&0x10);hb=inportb(base+5);delay(10);lb=inportb(base+4);result = lb + (hb&0x0f)5) /* make the output real */ pv1=5; else if (pv10) pv1=0; temp=(int)(4095*pv1/5.0); hb=temp8; lb=temp-(hb8); outportb(base,1); delay(10); outportb(base+4,lb); /* low 8 */ delay(10); outportb(base+5,hb); /* high 4 */void interrupt int_1c(void)time_counter+;outportb(0x20,0x20); /*键盘控制*/int scankey(void)int key0;key0=bioskey(1);/* function 1 returns 0 until a key is pressed */if(key0!=0)key0=bioskey(0);/* function 0 returns the key that is waiting */return key0;/*delayaction*/*tao=(int)(18.2*2) delay action=2 seconds*/float delayaction(float y0)float y_out;static float y_old36=0;int cyc;y_out=y_old36-1;for(cyc=1;cyc36;cyc+)y_old36-cyc=y_old36-cyc-1;y_old0=y0;return y_out;/*pid 主程序*/void pidset(void)key=scankey();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)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)tf=0;if(key=key_p)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;static float e1,e2,u1,delta_u1;/*here,u1 stands for the previous value of u*/if(kp10)printf(kp becomes a negative number,please restart.);else if(ti10) printf(ti becomes a negative number,please press restart.);else if(td10) printf(td becomes a negative number,please press restart.);elsec1=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;/*here,delta_u1 stands for the previous value of delta_u*/u0=u1+delta_u; e2=e1;e1=e;delta_u1=delta_u;u1=u0;errorcj_counter=sp1-pv1;return u0;/*手动控制*/else if(a_h1=h)if(manu=+)u+=10;if(manu=-)u-=10;sp1=pv1;u1=u;sp=pv1;e1=0;e2=0;delta_u1=0;errorcj_counter=sp1-pv1;return u;/*object:二阶惯性环节*/float object(float u1,float t1)/*g(s)=1/(4.7s+1)2,k=1,tp1=tp2=4.7*/static float y1,y2;float y;y=1/(31.49+t1)*(-22.09*y2+53.58*y1+t1*u1);y2=y1;y1=y;return y;/*显示与画图*/*初始化 crt*/void initial_sys(void)int graphdriver; int graphmode; detectgraph(&graphdriver,&graphmode); initgraph(&graphdriver,&graphmode,c:tc201ebgi);/*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;i4;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

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论