标题: 基于51单片机+PID恒温控制器制作 [打印本页]

作者: 离谱    时间: 2017-7-5 22:26
标题: 基于51单片机+PID恒温控制器制作
制作一个简易的恒温控制器学习PID。
使用到ds18b20 5V加热器(TB有卖) 场效应管IRF 640N用于开通和关断加热器。
设置预设值,通过PID不断矫正加热器输出,达到预设温度。

引脚分配    lcd    lcddata:    P0
            lcd_e:        P2^7
            lcd_rs:        P2^6
            lcd_rw:        P2^5
        
        设置按键    limit_choise:        P    //温度上下限选择按键
                increase_temperature        P    //增加温度限值按键
                reduce_temperature        P    //减少温度限值按键
        
        蜂鸣器报警    warning        P   

        温度传感器    temperature_sensor    P

        制热    heatting    P

        制冷    refrigerating    P

        LED显示        normal        P    //正常温度指示灯
                high_temperature    P    //高温指示灯
                low_temperature        P    //低温指示灯   

单片机源程序如下:
  1. #include <main.h>
  2. extern unsigned char time_value;
  3. extern bit flag;
  4. int   PWM=0;
  5. int  PWM_I,PWM_P;
  6. unsigned char time_value=0;
  7. bit  flag;
  8. uint temp_m1=0;
  9. int temp_m=0;  //温度放大100倍后的中转值
  10. int set_temp=0; //设置温度*100
  11. void InitTimer0(void)
  12. {
  13.     TMOD = 0x01;
  14.     TH0 = 0x0EC;
  15.     TL0 = 0x078;
  16.     EA = 1;
  17.     ET0 = 1;
  18.     TR0 = 1;
  19. }
  20. void main()//主函数
  21. {
  22.     init();//初始化函数
  23.         pid_init (&temp_PID);
  24.         InitTimer0();
  25.     temp_PID.Proportion =120;              //  Set PID Coefficients
  26.     temp_PID.Integral   =5;
  27.     temp_PID.Derivative =2;
  28.    
  29.         
  30.         
  31.   while(1)
  32.         {
  33.                 temp_control();//控制按键函数
  34.                 if(time_value<PWM)      { heatting=1;}else { heatting=0;}
  35.                
  36.                  if(time_value==30)            
  37.                 {
  38.                
  39.                 display_real_tenp(temp_m1);
  40.                 }//显示函数        
  41.                 if(time_value==60)      temp_m=unnormal_proccessing(temp_m1);//温度转换函数*100
  42.                   if(time_value==100)
  43.          {
  44.                   
  45.                    if(set_temp-temp_m>250)
  46.                    {
  47.                                       PWM=PWM_MAX;
  48.                    }
  49.                    else
  50.                    {
  51.            PWM_I=pid_calc(&temp_PID,temp_m);
  52.            PWM  =PWM_I ;
  53.            if( PWM>=100)PWM=100;
  54.            else if(PWM<=PWM_MIN)  PWM=PWM_MIN;
  55.                    }
  56.                   
  57.                   
  58.                   }
  59.                    if(time_value==120)
  60.          {                PWM_P=PWM/2;
  61.                         LcdWriteCom(0x80+0X40+0x0C);
  62.                                 LcdWriteData('0'+PWM_P/100);
  63.                                  LcdWriteCom(0x80+0X40+0x0D);
  64.                                 LcdWriteData('0'+PWM_P%100/10);
  65.                                 LcdWriteCom(0x80+0X40+0x0E);
  66.                                 LcdWriteData('0'+PWM_P%10);
  67.                  }
  68.         }               
  69. }

  70. void init()//初始化函数
  71. {
  72.         uint i,j;
  73.         //函数初始化
  74.         LcdInit();//LCD初始化函数
  75.         Ds18b20Init();
  76.         
  77.         //I/O口初始化
  78.         heatting=0;//不制热

  79.         
  80.         //LCD初始化显示
  81.         LcdWriteCom(0x80);//第一行显示
  82.         j=strlen(num1);
  83.         for(i=0; i<j; i++)
  84.         {
  85.                 LcdWriteData(num1[i]);        
  86.                 delay_ms(1);
  87.         }
  88.         LcdWriteCom(0x80+0x40);//第二行显示
  89.         j=strlen(num2);
  90.         for(i=0; i<j; i++)
  91.         {
  92.                 LcdWriteData(num2[i]);        
  93.                 delay_ms(1);
  94.         }
  95.         LcdWriteCom(0x04);  //关闭写一个指针加1
  96. }

  97. uint get_temp(uint temp)//计算温度函数
  98. {
  99.         float tp;
  100.         
  101.         tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  102.         //如果温度是正的那么,那么正数的原码就是补码它本身
  103.         temp=tp*0.0625*100+0.5;        
  104.         //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  105.         //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  106.         //算加上0.5,还是在小数点后面。
  107.         return temp;
  108. }

  109. void display_real_tenp(uint temp)//实时温度显示函数
  110. {
  111.         uchar datas[] = {0, 0, 0, 0}; //定义数组

  112.         datas[0] = temp % 10000 / 1000;
  113.         datas[1] = temp % 1000 / 100;
  114.         datas[2] = temp % 100 / 10;
  115.         datas[3] = temp % 10;

  116.         LcdWriteCom(0x80+0x0a);                 //写地址 80表示初始地址
  117.         LcdWriteData('0'+datas[0]); //十位

  118.         LcdWriteCom(0x80+0x0b);        //写地址 80表示初始地址
  119.         LcdWriteData('0'+datas[1]); //个位

  120.         LcdWriteCom(0x80+0x0d);         //写地址 80表示初始地址
  121.         LcdWriteData('0'+datas[2]); //显示小数点  

  122.         LcdWriteCom(0x80+0x0e);                 //写地址 80表示初始地址
  123.         LcdWriteData('0'+datas[3]); //显示小数点  

  124. }

  125. void temp_control()//控制温度上下限函数
  126. {
  127.         if(limit_choise==0)//选择按键
  128.         {
  129.                 delay_ms(5);
  130.                 if(limit_choise==0)
  131.                 {
  132.                         while(!limit_choise);
  133.                         limit_choise_num++;
  134.                         if(limit_choise_num>=2)
  135.                         {
  136.                                 limit_choise_num=0;
  137.                         }
  138.                 }
  139.         }
  140.         if(limit_choise_num==0)//正常显示
  141.         {
  142.                 LcdWriteCom(0x0c);//关闭光标
  143.         
  144.         }
  145.                         
  146.         if(limit_choise_num==1)//调节上限温度
  147.         {
  148.                 LcdWriteCom(0x80+0X40+2);
  149.                 LcdWriteCom(0x0f);//开启光标
  150.                 if(increase_temperature==0)//增加温度
  151.                 {
  152.                         delay_ms(5);
  153.                         if(increase_temperature==0)
  154.                         {
  155.                                 while(!increase_temperature);
  156.                                 up_limit_temp++;
  157.                                 if(up_limit_temp>=100)
  158.                                 {
  159.                                         up_limit_temp=0;
  160.                                 }
  161.                                 //写入新数据
  162.                                 LcdWriteCom(0x80+0X40+0x03);
  163.                                 LcdWriteData('0'+up_limit_temp/10);
  164.                                 LcdWriteCom(0x80+0X40+0x04);
  165.                                 LcdWriteData('0'+up_limit_temp%10);
  166.                                 LcdWriteCom(0x80+0X40+2);//光标回写
  167.                         }
  168.                 }
  169.                 if(reduce_temperature==0)//减少温度
  170.                 {
  171.                         delay_ms(5);
  172.                         if(reduce_temperature==0)
  173.                         {
  174.                                 while(!reduce_temperature);
  175.                                 up_limit_temp--;
  176.                                 if(up_limit_temp<0)
  177.                                 {
  178.                                         up_limit_temp=99;
  179.                                 }
  180.                                 //写入新数据
  181.                                 LcdWriteCom(0x80+0X40+0x03);
  182.                                 LcdWriteData('0'+up_limit_temp/10);
  183.                                 LcdWriteCom(0x80+0X40+0x04);
  184.                                 LcdWriteData('0'+up_limit_temp%10);
  185.                                 LcdWriteCom(0x80+0X40+2);//光标回写
  186.                         }
  187.                 }

  188.         }
  189.          set_temp=up_limit_temp*100;
  190.         temp_PID.SetPoint   =set_temp;
  191.         
  192. }

  193. int unnormal_proccessing(uint temp)//温度转换函数
  194. {
  195.         uchar datas[] = {0, 0, 0, 0}; //定义数组
  196.         int temp1=0;

  197.         datas[0] = temp % 10000 / 1000;
  198.         datas[1] = temp % 1000 / 100;
  199.         datas[2] = temp % 100 / 10;
  200. ……………………

  201. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
PID恒温控制器.zip (104.42 KB, 下载次数: 1186)



作者: faridzled    时间: 2017-7-6 04:40
thanks for sharing
作者: bbxyzzj    时间: 2017-7-6 08:16
感谢分享!
作者: lq3698    时间: 2017-7-6 09:12
兄弟没视频吗

作者: raymondau    时间: 2017-7-6 09:22
楼主是否能提供一下相关电路图,谢谢
作者: 离谱    时间: 2017-7-6 13:23
raymondau 发表于 2017-7-6 09:22
楼主是否能提供一下相关电路图,谢谢

电路图太丑  不要介意

WENKONG.rar

19.62 KB, 下载次数: 252, 下载积分: 黑币 -5


作者: 离谱    时间: 2017-7-6 13:25
lq3698 发表于 2017-7-6 09:12
兄弟没视频吗

没有视频,这个控制可以在设置温度上下0.3度浮动。有时间的可以慢慢调
作者: raymondau    时间: 2017-7-6 16:31
离谱 发表于 2017-7-6 13:23
电路图太丑  不要介意

谢谢楼主,请问能发一下电路图吗?您发的这个是PCB图啊
作者: 离谱    时间: 2017-7-6 16:49
raymondau 发表于 2017-7-6 16:31
谢谢楼主,请问能发一下电路图吗?您发的这个是PCB图啊

找了很久才找到

电路图.jpg (76.17 KB, 下载次数: 303)

电路图

电路图

PID温度控制.zip

13.8 KB, 下载次数: 233, 下载积分: 黑币 -5


作者: raymondau    时间: 2017-7-6 20:16
离谱 发表于 2017-7-6 16:49
找了很久才找到

收到了,谢谢
作者: 不倒翁.WZT    时间: 2017-7-12 06:22
标题: RE: 基于51单片机+PID恒温控制器制作
楼主朋友:请教一下,
pp->SumError=-500;  中pp->是什么意思?  pp是什么意思?
temp_PID.SetPoint=set_temp;中的“.”是什么意思?set_temp值究竟赋给了谁?我做过实验,如果本句修改为SetPoint=set_temp;  或  temp_PID=set_temp;  SetPoint=set_temp;两句,程序总体好用,当温度回降到脉宽接近100%输出时,有一段时间无输出,当温度回降到脉宽输出为100%时输出恢复正常。谢谢楼主。
作者: 海里没有大鲨鱼    时间: 2017-11-21 16:32
有仿真吗?兄弟
作者: linrumiao    时间: 2017-12-11 10:05
收到了,支持
作者: gdfg    时间: 2017-12-27 20:39
在这里面,算法起到了什么样的作用??

作者: tieq1952    时间: 2017-12-28 07:56
有实用价值
作者: 离谱    时间: 2017-12-31 23:37
gdfg 发表于 2017-12-27 20:39
在这里面,算法起到了什么样的作用??

自动控制输出,保持设定温度
作者: 离谱    时间: 2017-12-31 23:38
tieq1952 发表于 2017-12-28 07:56
有实用价值

互相学习
作者: vista2008    时间: 2018-3-11 16:59
学习了
作者: 2307393235    时间: 2018-3-23 15:19
学习一下PID
作者: 顾新鑫    时间: 2018-3-26 14:28
请问在这基础上,怎么增加遥控控制温度增减开关。
作者: 顾新鑫    时间: 2018-3-26 14:36
在此基础上,怎么增加遥控控制温度
作者: 201730645473    时间: 2018-4-16 22:28
厉害了!!学习!!
作者: tuojianzhi    时间: 2018-4-19 09:58
可否告知下楼主QQ,谢谢
作者: 数码家园    时间: 2018-4-23 07:12
谢谢分享!学习了
作者: yzh123    时间: 2018-4-24 08:45
学习了,学习pid
作者: qq984304095    时间: 2018-4-28 19:12
老哥,你的5V加热器是多少瓦的,使用什么给他供电
作者: 离谱    时间: 2018-5-15 17:20
qq984304095 发表于 2018-4-28 19:12
老哥,你的5V加热器是多少瓦的,使用什么给他供电

2W   可以用充电宝供电
作者: 离谱    时间: 2018-5-15 17:21
顾新鑫 发表于 2018-3-26 14:36
在此基础上,怎么增加遥控控制温度

遥控只需要设置一个变量,远程数据传过来的时候使用这个变量接收就好
作者: AAAA7    时间: 2018-5-16 16:40
楼主还在不。
作者: 15290037438    时间: 2018-6-24 12:15
可以学习了
作者: 1170183671    时间: 2018-6-26 12:05
感谢楼主的分享
作者: lq3698    时间: 2018-6-26 20:54
无法下载了????
作者: 33332    时间: 2018-6-28 14:54
thank you。能不能有电路图一起学习学习,小白一个
作者: TabHu    时间: 2018-7-5 18:08
好东西 ,学习了
作者: 蔬木果    时间: 2018-7-12 22:53
学习PID
作者: 村口王师傅    时间: 2018-8-20 20:31
非常好!
作者: 莫德尔    时间: 2018-8-22 16:33
你里面的左移  右移是不是弄错了  或者你注释有误                  byte = (byte >> 1) | (bi << 7);        这一段的注释是不是有误   你看看   但是这个PID算法  还是满真确的  而且用到了 结构体指针    感觉非常高大上                                       
作者: 莫德尔    时间: 2018-8-22 16:36
不倒翁.WZT 发表于 2017-7-12 06:22
楼主朋友:请教一下,
pp->SumError=-500;  中pp->是什么意思?  pp是什么意思?
temp_PID.SetPoint=set_ ...

此乃结构体指针 pp->SumError=-500; 相当于(*pp).SumError    为了方便用pp->代替(*pp)
作者: 小星是么    时间: 2018-8-27 14:30
可以

作者: 数码家园    时间: 2018-8-30 10:36
非常感谢楼主分享,今天试了一下,还有PWM 输出显示,挺不错的
作者: little4_su    时间: 2018-9-28 20:40
精度达到±0.3吗?
作者: dzbj2    时间: 2018-10-18 16:11
楼主,完善下 PID 算法转成 PWM 的解说?
作者: djzoom    时间: 2018-11-23 13:08
请问有人做出成品么?
作者: 单片机是什么    时间: 2018-11-24 20:40
楼主,ds18b20 5V加热器在tb上搜不到啊,只有ds18b20 5V温度传感器,请问这个加热器可以用别的替代吗?
作者: 3205440665    时间: 2019-1-2 14:48
正在学习pid,谢谢分享!!!!!
作者: 传说十六年    时间: 2019-1-10 23:48
结构体在哪里定义的 我怎么看不到
作者: nihao11    时间: 2019-4-16 22:46
thanks for sharing
作者: 徐长国    时间: 2019-4-25 09:39
场效应管可以改成继电器吗
作者: 徐长国    时间: 2019-4-26 10:36
徐长国 发表于 2019-4-25 09:39
场效应管可以改成继电器吗

可以改成继电器
作者: 2570235540    时间: 2019-5-7 14:51
感谢楼主,真的帮助很大谢谢了

作者: ygj    时间: 2019-5-24 10:56
徐长国 发表于 2019-4-26 10:36
可以改成继电器

固态继电器吗?一般的不行吧
作者: 一切随缘吧    时间: 2019-6-5 15:28
厉害了哦
作者: abc111111    时间: 2019-6-12 00:08
莫德尔 发表于 2018-8-22 16:36
此乃结构体指针 pp->SumError=-500; 相当于(*pp).SumError    为了方便用pp->代替(*pp)

感谢解答,我也有同样的疑问
作者: a1357787200    时间: 2019-6-12 13:49
学习学习
作者: 瞒心书生    时间: 2019-6-18 16:11
真好用啊
作者: zhuhong110450    时间: 2019-7-17 15:52
T12温控可以借鉴此PID温控算法不?
作者: StaryLL    时间: 2019-7-22 18:33
这个可以做出来吗?有做出来的朋友吗?
作者: 行百里    时间: 2019-9-20 16:49
谢谢您,祝工作顺利
作者: aaaaaa。    时间: 2019-10-22 13:25
DS18B20 5V加热器没找到,是不是PTC恒温发热片???
作者: 钱情锦绣    时间: 2019-12-9 00:21
学习一下,谢谢分享
作者: 1051248815    时间: 2020-4-13 09:08
感谢楼主的分享
作者: qwthh    时间: 2020-4-13 18:32
请问能用PROTEUS仿真吗 电路图里没看到加热啊 只有一个MOSFEI
作者: v韩国v看    时间: 2020-4-24 14:32
很喜欢,正要用这方面知识
作者: sunnyqingfeng    时间: 2020-5-26 09:35
单片机是什么 发表于 2018-11-24 20:40
楼主,ds18b20 5V加热器在tb上搜不到啊,只有ds18b20 5V温度传感器,请问这个加热器可以用别的替代吗?

5V 加热器和ds18b20不是一个东西
作者: pfdqwp    时间: 2020-5-26 12:05
赞一个,正好学习下!。。。。。。。。。。。
作者: 993118812    时间: 2021-3-2 17:10
本帖下载后  keil无法打开
作者: 51hei团团    时间: 2021-3-2 17:53
993118812 发表于 2021-3-2 17:10
本帖下载后……

Keil4可以打开,亲测

51hei.png (41.72 KB, 下载次数: 685)

51hei.png

作者: wellhope    时间: 2021-3-3 11:01
如果使用市电,不加过零吗?
作者: woyaodwn    时间: 2021-3-3 14:42
好东西,控制精度怎么样?
作者: 1336692    时间: 2021-3-16 12:03
NB(考古)
作者: lvanangel    时间: 2021-3-30 19:13
谢谢大佬,非常有用
作者: cuijb    时间: 2021-4-2 19:54
单片机是什么 发表于 2018-11-24 20:40
楼主,ds18b20 5V加热器在tb上搜不到啊,只有ds18b20 5V温度传感器,请问这个加热器可以用别的替代吗?

ds18b20是温度传感器, 5V加热器搞个10Ω3-5W电阻就行
作者: weq12345    时间: 2021-4-9 10:49
楼主肯定是抄人家的,有做出成品试过没,还有就是加入过零检测电路没
作者: woyaodwn    时间: 2021-12-28 10:03
高手好多啊,出个实用版本的啊,期待中




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