一个标准的PID算法
生活随笔
收集整理的這篇文章主要介紹了
一个标准的PID算法
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一個(gè)標(biāo)準(zhǔn)的PID算法
#include<reg51.h> #include<intrins.h> #include<math.h> #include<string.h> struct PID {unsigned int SetPoint; // 設(shè)定目標(biāo) Desired Valueunsigned int Proportion; // 比例常數(shù) Proportional Constunsigned int Integral; // 積分常數(shù) Integral Constunsigned int Derivative; // 微分常數(shù) Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors}; struct PID spid; // PID Control Structure unsigned int rout; // PID Response (Output) unsigned int rin; // PID Feedback (Input) sbit data1=P1^0; sbit clk=P1^1; sbit plus=P2^0; sbit subs=P2^1; sbit stop=P2^2; sbit output=P3^4; sbit DQ=P3^3; unsigned char flag,flag_1=0; unsigned char high_time,low_time,count=0;//占空比調(diào)節(jié)參數(shù) unsigned char set_temper=35; unsigned char temper; unsigned char i; unsigned char j=0; unsigned int s;/***********************************************************延時(shí)子程序,延時(shí)時(shí)間以12M晶振為準(zhǔn),延時(shí)時(shí)間為30us×time***********************************************************/ void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/***********************************************************寫一位數(shù)據(jù)子程序***********************************************************/ void write_bit(unsigned char bitval) {EA=0;DQ=0; /*拉低DQ以開始一個(gè)寫時(shí)序*/if(bitval==1){_nop_();DQ=1; /*如要寫1,則將總線置高*/}delay(5); /*延時(shí)90us供DA18B20采樣*/DQ=1; /*釋放DQ總線*/_nop_();_nop_();EA=1; }/***********************************************************寫一字節(jié)數(shù)據(jù)子程序***********************************************************/ void write_byte(unsigned char val) {unsigned char i;unsigned char temp;EA=0;TR0=0;for(i=0;i<8;i++) /*寫一字節(jié)數(shù)據(jù),一次寫一位*/{temp=val>>i; /*移位操作,將本次要寫的位移到最低位*/temp=temp&1;write_bit(temp); /*向總線寫該位*/}delay(7); /*延時(shí)120us后*/// TR0=1;EA=1; }/***********************************************************讀一位數(shù)據(jù)子程序***********************************************************/ unsigned char read_bit() {unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,開始讀時(shí)序*/_nop_();_nop_();DQ=1; /*釋放總線*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit); }/***********************************************************讀一字節(jié)數(shù)據(jù)子程序***********************************************************/ unsigned char read_byte() {unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*讀一字節(jié)數(shù)據(jù),一個(gè)時(shí)序中讀一次,并作移位處理*/value|=0x01<<i;delay(4); /*延時(shí)80us以完成此次都時(shí)序,之后再讀下一數(shù)據(jù)*/}EA=1;return(value); }/***********************************************************復(fù)位子程序***********************************************************/ unsigned char reset() {unsigned char presence;EA=0;DQ=0; /*拉低DQ總線開始復(fù)位*/delay(30); /*保持低電平480us*/DQ=1; /*釋放總線*/delay(3);presence=DQ; /*獲取應(yīng)答信號(hào)*/delay(28); /*延時(shí)以完成整個(gè)時(shí)序*/EA=1;return(presence); /*返回應(yīng)答信號(hào),有芯片應(yīng)答返回0,無芯片則返回1*/ }/***********************************************************獲取溫度子程序***********************************************************/ void get_temper() {unsigned char i,j;do{i=reset(); /*復(fù)位*/} while(i!=0); /*1為無反饋信號(hào)*/i=0xcc; /*發(fā)送設(shè)備定位命令*/write_byte(i);i=0x44; /*發(fā)送開始轉(zhuǎn)換命令*/write_byte(i);delay(180); /*延時(shí)*/do{i=reset(); /*復(fù)位*/} while(i!=0);i=0xcc; /*設(shè)備定位*/write_byte(i);i=0xbe; /*讀出緩沖區(qū)內(nèi)容*/write_byte(i);j=read_byte(); i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f); //得到小數(shù)部分s=(s*100)/16;j=j>>4;temper=i|j; /*獲取的溫度放在temper中*/}/*====================================================================================================Initialize PID Structure=====================================================================================================*/ void PIDInit (struct PID *pp) {memset ( pp,0,sizeof(struct PID)); //全部初始化為0 }/*====================================================================================================PID計(jì)算部分=====================================================================================================*/ unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) {unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差 pp->SumError += Error; // 積分 dError = pp->LastError - pp->PrevError; // 當(dāng)前微分 pp->PrevError = pp->LastError; pp->LastError = Error; return (pp->Proportion * Error // 比例項(xiàng) + pp->Integral * pp->SumError // 積分項(xiàng)+ pp->Derivative * dError); // 微分項(xiàng) }/***********************************************************溫度比較處理子程序***********************************************************/ void compare_temper() {unsigned char i;if(set_temper>temper) //是否設(shè)置的溫度大于實(shí)際溫度{if(set_temper-temper>1) //設(shè)置的溫度比實(shí)際的溫度是否是大于1度{high_time=100; //如果是,則全速加熱low_time=0;}else //如果是在1度范圍內(nèi),則運(yùn)行PID計(jì)算{for(i=0;i<10;i++){get_temper(); //獲取溫度rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {} }/*****************************************************T0中斷服務(wù)子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期******************************************************/ void serve_T0() interrupt 1 using 1 {if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;TL0=0xe0; }/*****************************************************串行口中斷服務(wù)程序,用于上位機(jī)通訊******************************************************/ void serve_sio() interrupt 4 using 2 {/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */ } void disp_1(unsigned char disp_num1[6]) {unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;elsedata1=0;_nop_();clk=1;_nop_();}} }/*****************************************************顯示子程序功能:將占空比溫度轉(zhuǎn)化為單個(gè)字符,顯示占空比和測(cè)得到的溫度******************************************************/ void display() {unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num); }/***********************************************************主程序***********************************************************/ void main() {unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TH0=0x2f;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structurespid.Proportion = 10; // Set PID Coefficients 比例常數(shù) Proportional Constspid.Integral = 8; //積分常數(shù) Integral Constspid.Derivative =6; //微分常數(shù) Derivative Constspid.SetPoint = 100; // Set PID Setpoint 設(shè)定目標(biāo) Desired Valuewhile(1) {if(plus==0) {EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){}if(plus==0){set_temper++;flag=0;} }else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){}if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5)temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30){display();count1=0;}compare_temper();}TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){}if(stop==0)disp_1(phil);// break;}EA=1; } }
總結(jié)
以上是生活随笔為你收集整理的一个标准的PID算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四轴飞行器1.1 Matlab 姿态显示
- 下一篇: 四轴飞行器1.4 姿态解算和Matlab