快热式家用电热水器的设计1

第12章 快热式家用电热水器的设计
12.1功能要求
当前,热水器已成为日常生活中不可缺少的家用电器,设计制造更实用、更方便、更安全、更节能的热水器是产品设计师和生产商家不断追求的目标。快热式电热水器与普通电热水器最大的区别在于它取消了储水罐,热水随开随用,不需预热,减少了电能浪费,另外还具有体积小、使用安全、安装方便等优点。设计要求为:
1. 用2位数码管显示出水温度,能显示设定功率档位。
2. 温度检测显示范围00~99℃,精确度±1℃。
3. 设置3个功率档位指示灯,1~4档一个灯亮,5~8档两个灯亮,9档3个灯全亮。0档无功率输出,档位灯不亮。
4. 设置3个轻触按钮,分别为电源开关键、“+”键和“-”键。加热功率分0~9档,按“+”键依次递增至9档,按“-”键依次递减至0。0-9档功率依次为0、1/9P、2/9P、3/9P、4/9P、5/9P、6/9P、7/9P、8/9P、P。
5. 出水温度超过65℃时停止加热,并蜂鸣报警,温度降到45℃以下时恢复。
6. 内胆温度超过105℃时停止加热,防止干烧。
12.2方案论证
按快热式电热水器的功能要求,决定采用如图12.1所示的模块组成系统,即电源电路、单片机控制器、温度检测电路、按键输入电路、LED数码管及指示灯电路、报警电路和加热控制电路。

图12.1 快热式电热水器系统组成框图
快热式电热水器为了达到“快热”的效果,取消了储水罐,使冷水在在进入加热管后立即被加热,这就要求加热管有较大的功率,家用电热水器一般采用方便可靠的电热丝加热方法。根据热学及流体力学原理结合实际实验室测试,可以得到水温与流量、加热功率之间的关系如表12.1。
表12.1中所列水温值和流量值可以满足大多数家庭用户使用要求,当最大的加热功率为7.5KW时,按220V供电计算电流约为34A,所以要求专线供电。

表12.1 水温与流量、加热功率的关系
2升/分钟 2.5升/分钟 3升/分钟 3.5升/分钟 4升/分钟
4.5KW 47 42 36 34 32
5.5KW 54 48 41 38 35
6.5KW 62 54 46 42 38
7.5KW 70 60 51 46 41
注:进水温度15℃,输入电压AC220V~

对于加热功率的控制,最简单的方法是由若干不同功率的电热丝组合得到几种加热功率,但由于快热式热水器的加热功率较普通的大,且档位设置较多,用电热丝组合的方法需要几组电热丝和继电器,成本增高且工作可靠性降低,所以比较理想的是采用可控硅控制功率,电路简单又控制方便。
温度检测的方法较多,最经典的方法就是用热敏电阻(或热敏传感器)组成电桥来采集信号,再经放大、AD转换后送单片机。目前比较先进的方法是采用专门的集成测温传感器(如DS18B20),直接将温度转换成数字信号

传送给单片机。为了简化电路又降低成本,本文采用了温度/频率转换测温法,直接将温度信息转换成频率信号,用单片机测出频率大小,从而间接测出温度值,温度/频率转换电路简单可靠,成本低廉。
12.3系统硬件电路的设计
快热式热水器控制系统电路如图12.2,由7个部分电路组成:单片机系统及外围电路、电源电路、按键输入电路、LED数码管及指示灯电路、报警电路、加热控制电路、温度检测电路。
控制器采用成本低廉且工作可靠的89C51或其兼容系列的单片机,采用12M的晶振。89C51对电源要求不甚严格,电源电路采用普通的市电降压整流,然后经集成稳压器(7805)稳压输出+5V电压。按键采用轻触小按钮。显示电路采用两位共阳数码管,由2个三极管9012驱动,3个LED指示灯用于指示加热功率。报警电路采用5V的自鸣式蜂鸣器。
12.3.1加热控制电路
图12.3为加热控制电路原理图,电热丝的加热功率由双向可控硅来控制,单片机通过光耦给可控硅触发信号,控制可控硅的导通角,从而控制电热丝的有效加热功率。为了在关机和超温保护的状态下能可靠地关断加热电源,电路中设计了继电器来控制加热电源。其中串联在继电器线圈回路的熔丝为105℃的热保险丝,当温度超过105℃时,热保险丝会熔断,防止加热管干烧。与电热丝并联的LED发光管用来指示电热丝的工作状态。
可控硅触发信号中需要对市电进行过零检测,以实现触发脉冲的相位延时。本电路中是利用三极管8050和一个非门实现过零检测的,电路如图12.4。




