找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 23331|回復(fù): 24
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)+PID算法水溫控制系統(tǒng)設(shè)計(jì)源碼與資料下載

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:376014 發(fā)表于 2018-7-20 16:56 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
基于51單片機(jī)的水溫控制系統(tǒng)制作

適合于51單片機(jī)愛(ài)好者

壓縮文件里有制作過(guò)程、代碼與原理圖。

本系統(tǒng)設(shè)計(jì)采用基于PID算法的單片機(jī)控制來(lái)實(shí)現(xiàn)水溫的調(diào)控。單片機(jī)控制部分采用AT89C51單片機(jī)為核心,采用軟件編程,實(shí)現(xiàn)用PID算法來(lái)控制PWM波的產(chǎn)生,繼而控制電爐的加熱來(lái)實(shí)現(xiàn)溫度控制。通過(guò)編程對(duì)PID各參數(shù)的調(diào)整,來(lái)達(dá)到提高加溫速度,減小超調(diào)的目的。
設(shè)計(jì)任務(wù)和主要內(nèi)容
  • 基本要求
一升水在1kw電爐下加熱,要求水溫在一定范圍內(nèi)可由人工設(shè)定,并能在環(huán)境溫度降低時(shí)自動(dòng)調(diào)節(jié),以保證設(shè)定的溫度基本不變。
  • 主要性能指標(biāo)
  • 溫度設(shè)定范圍為40~90℃,最小區(qū)分度為1℃,標(biāo)定溫度小于等于1℃。
  • 環(huán)境溫度降低時(shí)溫度控制的靜態(tài)誤差小于等于1℃。
  • 用十進(jìn)制數(shù)碼管顯示水的溫度。
  • 拓展功能
  • 采用適當(dāng)?shù)目刂品椒�,�?dāng)設(shè)定的溫度突變時(shí),減小系統(tǒng)的調(diào)節(jié)時(shí)間和超調(diào)量。
  • 溫度控制的靜態(tài)誤差小于等于0.2℃。
  • 在設(shè)定溫度發(fā)生突變時(shí),自動(dòng)打印水溫隨時(shí)間變化的曲線。
  •                       系統(tǒng)設(shè)計(jì)原理


該水溫控制系統(tǒng)主要由AT89S52單片機(jī)控制系統(tǒng)、溫度采樣轉(zhuǎn)換器、溫度控制電路。鍵盤顯示電路等四部分組成,總體框圖如上。
  • 方案論證與比較
(一)總體方案論證
根據(jù)題目的要求,我們提出了以下三種方案:
    方案1:采用傳統(tǒng)的二位模擬控制方法,選用模擬電路,用電位器設(shè)定給定值,采用上下限比較電路將反饋的溫度值與給定的值比較后,決定加熱或者不加熱。由于采用的模擬控制方式,系統(tǒng)受環(huán)境影響較大,不能實(shí)現(xiàn)復(fù)雜的控制算法使控制精度做得較高,而且不能用于顯示和鍵盤設(shè)定。
    方案2:采用單片機(jī)AT89S52為核心。采用數(shù)字溫度傳感器DS18B20采集溫度變化信號(hào),將其轉(zhuǎn)換成數(shù)字信號(hào)并通過(guò)單片機(jī)處理后去控制溫度,使其達(dá)到穩(wěn)定。使用單片機(jī)具有編程靈活,控制簡(jiǎn)單的優(yōu)點(diǎn),使系統(tǒng)能簡(jiǎn)單的實(shí)現(xiàn)溫度的控制及顯示,并且通過(guò)軟件編程能實(shí)現(xiàn)各種控制算法使系統(tǒng)還具有控制精度高的特點(diǎn)。
    比較上述兩種方案,方案2明顯改善了方案1的不足,具有控制簡(jiǎn)單、控制溫度精度高的特點(diǎn),因此本設(shè)計(jì)電路采用方案2。
(二)各部分電路方案論證
1、溫度采樣部分
    方案1:采用熱敏電阻,可滿足35℃--95℃的測(cè)量范圍,但熱敏電阻精度、重復(fù)性和可靠性都比較差,對(duì)于檢測(cè)精度小于1℃的溫度信號(hào)是不適用的。
    方案2:采用數(shù)字溫度傳感器DS18B20。DS18B20是支持一線總線接口的溫度傳感器,具有抗干擾性強(qiáng),體積小,靈活經(jīng)濟(jì)的特點(diǎn)。它的測(cè)量溫度范圍為-55℃~+125℃,在-10℃~+85℃范圍內(nèi),精度為±0.5℃且有9~12位分辨率可調(diào),使用電壓為3~5V無(wú)需備用電源。此外DS18B20集合了64位光刻ROM、溫度傳感器、非揮發(fā)的溫度報(bào)警觸發(fā)器TH和TL、配置寄存器,可以直接實(shí)現(xiàn)溫度的測(cè)量和轉(zhuǎn)換,無(wú)需再另接外部電路。
    方案3:采用溫度傳感器AD590。AD590具有體積小、質(zhì)量輕、線性度好、性能穩(wěn)定等優(yōu)點(diǎn)。其測(cè)量范圍在-50℃~+150℃,滿刻度范圍誤差為   ±0.3℃,當(dāng)電源電壓在5~10之間,穩(wěn)定度為1%時(shí)誤差只有±0.01℃,此外,AD590是溫度—電流傳感器,對(duì)于提高系統(tǒng)抗干擾能力有很大幫助。
     從系統(tǒng)電路設(shè)計(jì)的復(fù)雜度,性價(jià)比等方面考慮,決定選用方案2。
