找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3678|回复: 0
打印 上一主题 下一主题
收起左侧

单片机洗衣机节水控制系统的设计论文

[复制链接]
跳转到指定楼层
楼主
ID:326491 发表于 2018-5-10 06:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
摘要
自动化和节能化是目前洗衣机发展的主流趋势。本文根据对洗衣机节能指标的要求,通过方案对比,选择89C52单片机作为控制核心,实施以节水为主要目标的节能洗衣机理念的设计与实现。
本文详细阐述了系统的各个功能模块及其工作过程。洗衣机由键盘设定洗衣模式,并采用传感器检测洗衣过程中的水量、水的混浊程度等参数,通过单片机的八个子程序的处理,实现对洗衣机自动识别水量,自动识别浊度,自动决定漂洗时间和漂洗次数等功能的控制。

1 绪论
1.1 课题背景
1.2 课题的意义
1.3 设计内容
2 系统硬件设计
2.1 方案选择
2.2 系统总体结构设计
2.3 模块电路设计与元件选择
3 系统软件设计
3.1 系统主程序
3.2 计算时间子程序
3.3 中断程序
3.4 显示时间子程序
3.5 浊度数据AD转换及漂洗控制子程序
3.6 键盘扫描子程序
3.7 键盘服务子程序
3.8 工作模式设定程序
3.9 系统动作服务程序
4 系统调试与分析
5 总结
参考文献
致 谢
附录一 系统原理图
附录二 源程序

本系统实现了对洗衣机整个洗衣过程的控制,包括用户参数输入,洗涤,漂洗,浊度检测,脱水等几大步骤。洗衣机就会在每次漂洗完成后智能判断洗涤水的混浊情况,对于不同的污浊度设计了不同的漂洗时间。若在任何一次漂洗结束时进行的浊度检测结果表明洗涤水已足够清净,程序就会直接跳转至“脱水”模式进行衣物脱水,从而节约了大量的冗余漂洗时间和能源。波轮式全自动洗衣机的结构如图2.2所示[10]。     

2.3      模块电路设计与元件选择2.3.1   电源设计

电源模块是为整个电路系统和伺服机构提供能源和动力的重要保证。一般的直流稳压电源由整流电路、滤波电路和稳压电路等几部分组成[11]。

本机电源采用双路输出+5V和+12V,分别用于提供电子电路工作电源和电磁阀驱动电源。使用交流变压器将220V市电降压至15V,经过二极管整流桥整流、电容滤波和稳压管稳压,能输出稳定的直流5V和12V电压。电源模块的电路原理图如图2.3所示。

图2.3 双路稳压电源模块

2.3.3   LED灯显示与74HC573锁存器

节能洗衣机系统有六个基本的状态,分别是厚物洗涤,薄物洗涤,漂洗,脱水,暂停,停止和报警。本系统用六个发光二极管作为状态指示灯,使用共阳极接法,由单片机P1口通过一个锁存器来控制它们的亮灭。LED灯的电路接法如图2.6所示。                            BACK

图2.6  LED状态指示灯

锁存器(Latch)是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。典型的锁存器逻辑电路是 D 触发器电路[13]。本设计使用的74HC573锁存器的真值表如表2.2所示。  BACK

表2.2 锁存器的真值表

输出使能(/OE)

锁存使能(LE)

输入端(D)

输出端(Q)

L

H

H

H

L

H

L

L

L

L

X

Q0

H

X

X

Z


74HC573的八个锁存器都是透明的D型锁存器,当使能引脚LE为高电平时,Q输出将随数据D输入而变化;反之,锁存器进入锁存状态,D将保持原有信号的输出而不受输入信号变化的影响[14]。锁存器的引脚功能与封装如图2.7所示。

图2.7 锁存器的引脚及其功能

在在本课题的应用中,单片机P0口和P1口的八路 I/O 口上分别需要外接锁存器,这是为了实现数据和地址在I/O口上的复用。BACK

2.3.4   七段数码管显示
LED(Light Emiting Diode)是发光二极管英文名称的缩写。常用的LED有共阳极和共阴极2种。共阴极LED显示器的发光二极管的阴极连在一起,通常此公共阴极接地[15]。本次设计是用于显示时间,采用共阴极LED显示就可以有较好的显示效果。
在多位LED显示时,通常将所有位的段码线相应段并联在一起,由1个8位I/O口控制,形成段码线的多路复用,而各位的共阴极或共阳极分别由相应的地址线控制,形成各位的分时选通[16]。七段数码管电路如图2.8所示。  BACK
图2.8  七段数码管显示
2.3.5   浊度检测模块设计

TS浊度传感器是GE公司开发的一种专门用于家电产品的低成本传感器,主要用于洗衣机、洗碗机等产品的水污浊程度的测量,其内部结构原理图如图2.9所示。此种浊度传感器体积小,兼容TTL电平,使用方便[17],故本次设计采用TS浊度传感器。  BACK

图2.9 TS浊度传感器结构原理图

浊度传感器的工作原理是:当光线穿过一定量的水时,光线的透过量取决于该水的污浊程度:水越污浊,透过的光就越少。光接收端把透过的光强度转换为对应的电压大小。通过测量接收端的电压,就可以计算出水的污浊程度。洗涤水的透光度与洗涤时间t的关系曲线如图2.10所示。  BACK

(a)图为洗涤全过程的浊度变化 (b)图为轻污和重污的透光度比较
图2.10  洗涤水的透光度与洗涤时间t的关系曲线

在节能洗衣机系统中,浊度传感器安装在洗衣机的排水管口附近,如图2.11所示,在洗衣机开始排水时启动数据采集进行水质检测,并将检测结果送单片机。

