2016-1-11 10:06 上傳
點(diǎn)擊文件名下載附件
以下是單片機(jī)pid液位控制系統(tǒng)設(shè)計(jì)的論文預(yù)覽:
桂林電子科技大學(xué)信息科技學(xué)院
《自動(dòng)化儀表與過程控制》實(shí)訓(xùn)報(bào)告
班級(jí):自動(dòng)化一班
學(xué)號(hào): 00000000000000
姓 名:00
指導(dǎo)教師:xxx
2015 年 6 月 15 日
實(shí)訓(xùn)題目:液位控制系統(tǒng)
1 系統(tǒng)設(shè)計(jì)
1.1 設(shè)計(jì)要求
1.1.1 基本原理
水箱為雙容水箱,僅使用一個(gè)作為被控對(duì)象,即單容液位控制(將水箱設(shè)為自衡系統(tǒng)),水箱采用水泵進(jìn)行給水,水泵為12V直流電機(jī)控制,可采用PWM方式。液位傳感器為壓力式,輸出為電壓信號(hào)。設(shè)計(jì)調(diào)節(jié)器(模擬或數(shù)字式),能夠根據(jù)用戶設(shè)定,將水位控制在要求值(采用PID或PI規(guī)律)。
1.1.2 性能指標(biāo)要求
1、設(shè)計(jì)制作硬件系統(tǒng)電路,標(biāo)記姓名學(xué)號(hào)及制作日期;
2、實(shí)現(xiàn)水泵的控制、信號(hào)檢測(顯示)及調(diào)節(jié)器控制規(guī)律;
3、系統(tǒng)能夠盡快的克服擾動(dòng);
1.1.3 設(shè)計(jì)方法與步驟
1、根據(jù)設(shè)計(jì)基本原理和性能指標(biāo)要求選擇總體方案,畫出設(shè)計(jì)框圖;
2、參閱相關(guān)資料,根據(jù)設(shè)計(jì)框圖進(jìn)行電路的設(shè)計(jì);
3、列出元件清單;
4、畫原理圖,布PCB圖,并制作電路板;
5、根據(jù)器件由小到大的順序安裝電路,并進(jìn)行自檢測試;
6、數(shù)學(xué)建模、設(shè)計(jì)合適的控制參數(shù);
7、調(diào)試所制作的電路;
1.2 設(shè)計(jì)思路及設(shè)計(jì)框圖
1.2.1設(shè)計(jì)思路
調(diào)節(jié)器和PWM信號(hào)產(chǎn)生用51單片機(jī)執(zhí)行,單片機(jī)與驅(qū)動(dòng)模塊之間使用光電耦合器進(jìn)行隔離。液位變送器根據(jù)水壓不同輸出模擬電流信號(hào)(0-20mA),然后經(jīng)250歐電阻轉(zhuǎn)成0-5V的電壓信號(hào)經(jīng)過ADC0809芯片轉(zhuǎn)換成數(shù)字信號(hào),再把數(shù)字信號(hào)傳給單片機(jī)的P1口,用單片機(jī)進(jìn)行數(shù)據(jù)處理。用兩位數(shù)碼管顯示AD值(調(diào)試用的),經(jīng)多次測量AD值所對(duì)應(yīng)的液位高度,記下多組數(shù)據(jù),再用MATLAB,Polyfit(x,y,n)
函數(shù),擬合曲線,得到線性關(guān)系,然后再把之前顯示AD值的兩位數(shù)碼管用來顯示擬合出來的AD值所對(duì)應(yīng)的液位。另外兩位數(shù)碼管則用來顯示設(shè)定液位的高度。
水泵的驅(qū)動(dòng)用達(dá)林頓三級(jí)管驅(qū)動(dòng),可以通過單片機(jī)模擬出來的PWM控制水泵的轉(zhuǎn)速。
1.2.2總體設(shè)計(jì)框圖
2 各個(gè)模塊的程序的設(shè)計(jì)
1、PID算法控制:
#include"PID.H"
/*PID參數(shù)初始化*/
voidIncPIDInit(void)
{
//sptr->SumError = 0;
sptr->LastError = 0; //Error[-1]
sptr->PrevError = 0; //Error[-2]
sptr->Proportion = 100; //比例常數(shù)Proportional Const
sptr->Integral = 1;//積分常數(shù)Integral Const
sptr->Derivative = 1; //微分常數(shù)Derivative Const
}
/*增量式 PID 計(jì)算部分*/
intIncPIDCalc(int NextPoint)
{
register int iError,iIncpid; //當(dāng)前誤差
iError = sptr->SetPoint - NextPoint;//增量計(jì)算
iIncpid = sptr->Proportion *iError//E[k]項(xiàng)
-sptr->Integral*sptr->LastError//E[k-1]項(xiàng)
+ sptr->Derivative *sptr->PrevError; //E[k-2]項(xiàng)
//存儲(chǔ)誤差,用于下次計(jì)算
sptr->PrevError = sptr->LastError;
sptr->LastError = iError;
//返回增量值
return(iIncpid);
}
2、ADC0809模數(shù)轉(zhuǎn)換:
voidInitAdc(void) //ADC初始化
{
ST=0;
OE=0;
ST=1;
ST=0;
}
voidAdcObtainData(void) //ADC或出數(shù)據(jù)
{
while(EOC==0);
OE=1;
getdata=P1;
YEWEI=5*(getdata-50);
SHI=YEWEI>>4;
GE=YEWEI&0X0F;
OE=0;
DelayMs(200); //延時(shí)防止采集頻率過快
}
3、數(shù)碼管顯示模塊:
voidTimer1Interrupt(void) interrupt 3
{
TH1 = 0x0EC;
TL1 = 0x78;
switch(c)
{
case0:P2=0X8f;P0=dofly_DuanMa[0];break;//顯示2位液位值break;
case1:P2=0X4f;P0=dofly_DuanMa[YEWEI/100];break;
case2:P2=0X2f;P0=dofly_DuanMa[YEWEI%100/10];break;//顯示2位數(shù)液位break;
case3:P2=0X1f;P0=dofly_DuanMa[YEWEI%10];break;
}
c++;
if(c==4){c=0;}
d++;
if(d==400){d=0;}
}
4、按鍵控制模塊:
voidSheZhi(void)//按鍵設(shè)置液位高度
{
if(KeyPlus==0) //液位增加按鍵
{
DelayMs(100);//防止按鍵抖動(dòng)
while(!KeyPlus);
KZ++;
}
if(KeyMinus==0) //液位降低按鍵
{
DelayMs(100);//防止按鍵抖動(dòng)
while(!KeyMinus);
KZ--;
}
}
5、PWM電機(jī)控制模塊:
voidjishi(void) interrupt 1 using 1 //定時(shí)器中斷0輸出PWM
{
TH0 = (65536-50)/256; //求模 0.05ms
TL0 = (65536-50)%256; //求余
/*用來電機(jī)調(diào)速*/
speed_L++;
if(speed_L < PWM_L) //調(diào)速給出高電平占空比
{
ENA= 0;
}
else if(speed_L > PWM_L) //調(diào)速給出低電平占空比
{
ENA= 1;
}
if(speed_L == 256) //1S周期至256時(shí)清零
{
speed_L= 0;
ENA= 0;
}
CLK=~CLK;
}
3 制作與調(diào)試過程
①制作:本次實(shí)訓(xùn)在制作電路板的過程中,根據(jù)所查找的資料提供的原理圖進(jìn)行修改,從原理圖中減去了很多的元件。然后用AD軟件畫出原理圖,接著轉(zhuǎn)為PCB,手動(dòng)布線,并將PCB轉(zhuǎn)印在板子上,腐蝕、打孔后,完成實(shí)訓(xùn)電路板。
②調(diào)試:當(dāng)電路板制作完成后,需要調(diào)試電路板能否完成實(shí)訓(xùn)要求的功能,在調(diào)試的過程中我發(fā)現(xiàn)了數(shù)碼管是共陽的,隨后在P2口焊上1K上拉電阻,本次實(shí)訓(xùn)沒有用到三極管導(dǎo)致數(shù)碼管不夠亮,但是并不影響參數(shù)整定,而且晶振也換為12兆。
4功能測試
4.1測試儀器和設(shè)備
萬用表、傳感器設(shè)備、雙容水箱
4.2性能指標(biāo)測試
①實(shí)現(xiàn)液位標(biāo)定(誤差%5)
②完成參數(shù)的整定
5.硬件工作模塊
51最小系統(tǒng)
最小系統(tǒng)是指是指用最少的元件組成的單片機(jī)可以工作的系統(tǒng),它包括單片機(jī)、復(fù)位電路和時(shí)鐘電路。
復(fù)位電路:單片機(jī)第9腳為復(fù)位信號(hào)引腳(RST),復(fù)位信號(hào)高電平有效,但高電平維持時(shí)間必須維持在24個(gè)振蕩周期以上才能完成復(fù)位。系統(tǒng)使用12MHZ晶振則復(fù)位需要兩個(gè)機(jī)器周期。通電瞬間RC電路充電,RST引腳得到了一定脈寬的信號(hào),只要信號(hào)脈寬維持在復(fù)位允許時(shí)間,單片機(jī)即可復(fù)位。
起振電路:在外部連接晶振和起振電容便可構(gòu)成內(nèi)部振蕩電路,產(chǎn)生振蕩時(shí)鐘脈沖。
單片機(jī):AT89S52,它是一種低功耗、高性能CMOS8位微控制器,具有8K系統(tǒng)可編程Flash儲(chǔ)存器。
A/D轉(zhuǎn)換
ADC0809是一款8通道復(fù)用的8位AD轉(zhuǎn)換器,數(shù)據(jù)獲取的關(guān)鍵部分是它的八位8位模/數(shù)轉(zhuǎn)換器。這個(gè)部分由三部分組成:266R的階梯網(wǎng)絡(luò),連接逼近的電阻和比較器。ADC0809為8路模擬信號(hào)的份上采集轉(zhuǎn)換器。片內(nèi)有8路模擬選通開關(guān),以及相應(yīng)的通道抵制鎖存用譯碼電路,其轉(zhuǎn)換時(shí)間為100US左右。
電機(jī)模塊
5.實(shí)訓(xùn)心得
經(jīng)過本次實(shí)訓(xùn),讓我對(duì)過程控制這一門課有了更深刻的了解。特別是雙位控制和PID控制,不僅對(duì)理論有了跟深刻的了解,還對(duì)它們實(shí)際應(yīng)用有了一定的認(rèn)識(shí)。這次實(shí)訓(xùn)首先設(shè)計(jì)原理圖和布局PCB,然后做板子。在設(shè)計(jì)原理圖的時(shí)候沒有注意到數(shù)碼管是共陽的,也沒加三極管,導(dǎo)致數(shù)碼管很暗,后來在接數(shù)碼管位選的IO口上接了一個(gè)1K的上拉電阻,有效的解決了這個(gè)問題。其中本次實(shí)訓(xùn)的關(guān)鍵在于調(diào)試,這也是最難,它不僅考驗(yàn)了知識(shí),還考驗(yàn)了耐心。調(diào)試主要包括了測量參數(shù),利用參數(shù)經(jīng)數(shù)學(xué)計(jì)算工具擬合出曲線,還有就是不斷的修改程序,首先就是調(diào)節(jié)P值,不讓I作用,讓水位能在設(shè)定值的附近比較穩(wěn)定的上下波動(dòng),出現(xiàn)等幅振蕩最好。最后加入I調(diào)節(jié),調(diào)整I參數(shù),是系統(tǒng)跟加好的穩(wěn)定。不過本次實(shí)訓(xùn)中我只調(diào)了P,因?yàn)檎{(diào)了P水位也能比較穩(wěn)定的在設(shè)定值的附近微小的波動(dòng)。
附錄1:原件清單
51單片機(jī)
ADC0809 數(shù)碼管
達(dá)林頓三極管
四個(gè)獨(dú)石電容
兩個(gè)瓷片電容
多個(gè)電阻 RS232串口芯片
DB9
1K上拉電阻
若干插針
接線柱
12M晶振 三個(gè)按鍵
一個(gè)極性電容
光耦
下載接口
附錄2:程序清單
- #include <reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- uint c=0; //獲取液位AD值,
- unsigned char code dofly_DuanMa[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
- 0x90,0X88,0X83,0Xc6,0Xa1,0X86,0X8e};// 顯示段碼值0~9
- /*ADC0809*/
- sbit EOC=P3^2; //轉(zhuǎn)換結(jié)束信號(hào)
- sbit OE=P3^3; //允許輸出信號(hào)
- sbit ST=P3^4; //轉(zhuǎn)換啟動(dòng)信號(hào)
- sbit CLK=P3^5; //時(shí)鐘
- /*按鍵*/
- sbit KeyPlus=P2^0;//按鍵加
- sbit KeyMinus=P2^1;//按鍵減
- /*驅(qū)動(dòng)*/
- sbit ENA=P3^6;//進(jìn)出水控制
- double KZ=100;
- double YEWEI; //獲取液位AD對(duì)應(yīng)液位值,
- uint rout; // PID Response (Output)
- uint getdata;
- uint PWM_L;
- uint speed_L = 0;
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- void DelayMs(unsigned char t)
- {
- while(t--)
- {
- //大致延時(shí)1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- void InitTimer0(void)
- {
- TMOD = 0x11;
- TH0 = (65536-500)/256; //求模 0.5ms
- TL0 = (65536-500)%256; //求余
- TH1 = 0x0EC;
- TL1 = 0x78;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- ET1 = 1;
- TR1 = 1;
- }
- void InitAdc(void) //ADC初始化
- {
- ST=0;
- OE=0;
- ST=1;
- ST=0;
- }
- void AdcObtainData(void) //ADC或出數(shù)據(jù)
- {
- while(EOC==0);
- OE=1;
- getdata=P1;
- if(getdata<53)
- {
- getdata=53;
- }
- YEWEI=(double)5*((double)(getdata)-53);//AD值是70就對(duì)應(yīng)100mm的液位高度
- OE=0;
- DelayMs(200); //延時(shí)防止采集頻率過快
- }
- typedef struct PID
- {
- int SetPoint;//設(shè)定目標(biāo)Desired Value
- //long SumError; //誤差累計(jì)
- double Proportion; //比例常數(shù)Proportional Const
- double Integral; //積分常數(shù)Integral Const
- double Derivative; //微分常數(shù)Derivative Const
- int LastError; //Error[-1]
- int PrevError; //Error[-2]
- }
- PID;
- static PID sPID;
- static PID *sptr = &sPID;
- /*PID參數(shù)初始化*/
- void IncPIDInit(void)
- {
- //sptr->SumError = 0;
- sptr->LastError = 0; //Error[-1]
- sptr->PrevError = 0; //Error[-2]
- sptr->Proportion = 5; //比例常數(shù)Proportional Const
- sptr->Integral = 0;//積分常數(shù)Integral Const
- sptr->Derivative = 0; //微分常數(shù)Derivative Const
-
- }
-
- /*增量式 PID 計(jì)算部分*/
- int IncPIDCalc(int NextPoint)
- {
- register int iError,iIncpid; //當(dāng)前誤差
- iError = sptr->SetPoint - NextPoint;//增量計(jì)算
- iIncpid = sptr->Proportion * iError//E[k]項(xiàng)
- - sptr->Integral*sptr->LastError//E[k-1]項(xiàng)
- + sptr->Derivative * sptr->PrevError; //E[k-2]項(xiàng)
- //存儲(chǔ)誤差,用于下次計(jì)算
- sptr->PrevError = sptr->LastError;
- sptr->LastError = iError;
- //返回增量值
- return(iIncpid);
- }
- void SheZhi(void)//按鍵設(shè)置液位高度
- {
- if(KeyPlus==0) //液位增加按鍵
- {
- DelayMs(100); //防止按鍵抖動(dòng)
- while(!KeyPlus);
- KZ=KZ+10;
- }
- if(KeyMinus==0) //液位降低按鍵
- {
- DelayMs(100); //防止按鍵抖動(dòng)
- while(!KeyMinus);
- KZ=KZ-10;
- }
- }
- void Control(void) //液位控制
- {
- InitAdc();
- AdcObtainData();
- if(KZ>YEWEI)
- {
- if(KZ-YEWEI>50)
- {
- PWM_L=250;
- }
- else
- {
- rout=IncPIDCalc(YEWEI);
- PWM_L=(uchar)(rout);
- if(PWM_L>80)
- PWM_L=80;
- }
- }
- }
- void main(void)
- {
- InitTimer0();
- IncPIDInit(); //初始化PID
- while(1)
- {
- sptr->SetPoint = KZ ;
- SheZhi(); //調(diào)用設(shè)置函數(shù)
- Control();//調(diào)用控制函
- }
- }
- void jishi(void) interrupt 1 using 1 //定時(shí)器中斷0輸出PWM
- {
- TH0 = (65536-500)/256; //求模 0.5ms
- TL0 = (65536-500)%256; //求余
- /*用來水泵調(diào)速*/
- speed_L++;
- if(speed_L < PWM_L) //左輪PWM調(diào)速給出高電平占空比
- {
- ENA = 0;
- }
- else if(speed_L > PWM_L) //左輪PWM調(diào)速給出低電平占空比
- {
- ENA = 1;
- }
- if(speed_L == 300) //周期至300時(shí)清零
- {
- speed_L = 0;
- ENA = 0;
- }
- /*ADC時(shí)鐘*/
- CLK=~CLK;
- }
- void Timer1Interrupt(void) interrupt 3
- {
- TH1 = 0x0ec;
- TL1 = 0x78;
- switch(c)
- {
- case 0:P2=0X8f;P0=dofly_DuanMa[((uint)YEWEI)/16];break;//顯示2位當(dāng)前液位值break;
- case 1:P2=0X4f;P0=dofly_DuanMa[((uint)YEWEI)%16];break;
- case 2:P2=0X2f;P0=dofly_DuanMa[(uint)KZ/16];break;//顯示設(shè)定液位值break;
- case 3:P2=0X1f;P0=dofly_DuanMa[(uint)KZ%16];break;
- }
- c++;
- if(c==4){c=0;}
- }
復(fù)制代碼