找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 31412|回复: 58
收起左侧

PID控制的单片机炉温控制系统源码和Proteus仿真

  [复制链接]
ID:207506 发表于 2017-6-4 15:04 | 显示全部楼层 |阅读模式
功能要求:
1)    采用液晶显示器显示温度测量值。
2)    检测的温度范围为0~128
3)    温度超过警戒值时能报警提示。
4)  能通过键盘输入设定温度并显示。
5)  用PID控制温度,控温精度≦±2
DS18B20温度显示仿真如图DS18B20的值可以任意调整,模拟温度的采集,LCD的显示值随DS18B20的温度值变化而变化。当温度超过界限,LED亮,同时SOUNDER响,模拟警报系统。当按下k1,显示温度的最高位光标开始闪烁,进入设定温度调整,按下k2,光标右移,按下k3数值加1,按下k4数值减1

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):

PID控制仿真图

PID控制仿真图

DS18B20仿真图

DS18B20仿真图


PID控制仿真如图,电加热炉OVEN输出的模拟量经ADC0804转化成数字量,再送到LCD显示。OVEN的温度与设定温度在单片机内进行PID运算,PID输出量控制晶闸管的导通,从而控制OVEN的加热。

0.png

下面是51单片机的源码:                  
  1. #include<reg52.h>
  2. #include<math.h>
  3. float R;
  4. float Kp;
  5. float T;
  6. float Ti;
  7. float Td;
  8. float e2;
  9. float e1,e;
  10. float a0,a1,a2;
  11. #define ui unsigned int
  12. #define uc unsigned char
  13. sbit bj=P2^4;                             //低电平报警模块工作
  14. sbit lcden=P2^7;                         //LCD E
  15. sbit lcdrs=P2^6;                         //LCD    RS
  16. sbit lcdrw=P2^5; //                         //LCD RW
  17. sbit control=P2^3;                         //加热模块相关。低电平启动
  18. char lshi,lge,hshi,hge;
  19. uc num,flag;
  20. ui temp;
  21. sbit dsio=P3^7;                            //DS18B20输入口
  22. //延时
  23. void delay(ui z)
  24. {
  25.     uc x,y;
  26.     for(x=z;x>0;x--)
  27.         for(y=110;y>0;y--);
  28. }
  29. //DS18B20控制
  30. void dsinit()
  31. {
  32.     uc i;
  33.     dsio=0;
  34.     i=70;
  35.     while(i--);
  36.     dsio=1;
  37.     i=4;
  38.     while(i--);
  39. }
  40. void dswritebyte(uc dat)
  41. {
  42.     uc i,j;
  43.     for(j=0;j<8;j++)
  44.     {
  45.         dsio=0;
  46.         i++;
  47.         dsio=dat&0x01;
  48.         i=6;
  49.         while(i--);
  50.         dsio=1;
  51.         dat>>=1;
  52.     }
  53. }
  54. uc dsreadbyte()
  55. {
  56.     uc i,j,byte,b;
  57.     for(j=0;j<8;j++)
  58.     {
  59.         dsio=0;
  60.         i++;
  61.         dsio=1;
  62.         i++;i++;
  63.         b=dsio;
  64.         byte=(byte>>1)|(b<<7);
  65.         i=4;
  66.         while(i--);
  67.     }
  68.     return byte;
  69. }
  70. void dschangetemp()
  71. {
  72.     dsinit();
  73.     delay(1);
  74.     dswritebyte(0xcc);
  75.     dswritebyte(0x44);

  76. }
  77. void dsreadtemp()
  78. {
  79.     dsinit();
  80.     delay(1);
  81.     dswritebyte(0xcc);
  82.     dswritebyte(0xbe);
  83. }
  84. ui gettemp()
  85. {
  86.     int temp;
  87.     uc h,l;
  88.     dschangetemp();
  89.     dsreadtemp();
  90.     l=dsreadbyte();
  91.     h=dsreadbyte();
  92.     temp=h;
  93.     temp<<=8;
  94.     temp|=l;
  95.     temp=temp*0.0625*100+0.5;
  96.     return temp;
  97. }
  98. //LCD控制程序
  99. void lcdwritecom(uc com)
  100. {
  101.     lcdrs=0;
  102.     P0=com;
  103.     delay(10);
  104.     lcden=1;
  105.     delay(10);
  106.     lcden=0;
  107. }
  108. void lcdwritedata(uc date)
  109. {
  110.     lcdrs=1;
  111.     P0=date;
  112.     delay(10);
  113.     lcden=1;
  114.     delay(10);
  115.     lcden=0;
  116. }
  117. void lcdinit()
  118. {
  119.     lcdrw=0;
  120.     lcden=0;
  121.     lcdwritecom(0x38);
  122.     lcdwritecom(0x0c);
  123.     lcdwritecom(0x06);
  124.     lcdwritecom(0x01);
  125. }
  126. //LCD显示
  127. void lcddisplay(int temp)
  128. {
  129.     ui  tab[]={0,0,0,-2,0,0};
  130.     lcdwritecom(0x80);
  131.     lcdwritedata('+');
  132.     tab[0]=temp/10000;
  133.     tab[1]=temp%10000/1000;
  134.     tab[2]=temp%1000/100;
  135.     tab[4]=temp%100/10;
  136.     tab[5]=temp%10;
  137.     lcdwritecom(0x81);
  138.     for(num=0;num<6;num++)
  139.     {
  140.         lcdwritedata('0'+tab[num]);
  141.     }
  142. }

  143. void adjust()
  144. {
  145.     delay(100);
  146.     flag++;
  147.     if(flag==5)flag=1;
  148.     if(flag==1)
  149.     {
  150.         lcdwritecom(0x80+0x44);
  151.         lcdwritecom(0x0f);   
  152.      }
  153.      if(flag==2)
  154.     {
  155.         lcdwritecom(0x80+0x45);
  156.         lcdwritecom(0x0f);   
  157.      }
  158.     if(flag==3)
  159.     {
  160.         lcdwritecom(0x80+0x47);
  161.         lcdwritecom(0x0f);   
  162.      }
  163.     if(flag==4)
  164.     {
  165.         lcdwritecom(0x80+0x48);
  166.         lcdwritecom(0x0f);   
  167.      }
  168. }
  169. void inc()
  170. {
  171.     delay(100);
  172.     switch(flag)
  173.     {
  174.         case 1:lshi++; if(lshi==10)lshi=0;
  175.                         lcdwritedata('0'+lshi);
  176.                         lcdwritecom(0x10);
  177.                         break;
  178.         case 2:lge++; if(lge==10)lge=0;
  179.                         lcdwritedata('0'+lge);
  180.                         lcdwritecom(0x10);
  181.                         break;
  182.         case 3:hshi++; if(hshi==10)hshi=0;
  183.                         lcdwritedata('0'+hshi);
  184.                         lcdwritecom(0x10);
  185.                         break;
  186.         case 4:hge++; if(hge==10)hge=0;
  187.                         lcdwritedata('0'+hge);
  188.                         lcdwritecom(0x10);
  189.                         break;
  190.     }
  191. }
  192. void dec()
  193. {
  194.     delay(100);
  195.     switch(flag)
  196.     {
  197.         case 1:lshi--; if(lshi<0)lshi=9;
  198.                         lcdwritedata('0'+lshi);
  199.                         lcdwritecom(0x10);
  200.                         break;
  201.         case 2:lge--; if(lge<0)lge=9;
  202.                         lcdwritedata('0'+lge);
  203.                         lcdwritecom(0x10);
  204.                         break;
  205.         case 3:hshi--; if(hshi<0)hshi=9;
  206.                         lcdwritedata('0'+hshi);
  207.                          lcdwritecom(0x10);
  208.                         break;
  209.         case 4:hge--; if(hge<0)hge=9;
  210.                         lcdwritedata('0'+hge);
  211.                          lcdwritecom(0x10);
  212.                         break;
  213.     }
  214. }
  215. //键盘扫描
  216. void keyscan()
  217. {
  218.     uc test,num;
  219.     num=0;
  220.     test=P1;
  221.     if(test!=0xff)
  222.     delay(5);
  223.     test=P1;
  224.     if(test==0xf7)
  225.    
  226.     {
  227.         while(P1!=0xff);
  228.         num++;
  229.         while(1)
  230.         {
  231.             test=P1;
  232.             if(test!=0xff)
  233.             delay(5);
  234.             test=P1;
  235.             if(test!=0xff)
  236.             {
  237.                 if(test==0xf7)
  238.                     num++;
  239.                     if(num==2)
  240.                     {    lcdwritecom(0x0c);
  241.                         break;}
  242.                 switch(test)
  243.                 {
  244.                     case 0xfe:adjust();   
  245.                             break;
  246.                     case 0xfd:inc();
  247.                             break;
  248.                     case 0xfb:dec();
  249.                             break;
  250.                 }
  251.              }
  252.             while(P1!=0xff);
  253.         
  254.         }
  255.         }
  256. }
  257. //PID
  258. void PIDinit()
  259. {
  260.       
  261.        Kp=2;Ti=4;Td=1;T=1;R=25;
  262.        a0=Kp*(1+T/Ti+Td/T);
  263.        a1=-Kp*(1+(2*Td)/T);
  264.        a2=Kp*(Td/T);
  265.        e2=e1=0;
  266. }
  267. void PIDdeal()
  268. {
  269.     float y    ,u ;
  270.     y=gettemp();
  271.     e=y/100-R;
  272.     u=a0*e+a1*e1+a2*e2;
  273.     e2=e1;e1=e;
  274.     if(u>0.5||u<-0.5)
  275.     control=0;
  276.     else control=1;
  277. }
  278. void main()
  279. {
  280.     uc code tab2[]="SET:20~80C";
  281.     uc i;
  282.     TMOD=0x01;
  283.     TH0=(65535-10900)/256;
  284.     TL0=(65535-10900)%256;
  285.     ET0=1;
  286.     TR0=1;
  287.     lcdinit();
  288.     lcdwritecom(0x87);
  289.     lcdwritedata('C');
  290.     lcdwritecom(0x80+0x40);
  291.     for(i=0;i<10;i++)
  292.         lcdwritedata(tab2[i]) ;
  293.     lshi=2;lge=0;hshi=5;hge=0;
  294.     while(1)
  295.     {
  296.         lcddisplay(gettemp());
  297.         keyscan() ;
  298.         EA=1; while(1);
  299.     }
  300. }
  301. void t0() interrupt 1
  302. {   
  303.     uc i;
  304.     TH0=(65535-10900)/256;
  305.     TL0=(65535-10900)%256;
  306.     i++;
  307.     if(i==100)
  308.     {
  309.        void PIDinit();
  310.        void PIDdeal();
  311.     }
  312. }
