系统设计
回帖 (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;
电路图
系统设计图和电源模块:
温度控制模块
茶叶自动烘焙系统的研究与实现,研究了茶叶自动烘焙系统的基本原理和系统框图,通过温度检测模块,能实时检测三个不同温度数据,并将数据通过蓝牙模块传输到电脑。利用温度控制电路,采用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;
电路图
系统设计图和电源模块:
温度控制模块
举报
更多回帖