2、控制電路部分
方案1:可以用邏輯電路搭建一個(gè)控制器,實(shí)現(xiàn)PID控制。但系統(tǒng)還要附加顯示、溫度設(shè)定等功能,要附加很多電路,總體的電路設(shè)計(jì)和制作比較繁瑣。
   方案2:采用8031芯片,其內(nèi)部沒(méi)有程序存儲(chǔ)器,需要進(jìn)行外部拓展,這給電路增加了復(fù)雜度。
   方案3:本方案的CPU模塊采用2051芯片,其內(nèi)部有2KB單元的程序存儲(chǔ)器,不需要外部拓展程序存儲(chǔ)器,但由于系統(tǒng)用到較多的I/O口,因此此芯片的資源不夠用。
   方案4:采用AT89S52單片機(jī),其內(nèi)部有8KB單元的程序存儲(chǔ)器,不需要外部擴(kuò)展程序存儲(chǔ)器,而且其I/O口達(dá)32個(gè),完全滿足本次設(shè)計(jì)需要。
   比較這4種方案,綜合的考慮單片機(jī)各部分資源,本次設(shè)計(jì)選用方案4。
3、加熱方案和功率電路的選擇
方案1:加熱的裝置,根據(jù)題目,可以使用電熱爐進(jìn)行加熱,控制電爐的功率豈可控制加熱速度。水溫過(guò)高時(shí),一般只能關(guān)掉電爐,讓其自然冷卻。為求更好的控制效果,也可以裝置一個(gè)小風(fēng)扇,電爐加熱時(shí)風(fēng)扇關(guān)閉,水溫超高時(shí)關(guān)閉電爐開(kāi)啟風(fēng)扇加速散熱。
  方案2:可以采用可控硅控制加熱器的工作。通過(guò)單片機(jī)產(chǎn)生PWM信號(hào)來(lái)控制可控硅的導(dǎo)通和關(guān)斷,控制加熱器的加熱時(shí)間,從而控制加熱器的功率。
   從加熱的響應(yīng)速度考慮,采用方案2。因?yàn)榧訜岬墓β瘦^大,故電源采用市電220伏。                                                
設(shè)計(jì)電路圖如圖2所示                                          



                                                          DS18B20
                                    ISP下載口





AT89S52主控電路      MOC3041功率電路            LCD液晶顯示

  PCB圖如下

     功率電路
主控電路

  • 硬件電路設(shè)計(jì)
  本設(shè)計(jì)總體包括四個(gè)部分:主機(jī)控制部分、溫度采樣轉(zhuǎn)換部分、溫度控制部分、鍵盤顯示部分。
  • 溫度采樣轉(zhuǎn)換電路
   系統(tǒng)的溫度采樣轉(zhuǎn)換由DS18B20集成芯片來(lái)實(shí)現(xiàn)。電路圖如右
  DS18B20性能描述
    測(cè)量范圍在-55℃~+125℃,在-10℃~+85℃范圍內(nèi),精度為±0.5℃且有9~12位分辨率可調(diào),使用電壓為3~5V,無(wú)需備用電源。
DS18B20采用單總線通信技術(shù),通信穩(wěn)定可靠,且線路簡(jiǎn)單,容易實(shí)現(xiàn)。
其基本的通信過(guò)程如下:
主機(jī)拉低單總線產(chǎn)生至少480us的Tx復(fù)位脈沖;
然后由主機(jī)釋放總線,進(jìn)入Rx接收模式,主機(jī)釋放總線時(shí)會(huì)產(chǎn)生一個(gè)由低電平變?yōu)楦唠娖降纳仙兀?
單總線器件檢測(cè)到該上升沿后,延時(shí)15~60us;  
單總線器件通過(guò)拉低總線60~240us來(lái)產(chǎn)生應(yīng)答脈沖;
主機(jī)接收到從機(jī)的應(yīng)答信號(hào)后,說(shuō)明有單總線器件在線,然后主機(jī)就可以開(kāi)始對(duì)從機(jī)進(jìn)行ROM命令和功能命令操作。
DS18B20直接輸出數(shù)字量,可直接與單片機(jī)進(jìn)行通信,讀取測(cè)溫?cái)?shù)據(jù),電路非常簡(jiǎn)單。使用它,主要工作量集中在了單片機(jī)編程上。
  •      溫度控制電路