复制代码

上文是网上转载的给大家学习参考的,附件里面是我自己弄的,目前不成功,调试了好几天了,搞不定,求大神指导如何修改?
仿真失败的程序,求大神帮忙指导修改.7z (236.78 KB, 下载次数: 1193)

评分

参与人数 2黑币 +110 收起 理由
a920051220 + 10 很给力!
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:159139 发表于 2017-6-5 00:34 来自手机 | 显示全部楼层
谢谢分享,学习学习pID控制。
回复

使用道具 举报

ID:229561 发表于 2017-8-27 16:54 | 显示全部楼层
Node #00087 not found whilst binding pin V+ of U4_U10_ADC#0001!
仿真出现上述错误,请问是什么原因呢?
我的proteus版本是7.8
回复

使用道具 举报

ID:217820 发表于 2017-8-28 10:41 | 显示全部楼层
源程序有问题
回复

使用道具 举报

ID:126422 发表于 2017-11-4 09:48 | 显示全部楼层
楼主 pid在单片机中的运算,讲讲。
回复

使用道具 举报

ID:249705 发表于 2017-11-21 16:22 | 显示全部楼层

怎么解决?
回复

使用道具 举报

ID:249705 发表于 2017-11-21 16:27 | 显示全部楼层

楼主 是不是少了什么原件?
回复

