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