标题: PID控制的单片机炉温控制系统源码和Proteus仿真 [打印本页]

作者: smileml115    时间: 2017-6-4 15:04
标题: PID控制的单片机炉温控制系统源码和Proteus仿真
功能要求:
1)    采用液晶显示器显示温度测量值。
2)    检测的温度范围为0~128
3)    温度超过警戒值时能报警提示。
4)  能通过键盘输入设定温度并显示。
5)  用PID控制温度,控温精度≦±2
DS18B20温度显示仿真如图DS18B20的值可以任意调整,模拟温度的采集,LCD的显示值随DS18B20的温度值变化而变化。当温度超过界限,LED亮,同时SOUNDER响,模拟警报系统。当按下k1,显示温度的最高位光标开始闪烁,进入设定温度调整,按下k2,光标右移,按下k3数值加1,按下k4数值减1

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



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



下面是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, 下载次数: 1201)


作者: 3760609865    时间: 2017-6-5 00:34
谢谢分享,学习学习pID控制。
作者: alphacrux    时间: 2017-8-27 16:54
Node #00087 not found whilst binding pin V+ of U4_U10_ADC#0001!
仿真出现上述错误,请问是什么原因呢?
我的proteus版本是7.8
作者: CZP1234    时间: 2017-8-28 10:41
源程序有问题
作者: lijn    时间: 2017-11-4 09:48
楼主 pid在单片机中的运算,讲讲。
作者: 海里没有大鲨鱼    时间: 2017-11-21 16:22
CZP1234 发表于 2017-8-28 10:41
源程序有问题

怎么解决?

作者: 海里没有大鲨鱼    时间: 2017-11-21 16:27
CZP1234 发表于 2017-8-28 10:41
源程序有问题

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

作者: 海里没有大鲨鱼    时间: 2017-11-21 16:29
alphacrux 发表于 2017-8-27 16:54
Node #00087 not found whilst binding pin V+ of U4_U10_ADC#0001!
仿真出现上述错误,请问是什么原因呢 ...

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

作者: 哈哈哈WJ    时间: 2017-12-20 21:02
海里没有大鲨鱼 发表于 2017-11-21 16:29
你是怎么解决这个问题的?

解决了吗
作者: aqb3322    时间: 2018-1-16 22:09
这个资料真好。可以做成品了。
作者: nishiy    时间: 2018-1-23 11:09
为什么程序运行不了,仿真也运行不了
作者: whs123456    时间: 2018-4-9 11:37
怎么自动调节啊
作者: walt740    时间: 2018-4-13 00:37
好资料,51黑有你更精彩!!!
作者: 小猫小兔    时间: 2018-5-7 21:26
谢谢楼主的分享,我试试看能不能仿真出来。
作者: 295735223    时间: 2018-5-11 00:15
好资料,51黑有你更精彩!!!
作者: liyongan_1985    时间: 2018-5-11 08:57
果然是好资料,打算下载下俩看看
作者: kaili    时间: 2018-5-17 13:31
运行后无法设置温度,加热装置也不工作,蜂鸣器一直在报警
作者: zengzengbin    时间: 2018-5-22 13:47
程序有问题。
作者: 六月六月    时间: 2018-5-22 19:32
alphacrux 发表于 2017-8-27 16:54
**** 作者被禁止或删除 内容自动屏蔽 ****

运行不了是因为下载回来的protues图中adc0804有几个引脚的网络标号没有标上,可以参照楼主的截图自行添加
作者: zengzengbin    时间: 2018-5-23 16:56
这个有问题。
作者: 川大学子    时间: 2018-5-23 21:04
正好需要,就是不知道能不能完成整个仿真
作者: liuxiaoxiong    时间: 2018-6-19 20:42
能运行,lcd不显示,有哪位可以解释一下吗?
作者: liuxi1206    时间: 2019-1-10 21:03
谢谢分享,学习学习pID控制。
作者: 123xianbei    时间: 2019-1-16 15:17
楼主能不能注释下代码!PIDInit()和PIDDeal()看不懂什么意思,和平常的PID函数不太一样
作者: wacsl    时间: 2019-3-24 13:37
感谢分享,更想学习了
作者: recoo    时间: 2019-3-25 00:26
楼主精神可嘉啊
作者: lichangle    时间: 2019-4-23 17:13
这仿真有问题, 不会获取温度
估计楼主屏蔽了或者删除了一部分代码
作者: xiaobai1990    时间: 2019-5-7 22:19
楼主没有找到ADC0804的代码。
作者: ZOUZHUO    时间: 2019-5-8 12:40
CZP1234 发表于 2017-8-28 10:41
源程序有问题

哪里有

