基于W5500的实时远程温湿度监控系统

Home / 博客 / 基于W5500的实时远程温湿度监控系统

概述

工具:物联网云平台Yeelink  DHT11温湿度传感器   W5500EVB

编译环境:Keil4

目的:通过以太网实时监控远程某个位置的温度和湿度

在W5500EVB端连接DHT11温湿度传感器,并实时读取温度和湿度;通过W5500与网络连接,并与物联网云平台Yeelink中添加设备建立连接;之后系统会将读取的温度和湿度上传到物联网云平台Yeelink,这样就可以随时通过网络观察温度和湿度变化。 物联网云平台Yeelink还提供了一个简单的手机,登陆 Yeelink账号,也可以随时随地的观察温度和湿度的变化。

一、物联网云平台Yeelink

Yeelink是一个免费的云平台,旨在利用无线网络、开源硬件和软件,智能手机和App共同打造一个家庭智能中心。图1为Yeelink云平台首页截图。点击“快速开始”,我们可以注册一个账号,登陆后,可以添加自己的设备和传感器。它将复杂的传感器以极简的方式组到同一个网络内,可满足智能家居的各种需求。通过Yeelink提供的数据接口,用户可以把自己的传感器通过互联网接入Yeelink云平台,从而实现随时随地获取传感器数据,为一些智能家居设备接入互联网提供了云平台支持。(http://www.yeelink.net

图1 物联网云平台Yeelink首页

1. 登陆物联网云平台Yeelink,注册账号。注册账号以后,点击 账户》我的账户设置,可以看到有一个API KEY。

 

2. 根据开发指南添加设备

同大多数开源平台一样,Yeelink提供的API也是基于HTTP协议提交和接收数据。当我们在Yeelink上创建新的设备,并在设备上添加新的传感器后,会获得相应的设备ID和传感器ID,作为传感器在Yeelink平台上的唯一标识,我们可以使用Yeelink平台提供的URL,更新指定传感器的数据。有关于API文档的详细介绍请参考Yeelink网站,图2是与本节相关的设备添加介绍。

图2 添加设备信息

1)         点击管理设备,选择已经添加的设备,添加你的传感器,完成以后保存信息。

2)   保存以后会看到如图3所示内容。

URL:http://api.yeelink.net/v1.0/device/15855/sensor/27293/datapoints中提供了设备ID和传感器ID,这个会添加到程序中。

图3 设备添加显示页面

二、Yeelink平台API在线调试

1. 点击 API文档》在线调试,打开后在接口项添加生成的URL,在API Key项添加注册账户时生成的API KEY,请求方式选择GET模式,在Post中随意输入数据,如果您建立的设备可以运用,会得到正确回复,如图4所示。

yeelink4

图4  在线调试效果

Request显示了发送给网络的请求,主要注意请求方式,设备的ID号和API key,当然还有Yeelink平台的网址。Response显示恢复状态。

 

三、系统设计

1.电路设计

以太网控制芯片W5500整合了五层结构中的前四层,即物理层、数据链路层、网络层和传输层,并在内部利用硬件实现了TCP/IP协议栈。开发者无需专业的网络知识,使用W5500如同控制外部存储器一样简单,为用户提供了最简单的网络接入方法。全硬件TCP/IP协议栈完全独立于主控芯片,可以降低主芯片负载且无需移植繁琐的TCP/IP协议栈,便于产品实现网络化更新。

以太网控制芯片W5500具有以下特点:

1、W5500支持硬件TCP/IP协议,包括TCP、UDP、ICMP、IPv4、ARP、IGMP、PPPoE和以太网的PHY和MAC层,TCP/IP协议的硬件实现,使得应用协议的实现更简单容易;

2、支持8个独立的SOCKET同时工作,可同时工作在不同的工作模式;

3、支持掉电模式,并支持网络唤醒,最大程度地减少功率消耗和发热;

4、支持高速SPI接口(SPI MODE 0,3),SPI的时钟最高可达到80MHz,极大地提高了网络通信的数据传输速率;

5、内部集成32KB存储器用于发送/接收缓存;

DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC测温元件,并与一个高性能 8 位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。 DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个 I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。

