本文主要是介绍51单片机项目设计:智能宠物小屋(自动喂食喂水、自动通风换气、自动清洁)制作教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
智能宠物小屋
资料链接:https://download.csdn.net/download/mbs520/20365056
文章目录
- 智能宠物小屋
- 一、项目设计要求
- 二、硬件框架搭建
- 三、硬件材料选型
- 四、元件清单
- 五、原理图设计
- 六、电路主板焊接
- 七、程序框架设计
- 八、程序设计
- 九、下载验证
QQ交流群1:981140834
QQ交流群2:473982062
QQ交流群3:718245727
QQ交流群4:598455837
一、项目设计要求
以单片机为控制核心设计一个智能宠物小屋控制系统,设计基本要求如下:
1)具有自动喂食喂水、自动通风换气、自动清洁等功能;
2) 完成智能宠物小屋控制系统硬件电路设计;
3) 完成智能宠物小屋控制系统软件设计。
二、硬件框架搭建
(一)硬件框架
(二)设计功能
(1)实时时间、温度显示以及调控温度;
控制时钟芯片将当前时间显示在液晶屏上,设加、减、功能切换、参数切换四个按键,用于调节时间、调节功能闹钟及手动开启或关闭某功能设置;温度采集电路完成温度值的检测及数值的转换和线性化处理,处理后发送给单片机,由单片机控制温度值显示;
将采集的温度与标准温度值进行比对,若比设定值大的话就开启风扇至设定温度停止;
(2)定时喂食喂水。能够定时地为宠物提供食物和水;
通过时钟电路设定喂食时间,带扇叶的步进电机正转打开喂食口,让食物从料仓落到食盘,然后电机反转关闭喂食口;
通过时钟电路设定喂水时间,由单片机控制在水仓的水泵抽水通过塑料软管流入宠物水盆,水盆内有水位传感器测水位,达到标准水位停止抽水。
(3)定时清洁宠物生活区域。根据电机正反转循环清扫笼子底部;
设定清洁时间,控制带有清洁电刷的步进电机正反转清洁,利用红外检测宠物是否在屋内,若在屋内在下个清洁时间清洁,反之即时开启清洁;
三、硬件材料选型
(一)单片机选型
使用STC89C52单片机,其内部有2 bytes 片内RAM数据存储器。由于要随时要对程序进行修改和新增一些程序的功能,与AT89S52相比,STC89C52无需编程器和安装驱动就可以下载,而且片内带2 K bytes EEPROM 存储空间,因此选择STC89C52单片机作为主控系统。
(二)显示模块
采用LCD液晶屏显示,不但耗能少,而且可显示汉字与英文。在显示内容方面也变得更加灵活,修改程序编写就可完成,无需对硬件进行修改,也更便于扩展其他电路。此外,该模块硬件连接也比较简单易操作。与方案一较之,方案二耗能更少、显示更灵活、电路的扩展更方便,而且软硬件设计简单,因此选用LCD液晶屏为显示模块。
(三)水位传感器
Water Sensor水位传感器体积小巧、简单易用,可靠性高,易清洁,安装方便,价格低廉。输出信号为模拟信号,连接电路后可基本测出水位情况,满足水位检测要求。相比浮球式水位传感器,Water Sensor水位传感器简单易用。
(四)红外传感器
本文选用的红外感应模块为红外对管模块,主要是通过两个红外元件进行发射与接受进行感应。当发射载波频率与接收头固定频率处于一致的情况下,就可以接收红外感应。发射管先发送红外信号,红外信号会随着传送距离的加大慢慢减弱,当信号接触到检测体时,就形成红外反射。当反射的信号弱时,光敏二极管 L2 接收的红外光较弱,比较器LM393 的3脚电压大于2脚电压,接收检测引脚处于高电平状态,此时宠物较远;当反射信号较强,接收检测引脚处于低电平状态,此时宠物较近。
(五)时钟芯片模块
使用DS1302芯片实现时钟控制,DS1302 芯片是一款专门用于时钟控制的芯片,工作电压在2.0V-5.5V之间,可为实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,也可选择使用 24 或12 小时计时法,还可对每月的天数和闰年进行调整[7]。另外,它可以同步串行的方式完成与单片机之间的通信,因此,选用DS1302芯片作为时钟芯片。
(六)温度采集模块
采用数字式传感器DS18B20,具有测量范围广,测量精度高的特点。DS18B20只需要一条数据线就可以直接把数字温度值输出,无需外接AD电路,有利于电路简单化。因此,本系统选用DS18B20为温度传感器。
(七)电机驱动模块
使用H桥电路的L298N驱动器作为电机驱动模块。H桥电路可控制电机转速和方向,而且稳定性高。一片L298N驱动芯片可同时控制两个直流电机,过程并不复杂,通过主控芯片的I/O输入对输入端的逻辑电平状态进行改变,就可完成电机的正转反转控制,同时还具有过热自断和反馈检测的特性。另外,当电机出现卡死的情况时,芯片会启动过电流功能保护设备,所以选用L298N作为电机驱动模块。
(八)风扇,清理电机,水泵
直接选最便宜的直流电机
(九)其它
电阻、电容、晶振、二极管、三极管、蜂鸣器等…
四、元件清单
Description | Comment | Designator | Quantity |
电容 | 30pF | C1、C2 | 2 |
电容 | 10μF | C3 | 1 |
晶振 | 12M | X1 | 1 |
电机驱动 | L298N | LN1,LN2 | 2 |
温度传感器 | DS18B20 | IC1 | 1 |
红外传感器 | HW | IC2 | 1 |
单片机 | STC89C52 | IC3 | 1 |
时钟芯片 | DS1302 | IC4 | 1 |
电阻 | 10K | R1~R5 | 5 |
电阻 | 4.7K | R6 | 1 |
排阻 | 1K | Rp1 | 1 |
电位器 | 10K | WR1,WR2 | 1 |
蜂鸣器 | 有源 | BEEP | 1 |
液晶显示器 | LCD1602 | J4 | 1 |
按键 | 轻触 | Key1,Key2,Key3, Key4, Key5 | 5 |
发光二极管 | 红色 | LED1 | 1 |
风扇、水泵、电机 | 3-6V直流 | M1,M2,M3,M4 | 4 |
三极管 | 2N3906 | Q1,Q2,Q3,Q4 | 4 |
开关 | 拨动 | SW1 | 1 |
纽扣电池 | 3v | BAT1 | 1 |
晶振 | 32.768KHz | X2 | 1 |
二极管 | IN 4148 | D1,D2,D3 | 3 |
水位传感器 | 模拟 | T1 | 1 |
排针 | 4脚、多脚 | Header | 1 |
洞洞板 | 玻纤 | 9*15cm | 1 |
五、原理图设计
看不清,需要下载资料,用DXP或者AD软件打开
六、电路主板焊接
(一)先画布局图再进行焊接
(二)焊接好,并按照原理图连接好外围电路
七、程序框架设计
(一)主程序框架
其他具体框架参考论文
八、程序设计
篇幅有限、只贴出部分程序
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "ds1302.h"
#include "temp.h"
#include "lcd.h"
#include "eeprom.h"
#include <string.h>sbit K1 = P1^0; //按键
sbit K2 = P1^1;
sbit K3 = P1^2;
sbit K4 = P1^3;sbit LCD_LED = P2^4; //lcd背光
sbit BEEP = P1^4; //蜂鸣器
sbit IR = P1^5; //红外
sbit WIT_0 = P1^6; //水位检测
sbit WIT_1 = P1^7;sbit WATER_EN = P2^0; //水泵
sbit FAN_EN = P2^1; //风扇sbit CLR_EN_A = P2^2; //清理电机
sbit CLR_EN_B = P2^3; //清理电机sbit FEED_EN_A = P3^2; //喂食
sbit FEED_EN_B = P3^3; //喂食typedef unsigned int u16;
typedef unsigned char u8;//风扇启动时间
//8小时一次
u8 fan_time8[3] = {0x01,0x09,0x17};
//5小时一次
u8 fan_time5[5] = {0x00,0x05,0x10,0x15,0x20};
//3小时一次
u8 fan_time3[8] = {0x02,0x05,0x08,0x11,0x14,0x17,0x20,0x23};//时间结构体
typedef struct
{u8 hour;u8 min;u8 sec;
}type_time;//系统信息结构体
typedef struct
{type_time feed_time[5];//定时5个喂食时间u8 feed_time_sw[5]; //5个喂食闹钟开关 0关 1开type_time clr_time[5];//定时5个清理时间u8 clr_time_sw[5]; //5个清理闹钟开关 0关 1开
}type_Sysinfo;const u8 MENU_MAX = 6;//5个界面
u8 menu_val=1;//当前显示的界面页数float curr_temp;//当前温度
volatile u8 state=0; //系统工作状态//bit0 :进水状态//bit1 :风扇状态//bit2 :清理状态 正传//bit3 :清理状态 反转//bit4: 喂食状态 正传//bit5: 喂食状态 反转type_time curr_time;//当前时间
u8 fan_time = 5; //风扇每隔多长时间吹一次 hour
u8 fan_len_time = 5;//风扇转一次多少分钟 minunsigned int ti=0; //修改第几个时间参数 、修改第几个闹钟参数//日期
typedef struct
{u8 year;u8 month;u8 day;u8 hour;u8 min;u8 sec;
}type_date;type_Sysinfo sysinfo;void delay(unsigned int t );
void delay_ms(unsigned int t );void dis_sys_start(void );
void dis_menu1_date(u8 sel);
void dis_menu2_mdf_date(void);
void dis_menu3_mdf_fdtime(void );
void dis_menu4_mdf_clrtime(void );
void dis_menu5_state(void );
void ctrl_motor(void);
void dis_menu6_motor_ctrl(void );void key_scan(void );
u8 get_key_val(void);void save_sysinfo(void );
void read_sysinfo(void );/*******************************************************************************
* 函 数 名 : Timer0Init
* 函数功能 : 定时器0初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0Init()
{TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。TH0=0XFC; //给定时器赋初值,定时1msTL0=0X18; ET0=1;//打开定时器0中断允许EA=1;//打开总中断TR0=1;//开启定时器
}/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{u16 ucount=0;//只执行一次if(byte_read(0x2200) != 0x56)//如果是第一次执行{memset(&sysinfo,0,sizeof(sysinfo));save_sysinfo();//清除数据SectorErase(0x2200);byte_write(0x2200,0x56);}//关闭所有电机WATER_EN = 1; //水泵 FAN_EN = 1; //风扇CLR_EN_A = 1; //清理电机CLR_EN_B = 1; //清理电机FEED_EN_A = 1; //喂食FEED_EN_B = 1; //喂食LcdInit(); //lcd初始化//Ds1302Init(); //时钟初始化Ds18b20Init(); //温度传感器初始化Timer0Init(); //定时器初始化read_sysinfo();//读取系统信息LcdClean(); //LCD清屏dis_sys_start();//显示初始界面LcdClean(); //LCD清屏while(1) {switch(menu_val) //界面选择{case 1: //时间显示界面if(ucount %80 == 0)dis_menu1_date(1);ctrl_motor();//电机控制break;case 2: //时间修改模式dis_menu2_mdf_date();break;case 3: //设置喂食闹钟界面dis_menu3_mdf_fdtime();break;case 4: //设置清理闹钟界面dis_menu4_mdf_clrtime();break;case 5:if(ucount %100 == 0)dis_menu5_state(); //显示系统状态break;case 6:if(ucount %100 == 0)dis_menu6_motor_ctrl();//电机控制break;}key_scan();//按键烧苗ucount++;delay_ms(10);}
}/*******************************************************************************
* 函 数 名 : void Timer0() interrupt 1
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/void Timer0() interrupt 1
{static u16 i,speed;TH0=0XFC; //给定时器赋初值,定时1msTL0=0X18;i++;if(state & 0x01)speed=5;else speed = 10;if(state != 0)//有电机需要转动{if(i%speed == 0)//开启{if(state & 0x01)//水泵{WATER_EN = 0; //水泵 }else if(state & 0x02){FAN_EN = 0; //风扇 }else if(state & 0x04){CLR_EN_A = 0; //清理电机 正传CLR_EN_B = 1; //清理电机}else if(state & 0x08){CLR_EN_A = 1; //清理电机 反传CLR_EN_B = 0; //清理电机}else if(state & 0x10){FEED_EN_A = 1; //喂食电机 正传FEED_EN_B = 0; //喂食电机}else if(state & 0x20){FEED_EN_A = 0; //喂食电机 反传FEED_EN_B = 1; //喂食电机}}else //关闭{WATER_EN = 1; //水泵 6FAN_EN = 1; //风扇 10CLR_EN_A = 1; //清理电机 10CLR_EN_B = 1; //清理电机 10FEED_EN_B = 1;FEED_EN_A = 1;}}
}/*********延时函数***********/
void delay_ms(unsigned int t) //毫秒延时
{unsigned int a,b;for(a=0;a<t;a++)for(b=0;b<120;b++);
}void dis_sys_start(void)
{LcdWriteCom(0x80);LcdWritestr("Welcome!");LcdWriteCom(0xc0);LcdWritestr("Pet Feed System");delay_ms(2000);
}
/*******************************************************************************
* 函 数 名 : dis_menu1_date
* 函数功能 : 显示时间日期温度
*******************************************************************************/void dis_menu1_date(u8 sel)
{float tp;int temp;if(menu_val == 1){Ds1302ReadTime();//读取时间}//显示日期LcdWriteCom(0x80);LcdWritestr("20"); LcdWriteData(TIME[6]/16+0x30); //年LcdWriteData(TIME[6]%16+0x30);LcdWriteData('-');LcdWriteData(TIME[4]/16+0x30); //月LcdWriteData(TIME[4]%16+0x30);LcdWriteData('-');LcdWriteData(TIME[3]/16+0x30); //日LcdWriteData(TIME[3]%16+0x30);LcdWritestr(" ");switch(TIME[5]) //显示星期{ case 0:LcdWritestr("Mon"); break;case 1:LcdWritestr("Tue"); break;case 2:LcdWritestr("Wed"); break;case 3:LcdWritestr("Thu"); break;case 4:LcdWritestr("Fri"); break;case 5:LcdWritestr("Sat"); break;case 6:LcdWritestr("Sun"); break;}LcdWriteCom(0xC0);LcdWriteData(' ');LcdWriteData(TIME[2]/16+0x30); //时LcdWriteData(TIME[2]%16+0x30);LcdWriteData(':');LcdWriteData(TIME[1]/16+0x30); //分LcdWriteData(TIME[1]%16+0x30);LcdWriteData(':');LcdWriteData(TIME[0]/16+0x30); //秒LcdWriteData(TIME[0]%16+0x30);LcdWritestr(" ");curr_time.hour = TIME[2];curr_time.min = TIME[1];curr_time.sec = TIME[0];if(sel){EA = 0;//关中断temp = Ds18b20ReadTemp();//获取温度EA = 1;//开中断//显示温度if(temp< 0) {LcdWriteCom(0xca);LcdWriteData('-'); temp=temp-1;temp=~temp;tp=temp;temp=tp*0.0625*100+0.5; }else{ LcdWriteCom(0xca);LcdWriteData('+'); tp=temp;temp=tp*0.0625*100+0.5; }LcdWriteData(temp % 10000 / 1000 + 0x30);LcdWriteData(temp % 1000 / 100 + 0x30);LcdWriteData('.');LcdWriteData(temp % 100 / 10 + 0x30);LcdWriteData(temp % 10 + 0x30);curr_temp = (float) temp/100.0;}}/*************修改时间************/
void dis_menu2_mdf_date(void)
{static u16 ucount=0;ucount++;if(ucount ==30){dis_menu1_date(0);//显示静止时间if(ti == 7) //闪烁OK{LcdWriteCom(0xca);LcdWritestr(" ->OK ");}}else if(ucount == 60)//闪烁{ucount = 0;switch(ti){case 0:LcdWriteCom(0xc7);LcdWritestr(" ");break;case 1:LcdWriteCom(0xc4);LcdWritestr(" ");break;case 2:LcdWriteCom(0xc1);LcdWritestr(" ");break;case 3:LcdWriteCom(0x88);LcdWritestr(" ");break;case 4:LcdWriteCom(0x85);LcdWritestr(" ");break;case 5: LcdWriteCom(0x8c);LcdWritestr(" ");break;case 6:LcdWriteCom(0x80);LcdWritestr(" ");break;case 7:LcdWriteCom(0xca);LcdWritestr(" ");break;}}
}/*******************************************************************************
* 函 数 名 : dis_menu3_mdf_fdtime
* 函数功能 : 修改喂食时间界面
*******************************************************************************/
u8 feed_cnt=0; //当前修改的第几个时间
void dis_menu3_mdf_fdtime(void )
{static u16 ucount = 0;ucount++;if(ucount == 30){LcdWriteCom(0x80); //显示LcdWritestr("feed time ");LcdWriteCom(0x8a);LcdWriteData(feed_cnt+0x30);LcdWritestr(" ");LcdWriteCom(0xca); if(sysinfo.feed_time_sw[feed_cnt] == 0)LcdWritestr(" OFF ");else LcdWritestr(" ON ");LcdWriteCom(0xc1); LcdWriteData(sysinfo.feed_time[feed_cnt].hour/16+0x30);LcdWriteData(sysinfo.feed_time[feed_cnt].hour%16+0x30);LcdWriteData(':'); LcdWriteData(sysinfo.feed_time[feed_cnt].min/16+0x30);LcdWriteData(sysinfo.feed_time[feed_cnt].min%16+0x30);LcdWriteData(':'); LcdWriteData(sysinfo.feed_time[feed_cnt].sec/16+0x30);LcdWriteData(sysinfo.feed_time[feed_cnt].sec%16+0x30);}else if(ucount == 60 ){ucount =0;switch(ti){case 0:LcdWriteCom(0x8a);LcdWritestr(" ");break;case 1:LcdWriteCom(0xc7);LcdWritestr(" ");break;case 2:LcdWriteCom(0xc4);LcdWritestr(" ");break;case 3:LcdWriteCom(0xc1);LcdWritestr(" ");break;case 4:LcdWriteCom(0xcc);LcdWritestr(" ");break;}}}/*******************************************************************************
* 函 数 名 : dis_menu3_mdf_fdtime
* 函数功能 : 修改清理时间界面
*******************************************************************************/
void dis_menu4_mdf_clrtime(void )
{static u16 ucount = 0;ucount++;if(ucount == 30){LcdWriteCom(0x80); //显示LcdWritestr("clear time ");LcdWriteCom(0x8b);LcdWriteData(feed_cnt+0x30);LcdWritestr(" ");LcdWriteCom(0xca); if(sysinfo.clr_time_sw[feed_cnt] == 0)LcdWritestr(" OFF ");else LcdWritestr(" ON ");LcdWriteCom(0xc1); LcdWriteData(sysinfo.clr_time[feed_cnt].hour/16+0x30);LcdWriteData(sysinfo.clr_time[feed_cnt].hour%16+0x30);LcdWriteData(':'); LcdWriteData(sysinfo.clr_time[feed_cnt].min/16+0x30);LcdWriteData(sysinfo.clr_time[feed_cnt].min%16+0x30);LcdWriteData(':'); LcdWriteData(sysinfo.clr_time[feed_cnt].sec/16+0x30);LcdWriteData(sysinfo.clr_time[feed_cnt].sec%16+0x30);}else if(ucount == 60 ){ucount =0;switch(ti){case 0:LcdWriteCom(0x8b);LcdWritestr(" ");break;case 1:LcdWriteCom(0xc7);LcdWritestr(" ");break;case 2:LcdWriteCom(0xc4);LcdWritestr(" ");break;case 3:LcdWriteCom(0xc1);LcdWritestr(" ");break;case 4:LcdWriteCom(0xcc);LcdWritestr(" ");break;}}
}/*******************************************************************************
* 函 数 名 : dis_menu4_state
* 函数功能 : 显示系统状态
*******************************************************************************/
void dis_menu5_state(void )
{LcdWriteCom(0x80); //显示LcdWritestr("Pet: ");if(IR == 0)LcdWritestr("whthin ");elseLcdWritestr("absent ");LcdWriteCom(0xc0); LcdWritestr("water line: ");if(WIT_0==1 && WIT_1==1)LcdWritestr("0cm");else if(WIT_0==0 && WIT_1==1)LcdWritestr("1cm");else if(WIT_0==0 && WIT_1==0)LcdWritestr("3cm");}/*******************************************************************************
* 函 数 名 : dis_menu6_motor_ctrl
* 函数功能 : 电机控制
*******************************************************************************/
void dis_menu6_motor_ctrl(void )
{LcdWriteCom(0x80);LcdWritestr("motor:"); switch(state){case 0x01:LcdWritestr("water "); break;case 0x02:LcdWritestr("fan "); break;case 0x04:LcdWritestr("clear +"); break;case 0x08:LcdWritestr("clear -"); break;case 0x10:LcdWritestr("feed +"); break;case 0x20:LcdWritestr("feed -"); break;default:LcdWritestr("none "); }
}
/*******************************************************************************
* 函 数 名 : ctrl_motor
* 函数功能 : 外设电机控制
*******************************************************************************/void ctrl_motor(void)
{u8 i;static u8 clr_z_flag=0,clr_f_flag=0,code_flag=0,water_flag=0;static u8 feed_z_flag=0,feed_f_flag=0,feed_t_flag=0;static u8 ucount=0;//static u8 fan_flag=0;static u16 clr_cnt=0,water_cnt=0;//fan_cnt=0,static u16 feed_cnt=0,code_cnt=0;ucount++;
九、下载验证
根据实现的功能对宠物智能小屋主要功能进行验证。
宠物智能小屋系统上电后,系统显示初始化界面,
初始化后液晶第一行显示当前的日期与星期,第二行显示实时时间与温度。
可通过按键设定喂食、清洁闹钟时间
红外检测与水位检测验证。宠物检测到在小屋内显示“within”,未在小屋内显示“absent”。水位检测则在第二行显示water line: 具体水位厘米数。本系统也可以通过手动按键开启、关闭喂水功能。下图5.6为宠物未在小屋内,水位检测到为0cm,下图5.7为宠物在小屋内,水位检测到为3cm。
喂食定时时间到后,电机正转打开喂食口,喂食完成后,电机反转关闭喂食口。本系统也可以通过手动按键对电机进行正转、反转功能。
这篇关于51单片机项目设计:智能宠物小屋(自动喂食喂水、自动通风换气、自动清洁)制作教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!