此部分電路主要由光電耦合器MOC3041和雙向可控硅BTA16組成。以脈寬調(diào)制輸出控制電爐與電源的接通和斷開(kāi)比例,以通斷控制調(diào)壓法控制電爐的輸入功率。MOC3041的內(nèi)部集成了發(fā)光二極管、過(guò)零檢測(cè)電路和一個(gè)小功率雙向可控硅。當(dāng)單片機(jī)PWM輸出為1,MOC3041中的發(fā)光二極管發(fā)光,用于過(guò)零檢測(cè)電路的同步作用,內(nèi)部的雙向可控硅在過(guò)零后馬上導(dǎo)通,從而使觸發(fā)雙向可控硅BTA16導(dǎo)通,負(fù)載中有電流通過(guò),反之當(dāng)單片機(jī)PWM輸出為0,雙向可控硅截止,負(fù)載中沒(méi)有電流通過(guò)。光電耦合的耐壓值為400v,它的輸出級(jí)由過(guò)零觸發(fā)的雙向可控硅構(gòu)成,它控制著主電路雙向可控硅的導(dǎo)通和關(guān)閉�?刂撇糠蛛娐穲D如下






3、單片機(jī)控制部分
此部分是該系統(tǒng)的核心,系統(tǒng)的控制采用了單片機(jī)AT89S52。單片機(jī)AT89S52內(nèi)部有8KB字節(jié)的可編程FLASH存儲(chǔ)器和256字節(jié)的數(shù)據(jù)存儲(chǔ)器。故系統(tǒng)不必外拓存儲(chǔ)器,這樣大大減少了系統(tǒng)的硬件電路。電路原理圖如下:





4、按鍵及顯示部分
系統(tǒng)僅采用五個(gè)按鍵來(lái)進(jìn)行溫度的控制。
在顯示方面,我們采用了LCD1602的液晶顯示模塊,通過(guò)軟件編程,可以實(shí)現(xiàn)所需要的顯示。此外,液晶模塊的使用也比較簡(jiǎn)單,只要連接數(shù)據(jù)總線,選通端口和命令/數(shù)據(jù)端口即可。
  • 軟件設(shè)計(jì)
系統(tǒng)的硬件設(shè)計(jì)盡量簡(jiǎn)單,故工作任務(wù)主要在程序的設(shè)計(jì)上。


PID算法控制PWM輸出:
程圖如下
  1. void timer0() interrupt 1
  2.    {
  3. uchar flag;
  4. TH0=0xd8 ;                                   有
  5. TL0=0xf0 ;
  6. TR1=1 ;                                 無(wú)
  7. P24=1 ;     //啟動(dòng)輸出
  8. CJ++;   
  9. if(stemp>Wtemperature)       flag=0
  10. {
  11. ei=stemp-Wtemperature;                    flag=1
  12. E=E+ei;
  13. ex=ej-ei;
  14. ej=ei;
  15. if(ei<6)
  16. {Ui=U0-Kp*(ei+Ti*E-Td*ex);}
  17. else Ui=U0-Kp*ei;
  18. flag=Ui/100;
  19. switch(flag)
  20. {
  21. case 9:{TH1=0xdc;TL1=0xd8;}break;
  22. case 8:{TH1=0xe2;TL1=0xb4;}break;
  23. case 7:{TH1=0xe8;TL1=0x90;}break;
  24. case 6:{TH1=0xec;TL1=0x78;}break;
  25. case 5:{TH1=0xf0;TL1=0x60;}break;
  26. case 4:{TH1=0xf2;TL1=0x54;}break;
  27. case 3:{TH1=0xf4;TL1=0x48;}break;
  28. case 2:{TH1=0xf8;TL1=0x30;}break;
  29. case 1:{TH1=0xfc;TL1=0x18;}break;
  30. case 0:{TH1=0xfd;TL1=0xa8;}break;
  31. default:{TH1=0xff;TL1=0xfa;}break;
  32.           }
  33.          }
  34. else {TH1=0xff;TL1=0xfa;}
  35. }   
復(fù)制代碼
程序用T0和T1的嵌套來(lái)實(shí)現(xiàn)PWM波,T0控制波的頻率,T1控制占空比,其效果圖如下:




PID控制器:
PID控制器采用單片機(jī)軟件實(shí)現(xiàn)。輸出PWM控制信號(hào),定時(shí)器采用T0,T1的嵌套,T0定時(shí)是10MS,T1控制低電平的輸出。由于加熱器屬于帶滯后的一階對(duì)象,故式中Kp,Ki,Kd的選擇取決于加熱器的階躍響應(yīng)特性和實(shí)際經(jīng)驗(yàn),為了實(shí)現(xiàn)PID參數(shù)的實(shí)時(shí)整定,各溫度區(qū)間由實(shí)驗(yàn)測(cè)取最佳的Kp,Ki,Kd值。

  • 測(cè)試結(jié)果及分析
1、動(dòng)態(tài)溫控測(cè)量         
測(cè)量方式:接上系統(tǒng)的加熱裝置,裝入1L室溫的水,設(shè)定溫控溫度。記錄調(diào)節(jié)時(shí)間、超調(diào)溫度、穩(wěn)態(tài)溫度波動(dòng)幅度等。
測(cè)量條件:環(huán)境溫度18℃,加熱器功率1000W。
                 測(cè)量結(jié)果數(shù)據(jù)
