单片机交流
直播中

刘洋

8年用户 1352经验值
私信 关注
[问答]

怎么实现温控自动烘焙系统设计?

怎么实现温控自动烘焙系统设计?

回帖(1)

张硕

2021-11-8 10:44:22
茶叶自动烘焙系统的研究与实现,研究了茶叶自动烘焙系统的基本原理和系统框图,通过温度检测模块,能实时检测三个不同温度数据,并将数据通过蓝牙模块传输到电脑。利用温度控制电路,采用PID算法、51单片机进行控制及数据处理,能精确实时控制温度。系统主要51单片机最小系统、蓝牙模块、温度传感模块、驱动显示电路、输出控制电路、电源电路、储存电路、报警电路和按键电路输出等组成。利用所设计出的茶叶自动烘焙系统,对烘焙中的茶叶采集温度,当时温度过高时能自动控制停止加温。此系统具有易控制、工作可靠、测量精度高的优点,可实时检测、控制。

电路总体方案
电路总体框图。在设计时我发现蓝牙模块适合传输小数据,相对Wifi来说,使用蓝牙不需要使用网络,因此采用蓝牙模块设计。与电脑和手机的连接都很方便。






主程序
主程序的主要功能是负责读出温度值、处理温度值、在LCD液晶屏上显示温度值和并控制子程序输出。按键设定温度,当温度传感器故障时,蜂鸣器发声报警,如果没有故障则正常显示,控制继电器开关。如图3.1主程序流程图。











温度设定子程序
温度设定子程序用于处理按键,用于设定想要设置的温度值






系统测试
4.1 模块测试

温度采集模块的测试:当实际温度值变化时,LCD同步显示实际温度,采集模块正常工作。
LCD显示测试:首先观察LCD有无外部损坏,接着上电,LCD液晶屏会显示温度1、温度2、温度3的温度,按下按键,观察显示屏上显示出的设置set1是否变换set2、set3。经测试可LCD显示屏正常工作。
按键测试:按键长按时,数据变动一次,按键短按时数据根据按按键的次数改变,经检测按键正常工作。
蜂鸣器发声测试:将温度传感模块拔掉模拟温度传感器故障,蜂鸣器发出报警的声音,蜂鸣器正常工作。
温度控制模块的测试:设置好设定温度,当茶叶实际温度低于设定温度,继电器打开,模拟开始加热茶叶温度,当茶叶实际温度等于或高于设定温度,继电器关闭,结果说明温度控制模块工作正常。
蓝牙模块测试:通过串口能将数据传输到电脑和手机上,蓝牙模块正常工作。
4.2 系统功能
开机后再液晶屏上显示当前的状态,包括实际温度与状态。通过独立按键设置需要达到的温度值,s3是加键,s4是减键,s5是确定键,s6是设置键,按确定键后,当实际温度小于设置温度时,屏幕显示加热与实际温度,并打开加热管控制继电器,当实际温度高于设置温度时,显示恒温与实际温度,并关闭加热管。当温度传感器故障时,在屏幕上显示液位异常,并蜂鸣器报警。不管在任何时候都可以对温度值进行设置,设置后马上更新状态。该毕业设计是一个硬件,里面有包括了单片机最小系统、蓝牙模块、温度传感模块、驱动显示电路、输出控制电路、电源电路、储存电路、报警电路和按键电路输出等各个系统和电路。因此,系统功能还包括复位功能,储存功能,报警功能,显示功能等各项。外部继电器控制好连接了一个加热管,实际上是由热得快做出来的,把热得快剪成两份,一份带着插头,另一份带着加热管,分开装进输出控制电路里,加热管由继电器控制开关,插头插在220V电源上,给加热管提供能量,由于安全原因,并没有直接测试加热功能。
部分代码

#include "LCD1602.h"
#include "UART.H"
#include
#include
#include
#include


struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int PrevError; // Error[-2]
unsigned int SumError; // Sums of Errors
};


struct PID spid; // PID Control Structure
unsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)


unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char high_time1,low_time1,count1=0;//占空比调节参数
unsigned char high_time2,low_time2,count2=0;//占空比调节参数


