日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

一个标准的PID算法

發布時間:2025/6/15 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个标准的PID算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個標準的PID算法

#include<reg51.h> #include<intrins.h> #include<math.h> #include<string.h> struct PID {unsigned int SetPoint; // 設定目標 Desired Valueunsigned int Proportion; // 比例常數 Proportional Constunsigned int Integral; // 積分常數 Integral Constunsigned int Derivative; // 微分常數 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;//占空比調節參數 unsigned char set_temper=35; unsigned char temper; unsigned char i; unsigned char j=0; unsigned int s;/***********************************************************延時子程序,延時時間以12M晶振為準,延時時間為30us×time***********************************************************/ void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/***********************************************************寫一位數據子程序***********************************************************/ void write_bit(unsigned char bitval) {EA=0;DQ=0; /*拉低DQ以開始一個寫時序*/if(bitval==1){_nop_();DQ=1; /*如要寫1,則將總線置高*/}delay(5); /*延時90us供DA18B20采樣*/DQ=1; /*釋放DQ總線*/_nop_();_nop_();EA=1; }/***********************************************************寫一字節數據子程序***********************************************************/ void write_byte(unsigned char val) {unsigned char i;unsigned char temp;EA=0;TR0=0;for(i=0;i<8;i++) /*寫一字節數據,一次寫一位*/{temp=val>>i; /*移位操作,將本次要寫的位移到最低位*/temp=temp&1;write_bit(temp); /*向總線寫該位*/}delay(7); /*延時120us后*/// TR0=1;EA=1; }/***********************************************************讀一位數據子程序***********************************************************/ unsigned char read_bit() {unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,開始讀時序*/_nop_();_nop_();DQ=1; /*釋放總線*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit); }/***********************************************************讀一字節數據子程序***********************************************************/ unsigned char read_byte() {unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*讀一字節數據,一個時序中讀一次,并作移位處理*/value|=0x01<<i;delay(4); /*延時80us以完成此次都時序,之后再讀下一數據*/}EA=1;return(value); }/***********************************************************復位子程序***********************************************************/ unsigned char reset() {unsigned char presence;EA=0;DQ=0; /*拉低DQ總線開始復位*/delay(30); /*保持低電平480us*/DQ=1; /*釋放總線*/delay(3);presence=DQ; /*獲取應答信號*/delay(28); /*延時以完成整個時序*/EA=1;return(presence); /*返回應答信號,有芯片應答返回0,無芯片則返回1*/ }/***********************************************************獲取溫度子程序***********************************************************/ void get_temper() {unsigned char i,j;do{i=reset(); /*復位*/} while(i!=0); /*1為無反饋信號*/i=0xcc; /*發送設備定位命令*/write_byte(i);i=0x44; /*發送開始轉換命令*/write_byte(i);delay(180); /*延時*/do{i=reset(); /*復位*/} while(i!=0);i=0xcc; /*設備定位*/write_byte(i);i=0xbe; /*讀出緩沖區內容*/write_byte(i);j=read_byte(); i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f); //得到小數部分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計算部分=====================================================================================================*/ 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; // 當前微分 pp->PrevError = pp->LastError; pp->LastError = Error; return (pp->Proportion * Error // 比例項 + pp->Integral * pp->SumError // 積分項+ pp->Derivative * dError); // 微分項 }/***********************************************************溫度比較處理子程序***********************************************************/ void compare_temper() {unsigned char i;if(set_temper>temper) //是否設置的溫度大于實際溫度{if(set_temper-temper>1) //設置的溫度比實際的溫度是否是大于1度{high_time=100; //如果是,則全速加熱low_time=0;}else //如果是在1度范圍內,則運行PID計算{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中斷服務子程序,用于控制電平的翻轉 ,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; }/*****************************************************串行口中斷服務程序,用于上位機通訊******************************************************/ 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_();}} }/*****************************************************顯示子程序功能:將占空比溫度轉化為單個字符,顯示占空比和測得到的溫度******************************************************/ 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 比例常數 Proportional Constspid.Integral = 8; //積分常數 Integral Constspid.Derivative =6; //微分常數 Derivative Constspid.SetPoint = 100; // Set PID Setpoint 設定目標 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; } }

總結

以上是生活随笔為你收集整理的一个标准的PID算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。