pid溫度控制演算法
Ⅰ PID演算法控制溫度加熱系統,室溫(為防止分數流失,做成追加100分以上)
剛好前不久搞過PID,部分程序如下,僅供參考
/*==============================================================================
在使用單片機作為控制cpu時,請稍作簡化,具體的PID參數必須由具體對象通過實驗確定。
由於單片機的處理速度和ram資源的限制,一般不採用浮點數運算,而將所有參數全部用整數,
運算到最後再除以一個2的N次方數據(相當於移位),作類似定點數運算,可大大提高運算速度,
根據控制精度的不同要求,當精度要求很高時,注意保留移位引起的「余數」,做好余數補償。
這個程序只是一般常用pid演算法的基本架構,沒有包含輸入輸出處理部分。
==============================================================================*/
#include <string.h>
#include <stdio.h>
/*===============================================================================
PID Function
The PID function is used in mainly
control applications. PID Calc performs one iteration of the PID
algorithm.
While the PID function works, main is just a mmy program showing
a typical usage.
PID功能
在PID功能主要用於控制應用。 PID 計算器執行一個PID的迭代演算法。雖然PID功能的工程,
主要只是一個虛擬程序顯示一個典型的使用。
================================================================================*/
typedef struct PID {
double SetPoint; // 設定目標 Desired Value
double Proportion; // 比例常數 Proportional Const
double Integral; // 積分常數 Integral Const
double Derivative; // 微分常數 Derivative Const
double LastError; // Error[-1]
double PrevError; // Error[-2]
double SumError; // Sums of Errors
} PID;
/*================================ PID計算部分===============================*/
double PIDCalc( PID *pp, double NextPoint )
{
double 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 // 微分項
);
}
/*======================= 初始化的PID結構 Initialize PID Structure===========================*/
void PIDInit (PID *pp)
{
memset ( pp,0,sizeof(PID));
}
/*======================= 主程序 Main Program=======================================*/
double sensor (void) // 虛擬感測器功能 Dummy Sensor Function{ return 100.0;}
void actuator(double rDelta) // 虛擬驅動器功能 Dummy Actuator Function{}
void main(void)
{
PID sPID; // PID控制結構 PID Control Structure
double rOut; // PID響應(輸出) PID Response (Output)
double rIn; // PID反饋(輸入) PID Feedback (Input)
PIDInit ( &sPID ); // 初始化結構 Initialize Structure
sPID.Proportion = 0.5; // 設置PID系數 Set PID Coefficients
sPID.Integral = 0.5;
sPID.Derivative = 0.0;
sPID.SetPoint = 100.0; // 設置PID設定 Set PID Setpoint
for (;;)
{ // 模擬最多的PID處理 Mock Up of PID Processing
rIn = sensor (); // 讀取輸入 Read Input
rOut = PIDCalc ( &sPID,rIn ); // 執行的PID迭代 Perform PID Interation
actuator ( rOut ); // 所需的更改的影響 Effect Needed Changes
}
Ⅱ 位置式pid控制演算法
數字PID位置型控制算式如下:
u(k)=Kp[
e(k)
+??e(i)T/T??
+
Td(
e(k)-e(k)
)/T
]
Kp為比例增益,T為采樣周期,T??為積分時間常數,Td為微分時間常數,k采樣序號,??為累加器(i從0到k),由於該控制演算法提供了執行機構的位置u(k),如閥門的開度,所以被成為數字PID位置型控制演算法。
Ⅲ 請教溫控PID增量型演算法公式
南京星德機械提供:增量式PID控制演算法
當執行機構需要的不是控制量的絕對值,而是控制量的增量(例如去驅
動步進電動機)時,需要用PID的「增量演算法」。
Ⅳ 幾種常用溫控演算法的比較與總結
最近在做一個有關大氣VOCs實時監測的項目,由於該項目要求控溫精度在0.1度之內,所以就研究了一下有關溫控的演算法,我們知道對於一些大慣性的系統,比如加熱爐、智能小車中都會用到PID(比例、積分和微分)演算法,而PID演算法分為二值式、位置式、增量式和分段式,當然也有模糊式等。現根據在實際項目中的應用情況將其總結如下:
(1)二值式
二值式溫控演算法只存在兩個狀態,不是開,就是關。常用在一些控溫精度不高的場合。
(2)位置式
位置式PID演算法由於計算量比較大,降低了單片機的運行速度,需要單片機比較大的內存,所以在實際應用中應用的比較少,除非有特除要求的場合。
(3)增量式
增量式PID演算法相比二值式控溫精度比較高,相比位置式計算量減少了許多,提高了單片機的運行速度,也增大了單片機的選擇餘地(內存要求降低)。為了提高溫控的速度,減少溫控所需要的時間,所以該增加式PID演算法常與BangBang演算法、大林演算法相結合使用。BangBang演算法和大林演算法即是全功率加熱,比如BangBang-PID演算法通過會有一個閾值,一旦採用BangBang或大林演算法升溫到閾值時,就會自動切換到增量式PID演算法進行控溫。另外該閾值的選擇是個難點,閾值小了,升溫時間比較長,閾值大了,過沖量比較大,所以說該閾值的選擇需要從以下兩個方面去確定:升溫速率、距離設定值的差值大小等方面。
(4)分段式
分段式PID演算法雖然比模糊PID演算法差一些,但是模糊PID控制大多數還停留在理論階段,應用到實際系統的還比較少,控制效果如何還不是很確定。分段式PID演算法在某些方面與模糊式PID演算法有很多相近的地方,也是對信號進行閾值的劃分,然後在不同的閾值階段採用不同的控制參數。分段PID優於模糊PID的地方在於我們現有的工控機在編輯控制演算法時是數字式的,模糊PID演算法要想實現其功能除了要進行數據的離散化外,其用到的數據參數也比較多導致統計起來比較麻煩,經過以上對比分析,從系統的可實現性方面考慮,還是採用分段式PID演算法的比較多些。
根據項目的實際控制結果表明單純的採用單一的PID參數進行調節要想達到較為理想的控制效果是不容易的。所以可以根據控制對象的實際情況及偏差的大小,在不同的控制階段給定不同的PID調節參數,這樣可以在偏差大的時候加大比例調節,降低積分作用,偏差小的時候減少比例作用,加大積分作用。這樣既可以增加響應速度,超調量也不會太大,這就是分段PID的控制思想。 下面對普通PID與分段PID在同一控制變數下做出的反應做一下對比,他們的輸出曲線如下圖:
在上圖輸出曲線中可以看出在目標值情況相同的情況下,分段PID的響應速度更快,達到目標值時分段PID比普通PID所用的時間少一半,所用控制系統的快速性被分段PID明顯提高了。採用分段PID即是將一個控制過程進行分段控制,可以避免採用單一PID控制時對誤差積累較多的缺點(採用單一PID演算法時,剛開始啟動時目標值與實際值的差值會很大,如果有積分變數的話,積分變數大了會導致較大的積累偏差,導致消除困難,造成系統較大的系統超調;積分變數小了會導致精差消除較慢。),這樣在每一階段都對誤差進行消除,最後誤差結果會小很多。分段PID演算法的實現步驟:這里假定閾值a為偏差的50%,閾值b為偏差的30%。
a、根據工程需要設置閾值a>b>0;
b、當偏差較大,且偏差大於等於a時,採用PD控制,可加快系統響應;
c、當偏差較小,且大於b,小於a時採用PI控制;
d、當偏差小於b時,採用PID控制(P設的小些,I設的大些),可減少系統精差。
以上是對幾種常用PID演算法的比較和總結,在實際的項目中用的比較多的是增量式PID演算法和分段式PID演算法,分段式PID算比單一的增量式PID演算法控溫速度快,精度更高,雖然分段PID演算法參數整定比較繁瑣些,但鑒於它的控制速度快、精度高,還是推薦使用分段PID演算法應用於溫度控制、電機控制等領域或項目中。
Ⅳ 溫控PID演算法的具體實現(一)
經過本人發表的上一篇文章《幾種溫度演算法的比較與總結》可知,分段式PID演算法既可以提高溫控系統的響應速度,又可以提高溫控系統的控溫精度,現將以增量式PID演算法為例總結一下其具體的實現步驟或過程,希望能夠給奮顫培襪戰在PID演算法的同仁們提供一些有價值的內容。
一、溫控模型的建立
是選擇一階延遲控溫系統還是選擇二階延遲控溫系統,需要根據自己的實際控溫系統來確定;
二、溫控模型中K、T、τ的確定
茄激 溫控模型一旦確定,接下來就是確定K、T、τ的值。溫控模型中K、T、τ等值的確定方法有以下幾種方法:
1、系統辨識法
設定採集數據的時間間隔,PWM波形的占空比等參數後,記錄隨時間變化的溫度數據(注意:是在開環狀態下),溫度數據量越多越好,根據測試的數據利用Matlab的系統辨識工具箱進行辨識求得K、T、τ的值。
2、公式計演算法1
對溫控系統輸入固定占空比的PWM波,以固定時間間隔(比如1s)採集記錄溫度數據,然後利用兩點法計算公式計算出K、T、τ的值。
K = (y(∞) - y(0))/(Δu);
T = 1.5*(t(0.632) - t(0.28));
τ = 1.5 * ( t(0.28) - t(0.632)/3)。
注意:(1)、y(0)為室溫值,y(∞)溫度穩定後的溫度值。
(2)、Δy = y(∞) - y(0)。
(3)、 t(0.28)為室溫升溫至y(0) +0.28* Δy的時間值。
(4)、t(0.632)為室溫升溫至y(0) +0.632* Δy的時間值。
3、公式計演算法2
原理同公式計演算法1,只不過選中缺取的參考點不同,這里選取的參考點是t(0.39)和t(0.632),K的計算公式同公式計演算法1,以下是T和τ的計算公式:
T = 2*(t(0.632) - t(0.28));
τ = 2* t(0.28) - t(0.632)。
三、P、I、D參數的確定
1、Matlab模擬試驗法
通過在Matlab中輸入溫控模型和建立PID控制模塊,然後模擬查看溫控的曲線情況確定PID參數。
2、公式計演算法
根據以上測得的溫度數據,由Z-N或C-C公式算出PID參數。
3、現場調試法
根據調試人員對PID參數整定的經驗調試PID參數,通過現場PID的控溫情況確定PID參數值。
通過以上三種PID參數整定方法的比較,當然還有其他的有待驗證其可行性的PID參數整定方法,個人覺得綜合以上三種PID參數整定方法,最好的PID參數整定方法是:先用公式計演算法計算出PID參數值,然後在Matlab中驗證整定的PID參數情況,最後再根據現場的實際控溫情況進行微調,最終確定PID參數的值。
Ⅵ 用PID演算法實現溫度控制
第一步:把器件等各種實物連上...
第二步:開環,對PWM的控溫信號加階躍(改變PWM的占空比),由輸入輸出的結果大致得出加熱器的數學模型
第三部:由理論公式整定出PID參數
第四部:根據實際結果調節PID以達到你想要的指標
Ⅶ 怎樣用PID演算法對恆溫箱的溫度進行控制,求相關的51單片機匯編程序
本設計要求:本溫度控制系統為以單片機為核心,實現了對溫度實時監測和控制,實現了控制的智能化。設計恆溫箱溫度控制系統,配有溫度感測器,採用DS18B20數字溫度感測器,無需數模擬∕數字轉換,可直接與單片機梁祥進行數字傳輸,採用了PID控制技術,可以使溫度保持在要求的一個困備恆定范圍內,配有鍵盤,用於輸入設定溫度;配有數碼管LED用來顯示溫度。
技術參數和設計任務:
1、利用單片機AT89C2051實現對溫度的控制,實現保持恆溫箱在最高溫度為110℃。
2、可預置恆溫箱溫度,烘乾過程恆溫控制,溫度控制誤差小於±2℃。
3、預置時顯示設定溫度,恆溫時顯示實時溫度,採用PID控制演算法顯示精確到0.1℃。
4、溫度超出預置溫度±5℃時發出聲音報警。
5、對升、降溫過程沒有線性要求。
6、溫度檢測部分採用DS18B20數字溫度汪渣毀感測器,無需數模擬∕數字轉換,可直接與單片機進行數字傳輸
7、人機對話部分由鍵盤、顯示和報警三部分組成,實現對溫度的顯示、報警。
需要的話聯系用戶名扣扣
Ⅷ 溫度控制的PID演算法的C語言程序
//PID演算法溫控C語言2008-08-17 18:58
#include<reg51.h>
#include<intrins.h>
#include<math.h>
#include<string.h>
struct PID {
unsigned int SetPoint; // 設定目標 Desired Value
unsigned int Proportion; // 比例常數 Proportional Const
unsigned int Integral; // 積分常數 Integral Const
unsigned int Derivative; // 微分常數 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;//占空比調節參數
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));
}
/*====================================================================================================
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 匯流排上讀取一個位元組
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匯流排上寫一個位元組
void write_byte(char val)
{
byte i;
for (i=8;i>0;i--) //一次寫一個位元組
{
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;
}