***it bell=P3^6;                     //蜂鸣器
***it temper_relay=P2^3;         //加热电磁阀
***it temper_relay1=P2^4; //加热电磁阀
***it temper_relay2=P2^5; //加热电磁阀




uint real_temper=0;                 //实际温度值
uint real_temper1=0;     //实际温度值
uint real_temper2=0;         //实际温度值
uchar eeprom_value=0,set_temper=0;//eeprom值与设置温度值
uchar eeprom_value1=0,set_temper1=0;//eeprom值与设置温度值
uchar eeprom_value2=0,set_temper2=0;//eeprom值与设置温度值


uchar Temper_Flag=0,keep_temp_flag=0; //温度检测与恒温标志
uchar Temper_Flag1=0,keep_temp_flag1=0; //温度检测与恒温标志
uchar Temper_Flag2=0,keep_temp_flag2=0; //温度检测与恒温标志


uchar select_set=0;
uchar set_flag=0;        //设置温度标志
uchar bell_count;        //蜂鸣器报警数
uchar time_flag=0;


//定时器初始化 50ms
void Time_Init(void)
{
   TMOD=0X01;
   TH0=(65536-1000)/256;
   TL0=(65536-1000)/256;
   ET0=1;
   EA=1;
   TR0=1;
}


void PIDInit (struct PID *pp)
{
memset ( pp,0,sizeof(struct PID));
}


//PID计算部分
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
{
unsigned int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error // 比例项
+ pp->Integral*pp->SumError // 积分项
+ pp->Derivative*dError); // 微分项
}