图2.11  浊度传感器的工作示意图

浊度值是由TS浊度传感器测得浊度数据,送ADC0804进行模数转换后所得的数值。实际应用中,应根据不同容量的洗衣机进行实验来确定更准确的浊度值与对应的洗涤时间。表2.3表明衣物浊度与洗涤参考时间的关系。  BACK

表2.3 洗涤水浊度与洗涤参考时间的关系

序号

污浊程度A(十进制A/D值)

洗涤时间(min)

1

A ≤ 55

6

2

55 < A ≤ 94

8

3

94 < A ≤ 126

10

4

126 < A ≤ 152

12

5

152 < A ≤ 173

14

6

173 < A ≤ 191

16

7

191 < A ≤ 208

18

8

A > 208

20

  ADC0804是用CMOS集成工艺制成的逐次比较型摸数转换芯片。该芯片内有输出数据锁存器,当与控制器连接时,无须附加逻辑接口电路。逐次比较型AD由一个比较器和DA转换器通过逐次比较逻辑构成,从MSB开始,顺序地对每一位将输入电压与内置DA转换器输出进行比较,经多次比较而输出数字值。其优点是速度高、功耗低。ADC0804引脚如图2.12所示。  BACK

图2.12  ADC0804引脚功能

在本系统中,浊度信号转换为0V~5V电压信号,浊度传感器连接ADC0804的输入接口进行采样处理,然后将电压信号转换为8位数值0x00~0xff送入单片机P1口。TS浊度传感器及其数据AD采样电路如图2.13所示。  BACK

图2.13  TS浊度传感器及其数据AD采样电路
2.3.6   电机控制

本设计采用家用洗衣机常用的单相交流电机,这种电机有两个绕组:主绕组和副绕组,两个绕组在空间上相差90度。在启动绕组上串联一个容量较大的启动电容,由于电容器作用使启动绕组中的电流在时间上比运行绕组超前90度角,先到达最大值。在时间和空间上形成两个相同的脉冲磁场,使定子与转子之间产生一个旋转磁场,电机转子中产生感应电流,与旋转磁场互相作用产生电磁场转矩,使电机旋转起来。  BACK

普通单相电机这两个绕组完全一样,互相可以交换。要使电机反转,只要交换两个绕组中的一个绕组的首尾接线就可反转。电机的调速是通过一个串接线圈实现。单相交流电机的正反转控制原理如图2.14所示。  BACK

图2.14 单相交流电机的正反转控制

在本设计中,采用两只HJR1-2C电磁继电器控制电机正反转,一只HRS2H-S电磁继电器控制电机的旁路绕阻以实现脱水时电机的高转速工作。电机控制部分的电路原理图如图2.15所示。

图2.15  电机控制部分
2.3.7   水阀

水阀的动作采用电磁阀控制,使用两只HRS2H-S电磁继电器耦合来控制两个大功率电磁阀。进水或排水时,由单片机发出指令,使继电器触点吸合,接通水阀的电磁铁,带动阀门执行进水或排水操作。水阀电路如图2.16所示。

BACK

图2.16  水阀控制电路
2.3.8        水位传感器

  水位传感器采用吸簧式浮子传感器,它本身输出的就是数字信号。当水位有变化时,浮子随着水位上下浮动,内置磁石使对应高度的簧片吸合,触点导通;浮子离开时,当前触点断开,到下一个触点吸合。单片机扫描触点变化信号就可判断当前洗衣桶内的水位。水位传感器结构示意图如图2.17所示。  BACK

图2.17 水位传感器结构示意图
2.3.9   电磁继电器
本电路系统是低压控制高压类型的程控电子线路,由芯片输出的逻辑电平+5V来控制交流220V的负载电机。当继电器线圈两端有电流时,线圈产生的磁通使衔铁吸向铁芯极面,从而推动常闭触点断开,常开触点闭合;当线圈两端电流小于一定值时,机械反力大于电磁吸力,衔铁回到初始状态,常开触点断开,常闭触点接通。继电器原理图如图2.18所示。                            BACK
图2.18  继电器原理图
3          系统软件设计3.1      系统主程序

根据硬件设计要求,控制主程序流程如图3.1所示。洗衣机通电后,单片机上电进行程序的初始化操作,默认洗衣机工作模式为“厚物洗涤”,并显示此工作模式下的预设时间,然后扫描键盘,等待用户命令。当按下“开始”键后,系统就开始倒计时,并进入相应的工作模式程序开始洗涤.


  系统调试与分析

在完成节能洗衣机控制系统的设计后,将程序在系统硬件上进行功能验证。系统硬件组成部分如图4.1所示。

图4.1  节能洗衣机系统硬件部分

    系统上电后,会进入默认的“厚物洗涤”模式并等待操作,如图4.2所示。通过模式选择按键可切换至“薄物洗涤”模式。这时只要按下“开始”键,洗衣机就会按照程序设定开始工作。

图4.2  系统上电后的等待状态

在选定洗涤模式之后按下开始键,系统开始倒计时,并打开进水阀进水,如图4.3所示。在预定水位达到后,控制器关闭进水阀,主电机在程序的控制下间歇正反转,带动波轮和洗衣桶转动进行洗涤,如图4.4所示。                            BACK

图4.3  进水状态

图4.4  洗涤状态

    洗衣机完成漂洗后进入历时2分钟的脱水模式工作。如图4.5所示,脱水状态指示灯点亮,排水阀打开,电机在高速档运作。若此时在时间剩余1分钟内水位降至最低,则洗衣机直接跳出脱水程序,完成洗涤,进入停机等待状态。

