基於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所示。
圖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通過網線與路由器連接,電腦也通過網線與路由器連接,或者連接路由器建立的無線網。
圖5 W5500開發板與DHT11的連接電路
圖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模式。
- int main(void)
- {
- static uint8 i=0;
- uint8 ch=SOCK_HUMTEM;
- uint16 anyport=3000;
- uint8 server_ip[4]={42,96,164,52};// api.yeelink.net 的ip地址
- RCC_Configuration(); /* 配置單片機系統時鐘*/
- GPIO_Configuration();/* 配置GPIO*/
- NVIC_Configuration();/* 配置嵌套中斷向量*/
- // Timer_Configuration();
- Systick_Init(72);/* 初始化Systick工作時鐘*/
- USART1_Init(); /*初始化串口通信:115200@8-n-1*/
- at24c16_init();/*初始化eeprom*/
- printf(“W5500 EVB initialization over.\r\n”);
- Reset_W5500();/*硬重啟W5500*/
- WIZ_SPI_Init();/*初始化SPI接口*/
- printf(“W5500 initialized!\r\n”);
- set_default();
- set_network();
- while(1)
- {
- switch(getSn_SR(ch))
- {
- case SOCK_INIT:
- connect(ch, server_ip ,80);
- break;
- case SOCK_ESTABLISHED:
- //case SOCK_CLOSE_WAIT:
- if(getSn_IR(ch) & Sn_IR_CON)
- {
- setSn_IR(ch, Sn_IR_CON);
- }
- if( DHT11_GetValue(temp_rh))
- {
- memcpy(Buffer,post[i],strlen(post[i]));
- Buffer[231]=temp_rh[i]/10+0×30;
- Buffer[232]=temp_rh[i]%10+0×30;
- send(ch,(const uint8 *)Buffer,sizeof(Buffer));
- i=!i;
- printf(“RH:%d, Temp:%d\r\n”, temp_rh[0], temp_rh[1]);
- }
- // printf(“yeelink:%d\r\n”, temp_rh[1]);//用於yeelink串口工具
- Delay_ms(500);
- close(ch);
- // disconnect(ch);
- break;
- case SOCK_CLOSE_WAIT:
- // printf(“Send to Yeelink:OK\r\n”);
- break;
- case SOCK_CLOSED:
- printf(“Send to Yeelink:OK\r\n”);
- socket(ch, Sn_MR_TCP,anyport++ , 0×00);
- break;
- default:
- break;
- }
- }
- }
下面的代碼完成了單片機讀取溫濕度傳感器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列出溫、濕度的數據曲線。
圖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]={0×00,0×08,0xdc,0×11,0×11,0×11};
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







