c語言pid函數 pid算法c語言程序

什么是pid算法,難學嗎,用C語言,plc怎么實現?

一、什么是PID:

10年專注成都網站制作,企業(yè)網站制作,個人網站制作服務,為大家分享網站制作知識、方案,網站設計流程、步驟,成功服務上千家企業(yè)。為您提供網站建設,網站制作,網頁設計及定制高端網站建設服務,專注于企業(yè)網站制作,高端網頁制作,對樓梯護欄等多個行業(yè),擁有豐富的網站制作經驗。

PID即:Proportional(比例)、Integral(積分)、Differential(微分)的縮寫。顧名思義,PID控制算法是結合比例、積分和微分三種環(huán)節(jié)于一體的控制算法,它是連續(xù)系統(tǒng)中技術最為成熟、應用最為廣泛的一種控制算法,該控制算法出現于20世紀30至40年代,適用于對被控對象模型了解不清楚的場合。 ---百度百科

二、PID是否難學:

在工業(yè)應用中PID及其衍生算法是應用最廣泛的算法之一,是當之無愧的萬能算法,如果能夠熟練掌握PID算法的設計與實現過程,對于一般的研發(fā)人員來講,應該是足夠應對一般研發(fā)問題了,而難能可貴的是,在我所接觸的控制算法當中,PID控制算法又是最簡單,最能體現反饋思想的控制算法,可謂經典中的經典。經典的未必是復雜的,經典的東西常常是簡單的,而且是最簡單的,想想牛頓的力學三大定律吧,想想愛因斯坦的質能方程吧,何等的簡單!簡單的不是原始的,簡單的也不是落后的,簡單到了美的程度。 ---【1】

三、PID算法的C語言源碼:

PID 控制算法可以分為位置式 PID?和增量式 PID?控制算法

詳細見參考【1】【2】

參考:

【1】PID算法

【2】簡易PID算法的快速掃盲(超詳細+過程推導+C語言程序)

PID算法的C語言實現

基本流程

積分環(huán)節(jié):主要是用來消除 靜差 (系統(tǒng)穩(wěn)定后輸出值和設定值之間的差值,積分環(huán)節(jié)實際上就是偏差累積的過程,把累積的誤差加到原來系統(tǒng)上以抵消系統(tǒng)造成的靜差)

微分環(huán)節(jié):反映了偏差信號的變化規(guī)律,根據偏差信號的變化規(guī)律來進行超前調節(jié),從而增加系統(tǒng)的快速性

對上述公式進行離散化(采樣):兩個公式

增量型PID:

通過增量型PID公式可以看出,最終表達結果和最近三次的偏差有關,最終輸出結果應該為:

首先定義結構變量體:

然后初始化變量

最后編寫控制算法

基本算法,沒有考慮死區(qū)問題,沒有設定上下限

在啟動、結束或大幅度增減設定時,短時間內系統(tǒng)輸出有很大的偏差,會造成PID運算的積分積累,導致控制量超過執(zhí)行機構可能允許的最大動作范圍對應的極限控制量,從而引起較大的超調,甚至是振蕩。

為了克服這個問題,引入積分分離的概念,即當被控量和設定值偏差較大時,取消積分作用;當被控量接近設定值時,引入積分控制,以消除靜差,提高精度。

abs :絕對值

令index=0使積分環(huán)節(jié)失效

積分飽和現象:如果系統(tǒng)存在一個方向的偏差,PID控制器的輸出由于積分作用的不斷累加而加大,從而導致執(zhí)行機構達到極限位置。此時計算器輸出量超出正常運行范圍而進入飽和區(qū),一旦系統(tǒng)出現反向偏差,輸出量將逐漸從飽和區(qū)退出,進入飽和區(qū)越深則退出飽和區(qū)時間越長,在這段時間里,執(zhí)行機構仍然停留在極限位置而不隨偏差反向而立即做出相應改變,造成性能惡化。

采用梯形積分能夠減小余差,提高精度

改變積分系數,若偏差大,積分作用減弱,系數減?。蝗羝钚?,積分作用增強,系數增大。

變積分PID的基本思想是設法改變積分項的累加速度,使其與偏差大小對應。

使整個系統(tǒng)的穩(wěn)定速度非???/p>

比例系數Kp的作用是加快系統(tǒng)的響應速度提高系統(tǒng)的調節(jié)精度

積分系數Ki的作用是消除系統(tǒng)的穩(wěn)態(tài)誤差

微分系數Kd的作用是改善系統(tǒng)的動態(tài)特性

反應系統(tǒng)性能的兩個參數是系統(tǒng)誤差和誤差變化律

如何用c語言實現PID算法的參數計算

這個問題屬于PID的自整定,有簡單的繼電器算法,我試過,效果不理想。

說了半天,我也沒找到很好用的自整定程序,呵呵。

如果你找到好用的,希望能夠分享一下哦。

溫度控制的PID算法的C語言程序

//PID算法溫控C語言2008-08-17 18:58

#includereg51.h

#includeintrins.h

#includemath.h

#includestring.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;//占空比調節(jié)參數

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;ntime;n++)

for(m=0;m2;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;

}

/***********************************************************

寫一字節(jié)數據子程序

***********************************************************/

void write_byte(unsigned char val)

{

unsigned char i;

unsigned char temp;

EA=0; /*關中斷*/

TR0=0;

for(i=0;i8;i++) /*寫一字節(jié)數據,一次寫一位*/

{

temp=vali; /*移位操作,將本次要寫的位移到最低位*/

temp=temp1;

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;i2;i++){}

value_bit=DQ;

EA=1;

return(value_bit);

}

/***********************************************************

讀一字節(jié)數據子程序

***********************************************************/

unsigned char read_byte()

{

unsigned char i,value=0;

EA=0;

for(i=0;i8;i++)

{

if(read_bit()) /*讀一字節(jié)數據,一個時序中讀一次,并作移位處理*/

value|=0x01i;

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; /*發(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=(i4)0x7f;

s=(unsigned int)(j0x0f);

s=(s*100)/16;

j=j4;

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_tempertemper)

{

if(set_temper-temper1)

{

high_time=100;

low_time=0;

}

else

{

for(i=0;i10;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_temper0)

{

high_time=0;

low_time=100;

}

else

{

for(i=0;i10;i++)

{ get_temper();

rin = s; // Read Input

rout = PIDCalc ( spid,rin ); // Perform PID Interation

}

if (high_time100)

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;n6;n++)

{

// k=disp_num1[n];

for(a=0;a8;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;a5;a++)

for(b=0;b102;b++){}

if(plus==0)

{

set_temper++;

flag=0;

}

}

else if(subs==0)

{

for(a=0;a5;a++)

for(b=0;a102;b++){}

if(subs==0)

{

set_temper--;

flag=0;

}

}

else if(stop==0)

{

for(a=0;a5;a++)

for(b=0;b102;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(++count130)

{

display();

count1=0;

}

compare_temper();

}

TR0=0;

z=1;

while(1)

{

EA=0;

if(stop==0)

{

for(a=0;a5;a++)

for(b=0;b102;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(;useconds0;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;i0;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;i0;i--) //一次寫一個字節(jié)

{

DQ=0;

DQ=val0x01;

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;

}

網站題目:c語言pid函數 pid算法c語言程序
轉載來源:http://www.muchs.cn/article12/hhehdc.html

成都網站建設公司_創(chuàng)新互聯,為您提供網站改版、網站建設、商城網站網站排名、做網站、網站導航

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都網站建設公司