溫度控制PID自整定原理介紹
整定PID(三模式)控制器
整定溫度控制器涉及設(shè)置比例、積分和微分值,以得到對特定過 程的可能的最佳控制。如果控制器不包含自動整定算法,或者自 動整定算法未提供適合特定應(yīng)用的足夠控制,則必須用試誤法對 裝置進行整定。
下面是溫度控制器的標準整定步驟。也可以采用其他整定步驟, 但都使用類似的試誤法。請注意,如果控制器使用機械式繼電器 (而非固態(tài)繼電器),開始時應(yīng)使用較長的循環(huán)時間(20秒)。
可能需要用到以下定義 :
循環(huán)時間 – 也稱為工作周期,是控制器完成一個通斷循環(huán)所 用的總時間長度。示例: 對于20秒的循環(huán)時間,10秒接通時 間和10秒切斷時間代表50%的功率輸出。在比例帶內(nèi)時,控 制器將循環(huán)接通和切斷。
比例帶 – 以滿量程的%或度表示的溫度范圍,控制器的比例 作用發(fā)生在此范圍內(nèi)。比例帶越寬,在其內(nèi)發(fā)生比例作用的 圍繞設(shè)定值的區(qū)域越大。有時也用增益表示,增益是比例帶 的倒數(shù)。
積分,又稱為復(fù)位,是根據(jù)設(shè)定值調(diào)節(jié)比例帶寬以補償偏離 設(shè)定值的偏移量(固定偏差)的一個函數(shù),也就是說,它在 系統(tǒng)穩(wěn)定后將控制的溫度調(diào)節(jié)到設(shè)定值。
微分,又稱為速率,感應(yīng)系統(tǒng)溫度上升或下降的速率,并自 動調(diào)節(jié)比例帶,從而將下沖或過沖降到最小。
PID(三模式)控制器如果正確整定和使用的話,能具有優(yōu)異的 控制穩(wěn)定性。通過認真遵守這些指示,操作人員便可實現(xiàn)最快的 響應(yīng)時間和最小的過沖。整定這種三模式控制器的信息可能不同 于其它控制器整定步驟。對于主輸出,通常用自整定功能就可省 去使用此手動整定步驟的需要,但是,需要時可對自整定值進 行調(diào)整。
A.整定加熱控制的輸出
啟用輸出并啟動過程。
過程應(yīng)在設(shè)定值處運行,將用所需熱量輸入讓溫度穩(wěn)定。
在速率和復(fù)位斷開的情況下,溫度將穩(wěn)定,并在設(shè)定值和實際 溫度之間存在穩(wěn)態(tài)偏差,或固定偏差。通過觀察顯示屏上的測 量值,密切注意此溫度是否存在規(guī)則的循環(huán)或振蕩。(振蕩可 長達30分鐘。)
4.如果溫度沒有規(guī)則的振蕩,將PB除以2(見圖1)。讓過程 穩(wěn)定下來,然后再檢查是否有溫度振蕩。如果仍無振蕩, 再將PB除以2。重復(fù)此操作,直到得到循環(huán)或振蕩。轉(zhuǎn)至 第5步。
5.如果馬上觀察到振蕩,將PB乘以2。觀察得到的溫度幾分 鐘。如果振蕩持續(xù),以系數(shù)2不斷乘PB,直到振蕩停止。
此時,PB非常接近其臨界設(shè)置。小心地增大或減小PB設(shè) 置,直到溫度記錄中剛剛出現(xiàn)循環(huán)或振蕩為止。
如果甚至在1%的最小PB設(shè)置時過程溫度仍不發(fā)生振蕩, 請?zhí)^下面的第6步到第11步,轉(zhuǎn)至第B條。
在已經(jīng)達到的“臨界”BP設(shè)置下,讀取設(shè)定值與實際溫度 之間的穩(wěn)態(tài)偏差,或固定偏差。(由于溫度有一點循環(huán), 請使用平均溫度。)
測量相鄰波峰或波谷之間的振蕩時間,以分為單位 (見圖2)。使用圖表記錄儀最容易進行這種測量,但可每 隔一分鐘讀取一次測量值,以掌握時間。
此時,增大PB設(shè)置,直到溫度偏差(或固定偏差)增大 65%。
用在“臨界”BP設(shè)置下得到的初始溫度偏差乘以1.65或者 使用方便的線列圖I(見圖4)就可計算出所需的最終溫度偏 差。用試誤法嘗試幾次PB控制的設(shè)置,直到得到所需的最終 溫度偏差。
此時您已經(jīng)完成了得到控制器最佳性能所需的所有測量。 只需再做兩項調(diào)整 – 速率和復(fù)位。
使用第7步中測得的振蕩時間,按以下方法計算復(fù)位值, 以每分鐘重復(fù)次數(shù)為單位。
將此值輸入給RESET 1。
再使用第7步中測得的振蕩時間,按以下方法計算速率的 值,以分為單位。
將此值輸入給RATE 1。
如果出現(xiàn)過沖,可通過減少復(fù)位時間來消除。當對復(fù)位值 進行了更改時,也應(yīng)對速率調(diào)整進行相應(yīng)的更改,使速率值 等于:
即:如果復(fù)位 = 2 R/M,則速率= 0.08分鐘
若想在對系統(tǒng)擾動的“響應(yīng)時間”和“設(shè)置時間”之間得到 正確的平衡,可能需要進行多次設(shè)定值更改和隨之發(fā)生的復(fù) 位和速率控制時間調(diào)整??焖夙憫?yīng)常常伴隨著較大的過沖, 過程“穩(wěn)定下來”所需的時間也較短。相反,如果響應(yīng)較 慢,過程趨向于慢慢滑行到最終值,過沖很小或者沒有過 沖。應(yīng)由系統(tǒng)的要求決定采取哪種動作。
當?shù)玫綕M意的整定時,應(yīng)增大循環(huán)時間以節(jié)省接觸器的壽命 (適用于只有時間比例輸出的裝置(TPRI))。在不造成測量 值因負載循環(huán)而振蕩的情況下,應(yīng)盡量增大循環(huán)時間。
轉(zhuǎn)至第C節(jié)。
B. 未觀察到振蕩時的整定步驟
在最小PB設(shè)置下,測量設(shè)定值與實際溫度之間的穩(wěn)態(tài)偏 差,或固定偏差。
增大PB設(shè)置,直到溫度偏差(固定偏差)增大65%。線列 圖I(見圖4)提供了計算所需最終溫度偏差的簡便方法。
將RESET 1設(shè)置為一個較高的值(10 R/M)。將RATE 1設(shè) 置為一個對應(yīng)的值(0.02分)。此時,因復(fù)位作用,測 量值應(yīng)穩(wěn)定在設(shè)定溫度。
由于我們無法確定臨界振蕩時間,必須用試誤法確定復(fù) 位和速率調(diào)整的最佳設(shè)置。在溫度穩(wěn)定在設(shè)定值后,將 設(shè)定溫度的設(shè)置增加10度。觀察實際溫度上升過程中伴 隨的過沖。然后將設(shè)定溫度的設(shè)置返回其初始值,再觀 察實際溫度上升過程中伴隨的過沖。 過沖過大表明復(fù)位和/或速率值設(shè)置得太高。過阻尼響應(yīng) (無過沖)表明復(fù)位和/或速率值設(shè)置得太低。請參看圖 7。需要改善性能時,一次改變一個整定參數(shù),并觀察設(shè) 定值改變時該參數(shù)對性能的影響。讓參數(shù)遞增變化,直 到性能得到優(yōu)化。
當?shù)玫綕M意的整定時,應(yīng)增大循環(huán)時間以節(jié)省接觸器的壽 命(適用于只有時間比例輸出的裝置(TPRI))。在不造成 測量值因負載循環(huán)而振蕩的情況下,盡量增大循環(huán)時間。
圖7:設(shè)置復(fù)位和/或速率
C. 整定冷卻控制的主輸出
使用與加熱相同的步驟。過程應(yīng)在一個設(shè)定值處運行,要求 在溫度穩(wěn)定前進行冷卻控制。
D. PID控制器的簡化整定步驟
下面的步驟是分析過程對步進輸入的響應(yīng)曲線的圖形方法。 使用長圖記錄儀讀取過程變量(PV)會更加簡單。
從冷啟動(PV在室溫下)開始,在控制器不在環(huán)路中的 情況下(即開環(huán)時)以最大功率給過程供電。記錄此開 始時間。
經(jīng)過一些延遲后(讓熱量到達傳感器),PV將開始上 升。再經(jīng)過一段延遲后,PV將達到最大變化速率 (斜率)。記錄出現(xiàn)該最大斜率時的時間以及此時的 PV。記錄最大斜率,以度/分為單位。關(guān)閉系統(tǒng)電源。
從最大斜率點開始向后到環(huán)境溫度軸畫一條線,得到總 系統(tǒng)延時Td(見圖8)。也可以用下面的公式得到延時: Td = 達到最大斜率時的時間-(最大斜率處的PV – 環(huán)境溫度)/ 最大斜率s
應(yīng)用下面的公式獲得PID參數(shù):
比例范圍 = Td x 最大斜率x 100/量程 = 量程的%
復(fù)位 = 0.4 / Td =次/分
速率 = 0.4 x Td = 分
重啟系統(tǒng),在控制器處在環(huán)路中的情況下將過程帶到設(shè) 定值,并觀察響應(yīng)。如果響應(yīng)過沖太大或者振蕩,可以 在以下方向改變PID參數(shù)(稍稍改變,一次改變一個參 數(shù),并觀察過程響應(yīng)):加寬比例帶,降低復(fù)位值,并增大速率值。
示例: 圖8中的圖表記錄是在以最大功率給加熱爐供電時獲 得的。圖表比例尺為10?F/cm和5分/cm??刂破鞣秶鸀?100 ~ 600?F,或者說500?F的量程。
示例: 圖8中的圖表記錄是在以最大功率給加熱爐供電時獲 得的。圖表比例尺為10°F/cm和5分/cm??刂破鞣秶鸀?100 ~ 600°F,或者說500°F的量程。
最大斜率 = 18°F/5分
= 3.6°F/分
延時 = Td = 大約7分
比例帶 = 7分x3.6°F/分 x 100/500°F = 5%。
復(fù)位 = 0.4 /7分 = 0.06次/分
速率 = 0.4 x 7分 = 2.8分
圖8:系統(tǒng)延時
pid算法溫度控制c語言程序
基于PID算法的溫度控制系統(tǒng) 89C51單片機,通過鍵盤輸入預(yù)設(shè)值,與DS18B20測得的實際值做比較,然后驅(qū)動制冷或加熱電路。用keil C語言來實現(xiàn)PID的控制。
?
#include《reg51.h》
#include《intrins.h》
#include《math.h》
#include《string.h》
struct PID {
unsigned int SetPoint; // 設(shè)定目標 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 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;
/***********************************************************
延時子程序,延時時間以12M晶振為準,延時時間為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以開始一個寫時序*/
if(bitval==1)
{
_nop_();
DQ=1; /*如要寫1,則將總線置高*/
}
delay(5); /*延時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; /*關(guān)中斷*/
TR0=0;
for(i=0;i《8;i++) /*寫一字節(jié)數(shù)據(jù),一次寫一位*/
{
temp=val》》i; /*移位操作,將本次要寫的位移到最低位*/
temp=temp&1;
write_bit(temp); /*向總線寫該位*/
}
delay(7); /*延時120us后*/
// TR0=1;
EA=1; /*開中斷*/
}
/***********************************************************
讀一位數(shù)據(jù)子程序
***********************************************************/
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);
}
/***********************************************************
讀一字節(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ù),一個時序中讀一次,并作移位處理*/
value|=0x01《《i;
delay(4); /*延時80us以完成此次都時序,之后再讀下一數(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)答信號*/
delay(28); /*延時以完成整個時序*/
EA=1;
return(presence); /*返回應(yīng)答信號,有芯片應(yīng)答返回0,無芯片則返回1*/
}
/***********************************************************
獲取溫度子程序
***********************************************************/
void get_temper()
{
unsigned char i,j;
do
{
i=reset(); /*復(fù)位*/
}while(i!=0); /*1為無反饋信號*/
i=0xcc; /*發(fā)送設(shè)備定位命令*/
write_byte(i);
i=0x44; /*發(fā)送開始轉(zhuǎn)換命令*/
write_byte(i);
delay(180); /*延時*/
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);
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));
}
/*====================================================================================================
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); // 微分項
}
/***********************************************************
溫度比較處理子程序
***********************************************************/
compare_temper()
{
unsigned char i;
if(set_temper》temper)
{
if(set_temper-temper》1)
{
high_time=100;
low_time=0;
}
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/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);
}
}
// 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;
}
else
count=0;
TH0=0x2f;
TL0=0xe0;
}
/*****************************************************
串行口中斷服務(wù)程序,用于上位機通訊
******************************************************/
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;
else
data1=0;
_nop_();
clk=1;
_nop_();
}
}
}
/*****************************************************
顯示子程序
功能:將占空比溫度轉(zhuǎn)化為單個字符,顯示占空比和測得到的溫度
******************************************************/
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;
else
disp_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);
}
/***********************************************************
主程序
***********************************************************/
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 Structure
spid.Proportion = 10; // Set PID Coefficients
spid.Integral = 8;
spid.Derivative =6;
spid.SetPoint = 100; // Set PID Setpoint
while(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;
else
temper=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;
}
}
//DS18b20 子程序
#include 《REG52.H》
sbit DQ=P2^1; //定義端口
typedef unsigned char byte;
typedef unsigned int word;
//延時
void delay(word useconds)
{
for(;useconds》0;useconds--);
}
//復(fù)位
byte ow_reset(void)
{
byte presence;
DQ=0; //DQ低電平
delay(29); //480us
DQ=1; //DQ高電平
delay(3); //等待
presence=DQ; //presence信號
delay(25);
return(presence);
} //0允許,1禁止
//從1-wire 總線上讀取一個字節(jié)
byte read_byte(viod)
{
byte i;
byte value=0;
for (i=8;i》0;i--)
{
value》》=1;
DQ=0;
DQ=1;
delay(1);
if(DQ)value|=0x80;
delay(6);
}
return(value);
}
//向1-wire總線上寫一個字節(jié)
void write_byte(char val)
{
byte i;
for (i=8;i》0;i--) //一次寫一個字節(jié)
{
DQ=0;
DQ=val&0x01;
delay(5);
DQ=1;
val=val/2;
}
delay(5);
}
//讀取溫度
char Read_Temperature(void)
{
union{
byte c[2];
int x;
}temp;
ow_reset();
write_byte(0xcc);
write_byte(0xBE);
temp.c[1]=read_byte();
temp.c[0]=read_byte();
ow_reset();
write_byte(0xCC);
write_byte(0x44);
return temp.x/2;
}
評論
查看更多