找回密码
 立即注册

QQ登录

只需一步,快速开始

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

猫砂盆自动除尘风机的设计实现

[复制链接]
跳转到指定楼层
楼主


  • 家有恶猫,任性跋扈;
  • 贪吃贪睡,屎尿巨臭;
  • 爪力强劲,刨砂疯狂;
  • 猫砂四溅,尘土飞扬;
  • 娘子过敏,喷嚏不止;
  • 吾心痛焉,技以治之;



本设计用到的元器件:
1.STC12C5068AD为主控;
2.DS1302为时钟IC;
3.TD1030卫星定位授时模块授时;
4.TM1637模块用于显示时间;
5.E18-D80NK型光电开关为触发开关;
6.辅以土壤湿度监测模块监测砂盆附近花盆里的土壤湿度;
7.对外输出包括两路低电平有效的继电器模块(控制风扇、水泵的开关)、蜂鸣器、指示灯等。

实现的主要功能:

1.在恶猫进入砂盆后出发光电开关输出维持低电平,打开风扇开始通风除尘;
2.当恶猫大小便完毕离开砂盆,光电开关输出恢复高电平,使用单片机PCA模块的触发捕获功能捕获上升沿跳变,风扇延时开启2min后关闭;
3.每隔1h自动打开风扇2min通风除味;
4.每天早上07:10打开水泵30s向花盆喷水(润湿植物表层);
5.当土壤湿度模块检测到土壤湿度过低,启动水泵浇水;
6.每天早上7:00及晚上19:00自动打开卫星定位授时模块校准时间。


电路原理图如下:


