久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 15144|回復: 27
打印 上一主題 下一主題
收起左側

單片機PID算法的恒溫控制系統仿真與程序源碼設計(DS18B20傳感器)

  [復制鏈接]
跳轉到指定樓層
#
樓主做的基于51單片機主控的PID算法的恒溫控制系統,帶加熱指示燈與遞增和遞減按鈕.采用DS18B20做的溫度傳感器

電路原理圖如下:


仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


恒溫控制系統實物圖:


pcb圖:




恒溫控制系統的單片機源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #include<math.h>
  4. #include<string.h>
  5. struct PID {
  6. unsigned int SetPoint; // 設定目標 Desired Value
  7. unsigned int Proportion; // 比例常數 Proportional Const
  8. unsigned int Integral; // 積分常數 Integral Const
  9. unsigned int Derivative; // 微分常數 Derivative Const
  10. unsigned int LastError; // Error[-1]
  11. unsigned int PrevError; // Error[-2]
  12. unsigned int SumError; // Sums of Errors
  13. };
  14. struct PID spid; // PID Control Structure
  15. unsigned int rout; // PID Response (Output) 響應輸出
  16. unsigned int rin; // PID Feedback (Input)//反饋輸入
  17. unsigned char high_time,low_time,count=0;//占空比調節參數
  18. #define uchar unsigned char
  19. #define uint unsigned int

  20. sbit output=P1^0;
  21. sbit ds=P3^2;
  22. sbit DQ=P3^2;//ds18b20與單片機連接口
  23. sbit lcden=P2^7;//LCE使能引腳
  24. sbit lcdrs=P2^5;
  25. sbit lcdrw=P2^6;
  26. sbit ledred=P1^6;
  27. sbit ledgreen=P1^7;

  28. sbit key0=P2^0;//按鍵引腳
  29. sbit key1=P2^1;

  30. uchar set[2]={0};
  31. uchar code str1[]="now temp:      C";
  32. uchar code str2[]="set temp:      C";
  33. uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
  34. uchar n,num;
  35. int set_temper=30,temper,temp; //溫度變量定義
  36. unsigned int s;
  37. float         f_temp;//轉換后的溫度

  38. uint tvalue;         
  39. uchar tflag;//溫度正負標志

  40. void delay(i)//延時函數
  41. {
  42.         uint j;
  43.         for(i;i>0;i--)
  44.         for(j=110;j>0;j--);
  45. }


  46. void wr_com(uchar ml)//寫命令
  47. {
  48.         lcdrs=0;
  49.         P0=ml;
  50.         delay(5);
  51.         lcden=1;
  52.         delay(5);
  53.         lcden=0;

  54. }



  55. void wr_data(uchar shuju)//寫數據
  56. {
  57.         lcdrs=1;
  58.         //lcden=1;
  59.         P0=shuju;
  60.         delay(5);
  61.         lcden=1;
  62.         delay(5);
  63.         lcden=0;

  64. }

  65. void init()  //按照時序操作的初始化
  66. {        
  67.         lcdrw=0;
  68.         wr_com(0x38);//顯示模式設置,設置為16*2顯示,5*7點陣,八位數據口
  69.         wr_com(0x0c);//開顯示,但不開光標,光標不閃
  70.         wr_com(0x06);//顯示光標移動設置
  71.         wr_com(0x01);// 清屏
  72.         wr_com(0x80);        // 數據指針初始化
  73.         for(num=0;num<16;num++)
  74.                 {
  75.                         wr_data(str1[num]);//now temp
  76.                 }
  77.         wr_com(0x80+0x40); //地址初始化
  78.         for(num=0;num<16;num++)
  79.                 {
  80.                         wr_data(str2[num]);//set temp
  81.                 }         
  82. }

  83. /*************************DS1820程序****************************/
  84. void delay_18B20(unsigned int i)//延時1微秒
  85. {
  86.    while(i--);
  87. }

  88. void ds1820rst(void)/*ds1820復位*/
  89. {
  90.         unsigned char x=0;
  91.         DQ = 1;          //DQ復位
  92.         delay_18B20(4); //延時
  93.         DQ = 0;          //DQ拉低
  94.    TR0=0;
  95.         delay_18B20(100); //精確延時大于
  96.    TR0=1;
  97.         DQ = 1;          //拉高
  98.         delay_18B20(40);
  99. }

  100. uchar ds1820rd(void)/*讀數據*/
  101. {
  102.         unsigned char i=0;
  103.         unsigned char dat = 0;
  104.    TR0=0;
  105.         for (i=8;i>0;i--)
  106.         {   
  107.                 DQ = 0; //給脈沖信號
  108.                 dat>>=1;
  109.                 DQ = 1; //給脈沖信號
  110.                 if(DQ)
  111.                 dat|=0x80;
  112.                 delay_18B20(10);
  113.         }
  114.    return(dat);
  115. }

  116. void ds1820wr(uchar wdata)/*寫數據*/
  117. {
  118.         unsigned char i=0;
  119.    TR0=0;
  120.    for (i=8; i>0; i--)
  121.    {
  122.                 DQ = 0;
  123.                 DQ = wdata&0x01;
  124.                 delay_18B20(10);
  125.                 DQ = 1;
  126.                 wdata>>=1;
  127.    }
  128. }



  129. uint get_temper()//獲取溫度
  130. {  
  131.      
  132.         uchar a,b;

  133.         ds1820rst();   
  134.         ds1820wr(0xcc);//*跳過讀序列號*/
  135.         ds1820wr(0x44);//*啟動溫度轉換*/
  136.         ds1820rst();   
  137.         ds1820wr(0xcc);//*跳過讀序列號*/
  138.         ds1820wr(0xbe);//*讀取溫度*/
  139.         a=ds1820rd();
  140.         b=ds1820rd();
  141.    
  142.         tvalue=b;
  143.         tvalue<<=8;
  144.         tvalue=tvalue|a;
  145.    TR0=1;
  146.    if(tvalue<0x0fff)   tflag=0;
  147.    else {tvalue=~tvalue+1;tflag=1;}
  148.         tvalue=tvalue*(0.625);//溫度值擴大10倍,精確到1位小數
  149.         temp=tvalue;
  150.         return temp;
  151. }


  152. void dis_temp(int t)//顯示溫度
  153. {
  154.         uchar d0,d1,d2,d3;
  155.         //t=26;
  156.         if(tflag==0)
  157.         {
  158.                 d0=t/1000+0x30;
  159.                 d1=t%1000/100+0x30;
  160.                 d2=t%100/10+0x30;
  161.                 d3=t%10+0x30;
  162.                 if(d0==0x30)
  163.                 {
  164.                         wr_com(0x80+9);
  165.                         wr_data(d1);
  166.                         wr_com(0x80+10);
  167.                         wr_data(d2);
  168.                         wr_com(0x80+11);
  169.                         wr_data(0x2e);
  170.                         wr_com(0x80+12);
  171.                         wr_data(d3);
  172.                 }
  173.                 else
  174.                 {
  175.                         wr_com(0x80+9);
  176.                         wr_data(d0);
  177.                         wr_com(0x80+10);
  178.                         wr_data(d1);
  179.                         wr_com(0x80+11);
  180.                         wr_data(d2);
  181.                         wr_com(0x80+12);
  182.                         wr_data(' ');
  183.                 }
  184.                
  185.         }
  186.         else
  187.         {
  188.                 wr_com(0x80+9);
  189.                 wr_data('-');
  190.                 wr_com(0x80+10);
  191.                 wr_data(d1);
  192.                 wr_com(0x80+11);
  193.                 wr_data(d2);
  194.                 wr_com(0x80+12);
  195.                 wr_data(' ');
  196.                 //wr_com(0x80+12);
  197.                 //wr_data(d3);
  198.         }
  199.         wr_com(0x80+14);
  200.         wr_data(0xdf);
  201.         temper=t/10;
  202. }



  203. void keyscan()//鍵盤掃描
  204. {  

  205.    if(key0==0)
  206.    {
  207.                 delay(1);
  208.                 if(key0==0)
  209.                 {
  210.                         while(!key0);
  211.                         delay(1);
  212.                         while(!key0);
  213.                         set_temper++;

  214.                 }

  215.                 set[0]=set_temper/10;        //獲得設置溫度顯示值
  216.                 set[1]=set_temper%10;
  217.                 wr_com(0x80+0x40+9);
  218.                 wr_data(table[set[0]]);
  219.                 delay(1);
  220.                 wr_com(0x80+0x40+10);
  221.                 wr_data(table[set[1]]);
  222.                 delay(1);
  223.                 //wr_com(0x80+0x40+11);
  224.                 //wr_data(0x2e);
  225.                 //wr_com(0x80+0x40+14);
  226.                 //wr_data(0xdf);
  227.                 delay(1);
  228.         }
  229.         if(key1==0)
  230.    {
  231.                 delay(3);//延時去抖
  232.                 if(key1==0)
  233.                 {
  234.                         while(!key1);
  235.                         delay(3);
  236.                         while(!key1);
  237.                         set_temper--;//溫度減
  238.                         if(set_temper==0)
  239.                         {set_temper=0;}
  240.                 }

  241.         
  242.                 set[0]=set_temper/10;        //獲得設置溫度顯示值
  243.                 set[1]=set_temper%10;
  244.                 wr_com(0x80+0x40+9);        //顯示設置溫度值
  245.                 wr_data(table[set[0]]);
  246.                 delay(1);
  247.                 wr_com(0x80+0x40+10);
  248.                 wr_data(table[set[1]]);
  249.                 delay(1);
  250.                 //wr_com(0x80+0x40+11);
  251.                 //wr_data(0x2e);
  252.                 wr_com(0x80+0x40+14);
  253.                 wr_data(0xdf);
  254.                 delay(1);
  255.         }
  256. }

  257. void PIDInit (struct PID *pp)
  258. {
  259.         memset ( pp,0,sizeof(struct PID)); //用參數0初始化pp
  260. }



  261. unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) //PID計算
  262. {
  263.         unsigned int dError,Error;
  264.         Error = pp->SetPoint - NextPoint; // 偏差
  265.         pp->SumError += Error; // 積分
  266.         dError = pp->LastError - pp->PrevError; // 當前微分
  267.         pp->PrevError = pp->LastError;
  268.         pp->LastError = Error;
  269.         return (pp->Proportion * Error//比例
  270.         + pp->Integral * pp->SumError  //積分項
  271.         + pp->Derivative * dError); //   微分項
  272. }
  273. /***********************************************************
  274. 溫度比較處理子程序
  275. ***********************************************************/
  276. void compare_temper(void)
  277. {
  278.         unsigned char i;
  279.         if(set_temper>temper)         //設置溫度大于當前溫度
  280.         {
  281.                 ledred=0;
  282.                 ledgreen=1;
  283.                 if(set_temper-temper>1)         //溫度相差1度以上
  284.                 {         
  285.                         high_time=100;
  286.                         low_time=0;
  287.                 }
  288.                 else         //設置溫度不大于當前溫度
  289.                 {
  290.                         for(i=0;i<10;i++)
  291.                         {
  292.                                 get_temper();
  293.                                 rin = s; // Read Input
  294.                                 rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  295.                         }
  296.                         if (high_time<=100)         high_time=(unsigned char)(rout/800);
  297.                         else        high_time=100;
  298.                         low_time= (100-high_time);
  299.                 }
  300.         }
  301.         else if(set_temper<=temper)         //設置溫度不大于當前溫度
  302.         {
  303.                 ledred=1;
  304.                 ledgreen=0;
  305.                 if(temper-set_temper>0) //溫度相差0度以上
  306.                 {
  307.                         high_time=0;
  308.                         low_time=100;
  309.                 }
  310.                 else
  311.                 {
  312.                         for(i=0;i<10;i++)
  313.                         {
  314.                                 get_temper();
  315.                                 rin = s; // Read Input
  316.                                 rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  317.                         }
  318.                         if (high_time<100) high_time=(unsigned char)(rout/10000);
  319.                         else         high_time=0;
  320.                         low_time= (100-high_time);
  321.                 }
  322.         }
  323. }
  324. /*****************************************************
  325. T0中斷服務子程序,用于控制電平的翻轉 ,40us*100=4ms周期
  326. ******************************************************/
  327. void serve_T0() interrupt 1 using 1
  328. {
  329.         if(++count<=(high_time))         output=0;
  330.         else if(count<=100)
  331.         {
  332.                 output=1;
  333.         }
  334.         else count=0;
  335.         TH0=0x2f;
  336.         TL0=0x40;
  337. }


  338. /***********主函數**********/
  339. void main(void)
  340. {
  341.         unsigned char i;
  342.         init();//LCD初始化
  343.         TMOD=0x01;
  344.         TH0=0x2f;
  345.         TL0=0x40;
  346.         EA=1;
  347.         ET0=1;
  348.         TR0=1;
  349.         high_time=50;
  350.         low_time=50;
  351.         PIDInit ( &spid ); // Initialize Structure
  352.         spid.Proportion= 10; // Set PID Coefficients
  353.         spid.Integral = 8;
  354.         spid.Derivative =6;
  355.         spid.SetPoint =100; // Set PID Setpoint
  356.         set[0]=set_temper/10;
  357.         set[1]=set_temper%10;
  358.         wr_com(0x80+0x40+9);        //顯示設置溫度
  359.         wr_data(table[set[0]]);
  360.    delay(1);
  361.         wr_com(0x80+0x40+10);
  362. ……………………

  363. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
1DS18B20 控溫 源程序.rar (95.34 KB, 下載次數: 586)
仿真.rar (24.19 KB, 下載次數: 459)

評分

參與人數 3黑幣 +85 收起 理由
liwenyi666 + 30 樓主能加個QQ私聊一下嗎
dearluca + 5 回帖助人的獎勵!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

27#
ID:1134216 發表于 2024-10-21 11:32 | 只看該作者
設計的不錯啊
回復

使用道具 舉報

26#
ID:336378 發表于 2022-3-30 15:11 | 只看該作者
                        for(i=0;i<10;i++)
                        {
                                s=get_temper();//取得現在的溫度。
                                rin = s; // Read Input
                                rout = PIDCalc ( &spid,rin ); // Perform PID Interation
                        }
回復

使用道具 舉報

25#
ID:739402 發表于 2020-5-5 11:08 | 只看該作者
樓主能QQ私聊一下嗎?救助,感激不盡
回復

使用道具 舉報

24#
ID:732724 發表于 2020-5-5 10:56 來自手機 | 只看該作者
landing 發表于 2020-5-4 11:14
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。

能否加個QQ傳我 感激不盡
回復

使用道具 舉報

23#
ID:732724 發表于 2020-5-5 10:55 來自手機 | 只看該作者
landing 發表于 2020-5-4 11:14
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。

請問你能打開嗎?我打不開,顯示丟失什么文件
回復

使用道具 舉報

22#
ID:739026 發表于 2020-5-4 11:14 | 只看該作者
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。
回復

使用道具 舉報

21#
ID:491642 發表于 2019-5-11 15:49 | 只看該作者
謝謝樓主分享
回復

使用道具 舉報

20#
ID:509991 發表于 2019-4-16 21:17 | 只看該作者
樓主你這個是通過什么加熱裝置加熱的呀
回復

使用道具 舉報

19#
ID:507638 發表于 2019-4-13 19:45 | 只看該作者
樓主,沒有降溫處理嗎?
回復

使用道具 舉報

18#
ID:507638 發表于 2019-4-10 20:23 | 只看該作者
有沒有解析呢??
回復

使用道具 舉報

17#
ID:507638 發表于 2019-4-9 11:04 | 只看該作者
yzh123 發表于 2018-4-24 20:41
樓主你好,你的pid參數是怎么整定的?

要求精度不高的話通常設置都是一樣的
回復

使用道具 舉報

16#
ID:507638 發表于 2019-4-9 11:03 | 只看該作者
樓主能私聊下嗎
回復

使用道具 舉報

15#
ID:507638 發表于 2019-4-9 10:50 | 只看該作者
zxr961129 發表于 2018-6-7 21:13
感謝樓主,最近在做畢業設計,需要模糊pid方面的程序和仿真,很高興樓主能夠分享出來!

能互相交流下嗎
回復

使用道具 舉報

14#
ID:507638 發表于 2019-4-9 10:46 | 只看該作者
樓主能加QQ聊嗎
回復

使用道具 舉報

13#
ID:489404 發表于 2019-3-12 18:22 | 只看該作者
樓主你好,你的pid參數是怎么整定的?
回復

使用道具 舉報

12#
ID:450056 發表于 2018-12-20 23:49 來自手機 | 只看該作者
謝謝,樓主給力
回復

使用道具 舉報

11#
ID:245429 發表于 2018-12-20 20:58 | 只看該作者
學習了,下載下來以后試試
回復

使用道具 舉報

10#
ID:407060 發表于 2018-10-9 16:05 | 只看該作者
求救樓主 仿真的電路板在哪里,我打不開
回復

使用道具 舉報

9#
ID:280466 發表于 2018-9-1 19:52 | 只看該作者
可以嗎???
回復

使用道具 舉報

8#
ID:340241 發表于 2018-6-14 02:00 | 只看該作者
樓主流弊
回復

使用道具 舉報

7#
ID:304629 發表于 2018-6-7 21:13 | 只看該作者
感謝樓主,最近在做畢業設計,需要模糊pid方面的程序和仿真,很高興樓主能夠分享出來!
回復

使用道具 舉報

6#
ID:323102 發表于 2018-6-7 12:49 | 只看該作者
實際測量溫度不顯示誰幫幫我加qq2304146938
回復

使用道具 舉報

5#
ID:323102 發表于 2018-6-7 12:48 | 只看該作者
實際測量溫度不顯示誰幫幫我加qq2304146938
回復

使用道具 舉報

地板
ID:323102 發表于 2018-6-7 11:17 | 只看該作者
溫度顯示不出來怎么回事
回復

使用道具 舉報

板凳
ID:311660 發表于 2018-4-25 19:37 | 只看該作者
樓主我想對你的程序提幾個問題。在你的溫度比較處理子程序里面有一段程序是這樣的if(set_temper>temper)         //設置溫度大于當前溫度
        {
                ledred=0;
                ledgreen=1;
                if(set_temper-temper>1)         //溫度相差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);
  請問一下rin=s是不是表示的是PID的回饋輸入,那么既然如此的話rin不應該是等于輸出的溫度嗎?為什么是s呢?我看了一下程序除了一開始的定義unsigned int s;和剛剛那個地方s就沒有別的用處了。
      else         //設置溫度不大于當前溫度     這一條語句的注釋也不是很明白。  這個else是在if(set_temper-temper>1)         //溫度相差1度以上      這條語句后面,那么我感覺他的注釋應該是     溫度相差小于一度
      最后的話是這一句  if (high_time<=100)         high_time=(unsigned char)(rout/800);
                        else        high_time=100;
                        low_time= (100-high_time);整個都不太明白 ,特別是(rout/800)
希望樓主有空的話可以賜教一下,謝謝!

評分

參與人數 1黑幣 +80 收起 理由
admin + 80 贊一個!

查看全部評分

回復

使用道具 舉報

沙發
ID:311660 發表于 2018-4-25 10:18 | 只看該作者
謝謝樓主,最近剛好在做這方面的東西
回復

使用道具 舉報

樓主
ID:314339 發表于 2018-4-24 20:41 來自手機 | 只看該作者
樓主你好,你的pid參數是怎么整定的?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜影院在线观看 | 天天久久 | 亚洲精品2区 | 精品中文字幕一区二区三区 | 亚洲欧美一区二区三区视频 | 欧美不卡在线 | 国产分类视频 | 久久精品二区 | 国产精品久久久久久238 | 国产精品久久久久aaaa九色 | 日韩精品一区二区三区视频播放 | av首页在线| 国产精品久久久久久久久免费桃花 | 鲁一鲁资源影视 | 国产精品亚洲第一区在线暖暖韩国 | 日韩一区在线播放 | 久久久久国产一级毛片高清网站 | 黄色免费av | 特级做a爰片毛片免费看108 | 九九精品网 | 男人av网| 国产精品一级 | 7799精品视频天天看 | 欧美一级在线免费观看 | 密色视频| 一区二区不卡视频 | 欧美日韩国产高清 | 久久久免费在线观看 | 国产激情视频在线免费观看 | 国产丝袜一区二区三区免费视频 | 在线播放91| 欧美最猛黑人xxxⅹ 粉嫩一区二区三区四区公司1 | 国产欧美一区二区三区在线看蜜臀 | 国产yw851.c免费观看网站 | 亚洲视频一区在线观看 | 亚洲人人 | 日韩在线电影 | 色综合久久久 | 久草青青草 | 欧美日韩精品一区二区三区蜜桃 | 免费福利视频一区二区三区 |