图5是DHT11跟W5500EVB的电路设计图,比较简单。图6是实物连接图,DHT11上的VCC连接3V3D引脚,GND对应相连,Dout输出连接PA2引脚。通过USB给W5500EVB供电,W5500EVB通过网线与路由器连接,电脑也通过网线与路由器连接,或者连接路由器建立的无线网。

yeelink5

图5 W5500开发板与DHT11的连接电路

yeelink6

图6 实物连接

2.程序设计

本节将Yeelink上传数据的整个过程分为3个文件,main.c主文件实现W5500EVB上传数据的主流程,DHT11.c文件实现dht11对室内温湿度数据的采集,mcu_init.c文件实现W5500EVB的初始化。

为了使程序能方便地组建Yeelink所要求的JSON数据格式,我们把采集到数据直接替代这个字符串中的xx即可,其他的请求命令在上一节的在线调试结果中可以得到。

char  postT[]={//提交温度

“POST /v1.0/device/15738/sensor/27051/datapoints HTTP/1.1\r\n”

“Host:api.yeelink.net\r\n”

“Accept:*/*\r\n”

“U-ApiKey:fea57b9cc1ed5ad34d48430785b44e8f\r\n”

“Content-Length:12\r\n”

“Content-Type:application/x-www-form-urlencoded\r\n”

“Connection:close\r\n”

“\r\n”

“{\”value\”:xx}\r\n”

};//xx用来填充数值

这其中,device/ID/sensor/ID 这两处ID 已经在Yeelink网站上注册得到,一个是设备ID,一个是设备上的传感器的ID,同时,一个设备可以有若干个传感器。U-ApiKey则是你的身份识别码,同样是注册后获得,只有正确提交U-ApiKey才可以在Yeelink上面更新数据。Content-Length:后面的12,指的就是 {“value”:xx} 的长度,更具体的格式可以翻阅Yeelink的API文档。需要注意的是,在C语言中,双引号 “”需要使用转义字符。

在分析细节代码之前,我们还是先来看一下主函数。在这里完成了对W5500EVB的初始化,并在主循环里面完成了向Yeelink提交数据。由于这个程序需要访问Yeelink平台,也就要求W5500EVB能访问外网,因此这里我们要确保给W5500配置IP地址能访问外网。置W5500为客户端模式的调用过程:W5500_Init()–>Socket_Init(s)–>Socket_Connect(s),设置过程即完成,并与远程服务器连接。连接后就可以发送数据,在这里,数据发送完成后,链接会被Yeelink断开,下次发送需要重新进行Socket_Init(s)–>Socket_Connect(s)的过程。主程序第7行到第19行实现W5500EVB的初始化,初始化工作完成之后,单片机就可以读取DHT11数据和向Yeelink发送数据了。W5500EVB作为Yeelink客户端,在向Yeelink上传数据时为TCP连接,所以这里按照TCP的状态机模式写程序。第25行,socket初始化之后,W5500EVB就向Yeelink发送连接请求,从而完成了向Yeelink提交温湿度数据。第27行socket连接建立建立完成,首先把Sn_IR的第0位置1来清空中断,然后读取DHT11采集的数据,并保存在数组temp_rh中。第35行把发送的报文格式存在Buffer中;第36、37行是把Request报文中的xx替换成温度值或者湿度值。然后第38行发送请求报文到Yeelink 服务器。第38行切换数据类型,就是进行温度和湿度的切换,断开socket连接。第42行是socket等待关闭状态,这个状态很简单,由于这个状态是一方断开连接,还能够继续向服务器发送数据,所以就和socket建立连接状态基本相同了。第53行,socket关闭状态,打开socket并初始化TCP模式。

 

  1. int main(void)
  2. {
  3.   static uint8 i=0;
  4.   uint8 ch=SOCK_HUMTEM;
  5.   uint16 anyport=3000;
  6.   uint8 server_ip[4]={42,96,164,52};//  api.yeelink.net  的ip地址
  7.   RCC_Configuration(); /* 配置单片机系统时钟*/
  8.   GPIO_Configuration();/* 配置GPIO*/
  9.   NVIC_Configuration();/* 配置嵌套中断向量*/
  10. //  Timer_Configuration();
  11.   Systick_Init(72);/* 初始化Systick工作时钟*/
  12.   USART1_Init(); /*初始化串口通信:[email protected]*/
  13.   at24c16_init();/*初始化eeprom*/
  14.   printf(“W5500 EVB initialization over.\r\n”);
  15.   Reset_W5500();/*硬重启W5500*/
  16.   WIZ_SPI_Init();/*初始化SPI接口*/
  17.   printf(“W5500 initialized!\r\n”);
  18.   set_default();
  19.   set_network();
  20.   while(1)
  21.   {
  22.     switch(getSn_SR(ch))
  23.     {
  24.       case SOCK_INIT:
  25.          connect(ch, server_ip ,80);
  26.         break;
  27.       case SOCK_ESTABLISHED:
  28.        //case SOCK_CLOSE_WAIT:
  29.         if(getSn_IR(ch) & Sn_IR_CON)
  30.         {
  31.           setSn_IR(ch, Sn_IR_CON);
  32.         }
  33.         if( DHT11_GetValue(temp_rh))
  34.         {
  35.           memcpy(Buffer,post[i],strlen(post[i]));
  36.           Buffer[231]=temp_rh[i]/10+0x30;
  37.           Buffer[232]=temp_rh[i]%10+0x30;
  38.           send(ch,(const uint8 *)Buffer,sizeof(Buffer));
  39.           i=!i;
  40.           printf(“RH:%d, Temp:%d\r\n”, temp_rh[0], temp_rh[1]);
  41.         }
  42. //      printf(“yeelink:%d\r\n”, temp_rh[1]);//用于yeelink串口工具
  43.         Delay_ms(500);
  44.         close(ch);
  45. //      disconnect(ch);
  46.          break;
  47.       case SOCK_CLOSE_WAIT:
  48. //      printf(“Send to Yeelink:OK\r\n”);
  49.         break;
  50.       case SOCK_CLOSED:
  51.         printf(“Send to Yeelink:OK\r\n”);
  52.         socket(ch, Sn_MR_TCP,anyport++ , 0x00);
  53.         break;
  54.       default:
  55.         break;
  56.    }
  57.  }
  58. }

 

