计算机控制课设串级回路,华北电力大学过程计算机控制课设ddc串级回路pid闭环.docx...

a7f4a3f590493a1e451dd952a488fd7c.gif 华北电力大学过程计算机控制课设ddc串级回路pid闭环.docx

(26页)

96326a535f60d93c67d74e554abc2339.gif

本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!

9.90 积分

课程设计报告名称:过程计算机控制题目: 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.0集成开发环境软件;(2)模拟计算机一台(XMN-1型);(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闭环控制系统,为通信做好准备。五、实验结果(1)理想和实际PID阶跃响应曲线(2)被控对象(实物搭建二阶惯性环节)阶跃响应曲线上图通过D/A输出一个1伏左右的信号输入模拟的被控对象(惯性环节),A/D采集对象的输入信号及其响应,再使D/A输出一个幅度为2伏左右的阶跃信号,同时采集输入输出信号。然后,D/A再反向在输出一个幅度为2伏左右负的阶跃信号,同时采集输入输出信号,得出仿真对象飞升特性曲线。程序中,通过按键实现模拟对象输入信号的加减。当按下H按键时,且按下U键时,D/A输出一个1伏阶跃信号,再次按下按键时阶跃信号累加。每次按下D键时,D/A输出的阶跃信号递减1。(3)根据对象单位阶跃响应曲线求增益和惯性时间:利用切线法求对象的增益和用一阶等效的惯性时间:如上图所示做拐点切线,得对象增益和一阶等效惯性时间分别为: Ti≈13s(4)手自动切换:(5)设定值r、控制量u和被控对象输出的阶跃响应曲线:程序清单 /*---------------头文件定义---------------*/      #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 450       #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 e[3],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*e[0]+q1*e[1]+q2*e[2]+u1;       return u;  }/*-------------------------实际PID运算式--------------------------*/ float 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]=ee[0];            au1=u[4]-u[5];            k++; } }/*---------------头文件定义---------------*/ #include "stdio.h"  #include "math.h" #include "graphics.h"  #include "string.h" #include "dos.h" #include "bios.h" #include "conio.h"    /*中断程序头文件定义*/#include "stdlib.h" #include "io.h"/*--------------按键地址区定义--------------------*/ /*statements*/ double key_ESC=0x011b;   /*退出*/double key_E=0x1265;  double key_A=0x1e61;  /*自动*/double key_H=0x2368;  /*手动*/double key_U=0x1675;  /*自动时增SP,手动时增手操器输出*/double key_D=0x2064;  /*自动时减SP,手动时增手操器输出*/double key_I=0x1769;  /*理想PID*/double key_P=0x1970; /*实际PID*/ double key_up=0x4800;  /*手动时,增Kp*/double key_down=0x5000;  /*手动时,减Kp*/double key_left=0x4b00; /*手动时,减Ti*/ double key_right=0x4d00;  /*手动时,增Ti*/double key_pgup=0x4900; /*手动时,增Td*/ double key_pgdown=0x5100; /*手动时,减Td*//*--------------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; /*用于调节u_m的增减*/  int key=0; /*存键盘扫描结果*/ int time_counter=0;   /*中断计数*/ int cj_counter=0;   /*采样计数器*/ int Q_counter=800;  /* 采集步长   赋初始值*/ int stepdata[800]; int slopedata[800]; int error[800];/*--------------函数声明 -----------------*/ 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); float Object(float u1,float T1);   /*仿真对象*/void Initial_Sys(void);     /*初始化为图形模式*/void axis(void);  /*画坐标轴*/void Drawline(int cj,float pv1,float sp1,float u1,float e1); /*画线*//*主函数*/ void main(void){int i;  for(i=0;i<500;i++) { stepdata[i]=10; slopedata[i]=i; error[i]=0;} /* Set new INT_1C  and save old   */   disable();  /*保存旧中断,设置新中断*/fadd1C=getvect(0x1C);/*1C为定时器控制的软中断,平均一秒发生18.2次,即周期为55ms    中断程序*/  /* 开启中断服务*/  setvect(0x1C,INT_1C);  enable();  axis();  loop(); } /*主函数结束  下面为定时采值输出程序*/void loop() { do  {   if((cj_counter*T)0) printf("Parallal,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);    else printf("\t\tTf got a wrong value! Please exit and restart this program.\r");cj_counter++; }  }while(cj_counter<500);  /* 恢复中断*/  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,poll=0x10; outportb(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)<<8);  /*0 to 4095*/  result=result*5/4096;  /*0 V to +5V*/  return result; }   /*A/D conversion program,0 to +5 -- 0 to 4095*/ void DA(float pv1) {     int temp,i;     unsigned char hb,lb;  /*限幅 */if (pv1>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 关 键 词: 华北 电力大学 过程 进程 计算机控制 ddc 回路 pid 闭环

4d91c43bfc72ca913299809b07b4968f.gif  天天文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。

关于本文

本文标题:华北电力大学过程计算机控制课设ddc串级回路pid闭环.docx

链接地址: https://www.wenku365.com/p-32738997.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值