找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4154|回复: 2
收起左侧

51单片机PID恒温程序设计

  [复制链接]
ID:583596 发表于 2019-7-15 11:12 | 显示全部楼层 |阅读模式
我控制电路主要包括,数码管显示电路、按键电路、报警电路、H型全桥式驱动电热丝电路、温度检测电路及其控制电路。
如下图
a28202c80fd8bcb41e1207dc17c5095.png
通过代码控制使系统恒温,温度可以通过单片机设置,可以加减温度。温度的稳定是通过PID控制的,通过PID使温度差保持在百分之5内。

下面是PID控制程序
  1. void wendu_regulation_PID() //PID 控制调节温度子程序
  2. {
  3.         float PWM_out;
  4.         Kp_PID=16;Ki_PID=18.2;Kd_PID=4.8;
  5.         ek_PID[j]=wendu-w;
  6. switch(j)
  7. {
  8.         case
  9.         2:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j-1])+Ki_PID*ek_PID[j]+Kd_PID*(
  10.         ek_PID[j]-2*ek_PID[j-1]+ek_PID[j-2]);break;
  11.         case
  12.         1:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j-1])+Ki_PID*ek_PID[j]+Kd_PID*(
  13.         ek_PID[j]-2*ek_PID[j-1]+ek_PID[j+1]);break;
  14.         case
  15.         0:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j+2])+Ki_PID*ek_PID[j]+Kd_PID*(
  16.         ek_PID[j]-2*ek_PID[j+2]+ek_PID[j+1]);break;
  17. }
  18.         PWM=PWM_out;
  19.         if(PWM>100) PWM=100;
  20.         if(PWM<0) PWM=0;
  21.         j++;
  22.         if(j==3) j=0;
  23. }
复制代码
其中的数据要自己不断试验方可

