|
樓主做的基于51單片機(jī)主控的PID算法的恒溫控制系統(tǒng),帶加熱指示燈與遞增和遞減按鈕.采用DS18B20做的溫度傳感器
電路原理圖如下:
原理圖
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
仿真圖
恒溫控制系統(tǒng)實(shí)物圖:
實(shí)物圖
pcb圖:
PCB圖
恒溫控制系統(tǒng)的單片機(jī)源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #include<math.h>
- #include<string.h>
- struct PID {
- unsigned int SetPoint; // 設(shè)定目標(biāo) 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) 響應(yīng)輸出
- unsigned int rin; // PID Feedback (Input)//反饋輸入
- unsigned char high_time,low_time,count=0;//占空比調(diào)節(jié)參數(shù)
- #define uchar unsigned char
- #define uint unsigned int
- sbit output=P1^0;
- sbit ds=P3^2;
- sbit DQ=P3^2;//ds18b20與單片機(jī)連接口
- sbit lcden=P2^7;//LCE使能引腳
- sbit lcdrs=P2^5;
- sbit lcdrw=P2^6;
- sbit ledred=P1^6;
- sbit ledgreen=P1^7;
- sbit key0=P2^0;//按鍵引腳
- sbit key1=P2^1;
- uchar set[2]={0};
- uchar code str1[]="now temp: C";
- uchar code str2[]="set temp: C";
- uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
- uchar n,num;
- int set_temper=30,temper,temp; //溫度變量定義
- unsigned int s;
- float f_temp;//轉(zhuǎn)換后的溫度
- uint tvalue;
- uchar tflag;//溫度正負(fù)標(biāo)志
- void delay(i)//延時(shí)函數(shù)
- {
- uint j;
- for(i;i>0;i--)
- for(j=110;j>0;j--);
- }
- void wr_com(uchar ml)//寫(xiě)命令
- {
- lcdrs=0;
- P0=ml;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- void wr_data(uchar shuju)//寫(xiě)數(shù)據(jù)
- {
- lcdrs=1;
- //lcden=1;
- P0=shuju;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- void init() //按照時(shí)序操作的初始化
- {
- lcdrw=0;
- wr_com(0x38);//顯示模式設(shè)置,設(shè)置為16*2顯示,5*7點(diǎn)陣,八位數(shù)據(jù)口
- wr_com(0x0c);//開(kāi)顯示,但不開(kāi)光標(biāo),光標(biāo)不閃
- wr_com(0x06);//顯示光標(biāo)移動(dòng)設(shè)置
- wr_com(0x01);// 清屏
- wr_com(0x80); // 數(shù)據(jù)指針初始化
- for(num=0;num<16;num++)
- {
- wr_data(str1[num]);//now temp
- }
- wr_com(0x80+0x40); //地址初始化
- for(num=0;num<16;num++)
- {
- wr_data(str2[num]);//set temp
- }
- }
- /*************************DS1820程序****************************/
- void delay_18B20(unsigned int i)//延時(shí)1微秒
- {
- while(i--);
- }
- void ds1820rst(void)/*ds1820復(fù)位*/
- {
- unsigned char x=0;
- DQ = 1; //DQ復(fù)位
- delay_18B20(4); //延時(shí)
- DQ = 0; //DQ拉低
- TR0=0;
- delay_18B20(100); //精確延時(shí)大于
- TR0=1;
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd(void)/*讀數(shù)據(jù)*/
- {
- unsigned char i=0;
- unsigned char dat = 0;
- TR0=0;
- for (i=8;i>0;i--)
- {
- DQ = 0; //給脈沖信號(hào)
- dat>>=1;
- DQ = 1; //給脈沖信號(hào)
- if(DQ)
- dat|=0x80;
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*寫(xiě)數(shù)據(jù)*/
- {
- unsigned char i=0;
- TR0=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01;
- delay_18B20(10);
- DQ = 1;
- wdata>>=1;
- }
- }
- uint get_temper()//獲取溫度
- {
-
- uchar a,b;
- ds1820rst();
- ds1820wr(0xcc);//*跳過(guò)讀序列號(hào)*/
- ds1820wr(0x44);//*啟動(dòng)溫度轉(zhuǎn)換*/
- ds1820rst();
- ds1820wr(0xcc);//*跳過(guò)讀序列號(hào)*/
- ds1820wr(0xbe);//*讀取溫度*/
- a=ds1820rd();
- b=ds1820rd();
-
- tvalue=b;
- tvalue<<=8;
- tvalue=tvalue|a;
- TR0=1;
- if(tvalue<0x0fff) tflag=0;
- else {tvalue=~tvalue+1;tflag=1;}
- tvalue=tvalue*(0.625);//溫度值擴(kuò)大10倍,精確到1位小數(shù)
- temp=tvalue;
- return temp;
- }
- void dis_temp(int t)//顯示溫度
- {
- uchar d0,d1,d2,d3;
- //t=26;
- if(tflag==0)
- {
- d0=t/1000+0x30;
- d1=t%1000/100+0x30;
- d2=t%100/10+0x30;
- d3=t%10+0x30;
- if(d0==0x30)
- {
- wr_com(0x80+9);
- wr_data(d1);
- wr_com(0x80+10);
- wr_data(d2);
- wr_com(0x80+11);
- wr_data(0x2e);
- wr_com(0x80+12);
- wr_data(d3);
- }
- else
- {
- wr_com(0x80+9);
- wr_data(d0);
- wr_com(0x80+10);
- wr_data(d1);
- wr_com(0x80+11);
- wr_data(d2);
- wr_com(0x80+12);
- wr_data(' ');
- }
-
- }
- else
- {
- wr_com(0x80+9);
- wr_data('-');
- wr_com(0x80+10);
- wr_data(d1);
- wr_com(0x80+11);
- wr_data(d2);
- wr_com(0x80+12);
- wr_data(' ');
- //wr_com(0x80+12);
- //wr_data(d3);
- }
- wr_com(0x80+14);
- wr_data(0xdf);
- temper=t/10;
- }
- void keyscan()//鍵盤(pán)掃描
- {
- if(key0==0)
- {
- delay(1);
- if(key0==0)
- {
- while(!key0);
- delay(1);
- while(!key0);
- set_temper++;
- }
- set[0]=set_temper/10; //獲得設(shè)置溫度顯示值
- set[1]=set_temper%10;
- wr_com(0x80+0x40+9);
- wr_data(table[set[0]]);
- delay(1);
- wr_com(0x80+0x40+10);
- wr_data(table[set[1]]);
- delay(1);
- //wr_com(0x80+0x40+11);
- //wr_data(0x2e);
- //wr_com(0x80+0x40+14);
- //wr_data(0xdf);
- delay(1);
- }
- if(key1==0)
- {
- delay(3);//延時(shí)去抖
- if(key1==0)
- {
- while(!key1);
- delay(3);
- while(!key1);
- set_temper--;//溫度減
- if(set_temper==0)
- {set_temper=0;}
- }
-
- set[0]=set_temper/10; //獲得設(shè)置溫度顯示值
- set[1]=set_temper%10;
- wr_com(0x80+0x40+9); //顯示設(shè)置溫度值
- wr_data(table[set[0]]);
- delay(1);
- wr_com(0x80+0x40+10);
- wr_data(table[set[1]]);
- delay(1);
- //wr_com(0x80+0x40+11);
- //wr_data(0x2e);
- wr_com(0x80+0x40+14);
- wr_data(0xdf);
- delay(1);
- }
- }
- void PIDInit (struct PID *pp)
- {
- memset ( pp,0,sizeof(struct PID)); //用參數(shù)0初始化pp
- }
- unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) //PID計(jì)算
- {
- unsigned int dError,Error;
- Error = pp->SetPoint - NextPoint; // 偏差
- pp->SumError += Error; // 積分
- dError = pp->LastError - pp->PrevError; // 當(dāng)前微分
- pp->PrevError = pp->LastError;
- pp->LastError = Error;
- return (pp->Proportion * Error//比例
- + pp->Integral * pp->SumError //積分項(xiàng)
- + pp->Derivative * dError); // 微分項(xiàng)
- }
- /***********************************************************
- 溫度比較處理子程序
- ***********************************************************/
- void compare_temper(void)
- {
- unsigned char i;
- if(set_temper>temper) //設(shè)置溫度大于當(dāng)前溫度
- {
- ledred=0;
- ledgreen=1;
- if(set_temper-temper>1) //溫度相差1度以上
- {
- high_time=100;
- low_time=0;
- }
- else //設(shè)置溫度不大于當(dāng)前溫度
- {
- 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) //設(shè)置溫度不大于當(dāng)前溫度
- {
- ledred=1;
- ledgreen=0;
- if(temper-set_temper>0) //溫度相差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);
- }
- }
- }
- /*****************************************************
- T0中斷服務(wù)子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期
- ******************************************************/
- void serve_T0() interrupt 1 using 1
- {
- if(++count<=(high_time)) output=0;
- else if(count<=100)
- {
- output=1;
- }
- else count=0;
- TH0=0x2f;
- TL0=0x40;
- }
- /***********主函數(shù)**********/
- void main(void)
- {
- unsigned char i;
- init();//LCD初始化
- TMOD=0x01;
- TH0=0x2f;
- TL0=0x40;
- EA=1;
- ET0=1;
- TR0=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
- set[0]=set_temper/10;
- set[1]=set_temper%10;
- wr_com(0x80+0x40+9); //顯示設(shè)置溫度
- wr_data(table[set[0]]);
- delay(1);
- wr_com(0x80+0x40+10);
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
1DS18B20 控溫 源程序.rar
(95.34 KB, 下載次數(shù): 586)
2018-4-24 10:20 上傳
點(diǎn)擊文件名下載附件
溫控源程序
仿真.rar
(24.19 KB, 下載次數(shù): 459)
2018-4-25 00:40 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|