設(shè)定溫度/℃
     40
     50
     65
     80
超調(diào)溫度/℃
     1.1
     0.8
     0.2
     0.3
穩(wěn)態(tài)誤差/℃
     0.6
     0.4
     0.6
     0.6
調(diào)節(jié)時(shí)間/min
     3.37
     5.85
     10.05
     15.22
2、結(jié)果分析
由以上測(cè)量結(jié)果可見(jiàn),系統(tǒng)性能基本達(dá)到了所要求的指標(biāo)。
在溫控指標(biāo)中,影響系統(tǒng)性能的因素很多,最關(guān)鍵的是加熱器本身的物理
性質(zhì)及控制算法。傳感器必須加上防水設(shè)施,故溫度傳感難免遲滯,加熱器的加熱本身有延遲,水對(duì)流傳熱也會(huì)造成測(cè)溫的延遲,這些都會(huì)直接影響系統(tǒng)的控制性能�?刂扑惴ǚ矫�,需反復(fù)實(shí)驗(yàn)比較,在上升時(shí)間和超調(diào)量之間做權(quán)衡,選出綜合效果最好的PID系數(shù)。
  • 設(shè)計(jì)總結(jié)
  • 設(shè)計(jì)中遇到的問(wèn)題及其解決方法
因?yàn)槭侵苯咏尤?20V的市電,當(dāng)電路一通電,板面溫度突然升高,以致燒壞電路板。于是之后我們?cè)陔娐分屑由狭松崞?/div>
溫度傳感器DS18B20不能直接浸在水中測(cè)溫度,故我們將其固定在一導(dǎo)熱性相對(duì)好的金屬筒內(nèi),再?zèng)]入水中測(cè)量。
功率電路的輸出端原本應(yīng)該加上一個(gè)電容來(lái)矯正零相位,然而當(dāng)硬件電路都裝好后,進(jìn)行調(diào)試,發(fā)現(xiàn)加熱器一直工作,沒(méi)有辦法實(shí)現(xiàn)溫度的控制,檢查發(fā)現(xiàn)是電容的問(wèn)題。當(dāng)加上電容時(shí),在交流電的作用下,電路直接導(dǎo)通,根本不需要外加控制,故我們?nèi)サ袅嗽撾娙荩訜崞鬟@才受控。
  • 設(shè)計(jì)總結(jié)
     本系統(tǒng)設(shè)計(jì)是以AT89S51單片機(jī)為核心,采用軟件編程,運(yùn)用PID算法來(lái)控制PWM波的產(chǎn)生,繼而控制加熱器的加熱時(shí)間來(lái)實(shí)現(xiàn)溫度的控制。在軟硬件的調(diào)試過(guò)程中,出現(xiàn)了不少問(wèn)題,如電路板發(fā)燙,程序不起作用,加熱速度較慢等,但是在老師和同學(xué)的指導(dǎo)和幫助下,通過(guò)電路檢查,程序修改等工作,問(wèn)題基本上都得到了解決。在這一次設(shè)計(jì)過(guò)程中,我們了解了很多專業(yè)知識(shí),動(dòng)手能力也得到了提高。然而,系統(tǒng)還存在著一些問(wèn)題,如水溫達(dá)到穩(wěn)定的時(shí)間。