图12.2 快热式家用电热水器控制电路图


图12.3加热控制电路图


图12.4 过零检测电路图
12.3.2温度检测电路
温度检测电路组成如图12.5所示,温度/频率变换电路是利用反相器组成的RC多谐振荡器,其中的R24是一个热敏电阻,当温度变化时引起热敏电阻的阻值变化,从而改变了振荡器输出的方波频率。该频率的估算可用如下公式:
式12.1

图12.5 温度检测电路图
12.4系统程序的设计
按快热式热水器的功能,系统程序必需实现以下任务:显示扫描;按键扫描处理;加热控制;温度检测(包括超温报警)。51系列单片机实现多任务运行的方法就是分时复用,在程序设计的时候要相应地分配好各任务的CPU占用时间。对于以上几个任务稍加分析可以看出,显示扫描、按键扫描和加热控制任务相对而言有实时要求,而温度检测任务则可用定时(0.5~1s)实现。
12.4.1主函数
系统在上电复位后,先对温度寄存器、档位寄存器赋默认值,并进行清除超温标志,设置定时器及中断系统的工作方

式等初始化工作。
由于51系列单片机没有停机指令,我们可以利用主程序设置死循环反复运行各个任务。我们把有实时要求的子程序(显示扫描、按键扫描、加热控制)放在最内层的循环中,计算其运行一次占用的CPU时间,然后根据温度检测定时的间隔时间,计算出该循环的循环次数。本例中每运行一次有实时要求的子程序(即显示扫描、按键扫描、加热控制)约占用5ms CPU时间,运行测温子程序的时间间隔为0.5s,那么循环次数应为100次。图12.6为主函数程序流程图。

12.4.2显示扫描子函数
显示子函数完成两位共阳数码管的扫描显示任务,图12.7为显示扫描子函数程序流程图。


图12.6主函数程序流程图









图12.7显示扫描子函数程序流程图

12.4.3按键扫描处理子函数
按键扫描子函数负责逐个扫描档位“+”键、档位“-”键和开关键是否被按下,若有键被按下则作出相应处理。图12.8为按键扫描子函数程序流程图。



图12.8按键扫描子函数程序流程图

12.4.4加热控制函数
加热控制程序根据用户设定的加热档位和系统当前的状态,来决定是否加热和控制加热的功率并点亮相应的指示灯。如有超温标志还应打开蜂鸣器报警。图12.9为加热控制函数程序流程图。
加热控制程序通过控制继电器的通断来决定是否给电热丝通电加热,而加热的功率大小则由双向可控硅的导通角决定。系统程序利用外中断INT1检测市电的过零点,检测到过零点后,立即根据设定的加热档位给定时器T1赋一个延时参数,并打开定时器T1,允许其中断。当定时器T1计满溢出后触发中断,T1中断程序就会给可控硅发一个触发信号,使其导通。图12.10、12.11分别是过零检测函数程序流程图和可控硅触发信号控制函数程序流程图。












图12.9加热控制函数程序流程图







图12.10过零检测函数程序流程图

图12.11可控硅触发信号控制程序流程图





图12.12温度检测函数程序流程图
12.4.5温度检测函数
温度检测函数的基本原理就是将温度/频率转换电路测得的频率与事先建立好的温度/频率表进行比较,查找出与该频率相应的温度值。事先在实验测试后建立的温度/频率表是0~100℃温度所对应的频率值,它是一个频率对应于温度递减的非线性函数,我们在C语言中用一个一维数组Tab[101] 来表示,下标为温度,数组元素为频率值。计算温度的方法采用高效准确的二分法查表,查表的过程如下:
① 先给定查找的温度的最大值Tmax和最小值Tmin,即确定查找的范围,我们根据已有的温度表默认最大值Tmax=100,最小值Tmin=0;
② 假定测得温度Temp为最大

值和最小值之中间值即Temp=(Tmax+Tmin)/2;
③ 将实际测得的频率值T0rig与假定温度Temp在表格中对应的频率Tab[temp]相比较,如果相等,那么假定温度就是当前实际温度,即完成查找;
④ 如果T0rig> Tab[temp],说明实际温度应该在Tmin和Temp之间(因为递减函数特性),所以修改查找范围令Tmax=Temp,同理如果T0rig< Tab[temp],说明实际温度应该在Temp和Tmax之间,则令Tmin=Temp;
⑤ 检查查找范围,如果Tmax-Tmin<=1,判断T0rig更接近最大值对应的频率Tab[Tmax]还是最小值对应的频率Tab[Tmin],实际温度值取频率更接近的那个值即完成查找,
⑥ 如果Tmax-Tmin>1,那么重复第②③④⑤步骤直到完成查找。
温度检测程序完成温度计算后便刷新系统当前温度寄存器,并判断有无超温、置位或清除相应的标志位。图12.12为温度检测函数程序流程图。
单片机使用外中断INT0和计时器T0检测输入的频率大小,为了减少测量的系统误差相对值和随机误差对测量精度的影响,程序中取100个方波周期的和作为测量结果。程序中使用静态变量px0count进行外中断的计数,在测量开始时,我们给px0count赋值2是为了让频率测量有准确的起点。另外,为了区分测频的开始和结束,还使用了测频开始标志位T0tst和测频完成标志位Testok。图12.13为频率测试函数程序流程图。



