Shi 51 MCU soil humidity detection and automatic watering systems based

1, design requirements and objectives

By setting the program in the microcontroller watering humidity value when the humidity is lower than the set humidity, the sample collection value, the watering began, higher humidity, the alarm actuation signals, stop watering.

2, design ideas and solutions

 The graduation project is to design an automatic watering system, a single-chip control 51, automated system indoor potted plant watering. The system can monitor the moisture of the soil, and crops timely and adequate watering. 51 is a microcontroller core, and soil moisture detector YL-69, and a display control section and a detection circuit water relay driver circuits. The main study the relationship between soil moisture and watering time, various parts of irrigation control systems and equipment hardware, software programming. Detection section, MCU selection AT89C51 microcontroller, software selection C51 programming language. Soil moisture data acquisition and display circuit converts the amplified analog soil moisture detected by the microcontroller to a digital program control the precise temperature and humidity are displayed on the LED digital display, by the interrupt service routine in the microcontroller determines whether give watering potted, for water, the water system sends SCM signal to start watering, water if needed, for the next cycle is detected. Watering system watering also design a timer section, a different set watering time through the key switch, within a period of time, Microprocessor watering system watering began, not as a period, not poured water. Hardware:

3, part of the code

#include <reg52.h>	         //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义	变量范围0~255
#define uint  unsigned int	 //无符号整型 宏定义	变量范围0~65535

#include <intrins.h>

sbit SCL=P1^4;		//SCL定义为P1口的第3位脚,连接ADC0832SCL脚
sbit DO=P1^5;		//DO定义为P1口的第4位脚,连接ADC0832DO脚
sbit CS=P1^3;		//CS定义为P1口的第4位脚,连接ADC0832CS脚

sbit beep = P3^3;   //蜂鸣器IO口定义
uint temperature,s_temp ;  //温度的变量
uchar shidu;     //湿度等级
uchar s_high = 70,s_low = 25;	//湿度报警参数

sbit dianji = P1^6;     //电机IO定义

bit flag_300ms ;
uchar key_can;		 //按键值的变量
uchar menu_1;        //菜单设计的变量

//这三个引脚参考资料
sbit rs=P1^0;	 //1602数据/命令选择引脚 H:数据      	L:命令
sbit rw=P1^1;	 //1602读写引脚	         H:数据寄存器  	L:指令寄存器
sbit e =P1^2;	 //1602使能引脚          下降沿触发
uchar code table_num[]="0123456789abcdefg";

/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
	while(q--);
}

/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
	e=0;
	rs=0;
	rw=0;
	P0=com;
	delay_uint(3);
	e=1;
	delay_uint(25);
	e=0;
}

/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
	e=0;
	rs=1;
	rw=0;
	P0=dat;
	delay_uint(3);
	e=1;
	delay_uint(25);
	e=0;	
}

/********************************************************************
* 名称 : write_sfm2(uchar hang,uchar add,uchar date)
* 功能 : 显示2位十进制数,如果要让第一行,第五个字符开始显示"23" ,调用该函数如下
	 	 write_sfm1(1,5,23)
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_sfm2(uchar hang,uchar add,uint date)
{
	if(hang==1)   
		write_com(0x80+add);
	else
		write_com(0x80+0x40+add);
	write_data(0x30+date/10%10);
	write_data(0x30+date%10);	
}

/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
	 	 write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
	if(hang==1)   
		write_com(0x80+add);
	else
		write_com(0x80+0x40+add);
		while(1)
		{
			if(*p == '\0')  break;
			write_data(*p);
			p++;
		}	
}

/********************************************************************
* 名称 : init_1602()
* 功能 : 初始化1602液晶 
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602()
{
	write_com(0x38);
	write_com(0x38);
	write_com(0x0c);
	write_com(0x06);
	delay_uint(1000);
	write_string(1,0,"   shidu:00%    ");
	write_string(2,0," SH:00%  SL:00% ");
	write_sfm2(2,4,s_high);        //显示湿度上限
	write_sfm2(2,12,s_low);		   //显示湿度下限
}


/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
	uint i,j;
	for(i=0;i<q;i++)
		for(j=0;j<120;j++);
}

/***********读数模转换数据********************************************************/	
//请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的
						//  1  0  0 通道
						//  1  1  1 通道 
unsigned char ad0832read(bit SGL,bit ODD)
{
	unsigned char i=0,value=0,value1=0;		
		SCL=0;
		DO=1;
		CS=0;		//开始
		SCL=1;		//第一个上升沿	
		SCL=0;
		DO=SGL;
		SCL=1;  	//第二个上升沿
		SCL=0;
		DO=ODD;
		SCL=1;	    //第三个上升沿
		SCL=0;	    //第三个下降沿
		DO=1;
		for(i=0;i<8;i++)
		{
			SCL=0;
			SCL=1; //开始从第四个下降沿接收数据
			value<<=1;
			if(DO)
				value++;						
		}
		for(i=0;i<8;i++)
		{			//接收校验数据
			value1>>=1;
			if(DO)
				value1+=0x80;
			SCL=1;
			SCL=0;
		}
		SCL=1;	
		if(value==value1)				//与校验数据比较,正确就返回数据,否则返回0	
			return value;
	return 0;
}