單片機(jī)源程序如下:
  1. /***************************************************************
  2.         項(xiàng)目名稱:水溫控制系統(tǒng)設(shè)計(jì);
  3.         功    能:通過(guò)STC89C52單片機(jī)控制可控硅驅(qū)動(dòng)加過(guò)零檢測(cè)電路作為
  4.                           功率控制電路來(lái)控制加熱過(guò)程,通過(guò)鍵盤掃描來(lái)設(shè)定水溫,
  5.                           DS18B20實(shí)時(shí)測(cè)量水的溫度,將實(shí)際水溫與設(shè)定水溫比較
  6.                           通過(guò)PID控制算法調(diào)節(jié),是實(shí)際水溫與設(shè)定水溫接近。從而
  7.                           達(dá)到控制水溫的目的。
  8.         作    者:0903 藺一鋒
  9.         日    期:2010年11月3日
  10. ***************************************************************/
  11. #include<reg52.h>
  12. #include<stdio.h>
  13. #define uchar unsigned char
  14. #define uint unsigned int
  15. sbit s1=P2^0;
  16. sbit s2=P2^1;
  17. sbit s3=P2^2;
  18. sbit s4=P2^3;
  19. sbit s5=P2^4;
  20. sbit ds=P2^5;
  21. sbit beep=P2^6;
  22. sbit rd=P1^0;
  23. sbit rs=P1^1;
  24. sbit wr=P1^2;
  25. sbit lcden=P1^3;
  26. sbit PWM=P1^6;
  27. sbit led1=P1^4;
  28. sbit led2=P1^5;
  29. uchar set_temp,keytemp;
  30. uint temp;
  31. uchar c;
  32. bit flag,flag1,flag2;
  33. float f_temp,t;
  34. int timecount,z;
  35. float KP,KI,KD;
  36. float e1,e2,e3;
  37. float uk,duk;
  38. uchar HighL,HighH,PWMH;
  39. float k;
  40. uchar code table[]={"設(shè)定溫度:"};
  41. uchar code table1[]={"實(shí)測(cè)溫度:"};
  42. uchar code table2[]={"加熱"};
  43. uchar code table3[]={"保溫"};
  44. uchar code table4[]={"作者:0903鋒仔@"};
  45. uchar code table5[]={"系統(tǒng)初始化"};
  46. uchar code table6[]={"measured Temperature"};
  47. uchar code table7[]={"水溫控制系統(tǒng)設(shè)計(jì)"};
  48. uchar code table8[]={"    "};
  49. void delay(uint z)//延時(shí)函數(shù),延時(shí)5ms
  50. {
  51.         uint x,y;
  52.         for(x=z;x>0;x--)
  53.                 for(y=110;y>0;y--);
  54. }
  55. /***************************************
  56.                 鍵盤掃描函數(shù)
  57. 通過(guò)S5,S4,S3,S2,S1鍵來(lái)分別實(shí)現(xiàn)溫度設(shè)定值的
  58. 粗加,粗減,精加,精減,和確定功能。
  59. ***************************************/
  60. void keyscan()
  61. {
  62.         if(set_temp>=100)//將設(shè)定溫度限定在0-100度之間
  63.                 set_temp=100;
  64.         if(set_temp<=0)
  65.                 set_temp=0;
  66.         if(s5==0)//此鍵按下設(shè)定溫度加5
  67.         {
  68.                 delay(10);
  69.                 if(s5==0)
  70.                 {
  71.                         flag1=0;
  72.                         set_temp+=5;
  73.                         if(set_temp>=100)
  74.                         {
  75.                                 set_temp=100;
  76.                                 beep=0;
  77.                                 delay(1000);
  78.                                 beep=1;
  79.                         }
  80.                 }while(s5==0);
  81.         }
  82.         if(s4==0)//此鍵按下設(shè)定溫度減5
  83.         {
  84.                 delay(10);
  85.                 if(s4==0)
  86.                 {
  87.                         flag1=0;
  88.                         set_temp-=5;
  89.                         if(set_temp<=0)
  90.                         {
  91.                                 set_temp=0;
  92.                                 beep=0;
  93.                                 delay(1000);
  94.                                 beep=1;
  95.                         }
  96.                 }while(s4==0);
  97.         }
  98.         if(s3==0)//此鍵按下設(shè)定溫度加1
  99.         {
  100.                 delay(10);
  101.                 if(s3==0)
  102.                 {
  103.                         flag1=0;
  104.                         set_temp++;
  105.                         if(set_temp==100)
  106.                         {
  107.                                 set_temp=100;
  108.                                 beep=0;
  109.                                 delay(1000);
  110.                                 beep=1;
  111.                         }
  112.                 }while(s3==0);
  113.         }
  114.         if(s2==0)//此鍵按下設(shè)定溫度減1
  115.         {
  116.                 delay(10);
  117.                 if(s2==0)
  118.                 {
  119.                         flag1=0;
  120.                         set_temp--;
  121.                         if(set_temp==0)
  122.                         {
  123.                                 set_temp=0;
  124.                                 beep=0;
  125.                                 delay(1000);
  126.                                 beep=1;
  127.                         }
  128.                 }while(s2==0);
  129.         }
  130.         if(s1==0)//確定加熱狀態(tài)(加熱與不加熱)
  131.         {
  132.                 delay(10);
  133.                 if(s1==0)
  134.                 {
  135.                         flag1=1;
  136.                 }
  137.                 while(s1==0);
  138.         }
  139. }        
  140. /******************************************
  141.            DS18B20溫度采集模塊程序設(shè)計(jì)
  142. 通過(guò)DS18B20實(shí)時(shí)采集水溫,反映給單片機(jī)系統(tǒng)
  143. ******************************************/
  144. void dsreset()//DS18B20復(fù)位函數(shù)
  145. {
  146.         uint i;
  147.         ds=0;
  148.         i=103;
  149.         while(i>0)i--;
  150.         ds=1;
  151.         i=4;
  152.         while(i>0)i--;
  153. }
  154. bit tempreadbit()//從DS18B20 RAM讀一位數(shù)據(jù)
  155. {
  156.         uint i;
  157.         bit dat;
  158.         ds=0;i++;
  159.         ds=1;i++;i++;
  160.         dat=ds;
  161.         i=8;while(i>0)i--;
  162.         return(dat);
  163. }
  164. uchar tempread()//從DS18B20 RAM讀一字節(jié)數(shù)據(jù)
  165. {
  166.         uchar i,j,dat;
  167.         dat=0;
  168.         for(i=1;i<=8;i++)
  169.         {
  170.                 j=tempreadbit();
  171.                 dat=(j<<7)|(dat>>1);
  172.         }
  173.         return(dat);
  174. }        
  175. void tempwritebyte(uchar dat)//向DS18B20寫(xiě)以字節(jié)的數(shù)據(jù)
  176. {
  177.         uint i,j;
  178.         bit testb;
  179.         for(j=1;j<=8;j++)
  180.         {
  181.                 testb=dat&0x01;
  182.                 dat=dat>>1;
  183.                 if(testb)//寫(xiě)1
  184.                 {
  185.                         ds=0;
  186.                         i++;i++;
  187.                         ds=1;
  188.                         i=8;while(i>0)i--;
  189.                 }
  190.                 else//寫(xiě)0
  191.                 {
  192.                         ds=0;
  193.                         i=8;while(i>0)i--;
  194.                         ds=1;
  195.                         i++;i++;
  196.                 }
  197.         }
  198. }
  199. /*void readrom()
  200. {
  201.         dsreset();
  202.         delay(1);
  203.         tempwritebyte(0x33);
  204.         tempwritebyte(0xbe);
  205.         readrom=tempread();
  206. }
  207. void matchrom()
  208. {
  209.         dsreset();
  210.         delay(1);
  211.         tempwritebyte(0x55);
  212. }*/
  213. void tempchange()//啟動(dòng)溫度轉(zhuǎn)換
  214. {
  215.         dsreset();
  216.         delay(1);
  217.         tempwritebyte(0xcc);
  218.         tempwritebyte(0x44);
  219. }
  220. float get_temp()//溫度值讀取與處理函數(shù)
  221. {
  222.         uchar a,b;
  223.         dsreset();
  224.         delay(1);
  225.         tempwritebyte(0xcc);
  226.         tempwritebyte(0xbe);
  227.         a=tempread();
  228.         b=tempread();
  229.         temp=b;
  230.         temp<<=8;
  231.         temp=temp|a;
  232.         f_temp=(float)(temp*0.0625);
  233.         f_temp=f_temp*10;
  234.         return(f_temp);
  235. }
  236. /**********************************************
  237.                  12864顯示模塊
  238.    顯示實(shí)際溫度制和設(shè)定溫度值
  239. **********************************************/
  240. void write_com(uchar com)//向12864寫(xiě)指令
  241. {
  242.         rs=0;
  243.         wr=0;
  244.         delay(1);
  245.         P0=com;
  246.         lcden=1;
  247.         delay(1);
  248.         lcden=0;
  249.         delay(1);
  250. }
  251. void write_date(uchar date)//向12864寫(xiě)數(shù)據(jù)
  252. {
  253.         rs=1;
  254.         wr=0;
  255.         delay(1);
  256.         P0=date;
  257.         lcden=1;
  258.         delay(1);
  259.         lcden=0;
  260.         delay(1);
  261. }
  262. void display(float m,uchar n)//顯示設(shè)定溫度、實(shí)測(cè)溫度、加熱狀態(tài)
  263. {
  264.         uint i,j;
  265.         float b;
  266.         float p;
  267.         uchar a1,a2,a3;
  268.         uchar b1,b2,b3,b4;
  269.         if(n<100)
  270.         {
  271.                 a1=0;
  272.                 a2=n/10;
  273.                 a3=n%10;
  274.         }
  275.         else
  276.         {
  277.                 a1=1;
  278.                 a2=0;
  279.                 a3=0;
  280.         }
  281.         p=m;
  282.         j=(uint)(p*10);
  283.         b1=(uchar)(j/1000);
  284.         b2=(uchar)(j%1000/100);
  285.         b3=(uchar)(j%100/10);
  286.         b4=(uchar)(j%10);
  287.         write_com(0x90+5);//顯示設(shè)定溫度
  288.         write_date(0x30+a1);
  289.         write_date(0x30+a2);
  290.         write_date(0x30+a3);
  291.         write_com(0x88+5);//顯示實(shí)測(cè)溫度
  292.         write_date(0x30+b1);
  293.         write_date(0x30+b2);
  294.         write_date(0x2e);
  295.         write_date(0x30+b3);
  296.         write_date(0x30+b4);
  297.         b=((float)(b1*100+b2*10+b3))/10.0;
  298.         i=0;
  299.         if((b+0.2)<n)
  300.         {
  301.                 led1=0;
  302.                 write_com(0x98+1);
  303.                 while(table2[i]!='\0')
  304.                 {
  305.                         write_date(table2[i]);
  306.                         i++;
  307.                 }
  308.                 flag2=1;
  309.         }
  310.         else
  311.         {
  312.                 led1=1;
  313.                 i=0;
  314.                 write_com(0x98+1);
  315.                 while(table8[i]!='\0')
  316.                 {
  317.                         write_date(table8[i]);
  318.                         i++;
  319.                 }
  320.                 i=0;
  321.                 if((b=n)||((b>n)&&((b-0.2)<=n))||((b<n)&&((b+0.2)>=n)))
  322.                 {
  323.                         led2=0;
  324.                         write_com(0x98+4);
  325.                         while(table3[i]!='\0')
  326.                         {
  327.                                 write_date(table3[i]);
  328.                                 i++;
  329.                         }
  330.                 }
  331.         }
  332.         if(flag2==1)
  333.         {
  334.                 flag2=0;
  335.                 led2=1;
  336.                 i=0;
  337.                 write_com(0x98+4);
  338.                 while(table8[i]!='\0')
  339.                 {
  340.                         write_date(table8[i]);
  341.                         i++;
  342.                 }
  343.         }
  344. }
  345. /*****************************************************
  346.                         PID控制算法程序設(shè)計(jì)
  347. 通過(guò)PID控制算法可以使實(shí)際水溫在設(shè)定水溫周圍呈很小范圍的
  348. 波動(dòng),從而使實(shí)際水溫值接近設(shè)定水溫值
  349. *****************************************************/
  350. void conversion()//定時(shí)器2初值處理函數(shù)
  351. {
  352.         uint temp2;
  353.         temp2=65536-PWMH*10;
  354.         HighH=temp2/256;
  355.         HighL=temp2%256;
  356. }
  357. void senddate(float y)
  358. {
  359. //        uint i;
  360.         if(flag==1)
  361.         {
  362.                 ES=0;
  363.                 flag=0;
  364.                 c=0;
  365.                 TI=1;
  366.                 printf("The measured temp:%f",y);
  367. //                SBUF=1;
  368.                 while(!TI);
  369.                 TI=0;
  370.                 ES=1;
  371.         }        
  372. }
  373. void init()//初始化函數(shù)
  374. {
  375.         uint i,j;
  376.         TMOD=0x21;
  377.         TH1=0xfd;
  378.         TL1=0xfd;
  379.         TH0=(65536-50000)/256;
  380.         TL0=(65536-50000)%256;
  381.         PWMH=0;
  382.         conversion();
  383.         TH2=(65536-50000)/256;
  384.         TL2=(65536-50000)%256;
  385.         rd=1;
  386.         lcden=0;
  387.         write_com(0x30);
  388.         write_com(0x0c);
  389.         write_com(0x01);
  390.         write_com(0x90);
  391.         while(table5[i]!='\0')//系統(tǒng)初始化
  392.         {
  393.                 write_date(table5[i]);
  394.                 i++;
  395.                 delay(20);
  396.         }
  397.         for(j=0;j<=1;j++)//6個(gè)點(diǎn)的三次循環(huán)
  398.         {
  399.                 write_com(0x88+4);
  400.                 for(i=0;i<=5;i++)
  401.                 {
  402.                         write_date(0x2e);
  403.                         delay(200);
  404.                 }
  405.                 delay(100);
  406.                 write_com(0x88+4);
  407.                 for(i=0;i<=5;i++)
  408.                 {
  409.                         write_date(0x20);
  410.                 }
  411.                 delay(100);
  412.         }
  413.         i=0;
  414.         write_com(0x80);//顯示 水溫控制系統(tǒng)設(shè)計(jì)標(biāo)題
  415.         while(table7[i]!='\0')
  416.         {
  417.                 write_date(table7[i]);
  418.                 i++;
  419.         }
  420.         i=0;
  421.         write_com(0x90);//顯示 設(shè)定溫度
  422.         while(table[i]!='\0')
  423.         {
  424.                 write_date(table[i]);
  425.                 i++;
  426.         }
  427.         i=0;
  428.         write_com(0x88);//顯示 實(shí)測(cè)溫度
  429.         while(table1[i]!='\0')
  430.         {
  431.                 write_date(table1[i]);
  432.                 i++;
  433.         }
  434. //        tempwritebyte(0x4e);//設(shè)定DS18B20的分辨率為11位
  435. //        tempwritebyte(0x5f);
  436.         PWM=0;
  437.         e1=0;
  438.         e2=0;
  439.         e3=0;
  440.         duk=0;
  441.         uk=0;
  442.         KP=20;//PID控制算法參數(shù)
  443.         KI=0.061;
  444.         KD=30;
  445.         REN=1;//串口通信設(shè)置
  446.         SM0=0;
  447.         SM1=1;
  448.         ET0=1;
  449.         ET2=1;
  450.         TR0=1;
  451.         TR1=1;
  452.         TR2=1;//啟動(dòng)定時(shí)器2
  453.         EA=1;
  454.         ES=1;
  455. }        
  456. void main()
  457. {
  458.         init();
  459.         while(1)
  460.         {
  461.                 keyscan();//調(diào)用鍵盤掃描函數(shù)
  462.                 tempchange();//啟動(dòng)溫度轉(zhuǎn)換
  463.                 t=get_temp();//提取實(shí)測(cè)溫度
  464.                 display(t,set_temp);//顯示設(shè)定溫度和實(shí)測(cè)溫度
  465.                 senddate(t);//向上位機(jī)發(fā)送數(shù)據(jù)函數(shù)
  466.                 if((flag1==1))
  467.                 {
  468.                     if(timecount>=375)
  469.                         {
  470.                                 timecount=0;
  471.                                 e1=set_temp-t;
  472.                                 duk=(KP*(e1-e2)+KI*e1+KD*(e1-2*e2+e3));//PID控制算法式
  473.                             uk=uk+duk;
  474.                                 if(e1>=75)
  475.                                 {
  476.                                         z=4;
  477.                                 }
  478.                                 else if(e1>=50)
  479.                                 {
  480.                                         z=3;
  481. ……………………

  482. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼


所有資料51hei提供下載:
基于51單片機(jī)的水溫控制系統(tǒng).rar (18.56 MB, 下載次數(shù): 916)



評(píng)分

參與人數(shù) 2黑幣 +65 收起 理由
zbfdyw + 15 共享資料的黑幣獎(jiǎng)勵(lì)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏24 分享淘帖 頂4 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:455865 發(fā)表于 2018-12-27 10:38 | 只看該作者
我這份程序在原基礎(chǔ)上做了點(diǎn)修改,添加多了一點(diǎn)注釋,但思路基本一致

PID恒溫修改后.zip

100.24 KB, 下載次數(shù): 315, 下載積分: 黑幣 -5

回復(fù)

使用道具 舉報(bào)

板凳
ID:345098 發(fā)表于 2019-3-20 18:02 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報(bào)

地板
ID:386691 發(fā)表于 2019-4-26 13:13 | 只看該作者
謝謝分享!!
回復(fù)

使用道具 舉報(bào)

5#
ID:487891 發(fā)表于 2019-4-27 15:17 | 只看該作者
學(xué)習(xí)了
回復(fù)

使用道具 舉報(bào)

6#
ID:375715 發(fā)表于 2019-4-27 19:33 來(lái)自觸屏版 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報(bào)

7#
ID:276416 發(fā)表于 2019-5-10 11:33 | 只看該作者
怎么感覺(jué)PWM輸出沒(méi)有變化
回復(fù)

使用道具 舉報(bào)

8#
ID:387410 發(fā)表于 2019-5-13 20:47 來(lái)自觸屏版 | 只看該作者
嗯嗯,謝謝樓主分享,頂起
回復(fù)

使用道具 舉報(bào)

9#
ID:284093 發(fā)表于 2019-8-23 11:42 | 只看該作者
謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

10#
ID:630180 發(fā)表于 2019-10-25 18:03 | 只看該作者
謝謝樓主分享,頂起
回復(fù)

使用道具 舉報(bào)

11#
ID:545065 發(fā)表于 2019-11-27 21:23 | 只看該作者
我問(wèn)一下 這個(gè)電路圖在哪啊
回復(fù)

使用道具 舉報(bào)

12#
ID:603295 發(fā)表于 2019-12-6 23:53 | 只看該作者
頂一個(gè),謝謝樓主
回復(fù)

使用道具 舉報(bào)

13#
ID:556032 發(fā)表于 2020-4-14 23:34 | 只看該作者
感謝,研究中
回復(fù)

使用道具 舉報(bào)

14#
ID:739691 發(fā)表于 2020-4-27 22:39 | 只看該作者
哇.....想自學(xué)單片機(jī),但好難啊.....感覺(jué)就這個(gè)程序我至少要研究一個(gè)星期。
回復(fù)

使用道具 舉報(bào)

15#
ID:413383 發(fā)表于 2020-4-28 00:19 | 只看該作者
謝謝樓主分享,頂起
回復(fù)

使用道具 舉報(bào)

16#
ID:423031 發(fā)表于 2020-5-8 16:14 | 只看該作者
謝謝分享~~~~~~~~~·
回復(fù)

使用道具 舉報(bào)

17#
ID:748312 發(fā)表于 2020-5-10 16:50 | 只看該作者
很棒的資料,下載學(xué)習(xí),謝謝提供
回復(fù)

使用道具 舉報(bào)

18#
ID:748653 發(fā)表于 2020-5-10 22:06 | 只看該作者
除以800是為什么啊
回復(fù)

使用道具 舉報(bào)

19#
ID:302666 發(fā)表于 2020-5-10 23:16 | 只看該作者
厲害啊,我的鍋
回復(fù)

使用道具 舉報(bào)

20#
ID:187802 發(fā)表于 2020-5-12 12:16 | 只看該作者

很棒的資料,下載學(xué)習(xí),謝謝提供
回復(fù)

使用道具 舉報(bào)

21#
ID:754600 發(fā)表于 2020-5-30 22:01 | 只看該作者
沒(méi)有仿真請(qǐng)別下載
回復(fù)

使用道具 舉報(bào)

22#
ID:873326 發(fā)表于 2021-4-18 22:55 來(lái)自觸屏版 | 只看該作者
有仿真原件嗎
回復(fù)

使用道具 舉報(bào)

23#
ID:202793 發(fā)表于 2021-12-10 20:15 | 只看該作者
學(xué)習(xí)了真的高手很多
回復(fù)

使用道具 舉報(bào)

24#
ID:462629 發(fā)表于 2021-12-28 10:23 | 只看該作者
高手太厲害了,這個(gè)能實(shí)用嗎
回復(fù)

使用道具 舉報(bào)

25#
ID:1073609 發(fā)表于 2023-4-23 17:58 來(lái)自觸屏版 | 只看該作者
有模糊pid控制水溫的嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表