图4.5  系统“脱水”工作状态

    在系统的正常工作中,若有异常情况出现,系统会立刻中断当前工作任务,进入“报警”状态:使电机停车等待,蜂鸣器发出告警音响,如图4.6所示。当处理异常情况后,按下“开始”键洗衣机就会恢复到原来的工作状态,继续洗涤工作。

图4.6  系统进入“报警”状态

    经过硬件验证,本系统除具备洗衣机基本功能外,也具有智能判断浊度,自主决策漂洗时间,根据水位情况制定洗涤任务等功能,本课题设计最终实现节能洗衣机的预期功能。                            BACK



5          总结

本课题采用STC89C52单片机对家用洗衣机进行智能控制,设计的节水控制洗衣机系统充分应用了浊度检测技术,通过硬件设计与软件编程,实现了洗衣机的节能控制,一个按钮就能完成洗衣的全过程,且将洗衣机水耗降至最低。本设计系统的特点有:             BACK

(1) 由TS浊度传感器和水位传感器检测到衣物的污浊度与洗涤所用水量,既能保证洗净衣物又使洗涤时间缩短,最大限度地提高洗涤效果,节约能源及用水量,达到了本设计设定的节水这一主要目的。

(2) 本设计还考虑到半自动时的情况,用户可以根据自己的需求自由选择洗衣机的工作方式与洗涤时间。在洗衣机工作的任一过程中,用户可根据需要随时暂停洗衣机,机盖检测和过载保护能有效保证用户安全与洗衣机稳定工作,延长使用寿命。              BACK

在本课题的设计过程中,也出现了不少问题。如浊度传感器暂时找不到,找到的虽然精度高质量好,但是价格不菲。经过分析,发现浊度传感器在工作中输出的是0V~5V的模拟电压信号,而这个信号可用电位器输出,给设计和实物检验带来极大方便。             BACK

本设计仍存在一些不足之处,如洗衣机水位调节只有二级水位变化,在实际应用中可以增加水位调节级别,以便把洗衣机的节能功效发挥到最大;虽然系统消除了继电器动作单元对控制单元的影响,但在同块万用板上焊接的几个电磁继电器之间又相互影响,看来只有使用更规范的PCB电路板和更合理的布线才能消去这种干扰。在软件设计方面,本课题的软件设计只考虑了各功能模块都正常运行的情况,而没设计在某个关键器件故障时系统的自检与保护性停机的程序,故在不同的系统中可视具体情况在程序中加入更加全面的故障处理与保护功能以使系统完善。由于时间所限,本设计的硬件模拟只能做出节能洗衣机的几大基本功能,不能做出较完善和较全面的多功能控制系统,也是本设计的遗憾之处。


附录一 系统原理图


