进程 xml github arraylist webview openssl ide Egret Engine LimeJS Momentjs vue图表 vue优势 手机banner常用尺寸 iot系统 js获取月份 css面试题 完美解决cpu利用率低 mysql入门 mysql更新 安装python教程 python输出中文 java注释 java求和 javaworld java读取文件内容 java删除目录 java字符 java中collection java字符串相等 lanhelper java小程序 vbscript程序员参考手册 魔之符咒 jb51 getelementbyid 网络适配器下载 电脑基础 lol卡米尔 lrc软件 winsxs可以删除吗
当前位置: 首页 > 学习教程  > 编程语言

手机APP远程温湿度监控系统(连上公网、阿里云)

2021/1/28 23:02:54 文章标签:

APP界面: 实物图: 操作演示: 一、 硬件电路图 这里有两点需要说明: 1.第一点是关于LCD1602需不需要加上拉电阻的说明。 51单片机P0口作为IO口输出时,输出低电平为0 输出高电平为高组态(并非5V,相当于悬…

APP界面:
在这里插入图片描述
实物图:
在这里插入图片描述
操作演示:
在这里插入图片描述

一、 硬件电路图

在这里插入图片描述
这里有两点需要说明:

1.第一点是关于LCD1602需不需要加上拉电阻的说明。

51单片机P0口作为IO口输出时,输出低电平为0 输出高电平为高组态(并非5V,相当于悬空状态,也就是说P0
口不能真正的输出高电平)。给所接的负载提供电流,因此必须接上拉电阻(一电阻连接到VCC),

这句话是对的,但是当P0口作为总线输出的时候,他是不需要加上拉电阻的,例如图中P0口接的是LCD的数据口,赋值时 P0=DATA;

另一种情况是如果是用STM32来驱动的话,请注意。
还要根据LCD1602是5V还是3.3V来加上拉电阻。此处不细说。

2.第二点是关于继电器电路的说明。

图中的继电器电路我采用的是低电平触发,为什么是低电平触发而不是高电平触发呢?这也是有讲究的。

目前我这个系统想法是上电的时候,指示灯是暗的,当收到开启命令后,继电器“嗒”的一声,灯亮。

重点来了,51单片机上电瞬间IO口是高电平,所以
如果采用高电平触发的话,继电器一上电就吸合了。

三极管的作用是放大电流,因为51单片机的输出电流较小。

二、软件程序

1.单片机程序

单片机程序不难:
DHT11、LCD1602这些驱动程序网上都有
这里我把最主要的ESP8266通信程序
以及串口中断判断程序放出来。


//这里是某些宏定义
#define uchar unsigned char 
#define uint unsigned int 

volatile uchar Rec_stop = 0;  //接收停止位
volatile uchar flag = 0;      //连接标志位
volatile uchar RsPoint = 0;   //接收字节位
volatile uchar rec_buf[2];    //OK判断位
volatile uchar TX_Flag = 0;   //开启发送标志位
volatile uchar RX_Flag = 0;   //开启接收标志位
volatile uchar TH_Flag = 0;   //温湿度发送标志位

sbit keep_te = P1^6;   //定义保温开关接口
sbit keep_hu = P1^5;   // 定义保湿开关接口

1.1 ESP8266代码

void wifi_init()
{
    
    
    //esp8266复位
	memset(rec_buf,' ',sizeof(rec_buf));
   RsPoint=0;
    SendString("AT+RST\r\n");
    write_1602com(0x01);
	write_string(0x80,"AT+RST",0);
	while(Rec_stop==0);
	Rec_stop=0;
	write_string(0x80+0x40,rec_buf,0);
    delayms_1000ms(14);
	
    
    //设置sta兼ap模式
	memset(rec_buf,' ',sizeof(rec_buf));
  RsPoint=0;
    SendString("AT+CWMODE=1\r\n");
    write_1602com(0x01); 
	write_string(0x80,"AT+CWMODE=1",0);
    while(Rec_stop==0);
	Rec_stop=0;
    write_string(0x80+0x40,rec_buf,0);
    SendString("\r\n");
    delayms_1000ms(4);
    
	//清除回显
    memset(rec_buf,' ',sizeof(rec_buf));
   RsPoint=0;
    SendString("ATE0\r\n");
    write_1602com(0x01);  //清屏
	write_string(0x80,"ATE0",0);
    while(Rec_stop==0);
	Rec_stop=0;
    delayms_1000ms(4);

    //连接热点
	memset(rec_buf,' ',sizeof(rec_buf));
   RsPoint=0;
    SendString("AT+CWJAP=\"hhhh\",\"a123456789\"\r\n");
    write_1602com(0x01);
	write_string(0x80,"Linking AP...",0);
    while(Rec_stop==0);
	Rec_stop=0;
	write_string(0x80+0x40,rec_buf,0);
    delayms_1000ms(18);
    
    //设置单连接
  	memset(rec_buf,' ',sizeof(rec_buf));
    RsPoint=0;
    SendString("AT+CIPMUX=0\r\n");
    write_1602com(0x01);
	  write_string(0x80,"AT+CIPMUX=0",0);
    while(Rec_stop==0);
	  Rec_stop=0;
  	write_string(0x80+0x40,rec_buf,0);
    delayms_1000ms(4);
    
    //开始监听
    memset(rec_buf,' ',sizeof(rec_buf));
    SendString("AT+CIPSTART=\"TCP\",\"8.129.224.216\",3000\r\n");
    //这个就是公网的IP地址以及端口号。
    write_1602com(0x01);
    write_string(0x80,"AT+CIPSTART",0);
    while(Rec_stop==0);
    Rec_stop=0;
	  write_string(0x80+0x40,rec_buf,0);
    delayms_1000ms(4);

    //开启透传模式
		memset(rec_buf,' ',sizeof(rec_buf));
		SendString("AT+CIPMODE=1\r\n");
		write_1602com(0x01);
		write_string(0x80,"AT+CIPMODE=1",0);
		while(Rec_stop==0);
    Rec_stop=0;
		write_string(0x80+0x45,rec_buf,0);
    delayms_1000ms(4);


  //开始发送数据		
		memset(rec_buf,' ',sizeof(rec_buf));
		SendString("AT+CIPSEND\r\n");
		write_1602com(0x01);
		write_string(0x80,"AT+CIPSEND",0);
		while(Rec_stop==0);
    Rec_stop=0;
		write_string(0x80+0x40,rec_buf,0);
    delayms_1000ms(4);

//发送初始化的继电器开关值
    memset(rec_buf,' ',sizeof(rec_buf));
		SendString("{\"type\":\"kg\",\"wdkg\":\"0\",\"sdkg\":\"0\"}");
    write_1602com(0x01);
    write_string(0x80,"send_relay",0);	
		while(Rec_stop==0);
    Rec_stop=0;		
    write_string(0x80+0X40,"OK",0);
    delayms_1000ms(4);
    write_1602com(0x01);

//发送一段温湿度的数值
    memset(rec_buf,' ',sizeof(rec_buf));
		SendString("{\"type\":\"wsd\",\"wd\":\"0\",\"sd\":\"0\"}");
    write_1602com(0x01);
    write_string(0x80,"send_data",0);
}

1.2 串口判断字符代码

void Usart() interrupt 4//在中断里面进行两个判断,首先是WiFi响应"OK"的判断,接着是":A" ":B" ":C" ":D"的判断
{
	uchar receiveData;
    
    if(RI == 1)
    {       
				receiveData = SBUF;//出去接收到的数据
				flag = 1;
				RI = 0;//清除接收中断标志位	
					
				 if(TX_Flag == 1)	//进入通信部分 收发信息 做出反应
				 { 
								
					 if(receiveData == ':') 
							{
								RX_Flag = 1;
							}
							else if(RX_Flag == 1)
							{
								if(receiveData == 'A')
								{
								 SendString("{\"type\":\"kgchanged\"}");   //因为是低电平触发,所以改为0是触发
									keep_te=0;
									keep_hu=0;
								}
								if(receiveData == 'B')
								{
								 SendString("{\"type\":\"kgchanged\"}");
									keep_te=0;
									keep_hu=1;
									
								}
								if(receiveData == 'C')
								{
								 SendString("{\"type\":\"kgchanged\"}");
									keep_te=1;
									keep_hu=0;									
								}
								if(receiveData == 'D')
								{
								 SendString("{\"type\":\"kgchanged\"}");
									keep_te=1;
									keep_hu=1;
								}
								RX_Flag = 0; //自锁
								
							}
					}
				 
//上面的判断是来控制保温保湿开关的,下面的判断是用来判断ESP8266指令的OK返回
					if((RsPoint==0)&&(receiveData=='O'))
					{  
						rec_buf[RsPoint]=receiveData;
						RsPoint++;
					}
					else if((RsPoint==1)&&(receiveData=='K'))
					{
						rec_buf[RsPoint]=receiveData;
						RsPoint++;
						Rec_stop=1;
					}
					else
					{
						RsPoint=0;
					} 
									
	 }		 
}

RsPoint 代码解释。

因为我要判断对方有没有发送OK给我,OK是两个字符,占两个字节,而单片机是一个字节进入一次中断这样。所以接收到O进入中断,保存。接着处理剩下的K,进入下次中断、保存、接着Rec_stop置1,那么ESP8266就可以发送下一个指令了。

假设我收到的是OAK的话,那么Rec_stop也不会置1, 因为当时A的时候,RsPoint就会是0。
所以RsPoint的作用是保证O和K是连在一起的。

这里的重难点是连续字符的判断。

2.APP代码懒的贴了,太多。

需要完整代码的可以留下邮箱。


本文链接: http://www.dtmao.cc/news_show_650143.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?