//温度比较处理子程序
void compare_temper1(void)
{
  unsigned char i;
     if((set_temper)>(real_temper/10))
     {
      if((set_temper)-(real_temper/10)>1) //相差1度是开始PID调节  
         {
          high_time=100;  //实际温度与设置温度低一度以上时一直开启加热
          low_time=0;
         }
      else
         {
           for(i=0;i<10;i++) //计算10次
             {
                            EA=0; //关中断,防止影响读取数据
                            real_temper=DS18B20_Read_Tempereture(1);
                                EA=1;
                rin = real_temper; // 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);
         }
     }
      else if((set_temper)<=(real_temper/10)) //实际温度比设置温度高时关闭加热
             {
               if((set_temper)-(real_temper/10)>0)//来回调整
                 {
                   high_time=0;
                   low_time=100;
                 }
               else
               {
                 for(i=0;i<10;i++)
                 {  
                                    EA=0;
                                    real_temper=DS18B20_Read_Tempereture(1);
                                        EA=1;
                    rin = real_temper; // Read Input
                    rout = PIDCalc ( &spid,rin ); // Perform PID Interation
                 }
                 if (high_time<100)
                   high_time=(unsigned char)(rout/10000);
                 else
                   high_time=0;
                 low_time= (100-high_time);
               }
             }
}


//温度比较处理子程序
//void compare_temper1(void)
//{
//  unsigned char i;
//     if((set_temper1)>(real_temper1/10))
//     {
//      if((set_temper1)-(real_temper1/10)>1) //相差1度是开始PID调节  
//         {
//          high_time1=100;  //实际温度与设置温度低一度以上时一直开启加热
//          low_time1=0;
//         }
//      else
//         {
//           for(i=0;i<10;i++) //计算10次
//             {
//                            EA=0; //关中断,防止影响读取数据
//                            real_temper1=DS18B20_Read_Tempereture(2);
//                                EA=1;
//                rin = real_temper1; // Read Input
//                rout = PIDCalc ( &spid,rin ); // Perform PID Interation
//             }
//           if (high_time1<=100)         //换算调整值
//             high_time1=(unsigned char)(rout/800);
//           else
//             high_time1=100;
//           low_time1= (100-high_time1);
//         }
//     }
//      else if((set_temper1)<=(real_temper1/10)) //实际温度比设置温度高时关闭加热
//             {
//               if((set_temper1)-(real_temper1/10)>0)//来回调整
//                 {
//                   high_time1=0;
//                   low_time1=100;
//                 }
//               else
//               {
//                 for(i=0;i<10;i++)
//                 {  
//                                    EA=0;
//                                    real_temper1=DS18B20_Read_Tempereture(2);
//                                        EA=1;
//                    rin = real_temper1; // Read Input
//                    rout = PIDCalc ( &spid,rin ); // Perform PID Interation
//                 }
//                 if (high_time1<100)
//                   high_time1=(unsigned char)(rout/10000);
//                 else
//                   high_time1=0;
//                 low_time1= (100-high_time1);
//               }
//             }
// }
//
//温度比较处理子程序
//void compare_temper1(void)
//{
//  unsigned char i;
//     if((set_temper2)>(real_temper2/10))
//     {
//      if((set_temper2)-(real_temper2/10)>1) //相差1度是开始PID调节  
//         {
//          high_time2=100;  //实际温度与设置温度低一度以上时一直开启加热
//          low_time2=0;
//         }
//      else
//         {
//           for(i=0;i<10;i++) //计算10次
//             {
//                            EA=0; //关中断,防止影响读取数据
//                            real_temper2=DS18B20_Read_Tempereture(3);
//                                EA=1;
//                rin = real_temper2; // Read Input
//                rout = PIDCalc ( &spid,rin ); // Perform PID Interation
//             }
//           if (high_time2<=100)         //换算调整值
//             high_time2=(unsigned char)(rout/800);
//           else
//             high_time2=100;
//           low_time2= (100-high_time2);
//         }
//     }
//      else if((set_temper2)<=(real_temper2/10)) //实际温度比设置温度高时关闭加热
//             {
//               if((set_temper2)-(real_temper2/10)>0)//来回调整
//                 {
//                   high_time2=0;
//                   low_time2=100;
//                 }
//               else
//               {
//                 for(i=0;i<10;i++)
//                 {  
//                                    EA=0;
//                                    real_temper2=DS18B20_Read_Tempereture(3);
//                                        EA=1;
//                    rin = real_temper2; // Read Input
//                    rout = PIDCalc ( &spid,rin ); // Perform PID Interation
//                 }
//                 if (high_time2<100)
//                   high_time2=(unsigned char)(rout/10000);
//                 else
//                   high_time2=0;
//                 low_time2= (100-high_time2);
//               }
//             }
// }
//


//从EEPROM中读取温度设置值
void Read_Set_EEPROM_Value(void)
{
           set_temper=X24C02_Read(10);
        set_temper1=X24C02_Read(11);
        set_temper2=X24C02_Read(12);
}


//按键处理 温度值设定
void Set_Temper_Value(void)
{
    uchar value_temp;
        value_temp=P3&0x3C;           //根据按键连接口获取是否有按键按下
        if(value_temp!=0x3c)
        {
           _delay_ms(5);          //消抖
           if(value_temp!=0x3c)         //再次确认是否有键按下
           {
                    switch(value_temp)
                        {
                           case 0x38: //加键
                                if(set_flag==1)           //只有在设置按键按下后有效
                                        {
                                           if(select_set==1)
                                           {
                                              if(eeprom_value<99) //温度值上限99度
                                                  eeprom_value++;          //设置温度值加
                                                  LCD_write_Num_1(13,1,eeprom_value,2); //显示设置温度值
                                           }
                                           else if(select_set==2)
                                           {
                                              if(eeprom_value1<99) //温度值上限99度
                                                  eeprom_value1++;          //设置温度值加
                                                  LCD_write_Num_1(13,1,eeprom_value1,2); //显示设置温度值
                                           }
                                           else if(select_set==3)
                                           {
                                              if(eeprom_value2<99) //温度值上限99度
                                                  eeprom_value2++;          //设置温度值加
                                                  LCD_write_Num_1(13,1,eeprom_value2,2); //显示设置温度值
                                           }
                                        }
                           break;
                           case 0x34: //减键
                                if(set_flag==1)          //只有在设置按键按下后有效
                                        {
                                           if(select_set==1)
                                           {
                                              if(eeprom_value>0)//小于下限时       
                                                  eeprom_value--;        //设置温度值减
                                                  LCD_write_Num_1(13,1,eeprom_value,2); //显示设置温度值
                                           }
                                           else         if(select_set==2)
                                           {
                                              if(eeprom_value1>0)//小于下限时       
                                                  eeprom_value1--;        //设置温度值减
                                                  LCD_write_Num_1(13,1,eeprom_value1,2); //显示设置温度值
                                           }
                                           else         if(select_set==3)
                                           {
                                              if(eeprom_value2>0)//小于下限时       
                                                  eeprom_value2--;        //设置温度值减
                                                  LCD_write_Num_1(13,1,eeprom_value2,2); //显示设置温度值
                                           }
                                        }
                           break;
                           case 0x2c: //确定
                                if(set_flag==1)         //只有在设置按键按下后有效
                                {
                                        set_flag=0;         //退出设置
                                            LCD_write_str(8,1,"S:        ");
                                                if(select_set==1)
                                            {
                                                        X24C02_Write(10,eeprom_value); //将设置值写入EEPROM
                                                        _delay_ms(5);           //延迟EEPROM在写入后不能马上读,需要等待一定时间
                                                        Read_Set_EEPROM_Value(); //读取EEPROM 重新赋值设置比较值
                                            }
                                                else if(select_set==2)
                                            {
                                                        X24C02_Write(11,eeprom_value1); //将设置值写入EEPROM
                                                        _delay_ms(5);           //延迟EEPROM在写入后不能马上读,需要等待一定时间
                                                        Read_Set_EEPROM_Value(); //读取EEPROM 重新赋值设置比较值
                                            }
                                                else if(select_set==3)
                                            {
                                                        X24C02_Write(12,eeprom_value2); //将设置值写入EEPROM
                                                        _delay_ms(5);           //延迟EEPROM在写入后不能马上读,需要等待一定时间
                                                        Read_Set_EEPROM_Value(); //读取EEPROM 重新赋值设置比较值
                                            }
                                                select_set=0;
                                        }
                           break;
                           case 0x1c: //设置
                                select_set++;
                                        if(select_set==4)select_set=1;                                
                                        set_flag=1;         //进度设置
                                        if(select_set==1)
                                        {
                                                LCD_write_str(8,1,"Set1:   ");
                                                eeprom_value=X24C02_Read(10);        //读取EEPROM中的值进行设置
                                                LCD_write_Num_1(13,1,eeprom_value,2);  //显示设置初始值
                                        }
                                        else if(select_set==2)
                                        {
                                                LCD_write_str(8,1,"Set2:   ");
                                                eeprom_value1=X24C02_Read(11);        //读取EEPROM中的值进行设置
                                                LCD_write_Num_1(13,1,eeprom_value1,2);  //显示设置初始值
                                        }
                                        else if(select_set==3)
                                        {
                                                LCD_write_str(8,1,"Set3:   ");
                                                eeprom_value2=X24C02_Read(12);        //读取EEPROM中的值进行设置
                                                LCD_write_Num_1(13,1,eeprom_value2,2);  //显示设置初始值
                                        }                                                                                               


                           break;
                        }
           }
           while(value_temp!=0x3c)value_temp=P3&0x3C; //松手检测
        }        
}


//故障检测
void InDetect(void)
{
   if(DS18B20_Init(1)!=0) //温度传感器故障
   {
           Temper_Flag=1;        //置标志
   }
   else
   {
       Temper_Flag=0;
   }
   if(DS18B20_Init(2)!=0) //温度传感器故障
   {
           Temper_Flag1=1;        //置标志
   }
   else
   {
       Temper_Flag1=0;
   }
   if(DS18B20_Init(3)!=0) //温度传感器故障
   {
           Temper_Flag2=1;        //置标志
   }
   else
   {
       Temper_Flag2=0;
   }


   if((real_temper/10)    {
       keep_temp_flag=0;
   }
   else
   {
       keep_temp_flag=1;
   }
   if((real_temper1/10)    {
       keep_temp_flag1=0;
   }
   else
   {
       keep_temp_flag1=1;
   }
   if((real_temper2/10)    {
       keep_temp_flag2=0;
   }
   else
   {
       keep_temp_flag2=1;
   }
}


//状态显示
void State_Display(void)
{
   InDetect(); //故障检测
   if(set_flag==0)//没有设置时显示
   {
           if((Temper_Flag==1)||(Temper_Flag1==1)||(Temper_Flag2==1))
           {
              LCD_write_str(10,1,"Error ");         //温度异常
           }
           else
           {
                 if((keep_temp_flag==0)||(keep_temp_flag1==0)||(keep_temp_flag2==0))
                 {
                           LCD_write_str(10,1,"Hot   ");//加热
                 }
                 else
                 {
                    LCD_write_str(10,1,"Normal");        //正常
                 }
           }
   }
}


//输出蜂鸣器与继电器控制
void Output_Control(void)
{
           if((Temper_Flag==1)||(Temper_Flag1==1)||(Temper_Flag2==1))//温度故障时报警
        {
                   bell_count=4;
        }
        else  bell_count=0;
}


//设备初始化函数
void Device_Init(void)
{
    Time_Init();
        Init_uart();
          LCD_init();
        DS18B20_Init(1);
        DS18B20_Init(2);
        DS18B20_Init(3);
    LCD_write_str(0,0,"T1:");
        LCD_write_str(9,0,"T2:");
        LCD_write_str(0,1,"T3:");
        LCD_write_str(8,1,"S:        ");
        Read_Set_EEPROM_Value();
}


//主函数
int main(void)
{   
    Device_Init(); //设备初始化
        PIDInit ( &spid ); // 初始化PID
        spid.Proportion = 10; // Set PID Coefficients
        spid.Integral = 8;
        spid.Derivative =6;
        spid.SetPoint = 100; // Set PID Setpoint
    while(1)
    {
           if(time_flag==1)
           {
               time_flag=0;
                   if((Temper_Flag==0))  //温度传感器无故障时
                   {
                       EA=0;
                           real_temper=DS18B20_Read_Tempereture(1); //读取温度值
                           EA=1;
                       LCD_write_Num(3,0,real_temper,4);  //显示温度值
                           printf("Temper1_Value=%frn",real_temper/10.0);                  
                   }
                   else
                   {
                     LCD_write_str(3,0,"Eor "); //温度传感器有故障时
                         printf("Temper1_Value=Error!rn");
                   }
       
                   if((Temper_Flag1==0))  //温度传感器无故障时
                   {
                       EA=0;
                           real_temper1=DS18B20_Read_Tempereture(2); //读取温度值
                           EA=1;
                       LCD_write_Num(12,0,real_temper1,4);  //显示温度值
                           printf("Temper2_Value=%frn",real_temper1/10.0);       
                   }
                   else
                   {
                       LCD_write_str(12,0,"Eor "); //温度传感器有故障时
                           printf("Temper2_Value=Error!rn");
                   }
       
                   if((Temper_Flag2==0))  //温度传感器无故障时
                   {
                           EA=0;
                           real_temper2=DS18B20_Read_Tempereture(3); //读取温度值
                           EA=1;
                       LCD_write_Num(3,1,real_temper2,4);  //显示温度值
                           printf("Temper3_Value=%frn",real_temper2/10.0);       
                   }
                   else
                   {
                       LCD_write_str(3,1,"Eor "); //温度传感器有故障时
                           printf("Temper3_Value=Error!rn");
                   }
                   printf("==================================rn");
           }
           State_Display();
           Set_Temper_Value();
           compare_temper1();
           //compare_temper2();
           //compare_temper3();
           Output_Control();
    }
}


//定时器中断
void Time0(void) interrupt 1
{
   static uchar count=0;
   static uint m=0;
   TH0=(65536-1000)/256;
   TL0=(65536-1000)/256;


   m++;
   count++;
   //count1++;
   //count2++;
   if(m==1000) //1S计时
   {
     m=0;
         time_flag=1;
         if(bell_count>0)
    {
       bell=~bell;//蜂鸣器标志取反
       bell_count--;//次数减少      
    }
    else bell=1;//次数到达时关闭蜂鸣器
   }
   if(count<=(high_time))
     temper_relay=0;
   else if(count<=100)
     {
      temper_relay=1;
      }
   else
      count=0;
   
//   if(count1<=(high_time1))
//     temper_relay1=0;
//   else if(count<=100)
//     {
//      temper_relay1=1;
//      }
//   else
//      count1=0;
//
//   if(count2<=(high_time2))
//     temper_relay2=0;
//   else if(count2<=100)
//     {
//      temper_relay2=1;
//      }
//   else
//      count2=0;
电路图
系统设计图和电源模块:





温度控制模块







举报

更多回帖

发帖
×
20
完善资料,
赚取积分