部分单片机程序:
  1. #include "STC12C56XX.H"
  2. #include "intrins.h"
  3. #include "TM1637.h"
  4. #include "DS1302.h"
  5. /*定义各个端口*/
  6. sbit GPS_EN=P2^4;  //定义GPS模块使能端口
  7. sbit LED=P2^5;     //定义GPS_LED开关端口
  8. sbit FAN=P2^6;     //定义风机信号端口(继电器驱动)
  9. sbit PUMP=P2^7;    //定义水泵信号端口(继电器驱动)
  10. sbit SPK=P3^7;     //定义蜂鸣器信号端口
  11. sbit SD=P1^0;           //定义土壤湿度信号端口(数字信号)
  12. sbit GPS_RST=P1^4; //GPS手动对时按键
  13. sbit SW=P3^5;           //定义触发端口,低电平有效,一并捕获上升沿触发
  14. sbit EPCAI=IE^6;   //PCA模块和LVD监测中断允许位(在头文件中为EPCA_LVD)
  15. /*定义各个变量、数组及标志位*/  
  16. unsigned char hour,min,sec,hourr,minr,secr,hour1,hour2,min1,min2;//小时,分钟,秒钟,小时收到,分钟收到,秒钟收到,小时十位,小时个位,分钟十位,分钟个位
  17. bit rev_start,rev_stop;  //串口接收开始标志位,接收停止标志位
  18. bit flagT,flag_PCA;                 //计时标志位,PCA触发标志位
  19. unsigned int t50ms;                 //定时变量
  20. unsigned char buf[80];   //接收到GPS数据存储到该数组

  21. void delayms(unsigned int xms)//ms延时函数
  22. {
  23. unsigned int i,j;
  24. for(i=0; i<xms; i++)
  25. for(j=0; j<500; j++);
  26. }
  27.                                                                                                                                           
  28. void USART_Init()           //串口及定时器0,1初始化
  29. {
  30.         TMOD=0x21;                   //定时器1工作在方式2,8位自动重装,定时器0工作在模式1
  31.         SCON = 0x50;       //使用串行工作方式1,10位异步收发8位数据,波特率可变(由T1的溢出率控制)
  32.         TH1 = TL1=0xFD;    //9600波特率的初值
  33. //        TH1 = TL1=0xFA;    //4800波特率的初值
  34.         ES = 1;                           //开串口中断
  35.         TR1 = 1;                   //允许T1计数
  36.         TH0 = 0x3C;                   //装定时器0初值,TH0=(65535-50000)/256,TL0=(65535-50000)%256
  37.         TL0 = 0xB0;        //50ms中断一次
  38.         ET0 = 1;                   //开T0中断
  39.         TR0 = 1;                   //允许T0计数
  40.         EA=1;                           //开总中断
  41. }

  42. void PCA_Init()                   //PCA初始化,关于计数部分的配置可注释掉,这里只用到了捕获模式
  43. {
  44.         CCON=0;            //初始化PCA控制寄存器,PCA定时器停止运行,清零CF标志位,清零所有模式中断标志位
  45.         CL=0;              //重置PCA计数器
  46.         CH=0;
  47.         CMOD=0x00;         //设置PCA计数器时钟源为Fosc/12,禁止PCA计数器溢出中断
  48. //        CCAPM1=0x31;       //PCA模块1工作在16位捕获模式,跳变触发
  49.         CCAPM1=0x21;       //PCA模块1工作在16位捕获模式,上升沿触发
  50.         CR=1;              //PCA计数器启动
  51.         EPCAI=1;           //开PCA中断
  52.         EA=1;              //开总中断
  53. }
  54. /*  NMEA0183协议中最简定位信息GNRMC数据格式  */
  55. /*  $GNRMC,203741.00,A,3636.39993,N,12011.80057,E,0.023,,270718,,,A,V*19  */               
  56. /*  定位成功的GNRMC数据格式,串口调试模拟发送时务必要有换行标志"\n"符提示接收停止  */
  57. /*  $GNRMC,,V,,,,,,,,,,N,V*37  */
  58. /*  无信号时的GNRMC数据,即无效定位/授时数据,此时Write_time函数将从','和'V'中取值,所以需要判断定位/授时数据的有效性  */
  59. void Write_time()//将GPS授时数据取值转换并写入DS1302
  60. {
  61.         if((rev_stop==1)&&(buf[0]=='R')&&(buf[2]=='C')&&(buf[4]!=','))//如果接收到GPRMC,从'R'开始接受计数,当buf[4]!=','时,授时数据有效,否则无效
  62.         {
  63.                 ES=0;                                                                           //关闭串口中断
  64.                 hourr= (buf [4]-0x30)* 16+ buf[5] -0x30;   //取hour数值HEX
  65.                 minr=  (buf [6]-0x30)* 16+ buf[7]-0x30;           //取min数值HEX
  66.                 secr=  (buf[8]-0x30)* 16+ buf[9]-0x30;           //取sec数值HEX
  67.                 hourr=  hourr / 16 * 10 + hourr % 16;           //HEX-DEC
  68.                 hourr= (hourr+8) % 24;                     //UTC Time换算成北京时间,+8h
  69.                 hourr=hourr/10*16+hourr%10;                                   //DEC-HEX
  70.                 set_time(secr,minr,hourr);                                   //授时数据写入DS1302
  71.                 ES=1;                                                                           //开启串口中断
  72.                 rev_stop=0;                                                                   //接收停止标志位清零
  73.         }
  74.         
  75. }

  76. void Read_time()                //从DS1302中读取时间数据
  77. {
  78.         hour= ds1302_read(0x85);        //小时
  79.         min = ds1302_read(0x83);        //分钟
  80.         sec = ds1302_read(0x81);        //秒钟
  81. }

  82. void jisuan(void)               //根据接收到的授时数据取值
  83. {        
  84.         hour1=hour/16;                                //取hour十位
  85.         hour2=hour%16;                                //取hour个位
  86.         min1=min/16;                                //取min十位
  87.         min2=min%16;                                //取min个位
  88.         if (sec%2==0)                                //判断sec奇偶
  89.         {
  90.                 hour2=hour2+10;                        //":"闪烁,间隔1s,亮1s,灭1s
  91.         }            
  92. }                                          

  93. void da()   //长鸣一声,代表整点报时及动作开启
  94. {
  95.         SPK=1;
  96.         delayms(2000);
  97.         SPK=0;
  98. }

  99. void daa()  //短鸣一声,用于GPS授时时的声音提示
  100. {
  101.         SPK=0;
  102.         delayms(1000);
  103.         SPK=1;
  104.         delayms(1000);
  105.         SPK=0;
  106. }

  107. void didi() //短鸣两声,代表动作结束
  108. {
  109.         SPK=1;
  110.         delayms(500);
  111.         SPK=0;
  112.         delayms(300);
  113.         SPK=1;
  114.         delayms(500);
  115.         SPK=0;
  116. }

  117. void shan()        //GPS模块上的LED闪烁
  118. {
  119.         LED=0;
  120.         delayms(1000);
  121.         LED=1;
  122.         delayms(1000);
  123.         LED=0;
  124. }

  125. void Out(void) //定时输出
  126. {                                                                 
  127.         if((min==0x30)&&(sec==0x00))                                  {da();}          //每隔1h(xxh30m00s时),蜂鸣器长鸣一声
  128.         else if(((min>=0x30)&&(min<0x32))||(SW==0))                          {FAN=0;}               //风机启动2min(xxh30m00s-xxh32m00s),如果光电开关被触发且维持低电平,维持风机启动
  129.         else if((min==0x32)&&(sec==0x00))                             {FAN=1;didi();}  //2min后(xxh32m00s时),关闭风机,蜂鸣器短鸣两声                        
  130.         else if((min==0x00)&&(sec==0x00))                             {da();}                   //每个整点(xxh00m00s时),蜂鸣器长鸣一声,整点报时
  131.         else if((hour==0x07)&&(min==0x10)&&(sec==0x00))               {da();}               //每天早上07h10m00s,蜂鸣器长鸣一声
  132.         else if((hour==0x07)&&(min==0x10)&&(sec<0x30)&&(sec>=0x00))          {PUMP=0;}                   //水泵启动30s(07h10m00s-07h10m30s)
  133.         else if((hour==0x07)&&(min==0x10)&&(sec==0x30))                      {PUMP=1;didi();} //30s后(07h10m30s时),关闭水泵,蜂鸣器短鸣两声
  134.         else if(SD==1)                                                                              {PUMP=0;}                   //如果土壤湿度低于设定值,开启水泵浇水
  135. //        else if(SW==0)                                                                                      {FAN=0;}                   //如果光电开关被触发且维持低电平,维持风机启动
  136.         else {FAN=PUMP=1;SPK=0;}
  137. }

  138. void chufa()           //PCA触发定时执行
  139. {
  140.         if(flag_PCA==1)           //被触发
  141.         {
  142.                 FAN=0;                   //开启风机
  143.                 if(flagT==1)   //定时满2min
  144.                 {
  145.                         FAN=1;           //关闭风机
  146.                         flagT=0;   //清零定时标志位
  147.                         flag_PCA=0;//清零触发标志位
  148.                 }
  149.         }
  150. }

  151. void main()
  152. {
  153.         P2M0=0x00;
  154.         P2M1=0xf0;      //P24-P27强推挽输出
  155.         P3M0=0x20;
  156.         P3M1=0x80;      //P37强推挽输出,P35高阻输入
  157.         FAN=PUMP=SW=1;        //关闭风机、水泵,触发端口置高
  158.         SPK=0;                        //关闭蜂鸣器
  159.         GPS_EN=0;       //关闭GPS模块
  160.         LED=1;                 //开启GPS模块上的LED
  161.         GPS_RST=1;                //GPS手动对时按键端口置高
  162.         PCA_Init();                //PCA初始化
  163.     USART_Init();        //串口及定时器0初始化
  164.         while(1)
  165.     {
  166.                 if(((hour==0x07)&&(min==0x00))||((hour==0x19)&&(min==0x00))||(GPS_RST==0))          //每天(07:00、19:00)定时打开GPS校准时间再关掉,对时持续1min,也可手动触发校准
  167.                 {GPS_EN=1;shan();daa();ES=1;} //使能GPS模块,LED闪烁,蜂鸣器鸣响,开启串口中断
  168.                 else
  169.                 {GPS_EN=0;LED=0;ES=0;}                  //关闭GPS模块,LED关闭,关闭串口中断                  
  170.                 Write_time();                 //向DS1302中写入时间
  171.                 Read_time();                  //读取DS1302中的时间数据
  172.                 Out();                        //输出
  173.                 chufa();                                          //PCA触发执行延时
  174.                 jisuan();                     //接收时间数据并取值
  175.                 xsled(hour1,hour2,min1,min2); //显示时间
  176.     }
  177. }

  178. void Uart_Receive(void) interrupt 4   //串口中断,接收GNRMC授时数据
  179. {
  180.         unsigned char ch,num;                          //定义接收字符、数组计数变量
  181.         ES = 0;                                                          //关闭串口
  182.         if (RI)                           //如果接收完成则进入
  183.         {
  184.                 ch=SBUF;                                          //从串口缓冲寄存器中取值
  185.                 if(ch=='R')                   //如果收到字符'R',便开始接收
  186.                 {
  187.                         rev_start=1;                          //接收开始标志位置1
  188.                         rev_stop =0;              //接收停止标志置0
  189.                 }
  190.                 if(rev_start==1)              //标志位为1,开始接收
  191.                 {
  192.                         buf[num++]=ch;            //字符存到数组中
  193.                         if (ch=='\n')             //如果接收到换行
  194.                         {
  195.                                 buf[num]='\n';
  196.                                 rev_start=0;                  //接收开始标志位置0
  197.                                 rev_stop=1;           //接收停止标志位置1
  198.                                 num=0;                                  //计数置0
  199.                         }
  200.                 }
  201.         }
  202.         RI = 0;                           //RI清0,重新接收
  203.         ES = 1;                           //串口1中断允许
  204. }
  205. void TIM0(void) interrupt 1                          //定时器0中断函数
  206. {
  207.         TH0 = 0x3C;                                                  //重装初值
  208.         TL0 = 0xB0;
  209.         if(flag_PCA==1)                                          //如果触发
  210.         {
  211.                 t50ms++;                                          //开始计时
  212.                 if(t50ms>=2400)                                  //计时满2min时,实际测试约2min10sec
  213.                 {
  214.                         t50ms=0;                                  //清零计时变量
  215.                         flagT=1;                                  //计时标志位置1
  216.                 }
  217.         }
  218. }

  219. void PCA_isr() interrupt 6                  //PCA捕获模式中断函数
  220. {
  221.         CCF1=0;                           //清零中断标志位
  222.         flag_PCA=1;                                                  //触发执行标志位
  223. }                 
复制代码

全部资料51hei下载地址:
GPS授时.zip (54.18 KB, 下载次数: 16)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:519389 发表于 2019-4-23 11:00
我现在做做猫用品产品,有兴趣可以加微信一起探讨,微信15889751140

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

本版积分规则

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

Powered by 单片机教程网

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