计算机控制课设串级回路,华北电力大学过程计算机控制课设DDC串级回路PID闭环.doc...

本文介绍了PID控制器的基本原理及其在实际应用中的两种实现方式,包括理想PID和实际PID。通过C++代码展示了如何使用图形化界面实时展示系统响应与控制信号的变化。涵盖了A/D转换、D/A转换、键盘控制和PID参数调整等内容。
摘要由CSDN通过智能技术生成

#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运算式--------------------------*/

floatsjpid(floatkp,floattf,floattd,floatti,floate[3],floatdu1,floatu1)

{

intt=1;

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++) /*-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,"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;

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*/

doublekey_ESC=0x011b; /*退出*/

doublekey_E=0x1265;

doublekey_A=0x1e61; /*自动*/

doublekey_H=0x2368; /*手动*/

doublekey_U=0x1675; /*自动时增SP,手动时增手操器输出*/

doublekey_D=0x2064; /*自动时减SP,手动时增手操器输出*/

doublekey_I=0x1769; /*理想PID*/

doublekey_P=0x1970; /*实际PID*/

doublekey_up=0x4800; /*手动时,增Kp*/

doublekey_down=0x5000; /*手动时,减Kp*/

doublekey_left=0x4b00; /*手动时,减Ti*/

doublekey_right=0x4d00; /*手动时,增Ti*/

doublekey_pgup=0x4900; /*手动时,增Td*/

doublekey_pgdown=0x5100; /*手动时,减Td*/

/*--------------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; /*用于调节u_m的增减*/

intkey=0; /*存键盘扫描结果*/

inttime_counter=0; /*中断计数*/

intcj_counter=0;/*采样计数器*/

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);

floatObject(floatu1,floatT1); /*仿真对象*/

voidInitial_Sys(void);/*初始化为图形模式*/

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中断程序*/

/*开启中断服务*/

setvect(0x1C,INT_1C);

enable();

axis();

loop();

}

/*主函数结束下面为定时采值输出程序*/

voidloop()

{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);

elseprintf("\t\tTfgotawrongvalue!Pleaseexitandrestartthisprogram.\r");

cj_counter++;

}

}while(cj_counter<500);

/*恢复中断*/

disable();

setvect(0x1C,fadd1C);

enable();

}

/*D/Aconversionprogram,0to4095--0to+5*/

floatAD(unsignedcharchannal)

{

floatresult=0;

inti;

unsignedcharhb=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);/*0to4095*/

result=result*5/4096;/*0Vto+5V*/

returnresult;

}

/*A/Dconversionprogram,0to+5--0to4095*/

voidDA(floatpv1){

inttemp,i;

unsignedcharhb,lb; /*限幅 */

if(pv1>5)/*maketheoutputreal*/

pv1=5;

elseif(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);/*low8*/

for(i=0;i<10000;i++);

outportb(BASE+5,hb);/*high4*/

}

/*00----------------------------中断子程序-------------------------*/

voidinterruptINT_1C(void)

{time_counter++;

outportb(0x20,0x20);

}

/*键盘控制*/

intscankey(void)

{

intkey0; /*扫描键盘,判断是否有建按下*/

key0=bioskey(1);/*1:无键按下则返回0*/

if(key0!=0)

key0=bioskey(0);/*0:返回按下的键*/

returnkey0;

}

/*DelayAction*/

/*tao=(int)(18.2*2)Delayaction=2seconds*/

floatDelayAction(floaty0) /*软件延迟*/

{

floaty_out;

staticfloaty_old[36]={0};/*将ad延迟2s作为PV,T=0.2s,于是延迟36步*/

intcyc;

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;

returny_out;

}

/*PID主程序*/

voidPIDset(void) /*PID设置*/

{

key=scankey(); /*扫描键盘,并将按键存为key*/

if(A_H==H)/*手动状态*/

{if(key==key_up)

Kp+=0.2;

elseif(key==key_down)

Kp-=0.2;

elseif(key==key_left)

Ti-=0.2;

elseif(key==key_right)

Ti+=0.2;

elseif(key==key_pgup)

Td+=0.2;

elseif(key==key_pgdown)

Td-=0.2;

elseif(key==key_U)/*控制u_m增减*/

manu=+;

elseif(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*/

floatPID(floatsp1,floatpv1,floatKp1,floatTi1,floatTd1,floatTf1,charA_H1,floatT1){

floatdelta_u,u0,e,C1,C2,C3,C4; /*离散化后PID参数 当前时刻,u0为返回值*/

staticfloate1,e2,u1,delta_u1;/*前一时刻的值*/

if(Kp1<0)

printf("Kpbecomesanegativenumber,pleaserestart.");

elseif(Ti1<0) printf("Tibecomesanegativenumber,pleasepressrestart.");

elseif(Td1<0) printf("Tdbecomesanegativenumber,pleasepressrestart.");

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;

returnu0;

}

/*手动控制*/

elseif(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;

returnu;

}

}

}

/*显示与画图*/

/*初始化CRT*/

voidInitial_Sys(void){

intGraphDriver;

intGraphMode;

detectgraph(&GraphDriver,&GraphMode);

initgraph(&GraphDriver,&GraphMode,"C:\\TC201E\\BGI");}

/*drawbasiccoordinateaxis*/

voidaxis(void)

{

inti;

Initial_Sys();

setbkcolor(15);/*white0/black15*/

setcolor(9);/*linghtblue*/

rectangle(10,20,630,470);/*zoneofdrawing*/

line(ox,oy,xx,xy);/*axisandarrow*/

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);/*Smallfont,vert,5timesbigger*/

outtextxy(20,100,"TheOutput(Response)");

outtextxy(20,40,"U(t)");

settextstyle(2,0,5);/*Smallfont,horiz,5timesbigger*/

outtextxy(300,455,"Time");outtextxy(590,455,"t/sec");

setlinestyle(1,0,1);/*dotline,none,width*/

for(i=1;i<4;i++)/*eachinportstartingposition*/

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,thatis10px=1sec*/

line(ox+50*i-25,oy,ox+50*i-25,oy-10);

}

setlinestyle(0,0,1);/*realline,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-drawingandnotes*/

voidDrawline(intcj1,floatpv1,floatsp1,floatu1,floate1) /*画线*/

{staticintcj_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; /*Xcoordinate*/

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);/*darkgray*/

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值