使用道具 举报

ID:249705 发表于 2017-11-21 16:29 | 显示全部楼层
alphacrux 发表于 2017-8-27 16:54
Node #00087 not found whilst binding pin V+ of U4_U10_ADC#0001!
仿真出现上述错误,请问是什么原因呢 ...

你是怎么解决这个问题的?
回复

使用道具 举报

ID:264448 发表于 2017-12-20 21:02 | 显示全部楼层
海里没有大鲨鱼 发表于 2017-11-21 16:29
你是怎么解决这个问题的?

解决了吗
回复

使用道具 举报

ID:267327 发表于 2018-1-16 22:09 | 显示全部楼层
这个资料真好。可以做成品了。
回复

使用道具 举报

ID:278622 发表于 2018-1-23 11:09 | 显示全部楼层
为什么程序运行不了,仿真也运行不了
回复

使用道具 举报

ID:304318 发表于 2018-4-9 11:37 来自手机 | 显示全部楼层
怎么自动调节啊
回复

使用道具 举报

ID:57831 发表于 2018-4-13 00:37 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:311868 发表于 2018-5-7 21:26 来自手机 | 显示全部楼层
谢谢楼主的分享,我试试看能不能仿真出来。
回复

使用道具 举报

ID:289258 发表于 2018-5-11 00:15 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:295874 发表于 2018-5-11 08:57 | 显示全部楼层
果然是好资料,打算下载下俩看看
回复

