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

標題: 單片機PID算法的恒溫控制系統仿真與程序源碼設計(DS18B20傳感器) [打印本頁]

作者: 4564531513    時間: 2018-4-24 10:21
標題: 單片機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)


作者: yzh123    時間: 2018-4-24 20:41
樓主你好,你的pid參數是怎么整定的?
作者: dearluca    時間: 2018-4-25 10:18
謝謝樓主,最近剛好在做這方面的東西
作者: dearluca    時間: 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)
希望樓主有空的話可以賜教一下,謝謝!
作者: HUA1314HL    時間: 2018-6-7 11:17
溫度顯示不出來怎么回事
作者: HUA1314HL    時間: 2018-6-7 12:48
實際測量溫度不顯示誰幫幫我加qq2304146938
作者: HUA1314HL    時間: 2018-6-7 12:49
實際測量溫度不顯示誰幫幫我加qq2304146938
作者: zxr961129    時間: 2018-6-7 21:13
感謝樓主,最近在做畢業設計,需要模糊pid方面的程序和仿真,很高興樓主能夠分享出來!
作者: xiaozhizhidi    時間: 2018-6-14 02:00
樓主流弊
作者: fuzhoudaxuelin    時間: 2018-9-1 19:52
可以嗎???
作者: my411844867mm    時間: 2018-10-9 16:05
求救樓主 仿真的電路板在哪里,我打不開
作者: 單調的唯一的    時間: 2018-12-20 20:58
學習了,下載下來以后試試
作者: 公寓3    時間: 2018-12-20 23:49
謝謝,樓主給力
作者: wzd792124883    時間: 2019-3-12 18:22
樓主你好,你的pid參數是怎么整定的?
作者: jia333    時間: 2019-4-9 10:46
樓主能加QQ聊嗎
作者: jia333    時間: 2019-4-9 10:50
zxr961129 發表于 2018-6-7 21:13
感謝樓主,最近在做畢業設計,需要模糊pid方面的程序和仿真,很高興樓主能夠分享出來!

能互相交流下嗎

作者: jia333    時間: 2019-4-9 11:03
樓主能私聊下嗎

作者: jia333    時間: 2019-4-9 11:04
yzh123 發表于 2018-4-24 20:41
樓主你好,你的pid參數是怎么整定的?

要求精度不高的話通常設置都是一樣的
作者: jia333    時間: 2019-4-10 20:23
有沒有解析呢??
作者: jia333    時間: 2019-4-13 19:45
樓主,沒有降溫處理嗎?
作者: 1124xl    時間: 2019-4-16 21:17
樓主你這個是通過什么加熱裝置加熱的呀
作者: woshini88a    時間: 2019-5-11 15:49
謝謝樓主分享
作者: landing    時間: 2020-5-4 11:14
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。
作者: xdouble    時間: 2020-5-5 10:55
landing 發表于 2020-5-4 11:14
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。

請問你能打開嗎?我打不開,顯示丟失什么文件
作者: xdouble    時間: 2020-5-5 10:56
landing 發表于 2020-5-4 11:14
謝謝,剛好要寫一個恒溫PID控制,可以參考一下。

能否加個QQ傳我 感激不盡
作者: X.dobule    時間: 2020-5-5 11:08
樓主能QQ私聊一下嗎?救助,感激不盡
作者: cba_cba    時間: 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
                        }
作者: w2000000    時間: 2024-10-21 11:32
設計的不錯啊




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 亚洲精品一区二区三区在线观看 | h视频在线观看免费 | 人人看人人干 | 亚洲一区二区三区视频 | 国产成人精品一区 | 亚洲理论在线观看电影 | 国产精品成人国产乱一区 | 精品无码久久久久久国产 | 亚洲精品日韩综合观看成人91 | 三级成人在线观看 | 国产精品成人一区二区三区 | 国产一级成人 | 久久伊人亚洲 | 国产一区二区三区四区 | 久久九九影视 | 在线不卡视频 | 亚洲国产黄色av | 午夜视频网站 | 夜夜操天天干 | 国产成人精品免高潮在线观看 | 在线 丝袜 欧美 日韩 制服 | 久久久福利 | www日本高清| 国产乡下妇女做爰 | 欧美激情亚洲天堂 | 国产成人免费网站 | 久久久精彩视频 | 国产精品区一区二区三区 | 97av在线| 日韩一区二区三区视频在线播放 | 91免费在线视频 | 久久久久无码国产精品一区 | 成人在线播放网站 | 欧美日韩在线精品 | 四虎影音 | 日日做夜夜爽毛片麻豆 | 日韩精品免费视频 | 国产欧美日韩一区二区三区 | 国产在线一级片 | 精品欧美| 综合伊人 |