单片机源程序如下:

  1. <font color="rgb(0, 0, 0)">/*=======================================
  2.                             基于STC89C52单片机的
  3.                                           节能洗衣机控制程序设计
  4. =========================================*/
  5. #include<reg52.h>
  6. #include<intrins.h>
  7. #define uchar unsigned char
  8. #define uint unsigned int

  9. sbit dula = P2^6;                                          //段锁存。P0是数码管数据端
  10. sbit wela = P2^7;
  11. sbit beep = P2^3;
  12. sbit diola= P2^5;                                          //LED指示灯锁存

  13. sbit mod_hou =              P1^0;              //厚物指示
  14. sbit mod_bao =              P1^1;              //薄物指示
  15. sbit mod_rewash = P1^2;              //漂洗指示
  16. sbit mod_dry =              P1^3;              //甩干指示
  17. sbit mod_pause =P1^4;              //暂停指示
  18. sbit mod_stop = P1^5;              //停止指示
  19. sbit mod_error= P1^6;              //错误指示

  20. sbit mola = P2^4;                            //伺服控制的锁存器使能
  21. sbit molf = P1^0;
  22. sbit mort = P1^1;
  23. sbit mosp = P1^2;
  24. sbit wtin = P1^3;
  25. sbit wtot = P1^4;
  26. sbit adwr = P3^6;                            //ADC的控制针
  27. sbit adrd = P3^7;

  28. uint mh, ml, sh, sl;
  29. uchar we, du, count, fen, miao;                            //LED位锁,段锁,中断计数,分,秒
  30. uchar key_num, mod_flag, tmp_mod;              //按键返回值,模式标志,临时模式标志
  31. uchar adc_rewash, adc_display_mod;              //AD判断是否漂洗,AD结果是否显示;
  32. uchar adc_samp;                                                                                    //ADC转换结果变量
  33. uchar wt_h, wt_m, wt_l;                                                        //水位指示:高,中,低,水位标志
  34. uchar action_mod, wt_io_action;                            //工作标志缓存,进排水动作标志
  35. uchar rewash_times;                                                                      //记录漂洗次数
  36. bit flag_1s;                                          //1s标志位
  37. uint flag_1s_counter;              //1s计数

  38. uchar code table_of_duanma[] = {                            //共阴码段
  39.                             0x3f, 0x06, 0x5b, 0x4f,      // 0, 1, 2, 3,
  40.                             0x66, 0x6d, 0x7d, 0x07,     // 4, 5, 6, 7,
  41.                             0x7f, 0x6f, 0x40, 0x00 };    // 8, 9, -,              ,                           

  42. //=== 延时子程序 ====================================
  43. void delay(uchar z)
  44. {
  45.               uchar x, y;
  46.               for(x=z;x>0;x--)
  47.                             for(y=110;y>0;y--);
  48. }
  49. //=== 蜂鸣子程序 ====================================
  50. void beep_on(uchar beep_mod)              //蜂鸣器发声模式:
  51. {              //1-短促(按键响应 和 模式切换) 2-稍长(结束提示) 3-很长(报警)
  52.               uchar bp_ct;                                                                      //计算发声次数的局部变量
  53.               switch(beep_mod)
  54.               {
  55.                             case 1: {                            //模式 1 -短促(用于按键)
  56.                                           for( bp_ct=3;bp_ct>0;bp_ct-- )
  57.                                           {            
  58.                                                         beep = 0;
  59.                                                         delay(100);
  60.                                                         beep = ~beep;
  61.                                           }
  62.                                           beep = 1;
  63.                                                         }
  64.                                           break;
  65.                             case 2: {                            //模式 2 -稍长(结束提示)
  66.                                           for( bp_ct=5;bp_ct>0;bp_ct-- )
  67.                                           {              beep = 0;
  68.                                                         delay(500);
  69.                                                         beep = ~beep;
  70.                                           }
  71.                                           beep = 1;
  72.                                                         }
  73.                                           break;
  74.                             case 3: {                            //模式 3 -很长(报警)
  75.                                           for( bp_ct=7;bp_ct>0;bp_ct-- )
  76.                                           {            
  77.                                                         beep = 0;
  78.                                                         delay(500);
  79.                                                         beep = ~beep;
  80.                                           }
  81.                                           beep = 1;
  82.                                                         }
  83.                                           break;
  84.                             default:{               //其他情况视为错误,长2声
  85.                                           for( bp_ct=11;bp_ct>0;bp_ct-- )
  86.                                           {            
  87.                                                         beep = 0;
  88.                                                         delay(500);
  89.                                           }
  90.                                           beep = 1;
  91.                                                         }
  92.                                           break;
  93.               }
  94. }

  95. //=== 系统初始化 ==============================
  96. void init()
  97. {
  98.               fen = 15;
  99.               miao = 0;
  100.               count = 0;
  101.               wt_h = 0;
  102.               wt_m = 0;
  103.               wt_l = 1;

  104.               P0 = 0x00;                            //端口置位,防止干扰
  105.               P1 = 0xff;
  106.               P2 = 0x00;
  107.               wela = 0;
  108.               dula = 0;
  109.               diola= 0;
  110.               mola = 0;                            //关闭电机控制,等待指令操作
  111.               beep_on(2);                            //开机声音响应
  112.               beep = 1;                            //关闭蜂鸣器
  113.               rewash_times = 0;              //漂洗次数初值:0次

  114.               key_num=16;              //按键返回值:无按键
  115.               mod_flag=1;                            //模式标志
  116.               tmp_mod=0;                            //临时模式寄存标志

  117.               TMOD = 0x01;
  118.               TH0 = (65536-50000)/256;
  119.               TL0 = (65536-50000)%256;
  120.               IE = 0x82;                            //中断使能位置1: EA = 1,ET0 = 1。或直接设IE也得
  121. }

  122. //=== 倒计时 =========================
  123. void count_time()
  124. {
  125.               if(count==20)
  126.               {
  127.                             count=0;                            //倒计时:
  128.                             if(fen>0)                            //分钟大于0时
  129.                             {
  130.                                           if(miao>0 && miao<60)                            // 0 < miao < 60
  131.                                           {
  132.                                                         miao--;
  133.                                           }                                                        //秒减1
  134.                                           else                                          //if(miao<0 || miao>59)  //若秒不在0~59内
  135.                                           {
  136.                                                         miao=59;              //说明进位了,就拉回值域
  137.                                                         fen--;                            //然后分钟减1
  138.                                           }                                         
  139.                             }
  140.                             else if(fen==0)                            //分钟为0时,即在最后一分钟内时
  141.                             {
  142.                                           if(miao>0 && miao<=59)              //秒还没进位的话
  143.                                                         miao--;                                                        //秒就减1
  144.                                           else if(miao==0)                                                        //若秒走到0了,则计时时间到
  145.                                           {              TR0 = 0;                                                        //停定时器
  146.                                           //时间到00:00,当前模式工作完成,进入下一模式继续:
  147.                                                         beep_on(1);                                          //蜂鸣模式1:模式切换
  148.                                           }
  149.                             }
  150.               }
  151. }

  152. //=== 显示时间 ===========================
  153. void display_time()
  154. {
  155.               if(adc_display_mod != 1)              //若ADC结果不显示(≠1时),就进入时间显示
  156.               {                                                                                    //否则跳出。以此来消去AD显示时的时间部分干扰
  157.                             for(we=0xdf;we!=0xfe;we=_cror_(we,1))
  158.                             {                                                                       //we==1101 1111 开始右移            
  159.                                           wela = 0;
  160.                                           P0 = we;
  161.                                           wela = 1;                              //位选
  162.                                           wela = 0;
  163.                                           delay(1);//这个delay只能是1,大于3严重闪烁,大于5时间不走...
  164.                                           dula = 0;                            //段选
  165.                                                         switch(we)
  166.                                                         {
  167.                                                                       case 0xdf: P0=table_of_duanma[miao%10];
  168.                                                                                     break;
  169.                                                                       case 0xef: P0=table_of_duanma[miao/10];
  170.                                                                                     break;                                                      
  171.                                                                       case 0xf7: P0=0x40;                 // -              间位符
  172.                                                                                     break;
  173.                                                                       case 0xfb: P0=table_of_duanma[fen%10];
  174.                                                                                     break;
  175.                                                                       case 0xfd: P0=table_of_duanma[fen/10];
  176.                                                                                     break;
  177.                                                                       case 0xfe: P0=0x00;                //关闭最高位
  178.                                                                                     we=0xdf;                                         
  179.                                                                                     break;
  180.                                                         }                                                      
  181.                                           dula = 1;
  182.                                           delay(1);
  183.                                           P0 = 0x00;              //关数码管
  184.                                           dula = 0;
  185.                             }
  186.               }
  187. }

  188. //=== 工作模式指示灯 =========================
  189. void display_mod()                            //显示:仅用于点亮LED工作模式指示灯
  190. {
  191.               mola = 0;                                          //关闭电机控制锁存器使能
  192.               P1 = 0xff;                                          //改变 mod_flag
  193.               diola = 1;
  194.               delay(1);
  195.               switch(mod_flag)
  196.               {
  197.                             case 1:              {              mod_hou = 0;               }              //标志 1:厚物洗涤
  198.                                           break;
  199.                             case 2: {              mod_bao = 0;               }                            //标志 2:薄物洗涤
  200.                                           break;
  201.                             case 3: {              mod_rewash = 0; }                            //标志 3:漂洗
  202.                                           break;
  203.                             case 4: {              mod_dry = 0;              }                            //标志 4:甩干
  204.                                           break;
  205.                             case 5:              {              mod_pause = 0;              }              //标志 5:暂停
  206.                                           break;
  207.                             case 6: {              mod_stop = 0;              }                            //标志 6:停止
  208.                                           break;
  209.                             case 7: {              mod_error = 0;              }                            //标志 7:报警
  210.                                           break;
  211.               }
  212.               diola = 0;
  213. }

  214. //=== ADC Display =========================
  215. void adc_display(uchar bai_c,uchar sh_c,uchar g_c)              /
  216. {
  217.    P0=table_of_duanma[bai_c];                            //显示百位
  218.    dula=1;
  219.    dula=0;

  220.    P0=0xfe;                            //确定显示用数码管的位地址
  221.    wela=1;
  222.    wela=0;
  223.    delay(10);              //延时放在这是为了消除鬼影 

  224.    dula=0;
  225.    P0=table_of_duanma[sh_c];                            //显示十位
  226.    dula=1;
  227.    dula=0;

  228.    wela=0;
  229.    P0=0xfd;
  230.    wela=1;
  231.    wela=0;
  232.    delay(10);

  233.    P0=table_of_duanma[g_c];                            //显示个位
  234.    dula=1;
  235.    dula=0;

  236.    P0=0xfb;
  237.    wela=1;
  238.    wela=0;
  239.    delay(10);
  240. }
  241. //=== AD转换 =============================
  242. void adc_serve()            
  243. {
  244.               uchar a,A1,A2,A2t,A3;
  245.               dula=0;                                          //关闭7段数码管的显示
  246.               wela=1;                                          //打开有ADC片选的锁存器
  247.     P0=0;                                          //P0^7针为0时,选通ADCS
  248.     adwr=0;                            //AD写入,低电平有效(主要是为了启动AD转换)
  249.               display_mod();              //显示一下工作模式,(为了给AD转换延时)
  250.     adwr=1;                            //关ADC写入使能
  251.     P0=0xff;                            //关闭ADCS
  252.               if(adc_display_mod==1)                            //ADC显示标志为1(0就不显示结果)。
  253.               {    wela=0;
  254.                   for(a=10;a>0;a--)
  255.                   {
  256.                               delay(10);                                                                                                                                                                                          
  257.                    adc_display(A1,A2,A3);              //送去显示各个数位。
  258.                   }
  259.               }
  260.               wela = 1;                                          //重新打开有AD片选信号锁存器的锁存端            
  261.      P1 = 0xff;                                          //读取P1口之前先给其写全1
  262.      P0 = 0;                                          //选通ADCS
  263.                    adrd = 0;                            //AD读使能                  
  264.               adc_samp = P1;                            //AD数据读取赋给P1口
  265.                    adrd = 1;                            //关闭AD读使能
  266.      P0 = 0xff;                                          //关闭ADCS片选
  267.      adwr =0 ;                                          //打开AD写
  268.               if(adc_display_mod==1)                            // 若允许AD显示
  269.               {              A1=adc_samp/100;                            //分出百,十,和个位
  270.                             A2t=adc_samp%100;
  271.                             A2=A2t/10;
  272.                             A3=A2t%10;              //AD原理:透过的光多,电流大,说明水清,反之水浊
  273.               }                                                        //仿真输出是0~255数字。0(0v)为污浊,清净为255(5v).
  274.               if(adc_samp < 200)
  275.                             adc_rewash = 1;
  276.               else
  277.                             {
  278.                                           adc_rewash = 0;
  279.                             }
  280. }
  281. //=== 键盘扫描 =============================
  282. void key_serve()                                          //按键服务
  283. {                                                                                    //读取键值后进行相应的操作
  284.               uchar tmp_mod_memory=0, tmp_fen=0, tmp_miao=0;
  285.               diola=0;
  286.               P1 = 0xff;                                          //关闭LED灯,防按键干扰
  287.               switch(key_num)
  288.               {
  289.                             case 0: {                                          //厚物洗涤
  290.                                                         if(TR0==0 && (fen==0 || fen==10))            
  291.                                                         {
  292.                                                                       fen = 15;
  293.                                                                       miao = 0;
  294.                                                                       mod_flag = 1;              //工作模式1:厚物
  295.                                                                       tmp_mod = 1;
  296.                                                                       rewash_times = 0;
  297.                                                                       adc_rewash = 1;
  298.                                                                       beep_on(1);
  299.                                                                       }
  300.                                                         }
  301.                                           break;
  302.                             case 4: {                            //薄物洗涤
  303.                                                         if(TR0==0 && (fen==0 || fen==15))            
  304.                                                                       {
  305.                                                                       fen = 10;
  306.                                                                       miao = 0;
  307.                                                                       mod_flag = 2;                                                                      //工作模式2:薄物
  308.                                                                       rewash_times = 0;
  309.                                                                       adc_rewash = 1;
  310.                                                                       tmp_mod = 2;
  311.                                                                       beep_on(1);
  312.                                                                       }
  313.                                                         }
  314.                                           break;
  315.                             case 1: {                            // 开始              键
  316.                                                         if(TR0==0)                                                                                    //定时器不工作时,才响应
  317.                                                                       {
  318.                                                                       mod_flag = tmp_mod;                            //从临时变量读取原工作模式
  319.                                                                       TR0 = 1;
  320.                                                                       beep_on(1);
  321.                                                                       }
  322.                                                         }
  323.                                           break;
  324.                             case 5: {                            // 暂停 键
  325.                                                         if(mod_flag != 5 && TR0==1)
  326.                                                                       {
  327.                                                                       tmp_mod = mod_flag;              //当前工作模式存入临时变量中
  328.                                                                       TR0 = 0;
  329.                                                                       mod_flag = 5;                            //工作模式5:暂停
  330.                                                                       beep_on(1);            
  331.                                                                       }
  332.                                                         }                                                      
  333.                                           break;
  334.                             case 9:              {                            //停止 键:
  335.                                                         if(TR0 == 1)                                                        //定时器在工作时,才响应
  336.                                                                       {
  337.                                                                       tmp_mod = mod_flag;                            //当前工作模式存入临时变量中
  338.                                                                       P1 = 0xff;
  339.                                                                       TR0 = 0;                                                        //关定时器
  340.                                                                       fen = 00;
  341.                                                                       miao= 00;
  342.                                                                       rewash_times = 0;                            //重置漂洗次数
  343.                                                                       adc_rewash = 1;                                          //重置漂洗允许标志位                                         
  344.                                                                       mod_flag = 6;                                          //工作模式6:停止
  345.                                                                       beep_on(2);                                                        //蜂鸣器模式2:停止
  346.                                                                       }
  347.                                                         }                                                                                                  //然后停止,等待
  348.                                           break;
  349.                             case 2: {                 // 报警
  350.                                                         if( (mod_flag != 5) && (mod_flag != 6) && TR0==1 )            
  351.                                                                       {
  352.                                                                       tmp_mod = mod_flag;              //当前工作模式存入临时变量中
  353.                                                                       P1 = 0xff;                                          //LED防干扰,先关闭            
  354.                                                                       TR0 = 0;
  355.                                                                       mod_flag = 7;                            //工作模式7:报警
  356.                                                                       beep_on(2);                                          //蜂鸣器模式2:停止
  357.                                                                       }
  358.                                                         }
  359.                                           break;
  360.                             case 6: {                 // 机盖打开(6键是 机盖)
  361.                                                         if( (mod_flag != 5) && (mod_flag != 6) && TR0==1 )            
  362.                                                                       {
  363.                                                                       tmp_mod = mod_flag;              //当前工作模式存入临时变量中
  364.                                                                       P1 = 0xff;                                                        //LED防干扰,先关闭
  365.                                                                       TR0 = 0;
  366.                                                                       mod_flag = 5;                                          //工作模式7:报警
  367.                                                                       beep_on(2);                                                        //蜂鸣器模式2:停止
  368.                                                                       }
  369.                                                         }
  370.                                           break;
  371.               //演示专用:水位模拟键的动作
  372.                             case 12: {
  373.                                                         P1 = 0x0ff;
  374.                                                         wt_h = 1;              //高水位
  375.                                                         wt_m = 0;
  376.                                                         wt_l = 0;
  377.                                                         }
  378.                                           break;
  379.                             case 13: {
  380.                                                         P1 = 0x0ff;
  381.                                                         wt_h = 0;
  382.                                                         wt_m = 1;              //中水位
  383.                                                         wt_l = 0;
  384.                                                         }
  385.                                           break;
  386.                             case 14: {
  387.                                                         P1 = 0x0ff;
  388.                                                         wt_h = 0;
  389.                                                         wt_m = 0;
  390.                                                         wt_l = 1;              //低水位
  391.                                                         }
  392.                                           break;
  393.               //演示专用:分钟速减键
  394.                             case 3: {
  395.                                                         P1 = 0xff;
  396.                                                         mola=0;
  397.                                                         diola=0;                              //以上防干扰用
  398.                                                         if(fen != 1)
  399.                                                                       fen=1;
  400.                                                         }
  401.                                           break;
  402.               //演示专用:秒钟速减键
  403.                             case 7: {
  404.                                                         P1 = 0xff;
  405.                                                         mola=0;
  406.                                                         diola=0;                              //以上防干扰用
  407.                                                         if(miao!=1)
  408.                                                                       miao=1;
  409.                                                         }
  410.                                           break;
  411.               //演示专用:从 时间显示 切换到 AD转换结果显示
  412.                             case 11: {
  413.                                                         if(adc_display_mod==0)                            //显示模式不在AD显示时,响应
  414.                                                         {            
  415.                                                                       tmp_fen = fen;                                          //先保存当前计时时间
  416.                                                                       tmp_miao = miao;
  417.                                                                       adc_display_mod = 1;              //模式1为AD结果显示;
  418.                                                                       adc_serve();                                                        //(0为不显示,后台运行)
  419.                                                                       EA = 0;                                                                      //关中断,优化显示效果(消鬼影)
  420.                                                                       TR0 = 0;            
  421.                                                         }
  422.                                           }
  423.                                           break;
  424.               //演示专用:从 AD转换结果 切换到 时间显示
  425.                             case 15: {              //切换到Time时间显示
  426.                                                         if(adc_display_mod==1)
  427.                                                         {            
  428.                                                                       fen = tmp_fen;                                          //读取暂存的时间数据
  429.                                                                       miao = tmp_miao;
  430.                                                                       adc_display_mod = 0;              //不显示ADC结果
  431.                                                                       EA = 1;                                                                      //开中断,回到时间显示            
  432.                                                                       TR0 = 1;            
  433.                                                         }
  434.                                           }
  435.                                           break;
  436.               }
  437. }
  438. //=== 键盘扫描 ===============================
  439. void key_scan()                            //键盘扫描:将获取新的key_num值
  440. {
  441.               uchar temp, tempp=30;//临时键值            
  442.               uchar key_en=1;              //键盘监视:有按键动作时才执行Key_serve,否则仅仅作扫描。不然延时太严重,LED会闪烁

  443.               P3 = 0x0f;                            //低4位置1,放入4行。
  444.               temp = P3^0x0f;              //异或,把相异的一行变成1,其它全为0
  445.                                           switch(temp)              //判断是哪行有键按下了(0-3行)
  446.                                           {                                                        //就给相应键值的行提前量
  447.                                                         case 1: key_num = 0; break;
  448.                                                         case 2: key_num = 1; break;
  449.                                                         case 4: key_num = 2; break;
  450.                                                         case 8: key_num = 3; break;
  451.                                                         default: {              //无按键
  452.                                                                                     key_num= 16;
  453.                                                                                     key_en=0;
  454.                                                                                     }              break;
  455.                                           }
  456.                            
  457.                                           P3 = 0xf0;                            //高4位置1,放入4列。
  458.                                           temp = (P3>>4)^0x0f;              //将高位移到低位,用异或找出按下的列
  459.                                           switch(temp)              //判断列按下,在先前的键值中加入列数得键值
  460.                                           {
  461.                                                         case 1: key_num += 0; break;
  462.                                                         case 2: key_num += 4; break;
  463.                                                         case 4: key_num += 8; break;
  464.                                                         case 8: key_num += 12;
  465.                                           }
  466.                                           if(key_en==1 && temp!=tempp)              //如果有键盘操作,才执行按键服务
  467.                                           {
  468.                                                         tempp = key_num;
  469.                                                         key_serve();
  470.                                           }
  471.                                           temp = key_num;
  472.                                           display_mod();              //指示工作模式的LED灯变化
  473. }

  474. //=== 系统动作控制 =====================
  475. void action_serve(uchar action_mod)                            //主电机动作
  476. {
  477.               P0 = 0xff;
  478.               diola = 0;
  479.               switch(action_mod)
  480.               {
  481.                             case 1: {              //模式1 - 1分钟电机间歇正反转 ==》洗涤

  482.                                           if( ((miao<55)&&(miao>45)) || ((miao<25)&&(miao>15)) )
  483.                                           {            
  484.                                                         mola = 1;
  485.                                                         P1 = 0xfe;              //电机正转
  486.                                                         mola = 0;
  487.                                           }
  488.                                           else if( ((miao<40)&&(miao>30))||((miao<10)&&(miao>0)) )
  489.                                           {
  490.                                                         mola = 1;
  491.                                                         P1 = 0xfd;              //电机反转
  492.                                                         mola = 0;
  493.                                           }
  494.                                           else
  495.                                           {
  496.                                                         mola = 1;            
  497.                                                         P1 = 0xff;              //电机停车
  498.                                                         mola = 0;            
  499.                                           }
  500.                             }
  501.                                           break;
  502.                             case 2: {              //模式2 -电机加速 ==》脱水
  503.                                           mola = 1;
  504.                                           P1 = 0xea;                            //speed
  505.                                           mola = 0;
  506.                                           if(fen==0 && miao==0)                            //计时时间到
  507.                                           action_mod = 7;
  508.                             }
  509.                                           break;
  510.                             case 3: {              //模式3 -进水
  511.                                           mola = 1;
  512.                                           P1 = 0xf7;              //开进水阀
  513.                                           mola = 0;
  514.                             }
  515.                                           break;
  516.                             case 4: {              //模式4:-排水
  517.                                           mola = 1;
  518.                                           P1 = 0xef;              //开排水阀
  519.                                           mola = 0;
  520.                             }
  521.                                           break;
  522.                             case 7: {              //模式7:空(停机,等待)
  523.                                           mola = 1;
  524.                                           P1 = 0xff;              //关停全部伺服
  525.                                           mola = 0;
  526.                             }
  527.                                           break;
  528.                             default:{              //其他不可预知的状态
  529.                                           mola = 1;
  530.                                           P1 = 0xff;              //关停全部伺服
  531.                                           mola = 0;
  532.                                                         }
  533.                                           break;
  534.               }
  535. }
  536. //=== 工作模式子程序 ====================================
  537. void working_mod()              //工作模式:读取模式标志 mod_flag,判断系统任务
  538. {
  539.               uchar t;                                          //报警次数设定
  540.               uchar dirty_level;              //水的污浊级别
  541.               switch(mod_flag)
  542.               {
  543.                             case 1: {                             //---‘厚物’洗涤---              (按键处设定时间了)
  544.                                                         tmp_mod = mod_flag;              //当前工作模式存入临时变量中
  545.                                                         if(wt_h==0 && (fen+2)>=15 && TR0==1)
  546.                                                                       action_serve(3);                                                        //进水
  547.                                                         if(wt_h==1 && fen!=0)                                          //水位控制
  548.                                                                       action_serve(1);                                                        //进行厚物洗涤                                         
  549.                                                         if(fen==0 && miao!=0)                                                        //结束前1分钟
  550.                                                                       {
  551.                                                                                     action_serve(4);                                                        //排水
  552.                                                                                     adc_serve();              //在排水时检测浊度
  553.                                                                                     delay(1);              //ADC needs time
  554.                                                                       }
  555.                                                         if((fen==0 && wt_l==1))                            //如果时间到最后1min 或 水位低
  556.                                                                       {
  557.                                                                                     beep_on(1);
  558.                                                                                     miao=0;
  559.                                                                                     adc_rewash=1;                            //漂洗标志置1
  560.                                                                                     TR0 = 0;
  561.                                                                                     mod_flag = 3;                            //就进入漂洗程序
  562.                                                                       }
  563.                                                         }
  564.                                           break;
  565.                             case 2: {                            //---‘薄物’洗涤---              (按键处设定时间了)
  566.                                                         tmp_mod = mod_flag;              //当前工作模式存入临时变量中
  567.                                                         if(wt_m==0 && (fen+1)>=10 && TR0==1)
  568.                                                                       action_serve(3);                                                        //进水(1min)
  569.                                                         if(wt_m==1 && fen!=0)                                          //从8min开始
  570.                                                                       action_serve(1);                                                        //进行薄物洗涤
  571.                                                         if(fen==0 && miao!=0)                                          //提前1分钟排水
  572.                                                                       action_serve(4);                                                        //排水
  573.                                                         if((fen==0 && wt_l==1))                                          //如果时间到 或 水位低
  574.                                                                       {
  575.                                                                                     beep_on(1);
  576.                                                                                     miao=0;
  577.                                                                                     adc_rewash=1;                                          //漂洗标志置1
  578.                                                                                     TR0 = 0;
  579.                                                                                     mod_flag = 3;                                          //就进入漂洗程序
  580.                                                                       }
  581.                                                         }
  582.                                           break;
  583.                             case 3: {                            //---漂洗---
  584.                                                         tmp_mod = mod_flag;                            //当前工作模式存入临时变量中
  585.                                                         adc_serve();                                                                      //AD判断水的污浊程度
  586.                                                         if((rewash_times <= 4) && (adc_rewash==1))            
  587.                                                         {
  588.                                                                       if(TR0==0)                            //若定时器还没开启,就进入 时间设定                                                                                      {                            //4级洗衣水污浊程度判断后设定rewash时间
  589.                                                                                     if( adc_samp < 100 )              //若AD检测结果 小于100:很污浊
  590.                                                                                     {              fen = 10;
  591.                                                                                                   miao = 0;
  592.                                                                                                   dirty_level = 3;              //3级污浊
  593.                                                                                     }
  594.                                                                                     else if( (adc_samp >= 100) && (adc_samp < 150))
  595.               //AD结果 在 100 到 150 之间:比较污浊
  596.                                                                                     {              fen = 7;
  597.                                                                                                   miao = 0;
  598.                                                                                                   dirty_level = 2;              //2级污浊
  599.                                                                                     }
  600.                                                                                     else if( (adc_samp >=150) && (adc_samp < 200) )
  601.               //AD结果 在 150 到 200 之间:轻微污浊
  602.                                                                                     {              fen = 5;
  603.                                                                                                   miao = 0;
  604.                                                                                                   dirty_level = 1;              //1级污浊
  605.                                                                                     }                                                                                    //时间设定完成
  606.                                                                                     rewash_times++;                                          //漂洗次数加1
  607.                                                                                     TR0 = 1;
  608.                                                                       }
  609.                                                                       else if(TR0==1 && fen!=0 && wt_l==1)
  610.                                                                       {
  611.                                                                                     action_serve(3);                            //开进水阀
  612.                                                                       }                                                                                                  //定时器是开着的,就执行下面
  613.                                                                       else if(fen!=0 && miao!=0 && wt_l!=1)                                                                                                                                                          action_serve(1);                            //开电机,漂洗
  614.                                                                       else if( fen==0 && miao!=0 && wt_l!=1 )                                                                                                                                            {            
  615.                                                                                                   action_serve(4);              //排水
  616.                                                                                                   adc_serve();                            //同时进行浊度检测
  617.                                                                       }
  618.                                                         }
  619.                                                         else if( fen==0 && miao!=0 && wt_l==1)            
  620.               //在结束漂洗前1min内 and 低水位到
  621.                                                                       {
  622.                                                                                     miao = 0;
  623.                                                                                     wt_l = 0;
  624.                                                                       }

  625.                                                         else if((rewash_times > 4) || (adc_rewash==0))            
  626. //若漂洗超过4次 或 由AD结果说明不需要再漂洗了
  627.                                                                       {
  628.                                                                                     adc_rewash = 0;                                          //停止漂洗
  629.                                                                                     mod_flag = 4;                                          //进入甩干程序
  630.                                                                                     TR0 = 0;                                                        //进入甩干模式前先停定时器
  631.                                                                       }
  632.                                           }
  633.                                           break;
  634.                             case 4: {                            //---脱水---
  635.                                                         tmp_mod = mod_flag;                                                        //当前工作模式存入临时变量中
  636.                                                         if(adc_rewash==0 && TR0 == 0)              //如果满足甩干初始条件
  637.                                                                       {              fen=2;                                                                      //设定甩干时间为2分钟
  638.                                                                                     miao=0;
  639.                                                                                     TR0 = 1;                                                        //开始计时
  640.                                                                       }
  641.                                                         if(TR0==1)
  642.                                                                       action_serve(2);                                          //伺服动作2:甩干
  643.                                                         if(wt_l==1)              //若低水位到
  644.                                                                       {            
  645.                                                                       if(fen==1 && miao>10)
  646. ……………………

  647. …………限于本文篇幅 余下代码请从51黑下载附件…………
  648. </font>
复制代码

所有资料51hei提供下载:

单片机洗衣机节水控制系统的设计.doc (1.81 MB, 下载次数: 41)





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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