图12.13频率测试函数程序流程图
12.5调试及性能分析
快热式热水器硬件电路不包含任何可调节元件,因此只要器件质量可靠,管脚焊接正确,硬件电路无需调试。该电路中测温部分的振荡电路对电容C1的容量比较敏感,若此电路要批量化生产应用可在热敏电阻R24上再串一个可变电阻,以补偿C1的容量变化。
在初次试做本电路或关键硬件参数有调整时,应对系统软件中控制加热功率的可控硅导通角延时参数表和温度/频率转换表这两部分进行调试。
可控硅导通角延时参数主要由市电的频率和过零检测电路的脉冲宽度决定,可以先根据市电频率,按等功率的要求计算理论值,再根据过零检测电路的脉冲宽度加以调整。
温度/频率转换表可以用对照标准温度计实测的办法进行测试。图12.14是用实际电路在实验室测得的温度/频率曲线图。
用这个方案设计的快热式家用电热水器,电路简单,成本较低,经试验运行证明工作稳定可靠,在无需改变硬件的条件下,如加入PID等自动控制程序还可以升级成自动控温的电热水器。

图12.14温度/频率曲线图
12.6控制源程序清单
以下是快热式电热水器控制源程序清单,采用C51编写,在Keil uVision2 V2.30(C51.exe V7.0)环境下调试通过,并下载到AT89C51测试运行成功。
/*--------------------------------------

热式热水器程序
MCU AT89C51 XAL 12MHz
Build by Gavin Hu, 2005.3.18
--------------------------------------*/
#include
#include
#include
void delay(unsigned int); //延时函数
void display(void); //显示函数
unsigned char keyscan(void); //按键扫描处理函数
void heatctrl(void); //加热控制函数
void temptest(void); //测温函数
sbit swkey=P1^0; //开关键
sbit upkey=P1^1; //加热档位“+”键
sbit downkey=P1^2; //加热档位“-”键
sbit buzz=P1^05; //蜂鸣器输出端
sbit triac=P1^6; //可控硅触发信号输出端
sbit relay=P1^7; //继电器控制信号输出端
sbit led1=P2^5; //加热档位指示灯1
sbit led2=P2^6; //加热档位指示灯2
sbit led3=P2^7; //加热档位指示灯3
signed char data ctemp; //当前测得水温寄存器
unsigned char data dispram[2]={0x10,0x10}; //显示区缓存
unsigned char data heatpower,px0count; //加热档位寄存器、外中断0计数器
bit tempov,t0tst,testok; //超温标志、测温开始标志、测温完成标志
/*----------------------------------------------
主函数 void main(void)
无参数,无返回值
循环调用显示、键扫描、温度检测、加热控制函数
----------------------------------------------*/
void main(void)
{
unsigned char i,j;
ctemp=15; //初始化水温寄存器
heatpower=5; //初始化加热档位为5档
tempov=0; //清除超温标志
swkey=0; //默认开关键被按下,进入待机状态
TMOD=0x11; //设定T0和T1工作方式为16位定时器
TCON=0x05; //设置外中断0和1为下降沿触发
IP=0x01; //设置外中断0优先
IE=0x80; //打开总中断
while (1)
{
i=1;
do{
for (j=0;j<100;j++) //循环100次约0.5s
{
if (keyscan()) i=6; //如果有键按下,显示当前档位3s
display(); //调用显示函数一次约4ms
heatctrl(); //调用加热控制函数
}//end for (b=0;b<100;b++)
temptest(); //每0.5s进行一次测温
} while (--i); //通过改变循环次数i的大小决定是否刷新显示
j=abs(ctemp); //取温度绝对值
dispram[1]=j%10; //取个位数送显示
j/=10; //取十位数
dispram[0]=j?j:0x11; //送显示(带灭零)
}//end while (1)
}

