找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机智能控制洗衣机程序+仿真(根据污泥度和油脂度计算电动机的转动时间)

  [复制链接]
跳转到指定楼层
楼主
ID:232052 发表于 2019-1-23 18:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用智能控制的算法实现的,三角形隶属函数,输入为污泥度和油脂度,输出为电动机的转动时间,程序都有详细标注

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. /**********
  2.         论域e ec u  规则r
  3.         e[e_length]    e_length  5+1  //第一个输入变量表的长度
  4.         ec[ec_length]  ec_length 5+1                //第二个输入变量表的长度
  5.         u[]
  6.         r[r_Line_width][r_Column_width]   r_Line_width   5 //规则表的行
  7.                                                                                                                                                 r_Column_width 5//规则表的列
  8.         //等级表自动生成的
  9.         unsigned char e_level[e_length-1]={0};
  10.         unsigned char ec_level[ec_length]={0};
  11.         unsigned char u_level[u_level_length]={0};

  12.         unsigned char x;//第一个电压的等级
  13.         unsigned char y;//第二个电压的等级
  14.         unsigned char z;//输出等级
  15. *************/
  16. #include <REG52.H>//头文件

  17. #include "TLC2543.h"
  18. #define uchar unsigned char//宏定义
  19. #define uint  unsigned int
  20. /*******************************数码表****************************/
  21. unsigned char code Tab[11]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //数码管显示0~9的段码表
  22. /************修改长度区****************************/
  23. //论域的长度
  24. #define e_length  5+1  //e的长度
  25. #define ec_length 5+1                //第二个输入变量表的长度
  26. #define  u_length  5
  27. //规则表的行列
  28. #define r_Line_width   5 //规则表的行
  29. #define r_Column_width 5//规则表的列
  30. /*************论域表****************************/
  31.                                                                                                         //   0    1     2   3     4
  32. double code e[e_length]  ={0,   0.7,  2.0,  3.0,  4.2,  5};//5个范围6个数代表实际输入电压
  33. double code ec[ec_length]={0,   0.7,  2.0,  3.0,  4.2,  5};//5个范围6个数
  34. unsigned char code u[u_length]={28,34,40,46,52};
  35. /*************论域等级表****************************/
  36. unsigned char e_level[e_length-1]={0};//等级表自动生成的
  37. unsigned char ec_level[ec_length-1]={0};
  38. unsigned char u_level[u_length]={0};
  39. /*****************规则表**************************/
  40. unsigned char r[r_Line_width][r_Column_width]=   //规则表(里面的数据代表的输出等级)
  41. {
  42.         1,1,2,3,4,
  43.         1,2,3,4,5,
  44.         2,3,3,4,5,
  45.         3,4,4,5,5,
  46.         4,5,5,5,5
  47. };

  48. //两个输入和一个输出得等级
  49. unsigned char x;//第一个电压的等级
  50. unsigned char y;//第二个电压的等级
  51. unsigned char z;//输出等级
  52. //两个真实的电压
  53. double e_u;
  54. double ec_u;
  55. unsigned char u_t;//电动机转动时间

  56. //tlc2543读取的两个电压
  57. uint ad_value1=0;
  58. uint ad_value2=0;

  59. unsigned char int_time;        //记录中断次数
  60. unsigned char second;        //储存秒
  61. unsigned char second1;        //储存秒
  62. uint t=0,tt=0;
  63. uint t1=0,tt1=0;
  64. //按键定义
  65. sbit k_start=P0^7;
  66. sbit k_stop=P0^6;
  67. sbit k3=P0^2;
  68. sbit sg=P0^3;

  69. sbit Upper_leve=P0^4;//上液位
  70. sbit Lower_level=P0^5;//下液位

  71. sbit ledon=P0^7;

  72. sbit washing_led=P2^0;//洗涤灯
  73. sbit drying_led=P2^1;//甩干灯

  74. sbit in_led=P2^5;//进水灯
  75. sbit out_led=P2^6;//排水灯

  76. sbit p30=P3^0;
  77. sbit p31=P3^1;

  78. sbit beepon=P2^7;//蜂鸣器

  79. sbit sm1=P3^6;//进水阀门
  80. sbit sm2=P3^7;//出水阀门
  81. void DisplaySecond(unsigned char k);
  82. unsigned char rule_process(double e_local[e_length] ,double ec_local[ec_length],unsigned char r_local[r_Line_width][r_Column_width])
  83. {
  84.         //将两个输入的论域分为等级存在两个表中分别为01234....
  85.         uchar i=0;
  86.         uchar j=0;
  87.         uchar t;
  88.         //等级i分为01234
  89.         for(i=0;i<e_length-1;i++)//循环01234
  90.         {
  91.                         e_level[i]=i;                //存进去表01234
  92.                         if ( (e_local[i]<e_u) && (e_u<=e_local[i+1]) )    //e电压大于第0个数小于第一个数
  93.                         x=i;                                                                                                                                                                                        //  x等级为0
  94.         }
  95.         
  96.         //等级j分为01234
  97.         for(j=0;j<ec_length-1;j++)
  98.         {        

  99.                         ec_level[j]=j;        
  100.                         if ( (ec_local[j]<ec_u) && (ec_u<=ec_local[j+1]) )  //ec电压大于第0个数小于第一个数
  101.                                 y=j;                                                                                                                                                                        // y等级为0               
  102.         }        
  103.         z=r_local[x][y];//确定输出z的等级(查找规则)等级输出为12345
  104.         t=u[z-1];//输出电动机转动的时间//等级输出01234所对应的时间
  105.         return t;
  106. }
  107. //延时函数
  108. void delay2(void)
  109. {
  110.         unsigned char m;
  111.         for(m=0;m<200;m++);
  112. }

  113. void delay1(int s)
  114. {
  115.         int i;
  116.         for(;s>0;s--)
  117.         for(i=0;i<65;i++);
  118. }

  119. void delay(uint i)
  120. {
  121.         uchar j;
  122.         for(i;i>0;i--)
  123.         for(j=255;j>0;j--);
  124. }
  125. //显示函数
  126. void DisplaySecond(unsigned char k)
  127. {
  128.    
  129.                 sm1=0;        //P2.6引脚输出低电平, DS6点亮
  130.                 P1=Tab[k/10];          //显示十位
  131.                 delay2();
  132.                 delay2();
  133.                 sm1=1;
  134.                 sm2=0;       //P2.7引脚输出低电平, DS7点亮
  135.                 P1=Tab[k%10];         //显示个位
  136.                 delay2();
  137.                 delay2();
  138.                 P3=0xff;     //关闭所有数码管
  139.                 P1=1;        //显示个位
  140.                 delay2();
  141.                 delay2();
  142. }

  143. //响蜂鸣器程序
  144. void beep()
  145. {
  146.         p30=0;
  147.         p31=0;
  148.         t=0;
  149.         while(1)
  150.         {
  151.                 beepon^=1;
  152.                 delay(300);
  153.                 if(t>=80) break;
  154.         }
  155.         beepon=0;

  156. }
  157.   
  158. void Washing(uint Washing_time_sec)
  159. {         

  160.         t=0;
  161.         tt=0;        
  162.         int_time=0;
  163.         second=Washing_time_sec;
  164.         //洗涤的时间
  165.         while(1)
  166.         {        
  167.                         //每20代表真实的一秒
  168.                 if(tt>=Washing_time_sec*20) break; //洗涤时间总共是Washing_time_sec秒  时间到了退出循环
  169.                 t=0;
  170.                 //正转2s        
  171.                 while(t<40&&tt<=Washing_time_sec*20)
  172.                 {        
  173.                         p31=0;
  174.                         p30=1;        //正转 2s
  175.                         DisplaySecond(second);
  176.                 }
  177.                 t=0;
  178.                 //反转 2s        
  179.                 while(t<40&&tt<=400)
  180.                 {
  181.                         p30=0;
  182.                         p31=1;
  183.                         DisplaySecond(second);
  184.                 }
  185.         }
  186.                 //停止转动
  187.                 p30=0;
  188.                 p31=0;        

  189. }
  190. void out_water()
  191. {
  192.         p30=0;
  193.         p31=0;
  194.         out_led=1;        //排水阀灯亮 等待霍尔开关2
  195.         while(Lower_level);
  196.         if(Lower_level==0)  //如果闭合
  197.         out_led=0;        //排水灯灭
  198. }

  199. void in_water()
  200. {
  201.         p30=0;
  202.         p31=0;
  203.         in_led=1;//进水灯亮起
  204.         while(Upper_leve);//等待
  205.         if(Upper_leve==0)//进水完毕
  206.         in_led=0;//进水灯关闭
  207. }

  208. void drying(uint Drying_time)
  209. {

  210.         t=0;
  211.         int_time=0;
  212.         DisplaySecond(0);
  213.         second=Drying_time;
  214.         while(t<=Drying_time*20)
  215.         {        
  216.         p31=0;
  217.         p30=1;        
  218.         if(second>=0)
  219.         DisplaySecond(second);
  220.         }
  221. }

  222. void work()
  223. {  
  224.         //甩干占4s  两次占8s 两次进出水共计6s 所以两次洗涤  (u_t-14)/2
  225.         in_water();                    //等待进水完毕才往下走
  226.         Washing((u_t-14)/2);                     //洗涤10S
  227.         out_water();                                                                //洗涤结束开始排水//等待排水排干再继续往下走
  228.         drying(4);                                                                         //甩干4s
  229.         in_water();                                                                                //进水开始等待进水结束
  230.         Washing((u_t-14)/2);                                                        //漂洗10S
  231.         out_water();               //漂洗结束开始排水//等待排水排干再继续往下走
  232.         drying(4);         
  233.         beep();
  234. }

  235. void Read_voltage()
  236. {
  237.                 //                        e_u=3;  //输入电压
  238.                 //                        ec_u=4; //输入电压
  239.                 //                        u_t=rule_process(e,ec,r);//输入参数为e  ec 和r
  240.                 //真实得到电压小数   第一个电压
  241.                 //小数两位b=(uint)(e_u*1000)%1000/10
  242.                 //整数一位a=(uint)(e_u*1000)/1000
  243.                 ad_value1=(read2543(0)*5000.0)/4095;//第一通道//输出电压是一个4位整数
  244.                 e_u=ad_value1/1000.0;   

  245.                 ad_value2=(read2543(1)*5000.0)/4095;//第二通道//输出电压是一个4位整数
  246.                 ec_u=ad_value2/1000.0;                    //第二个电压

  247. }
  248. int main(void)
  249. {         

  250.   TMOD=0x01;       //方式1 16位计数器
  251.   TH0=-50000/256;   //设定初值
  252.   TL0=-50000%256;
  253.   EA=1;               //开总中断
  254.   ET0=1;             //开定时器0中断
  255.   TR0=1;             //启动定时器0
  256.   P2=0;
  257.   int_time=0;     //中断次数初始化
  258.   second=00;           //秒初始化
  259.          while(1)
  260.     {               
  261.                                 if(k_start==0)        
  262.                                 {
  263.                                         while(1)
  264.                                         {
  265.                                                 Read_voltage();             //将两个的电压读入到e_u ec_u
  266.                                                 u_t=rule_process(e,ec,r);  //输入参数为e  ec 和r
  267.                                                 work();
  268.                                         }
  269.                                 
  270.                                 }
  271.                                        
  272.                                 
  273. //                                DisplaySecond(u_t);        //显示出应该输出的电机转动的时间        
  274. }
  275.         return 0;
  276. }  


  277. void time0() interrupt 1 using 1
  278. {  
  279. ……………………

  280. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
程序加仿真洗衣机版本五.rar (161.4 KB, 下载次数: 140)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:247166 发表于 2019-1-24 19:01 | 只看该作者
太好了,谢谢
回复

使用道具 举报

板凳
ID:506687 发表于 2019-4-8 18:01 | 只看该作者

这个真的能够做出来东西吗?里面的文件齐不齐全呢?适合小白吗?
回复

使用道具 举报

地板
ID:477512 发表于 2019-5-17 11:11 | 只看该作者
已经下载,谢谢分享!
回复

使用道具 举报

5#
ID:67838 发表于 2023-8-31 01:13 | 只看该作者

已经下载,谢谢分享!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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