作者: lyfe    时间: 2019-5-8 22:24
可以向大家咨询下关于PID控温的其他问题吗?我的问题是:为什么protues仿真中lcd不显示呢?求帮助,谢谢您了
作者: 123@4    时间: 2019-5-23 20:24
程序有点问题,按键也没有进行定义
作者: 某偶像练习生    时间: 2019-6-5 13:57
大神厉害 刚好需要用到
作者: 煙花易冷    时间: 2019-6-16 18:15
编译代码没问题,一仿真就出现23 ERROR(S),都是ERROR L121: IMPROPER FIXUP.怎么解决啊,在线等,急
作者: 煙花易冷    时间: 2019-6-17 12:07
煙花易冷 发表于 2019-6-16 18:15
编译代码没问题,一仿真就出现23 ERROR(S),都是ERROR L121: IMPROPER FIXUP.怎么解决啊,在线等,急

这个问题解决了,把工程设置中Options里的ROM改为large就行了。
可是仿真成功后,按键设置无反应,电热炉也不加热,LCD显示也不改变。
作者: yusan12342019    时间: 2019-6-17 15:08
值得学习
作者: 夏娜不灼眼    时间: 2019-6-17 18:16
LCD显示不成功啊
作者: Robust59    时间: 2019-6-19 08:37
楼主,出现关键性错误是怎么回事
作者: ljb6869118    时间: 2019-6-19 11:44
kaili 发表于 2018-5-17 13:31
运行后无法设置温度,加热装置也不工作,蜂鸣器一直在报警

请问怎么解决了

作者: wgykk    时间: 2019-12-24 13:37
好资料,前来学习
作者: MIGRAINE    时间: 2019-12-29 22:34
用oven那个图的程序在哪啊?
作者: puyong    时间: 2020-3-26 10:09
不能用,慎重下载
作者: lele5211314    时间: 2020-4-4 11:12
程序不能用,下载的程序里面没有关于ADC0804的代码
作者: 请问请4    时间: 2020-5-12 21:48
基于AT89S51单片机炉温控制系统的模块电路设计
作者: tangjun    时间: 2020-6-9 17:26
马克 ,攒够积分再来。
作者: hyfwyy    时间: 2020-6-28 12:48
楼主,请问可以分享一下adc的程序嘛?或者请问一下oven模块输出电压和实际温度的关系,谢谢
作者: 51hei电控200522    时间: 2020-8-2 22:00
alphacrux 发表于 2017-8-27 16:54
**** 作者被禁止或删除 内容自动屏蔽 ****

附件应该是忘记保存最后新的了,需要把adc0804的电源的数据输出口全部都接上,具体可以参照楼主截图。
作者: 51hei电控200522    时间: 2020-8-2 22:01
ADC0804的程序和OVEN的控制程序都没有上传先看PID动态效果的不建议下载了哦
作者: zyx@    时间: 2020-8-12 11:18
垃圾吧,仿真没一个成功的,按键没反应,第二个仿真也有错误
作者: zyx@    时间: 2020-8-12 12:01
能不能认真点,仿真液晶屏显示第一张中,功能不是设置最高温和最低温吗,你上面就显示一个温度设置个锤子
作者: zyx@    时间: 2020-8-12 14:42
CZP1234 发表于 2017-8-28 10:41
源程序有问题

绝对有问题,又一个进坑了,擦
作者: 阿giao    时间: 2020-9-10 20:01
仿真出现错误 咋整 有改好的没
作者: Highnose    时间: 2020-10-22 21:49
电路没连完,网页图里是对的,仿真原理图是错的,程序也不对蛋
作者: qzsulin    时间: 2020-11-12 11:47
程序不完整,没办法用
作者: 51hei电控200522    时间: 2021-4-13 23:01
这个仿真不推荐大家下载了,认真查看过之后并没有晶闸管驱动oven加热的代码,没有adc084的代码。良心建议!!!!
作者: c51单片机小白    时间: 2021-4-14 18:43
51hei电控200522 发表于 2021-4-13 23:01
这个仿真不推荐大家下载了,认真查看过之后并没有晶闸管驱动oven加热的代码,没有adc084的代码。良心建议! ...

要是早看到就好了老哥你也在写pid温控吗?能交流下吗
作者: luobog    时间: 2021-4-22 22:48
c51单片机小白 发表于 2021-4-14 18:43
要是早看到就好了老哥你也在写pid温控吗?能交流下吗

老哥你写的咋样了?能讨论讨论吗
作者: Ux.。    时间: 2021-6-2 20:31
谢谢分享 对51单片机PID调控有更好认识

作者: woyaodwn    时间: 2021-12-28 10:05
这个搞起来了吗
作者: zxw517    时间: 2023-4-18 00:14
学习了,PID的模糊运算有点不容易




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1