单片机源程序如下:
  1. /**************************************************************************************
  2. *                              DS18B20温度传感器实验                                                                                                  *
  3. 实现现象:        具体接线操作请看视频。
  4.                         下载程序后,在温度传感器接口处,按照丝印方向插好温度传感器,数码管就会显示
  5.                         检测的温度值,
  6. 注意事项:                                                                                                                                                                  
  7. ***************************************************************************************/

  8. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
  9. #include"temp.h"       

  10. typedef unsigned int u16;          //对数据类型进行声明定义
  11. typedef unsigned char u8;

  12. sbit LSA=P2^2;
  13. sbit LSB=P2^3;
  14. sbit LSC=P2^4;
  15. sbit k3=P1^0;
  16. sbit k1=P1^1;
  17. sbit k2=P1^2;
  18. sbit beep=P1^3;
  19. char num=0;
  20. u8 DisplayData[8];
  21. u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  22. u16 wendu=3160;
  23. u16 PWM;
  24. u16 w;
  25. u8 Kd_PID,Kp_PID,Ki_PID,ek_PID[3];
  26. u16 a=0;
  27. u8 j;

  28. /*******************************************************************************
  29. * 函 数 名         : delay
  30. * 函数功能                   : 延时函数,i=1时,大约延时10us
  31. *******************************************************************************/
  32. void delay(u16 i)
  33. {
  34.         while(i--);       
  35. }



  36. void ad()        //定时器初始化
  37. {
  38.          TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
  39.         TH0=0XFC;        //给定时器赋初值,定时1ms
  40.         TL0=0X18;       
  41.         ET0=1;//打开定时器0中断允许
  42.         EA=1;//打开总中断
  43.         TR0=1;//打开定时器
  44. }



  45. /*******************************************************************************
  46. * 函 数 名         : datapros()
  47. * 函数功能                   : 温度读取处理转换函数
  48. * 输    入         : temp
  49. * 输    出         : 无
  50. *******************************************************************************/

  51. void datapros(int temp)          
  52. {
  53.            float tp;  
  54.         if(temp< 0)                                //当温度值为负数
  55.           {
  56.                 DisplayData[0] = 0x40;           //   -
  57.                 //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
  58.                 temp=temp-1;
  59.                 temp=~temp;
  60.                 tp=temp;
  61.                 temp=tp*0.0625*100+0.5;       
  62.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  63.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  64.                 //算加上0.5,还是在小数点后面。

  65.           }
  66.         else
  67.           {                       
  68.                 DisplayData[0] = 0x00;
  69.                 tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  70.                 //如果温度是正的那么,那么正数的原码就是补码它本身
  71.                 temp=tp*0.0625*100+0.5;       
  72.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  73.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  74.                 //算加上0.5,还是在小数点后面。
  75.         }
  76.         DisplayData[0] = smgduan[temp % 10000 / 1000];
  77.         DisplayData[1] = smgduan[temp % 1000 / 100] | 0x80;
  78.         DisplayData[2] = smgduan[temp % 100 / 10];
  79.         DisplayData[3] = smgduan[temp % 10];
  80.         DisplayData[4] = smgduan[wendu /1000];
  81.         DisplayData[5] = smgduan[wendu % 1000/100]| 0x80;
  82.         DisplayData[6] = smgduan[wendu % 100/10];
  83.         DisplayData[7] = smgduan[wendu %10];
  84.        
  85. }


  86. /*******************************************************************************
  87. * 函 数 名         : keypros1
  88. * 函数功能                   : 按键处理函数,判断按键k1是否按下
  89. ********************************************************************************/
  90. void keypros1()
  91. {
  92.         if(k1==0)                  //检测按键K1是否按下
  93.         {       
  94.                 delay(1000);   //消除抖动 一般大约10ms
  95.                 if(k1==0)         //再次判断按键是否按下
  96.                 {
  97.                         wendu=wendu+10;          //温度加0.1度
  98.                 }
  99.                 while(!k1);         //检测按键是否松开
  100.         }               
  101. }                    

  102. /*******************************************************************************
  103. * 函 数 名         : keypros2
  104. * 函数功能                   : 按键处理函数,判断按键k2是否按下
  105. *******************************************************************************/
  106. void keypros2()
  107. {
  108.         if(k2==0)                  //检测按键K2是否按下
  109.         {       
  110.                 delay(1000);   //消除抖动 一般大约10ms
  111.                 if(k2==0)         //再次判断按键是否按下
  112.                 {
  113.                         wendu=wendu-10;          //温度减0.1度
  114.                 }
  115.                 while(!k2);         //检测按键是否松开
  116.         }               
  117. }



  118. /*******************************************************************************
  119. * 函数名         :DigDisplay()
  120. * 函数功能                 :数码管显示函数
  121. * 输入           : 无
  122. * 输出                  : 无
  123. *******************************************************************************/
  124. void DigDisplay()
  125. {
  126.         u8 i;
  127.         for(i=0;i<8;i++)
  128.         {
  129.                 switch(i)         //位选,选择点亮的数码管,
  130.                 {
  131.                         case(0):
  132.                                 LSA=0;LSB=0;LSC=0; break;//显示第0位
  133.                         case(1):
  134.                                 LSA=1;LSB=0;LSC=0; break;//显示第1位
  135.                         case(2):
  136.                                 LSA=0;LSB=1;LSC=0; break;//显示第2位
  137.                         case(3):
  138.                                 LSA=1;LSB=1;LSC=0; break;//显示第3位
  139.                         case(4):
  140.                                 LSA=0;LSB=0;LSC=1; break;//显示第4位
  141.                         case(5):
  142.                                 LSA=1;LSB=0;LSC=1; break;//显示第5位
  143.                     case(6):
  144.                                 LSA=0;LSB=1;LSC=1; break;//显示第6位
  145.                         case(7):
  146.                                 LSA=1;LSB=1;LSC=1; break;//显示第7位
  147.                        
  148.                 }
  149.                 P0=DisplayData[i];//发送数据
  150.                 delay(100); //间隔一段时间扫描       
  151.                 P0=0x00;//消隐
  152.         }               
  153. }

  154. /*******************************************************************************
  155. * 函 数 名       : heat
  156. * 函数功能                 : PWM 调压控温子程序
  157. * 输    入       : 无
  158. * 输    出             : 无
  159. *******************************************************************************/
  160. void heat(PWM) //PWM 调压控温子程序
  161. {
  162.          if(a<PWM)
  163.          k3=1;
  164.         if(a>PWM)
  165.                 {k3=0;}
  166.         if(a>100){a=0;}
  167. }       


  168. /*******************************************************************************
  169. * 函 数 名       : wendu_bili
  170. * 函数功能                 : 比例控制调节速度子程序
  171. * 输    入       : 无
  172. * 输    出             : 无
  173. *******************************************************************************/
  174. void wendu_regulation_PID() //PID 控制调节温度子程序
  175. {
  176.         float PWM_out;
  177.         Kp_PID=16;Ki_PID=18.2;Kd_PID=4.8;
  178.         ek_PID[j]=wendu-w;
  179. switch(j)
  180. {
  181.         case
  182.         2:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j-1])+Ki_PID*ek_PID[j]+Kd_PID*(
  183.         ek_PID[j]-2*ek_PID[j-1]+ek_PID[j-2]);break;
  184.         case
  185.         1:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j-1])+Ki_PID*ek_PID[j]+Kd_PID*(
  186.         ek_PID[j]-2*ek_PID[j-1]+ek_PID[j+1]);break;
  187.         case
  188.         0:PWM_out=Kp_PID*(ek_PID[j]-ek_PID[j+2])+Ki_PID*ek_PID[j]+Kd_PID*(
  189.         ek_PID[j]-2*ek_PID[j+2]+ek_PID[j+1]);break;
  190. }
  191.         PWM=PWM_out;
  192.         if(PWM>100) PWM=100;
  193.         if(PWM<0) PWM=0;
  194.         j++;
  195.         if(j==3) j=0;
  196. }                                       




  197. /*******************************************************************************
  198. * 函 数 名       : main
  199. * 函数功能                 : 主函数
  200. * 输    入       : 无
  201. * 输    出             : 无
  202. *******************************************************************************/
  203. void main()
  204. {                ad();       
  205.         while(1)
  206. {        
  207.                         int qq;
  208.                       keypros1();  //温度加0.1                 
  209.                    keypros2();        //温度减0.1
  210.                    qq=Ds18b20ReadTemp();
  211.                    datapros(qq);         //数据处理函数
  212.                    w=qq*0.0625*100+0.5;         //浮点数变成整数
  213.                   
  214.                          wendu_regulation_PID();
  215.                           heat(PWM);
  216.                          DigDisplay();//数码管显示函数
  217.                         if(w>59.4||w<19.8)
  218.                    {beep=~beep;delay(100);}       
  219.         }               
  220. }

  221. void Timer0() interrupt 1//定时器 T0 定时 0.01 秒
  222. { static u16 i;
  223.         TH0=0xFC;
  224.         TL0=0x18;
  225.         i++;
  226.         if(i==10) //定时达到 0.01 秒读取温度传感器的温度值
  227. {               
  228.                 a++; i=0;
  229.                  
  230. }
  231.        
  232. }                                  
复制代码
下面的源代码下载链接
PID.rar (45.36 KB, 下载次数: 140)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:57896 发表于 2019-7-16 18:27 | 显示全部楼层
不错,有空仿真一下看看
回复

使用道具 举报

ID:77840 发表于 2021-3-30 16:27 | 显示全部楼层
井井有条,每个函数都单独注解出来,让我们这些初学者一目了然,各个函数和语法功能都能清晰看到如何使用。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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