使用道具 举报

ID:330939 发表于 2018-5-17 13:31 | 显示全部楼层
运行后无法设置温度,加热装置也不工作,蜂鸣器一直在报警
回复

使用道具 举报

ID:327959 发表于 2018-5-22 13:47 | 显示全部楼层
程序有问题。
回复

使用道具 举报

ID:324374 发表于 2018-5-22 19:32 | 显示全部楼层
alphacrux 发表于 2017-8-27 16:54
**** 作者被禁止或删除 内容自动屏蔽 ****

运行不了是因为下载回来的protues图中adc0804有几个引脚的网络标号没有标上,可以参照楼主的截图自行添加
回复

使用道具 举报

ID:327959 发表于 2018-5-23 16:56 | 显示全部楼层
这个有问题。
回复

使用道具 举报

ID:336840 发表于 2018-5-23 21:04 | 显示全部楼层
正好需要,就是不知道能不能完成整个仿真
回复

使用道具 举报

ID:353526 发表于 2018-6-19 20:42 来自手机 | 显示全部楼层
能运行,lcd不显示,有哪位可以解释一下吗?
回复

使用道具 举报

ID:466140 发表于 2019-1-10 21:03 | 显示全部楼层
谢谢分享,学习学习pID控制。
回复

使用道具 举报

ID:217128 发表于 2019-1-16 15:17 | 显示全部楼层
楼主能不能注释下代码!PIDInit()和PIDDeal()看不懂什么意思,和平常的PID函数不太一样
回复

使用道具 举报

ID:496761 发表于 2019-3-24 13:37 | 显示全部楼层
感谢分享,更想学习了
回复

使用道具 举报

ID:497626 发表于 2019-3-25 00:26 | 显示全部楼层
楼主精神可嘉啊
回复

使用道具 举报

ID:20793 发表于 2019-4-23 17:13 | 显示全部楼层
这仿真有问题, 不会获取温度
估计楼主屏蔽了或者删除了一部分代码
回复

使用道具 举报

ID:75969 发表于 2019-5-7 22:19 | 显示全部楼层
楼主没有找到ADC0804的代码。
回复

使用道具 举报

ID:530517 发表于 2019-5-8 12:40 | 显示全部楼层

哪里有
回复

使用道具 举报

ID:514111 发表于 2019-5-8 22:24 | 显示全部楼层
可以向大家咨询下关于PID控温的其他问题吗?我的问题是:为什么protues仿真中lcd不显示呢?求帮助,谢谢您了
回复

使用道具 举报

ID:409526 发表于 2019-5-23 20:24 | 显示全部楼层
程序有点问题,按键也没有进行定义
回复

使用道具 举报

ID:526050 发表于 2019-6-5 13:57 | 显示全部楼层
大神厉害 刚好需要用到
回复

使用道具 举报

ID:448370 发表于 2019-6-16 18:15 | 显示全部楼层
编译代码没问题,一仿真就出现23 ERROR(S),都是ERROR L121: IMPROPER FIXUP.怎么解决啊,在线等,急
回复

使用道具 举报

ID:448370 发表于 2019-6-17 12:07 | 显示全部楼层
煙花易冷 发表于 2019-6-16 18:15
编译代码没问题,一仿真就出现23 ERROR(S),都是ERROR L121: IMPROPER FIXUP.怎么解决啊,在线等,急

这个问题解决了,把工程设置中Options里的ROM改为large就行了。
可是仿真成功后,按键设置无反应,电热炉也不加热,LCD显示也不改变。
回复

使用道具 举报

ID:564483 发表于 2019-6-17 15:08 | 显示全部楼层
值得学习
回复

使用道具 举报

ID:562503 发表于 2019-6-17 18:16 | 显示全部楼层
LCD显示不成功啊
回复

使用道具 举报

ID:562818 发表于 2019-6-19 08:37 | 显示全部楼层
楼主,出现关键性错误是怎么回事
回复

使用道具 举报

ID:565736 发表于 2019-6-19 11:44 | 显示全部楼层
kaili 发表于 2018-5-17 13:31
运行后无法设置温度,加热装置也不工作,蜂鸣器一直在报警

请问怎么解决了
回复

使用道具 举报

ID:672345 发表于 2019-12-24 13:37 | 显示全部楼层
好资料,前来学习
回复

使用道具 举报

ID:676780 发表于 2019-12-29 22:34 | 显示全部楼层
用oven那个图的程序在哪啊?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表