/*************定时器0初始化程序***************/
void time_init()	  
{
	EA   = 1;	 	  //开总中断
	TMOD = 0X01;	  //定时器0、定时器1工作方式1
	ET0  = 1;		  //开定时器0中断 
	TR0  = 1;		  //允许定时器0定时
}


/********************独立按键程序*****************/
uchar key_can;	 //按键值

void key()	 //独立按键程序
{
	static uchar key_new;
	key_can = 20;                   //按键值还原
	P3 |= 0xf0;
	if((P3 & 0xf0) != 0xf0)		//按键按下
	{
		delay_1ms(1);	     	//按键消抖动
		if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
		{						//确认是按键按下
			key_new = 0;
			switch(P3 & 0xf0)
			{
				case 0xd0: key_can = 3; break;	   //得到k2键值
				case 0xb0: key_can = 2; break;	   //得到k3键值
				case 0x70: key_can = 1; break;	   //得到k4键值
			}					
		}			
	}
	else 
		key_new = 1;	
}

/****************按键处理显示函数***************/
void key_with()
{
	if(key_can == 1)	 //设置键
	{
		menu_1 ++;
		if(menu_1 >= 3)
		{
			menu_1 = 0;
			init_1602() ;  //初始化显示
		}
	}
	if(menu_1 == 1)			//设置湿度上限
	{
		if(key_can == 2)
		{
			s_high ++ ;		//湿度上限值加1 
			if(s_high > 99)
				s_high = 99;
		}
		if(key_can == 3)
		{
			s_high -- ;		//湿度上限值减1 
			if(s_high <= s_low)
				s_high = s_low + 1 ;
		}
		write_sfm2(2,4,s_high);        //显示湿度上限
		write_sfm2(2,12,s_low);		   //显示湿度下限
		write_com(0x80+0x40+4);           //将光标移动到第2行第到3位
		write_com(0x0f);                  //显示光标并且闪烁

	}	
	if(menu_1 == 2)			//设置湿度下限
	{
		if(key_can == 2)
		{
			s_low ++ ;	  //湿度下限值加1 
			if(s_low >= s_high)
				s_low = s_high - 1;
		}
		if(key_can == 3)
		{
			s_low --;	  //湿度下限值减1 
			if(s_low <= 1)
				s_low = 1;
		}
		write_sfm2(2,4,s_high);        //显示湿度上限
		write_sfm2(2,12,s_low);		   //显示湿度下限
		write_com(0x80+0x40+12);           //将光标移动到第2行第到3位
		write_com(0x0f);                  //显示光标并且闪烁
	}	
}  

/****************报警函数***************/
void clock_h_l()
{
	static uchar value,value1;
	if(shidu <= s_low)
	{
		value ++;
		if(value >= 2)
		{
			value = 10;
			beep = ~beep;	  //蜂鸣器报警
			dianji = 0;       //打开电机
		}
	}else 
		beep = 1;   //关闭蜂鸣器
	
	if(shidu >= s_high)
	{
		value1 ++;
		if(value1 >= 2)
		{
			value1 = 10;
			beep = 1;   //关闭蜂鸣器
			dianji = 1;       //关机电机
		}
	}else 
		value1 = 0;
}

/***************主函数*****************/
void main()
{
	init_1602();			   //1602液晶初始化
	time_init();				//初始化定时器 
	while(1)
	{
		key();					//独立按键程序
		if(key_can < 10)
		{
			key_with();			//按键按下要执行的程序
		}
		if(flag_300ms == 1)
		{		
			flag_300ms = 0;	  
			clock_h_l();	 //报警函数 
			if(beep == 1)
			{
				shidu = ad0832read(1,0);	//读出湿度
				shidu = 99 - shidu * 99 / 255;
			}
			if(menu_1 == 0)
			{
				write_sfm2(1,9,shidu);		   //显示湿度等级
			}
		} 
		delay_1ms(1);
	}
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{	
	static uchar value;
	TH0 = 0x3c;
	TL0 = 0xb0;     // 50ms
	value ++;	 
	if(value % 6 == 0)
	{
		flag_300ms = 1;	   //300ms
		value = 0;
	}
}

For complete information:

https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=614259061450&ut_sk=1.WUpxx7gpwUoDAMmnnrBIzAno_12431167_1585221475158.Copy.detail.614259061450.1828622527&forceFlush=1

Published 23 original articles · won praise 7 · views 304

Guess you like

Origin blog.csdn.net/weixin_41017942/article/details/105125371