/*--------------------------------------
延时函数 void delay(unsigned int dt)
参数:dt,无返回值
延时时间=dt*500机器周期
--------------------------------------*/
void delay(unsigned int

dt)
{
register unsigned char bt; //定义寄存器变量
for (; dt; dt--)
for (bt=250; --bt; ); //此句编译时以“DJNZ”实现,250*2=500机器周期
}

/*--------------------------------------
显示函数 void display(void)
无参数,无返回值
两位共阳数码管扫描显示
--------------------------------------*/
void display(void)
{
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0xff};
unsigned char i,a;
a=0xfe; //位选赋初值
for (i=0; i<2; i++) //循环扫描两位数码管
{
P2|=0x1f; //清除位选
P0=table[dispram[i]]; //送显示段码
P2&=a; //选通一位
delay(4); //延时2ms
a=_crol_(a,1); //改变位选字
P0=0xff; //消影
}
}

/*----------------------------------------------------------
按键扫描处理函数 unsigned char keyscan(void)
无参数,返回值:无符号字符型,无键按下为0,有键按下为其它
影响全局变量:heatpower
----------------------------------------------------------*/
unsigned char keyscan(void)
{
unsigned char i,ch;
if (upkey==0) //“+”键
{
buzz=0; //打开蜂鸣器(发出按键音)
for (i=0;i<5;i++) display(); //延时消抖
buzz=1; //关闭蜂鸣器
if (heatpower<9) heatpower++; //档位加一
dispram[0]=0;
dispram[1]=heatpower; //显示当前档位
while (upkey==0) display(); //等待键释放
return (1); //返回有键按下
}
else if (downkey==0) //“-”键
{
buzz=0; //打开蜂鸣器(发出按键音)
for (i=0;i<5;i++) display(); //延时消抖
buzz=1; //关闭蜂鸣器
if (heatpower>0) heatpower--; //档位减一
dispram[0]=0;
dispram[1]=heatpower; //显示当前档位
while (downkey==0) display(); //等待键释放
return (2); //返回有键按下
}
else if (swkey==0) //开关键
{
buzz=0; //打开蜂鸣器(发出按键音)
for (i=0;i<30;i++) display(); //延时消抖
buzz=1; //关闭蜂鸣器
swkey=1; //置位开关键
while (swkey==0) display(); //等待键释放
ch=IE; //暂存中断控制字IE
IE=0x00; //禁止中断
P0=0xff;
P1=0xff;
P2=0xff; //清除端口输出
dispram[0]=0x10;
dispram[1]=0x10; //显示“--”
display();
while (1)
{
while (swkey) display(); //等待开关键按下
buzz=0; //打开蜂鸣器(发出按键音)
for (i=0;i<10;i++)

display();//延时消抖
buzz=1; //关闭蜂鸣器
if (swkey==0) break; //确认开关键被按下
}
while (swkey==0) display(); //等待键释放
IE=ch; //还原中断控制字IE
return (0); //返回无键按下
}
else return (0); //无任何键按下时由此返回
}

/*--------------------------------------
加热控制函数 void heatctrl(void)
无参数,无返回值
判断是否加热、加热功率及档位指示灯处理
--------------------------------------*/
void heatctrl(void)
{
if (!tempov) //当没有超温标志时
{
relay=0; //接通继电器
buzz=1; //关闭蜂鸣器
switch (heatpower) //判断加热档位
{
case 0: {EX1=0;ET1=0;triac=1;led1=1;led2=1;led3=1;break;}//0档不加热,指示灯不亮
case 1:
case 2:
case 3:
case 4: {led1=0;led2=1;led3=1;EX1=1;break;} //1~4档1号指示等亮
case 5:
case 6:
case 7:
case 8: {led1=0;led2=0;led3=1;EX1=1;break;} //5~8档1号、2号指示灯亮
case 9: {EX1=0;ET1=0;led1=0;led2=0;led3=0;triac=0;break;} //9档全功率,指示灯全亮
}
}
else //当有超温标志时
{
relay=1; //断开继电器
EX1=0; ET1=0; triac=1; //关闭可控硅
buzz=0; //蜂鸣报警
}
}

