PID是比例,積分,微分的縮寫. 比例調(diào)節(jié)作用:是按比例反應系統(tǒng)的偏差,系統(tǒng)一旦出現(xiàn)了偏差,比例調(diào)節(jié)立即產(chǎn)生調(diào)節(jié)作用用以減少偏差。比例作用大,可以加快調(diào)節(jié),減少誤差,但是過大的比例,使系統(tǒng)的穩(wěn)定性下降,甚至造成系統(tǒng)的不穩(wěn)定。積分調(diào)節(jié)作用:是使系統(tǒng)消除穩(wěn)態(tài)誤差,提高無差度。因為有誤差,積分調(diào)節(jié)就進行,直至無差,積分調(diào)節(jié)停止,積分調(diào)節(jié)輸出一常值。積分作用的強弱取決與積分時間常數(shù)Ti,Ti越小,積分作用就越強。反之Ti大則積分作用弱,加入積分調(diào)節(jié)可使系統(tǒng)穩(wěn)定性下降,動態(tài)響應變慢。積分作用常與另兩種調(diào)節(jié)規(guī)律結合,組成PI調(diào)節(jié)器或PID調(diào)節(jié)器。微分調(diào)節(jié)作用:微分作用反映系統(tǒng)偏差信號的變化率,具有預見性,能預見偏差變化的趨勢,因此能產(chǎn)生超前的控制作用,在偏差還沒有形成之前,已被微分調(diào)節(jié)作用消除。因此,可以改善系統(tǒng)的動態(tài)性能。在微分時間選擇合適情況下,可以減少超調(diào),減少調(diào)節(jié)時間。微分作用對噪聲干擾有放大作用,因此過強的加微分調(diào)節(jié),對系統(tǒng)抗干擾不利。此外,微分反應的是變化率,而當輸入沒有變化時,微分作用輸出為零。微分作用不能單獨使用,需要與另外兩種調(diào)節(jié)規(guī)律相結合,組成PD或PID控制器。
程序如下: - /***********************************************************************
- PID溫度控制程序
- 程序說明:
- 系統(tǒng)上電后顯示 “--溫度”
- 表示需要先設定溫度才開始進行溫度檢測
- 溫度設定完畢后程序才開始進行PID溫控
- ***********************************************************************/
- #include <reg52.h>
- #include <absacc.h>
- #include"DS18B20.H"
- #include"PID.H"
- #define uchar unsigned char
- #define uint unsigned int
- unsigned char code tab[]=
- {
- 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xBF
- }
- ;
- /*個位0~9的數(shù)碼管段碼*/
- unsigned char code sao[]=
- {
- 0x7f,0xbf,0xdf,0xef
- }
- ;
- //掃描碼
- uchar set=30,keyflag=1 ; //set初始化為30° keyflag為進入溫度設定的標志位
- //4個按鍵使用說明
- sbit key_out=P1^0 ; //用于溫度設定后的退出
- sbit key_up=P1^1 ; //設定溫度加
- sbit key_down=P1^2 ; //設定溫度減
- sbit key_in=P1^3 ; //在程序的運行中如需要重新設定溫度 按下此鍵才能進入設置模式并且此時是停在溫度控制的,按下key_out鍵后才表示設定完畢
- void Show_key();
- /***********************************************************/
- void delays(unsigned char k)
- {
- unsigned char i,j ;
- for(i=0;i<k;i++)
- for(j=0;j<50;j++);
- }
- /*********************************************************
- //數(shù)碼管顯示函數(shù)
- P0口 作為數(shù)據(jù)口
- P2口的低四位作為掃描口
- 變量 x表示掃描
- d表示是否要加小數(shù)點 為1是 為0不加
- y表示傳遞的數(shù)值
- *********************************************************/
- LCD_disp_char(uchar x,bit d,uchar y)
- {
- P2=0XFF ;
- P0=0xFF ;
- if(d==0)
- P0=tab[y];
- else
- P0=tab[y]&0x7f ; //與上0x7f表示是否要加小數(shù)點
- P2=sao[x]; //打開掃描端號
-
- }
- /*********************************************************
- 按鍵掃描
- *********************************************************/
- void keyscan(void)
- {
- if(key_in==0) //按鍵進入函數(shù)
- {
- delays(10); //延時消抖 (以下同)
- if(key_in==0)
- {
- while(key_in==0)
- {
- Show_key(); //如果一直按著鍵不放 就一直顯示在當前狀態(tài) (以下同)
- }
- keyflag=1 ; //按鍵標志位
- }
- }
- /***********************/
- if(key_out==0) //按鍵退出
- {
- delays(10);
- if(key_out==0)
- {
- while(key_out==0)
- {
- Show_key();
- }
- keyflag=0 ;
- set_temper=set ;
- }
- }
- /*************************/
- if(key_up==0) //設定溫度的加
- {
- delays(10);
- if(key_up==0)
- {
- while(key_up==0)
- {
- Show_key();
- }
- if(keyflag==1)
- {
- set++;
- if(set>90) //如果大于90°就不在加
- set=90 ;
- }
- }
- }
- /*************************/
- if(key_down==0) //溫度設定的減
- {
- delays(10);
- if(key_down==0)
- {
- while(key_down==0)
- {
- Show_key();
- }
- if(keyflag==1)
- {
- set--;
- if(set<30) //溫度減到30°時不在往下減
- set=30 ;
- }
- }
- }
- }
- /*********************************************************************
- 按鍵按下時的顯示函數(shù)
- ***********************************************************************/
- void Show_key()
- {
- output=1 ;
- LCD_disp_char(3,0,10); //顯示 -
- delays(3);
- LCD_disp_char(2,0,10); //顯示- (表示溫度設定 )
- delays(3);
- LCD_disp_char(1,0,set/10); //顯示溫度十位
- delays(3);
- LCD_disp_char(0,0,set%10); //顯示溫度個位
- delays(3);
- }
- /*****************************************************************/
- void main()
- {
- unsigned int tmp ;//聲明溫度中間變量
- unsigned char counter=0 ;
- PIDBEGIN(); //PID參數(shù)的初始化
- output=1 ; //關閉繼電器輸出
- while(1)
- {
- keyscan();
- if(keyflag)
- {
- Show_key(); //顯示溫度設定
- }
- else
- {
- if(counter--==0)
- {
- tmp=ReadTemperature();//每隔一段時間讀取溫度值
- counter=20 ;
- }
- LCD_disp_char(3,0,tmp/1000); //顯示溫度十位
- delays(3);
- LCD_disp_char(2,1,tmp/100%10); //顯示溫度個位
- //顯示小數(shù)點
- delays(3);
- LCD_disp_char(1,0,tmp/10%10); //顯示溫度小數(shù)后一位
- delays(3);
- LCD_disp_char(0,0,tmp%10);//顯示溫度小數(shù)后二位
- delays(3);
- P2=0XFF ;
- P0=0xff ;
- compare_temper(); //比較溫度
-
-
- }
- }
- }
- /**********************************************************************************************************************************************/
- //PID算法溫控C語言2008-08-17 18:58
- #ifndef _PID_H__
- #define _PID_H__
- #include<intrins.h>
- #include<math.h>
- #include<string.h>
- struct PID
- {
- unsigned int SetPoint ;
- // 設定目標 Desired Value
- unsigned int Proportion ;
- // 比例常數(shù) Proportional Const
- unsigned int Integral ;
- // 積分常數(shù) Integral Const
- unsigned int Derivative ;
- // 微分常數(shù) Derivative Const
- unsigned 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 output=P1^4;
- unsigned char high_time,low_time,count=0 ;
- //占空比調(diào)節(jié)參數(shù)
- unsigned char set_temper ;
- void PIDInit(struct PID*pp)
- {
- memset(pp,0,sizeof(struct PID)); //PID參數(shù)初始化全部設置為0
- }
- 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 ;
- //EA=0;
- if(set_temper>temper)
- {
- if(set_temper-temper>1)
- {
- high_time=100 ; //大于1°不進行PID運算
- low_time=0 ;
- }
- else
- { //在1°范圍內(nèi)進行PID運算
- for(i=0;i<10;i++)
- {
- //get_temper();
- rin=s;
- // Read Input
- rout=PIDCalc(&spid,rin); //執(zhí)行PID運算
- // Perform PID Interation
- }
- if(high_time<=100) //限制最大值
- high_time=(unsigned char)(rout/800);
- else
- high_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 Input
- rout=PIDCalc(&spid,rin);
- // Perform PID Interation
- }
- if(high_time<100) //此變量是無符號字符型
- high_time=(unsigned char)(rout/10000);
- else
- high_time=0 ;//限制不輸出負值
- low_time=(100-high_time);
- //EA=1;
- }
- }
- }
- /*****************************************************
- T0中斷服務子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期
- ******************************************************/
- void serve_T0()interrupt 1 using 1
- {
- if(++count<=(high_time))
- output=0 ;
- else if(count<=100)
- {
- output=1 ;
- }
- else
- count=0 ;
- TH0=0x2f ;
- TL0=0xe0 ;
- }
- void PIDBEGIN()
- {
-
- TMOD=0x01 ;
- TH0=0x2f ;
- TL0=0x40 ;
-
- EA=1 ;
- ET0=1 ;
- TR0=1 ;
-
- high_time=50 ;
- low_time=50 ;
- PIDInit(&spid);
- // Initialize Structure
- spid.Proportion=10 ;
- // Set PID Coefficients
- spid.Integral=8 ;
- spid.Derivative=6 ;
- spid.SetPoint=100 ;
- // Set PID Setpoint
-
- }
- #endif
復制代碼
|