下面的代码完成了单片机读取温湿度传感器DHT11数据。DHT11 数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由 5Byte(40Bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先出。DHT11 的数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和。其中校验和数据为前四个字节相加。传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。

逐行分析一下单片机读取DHT11采集的数据的驱动程序,第4行我们选取单片机的PA2引脚作为传输数据的接口,开始总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低20毫秒,保证DHT11能检测到起始信号,然后把总线的电平拉高,开始信号结束,然后延时等待40us, 读取DHT11的响应信号。第8行,如果总线为低电平,说明DHT11发送响应信号,当响应信号结束,把响应信号拉高,等待温湿度数据的读取,第14行到第18行为读取40bit的传输数据,最后拉高总线电平,结束数据传输。第21行,如果校验正确,返回1,说明单片机正确读取DHT11采集的数据。如果读取数据不成功,返回0。

 

/*单片机读取DHT11采集的数据*/

1 uint8 DHT11_GetValue(uint8 *p)

2 {

3     uint8 temp,temp1,temp2;

4       GPIO_DHT_Out_Mode();

    /*总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号*/

5     GPIO_ResetBits(GPIOA,PA2);

6     Delay_ms(20);/*精确延时20ms*/

7     GPIO_SetBits(GPIOA,PA2);

    /*主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号*/

8     Delay_us(40);//精确延时40us

9     GPIO_DHT_Input_Mode();

    /*总线为低电平,说明DHT11发送响应信号*/

10    if(!rDHT11)

11    {

      /*判断从机发出的低电平响应信号是否结束*/

12      while(!rDHT11);

      /*DHT11发送响应信号后,再把总线拉高80us*/

13      while(rDHT11);

14      p[0]=DHT11_ReadData();/*8bit湿度整数数据*/

15      temp1=DHT11_ReadData();/*忽略无效数据*/

16      p[1]=DHT11_ReadData();/*8bit温度整数数据*/

17      temp2=DHT11_ReadData();/*忽略无效数据*/

18      temp=DHT11_ReadData();/*8bit校验和*/

19      GPIO_DHT_Out_Mode();

20      GPIO_SetBits(GPIOA,PA2);

21      if(temp==(p[0]+p[1]+temp1+temp2))

22      {

23           return 1;

24      }

25    }

26    return 0;

27}

 

四、测试效果

连接好线路之后,下载程序并运行。W5500EVB便可不断向Yeelink平台提交采集道德温度、湿度各一次了。我们可以看到采集到的实时数据已图形化显示,图7列出温、湿度的数据曲线。

yeelink7

图7 温度和湿度采集情况

通过上面Yeelink的截图,我们已成功地将温湿度传感器DHT11采集到的数据传到了云平台Yeelink上,这样便可随时随地监控室内的温湿度了。我们也可以自己再添加一些光强、气压等传感器,就可以模拟实现一个简单的智能家居系统,如果再加上暖气和加湿器的控制,就构成了我们前文所说的智能家居系统,可以随时随地控制居家的温度和湿度了。

Yeelink还提供了一个手机APP,我们也可以随时随地的登陆Yeelink监控自己系统所有传感器的变化情况。

 

五、常见问题及解决办法

1.在申请账号时要注意生成的API KEY,添加设备时会生成一个URL请求,里面提供了设备ID device/xxxx,传感器ID sensor/xxxx。这几个信息与程序开头建立的请求报文中信息是一一对应的,因此应该把程序中这些信息修改为我们自己申请账号和添加设备是得到的信息。

2. 在报文中提供了数据传递的位置,”{\”value\”:xx}\r\n”,在读取数据时要确定要确定数据在Buffer缓存中的具体位置。由于每个人建立的请求报文所占用的字节不同,那么存储数据的位置也大不相同。如果不能正确判断数据位置,很容易产生错误的想法,去把问题放在其他位置上。可以在程序中读取完Buffr后添加串口打印程序,或者查找具体的判断字符在字符串中位置的函数并添加,减少不必要的错误。

3. 在读取数据的过程中,每读一次数据Socket就要关闭在开一次,但是测试发现在等待关闭的情况读取几次以后就不能正常关闭,如果出现这种问题,可以直接通过close()关闭Socket后再打开。

4. 由于网页不能实时自动更新,所以我们要间断性的刷新网页来观察数据变化情况,否则会给人错误的看法。

5. 在device文件中设置了默认的MAC地址、IP地址、网关和子网掩码,要注意保持IP地址与路由器的IP在同一个网段内,否则不能建立连接。也能和周围的发生冲突。

void set_default(void)

{

uint8 mac[6]={0x00,0x08,0xdc,0x11,0x11,0x11};

uint8 lip[4]={192,168,1,113};

uint8 sub[4]={255,255,255,0};

uint8 gw[4]={192,168,1,1};

uint8 dns[4]={8,8,8,8};

memcpy(ConfigMsg.lip, lip, 4);

memcpy(ConfigMsg.sub, sub, 4);

memcpy(ConfigMsg.gw,  gw, 4);

memcpy(ConfigMsg.mac, mac,6);

memcpy(ConfigMsg.dns,dns,4);

 

ConfigMsg.dhcp=0;

ConfigMsg.debug=1;

ConfigMsg.fw_len=0;

 

ConfigMsg.state=NORMAL_STATE;

ConfigMsg.sw_ver[0]=FW_VER_HIGH;

ConfigMsg.sw_ver[1]=FW_VER_LOW;

 

}

6. 要理解Http方法:Get请求与Post请求的区别

    Get是向服务器发送索取数据的一种请求,Get是获取信息,而不是修改信息。Get是用来从服务器上获得数据,Get将表单中数据的按照variable=value的形 式,添加到action所指向的URL后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;Get是不安全的,因为在传输过程,数据被放在请求的URL中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。Get传输的数据量小,这主要是因为受URL长度限制;Get限制Form表单的数据集的值必须为ASCII字符。

而Post是向服务器提交数据的一种请求,Post请求则作为http消息的实际内容发送给web服务器,数据放置在HTML Header内提交,Post没有限制提交的数据。Post是用来向服务器上传递数据,Post是将表单中的数据放在form的数据体中,按照变量和值相对应的方式,传递到action所指向URL。Post的所有操作对用户来说都是不可见的。Post可以传输大量的数据,所以在上传文件只能使用Post,Post支持整个ISO10646字符集,默认是用ISO-8859-1编码。

By Andy