/*--------------------------------------
测温函数 void temptest(void)
无参数,无返回值,
影响全局变量:ctemp,tempov
测量并查表计算温度,判断是否超温
--------------------------------------*/
void temptest(void)
{
signed char temp,tempmin,tempmax;
unsigned int t0rig;
unsigned int code temptab[]={0x6262,0x61eb,0x6171,0x60f7,0x6047,0x5ff7,0x5f6e,0x5eef,0x5e53,0x5dbe,0x5d4b,0x5ca5,0x5c17,\
0x5b6b,0x5ada,0x5a5c,0x599b,0x58ff,0x5869,0x57b0,0x570d,0x5663,0x55c6,0x550e,0x5444,0x5396,\
0x52dd,0x5240,0x5189,0x50b0,0x5005,0x4f20,0x4e69,0x4db1,0x4cef,0x4c42,0x4b64,0x4aaa,0x49e1,\
0x48fc,0x4847,0x476c,0x46b1,0x4604,0x4503,0x4449,0x4356,0x4299,0x41c0,0x40ce,0x3ff0,0x3f2b,\
0x3e33,0x3d86,0x3ca6,0x3bd2,0x3b26,0x3a39,0x3973,0x38a6,0x37ef,0x373f,0x3687,0x35c3,0x3507,\
0x3487,0x33bc,0x32ed,0x324f,0x319e,0x3106,0x3053,0x2fa6,0x2f2a,0x2e88,0x2e00,0x2d63,0x2cd6,\
0x2c65,0x2bae,0x2b28,0x2a97,0x2a07,0x298e,0x2914,0x287a,0x280d,0x278a,0x2703,0x2687,0x2626,\
0x25e5,0x256d,0x24ee,0x2489,0x2414,0x23bc,0x2356,0x22d9,0x2278,0x2203}; //温度频率表
px0count=2; //测频中断函数参数
t0tst=1; //置测频程序开始标志
EX0=1; //打开测

频外中断
testok=0; //清除测频程序完成标志
while (!testok) display(); //等待测试完成
t0rig=(unsigned int)TH0<<8|TL0; //字节合成字
tempmin=0; //以下是二分查表法计算温度值
tempmax=100; //tempmin和tempmax为温度表的范围
while (1)
{
temp=(tempmax+tempmin)/2; //假定当前温度为最大值与最小值之中点值
if (t0rig==temptab[temp]) break; //若实际值等于假定值结束查找
else if (t0rig>temptab[temp]) tempmax=temp;//若实际值大于假定值,减小查找范围的最大值
else tempmin=temp; //若实际值小于假定值,增大查找范围的最小值
if (tempmax-tempmin<=1) //若查找范围已缩小到1度之间,
{ //判断实际值更接近哪个端点
if (temptab[tempmax]+temptab[tempmin]>2*t0rig) temp=tempmax;//接近最大值取最大值
else temp=tempmin; //接近最小值取最小值
break; //结束查找
}
}
ctemp=temp; //刷新当前温度寄存器
if (temp>65) tempov=1; //如果温度超过65度置位超温标志
else if (temp<45) tempov=0; //当温度回落到45度以下时清除超温标志
}

/*------------------------------------------
测温频率测试函数 void tempfrequency(void)
使用外部X0中断,寄存器组1
测出温度——频率转换电路的频率
------------------------------------------*/
void tempfrequency(void) interrupt 0 using 1
{
if (--px0count) return; //找齐起点或计数
if (t0tst) //如果是起点
{
t0tst=0; //清除测频开始标志
px0count=100; //取100个方波为一次测频
TH0=0;
TL0=0; //清除计时器T0
TR0=1; //开始计时
}
else //如果是终点
{
TR0=0; //停止计时
EX0=0; //停止测频外中断
testok=1; //置位测频完成标志
}
}

/*--------------------------------------
加热控制过〇检测函数 void pass0(void)
使用外部X1中断,寄存器组2
检测过〇点,给定时器T1赋初值
--------------------------------------*/
void pass0(void) interrupt 2 using 2
{
unsigned char code powertab[]={0xd8,0xf0,0xe2,0x63,0xe5,0x25,0xe8,0x3e,0xeb,0x16,0xed,0xda,0xf0,0xb2,0xf3,0xcb,0xf7,0x8d,0xf7,0x8d};//10个功率档位的可控硅导通角延时参数表
TH1=powertab[2*heatpower]-1;
TL1=powertab[2*heatpower+1]; //市电过零后,根据当前设置的档位给定时器T1赋延时参数
ET1=1; //允许定时器T1中断
TR1=1; //打开定时器T1
}

/*------------------------------------------
可控硅触发信号

控制函数 void triacctrl(void)
使用定时器T1中断,寄存器组3
向可控硅送出触发信号
------------------------------------------*/
void triacctrl(void) interrupt 3 using 3
{
register unsigned char i;
triac=0; //输出可控硅导通信号
ET1=0; //关闭定时器T1中断
TR1=0; //终止定时器运行
for (i=0;i<2;i++); //延时,保证导通信号有足够的宽度
triac=1; //完成可控硅导通信号
}


相关文档
最新文档