2015年9月21日 星期一

使用 Arduino IDE 開發 ESP8266 物聯網應用 - ThingSpeak, HTTP GET / POST 資料上傳方法

網頁最後修改時間:2015/09/22

在部落格的另一篇關於物聯網應用的網頁中,已經說明了使用 HTTP GET 上傳感測器資料到到 IoT ( Internet-of-Thing, 物聯網 ) Server ( 這裡以 ThingSpeak 為例 ) 的方法 ( HTTP POST 的方法請查閱該網頁所提供的參考連結 )。而在此篇網頁,將延續在 Arduino IDE 撰寫程式碼的方式,但會捨棄使用 Arduino 板,改用 ESP8266 做為微控制器與週邊裝置通訊,撰寫與說明如何在 Arduino IDE 撰寫 ESP8266 使用 HTTP GET 和 POST 上傳資料到 ThingSpeak.com 的 Sketch!

看過此篇之後就會發現到,使用 ESP8266 Arduino IDE 開發板 ( 下面簡稱:開發板 )
  • ESP8266 無線網路模組就是微控制器
  • 不需要額外處理與設置 AT 指令
  • 利用熟悉的 Arduino 語法開發 ESP8266 就像開發其他 Arduino 板子一樣簡單
  • ... 
更多、更多好處等著使用者自己去發掘 !

/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
有購買商品的使用者,網頁中所需相關資料已放置於雲端硬碟,請自行下載使用!
其餘的使用者,請自行依照提供之連結下載相關資料,程式碼複製貼上使用!
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*

NOTE:本篇網頁所使用的程式經過 ESP8266 UNO Arduino IDE 開發板 (Type B1) 測試通過!不過,同樣適用於其他使用 Arduino IDE 開發的 ESP8266, ESP-## 型號的板子,但請自行測試!
除了與網頁內容相關的討論之外,像是 Arduino IDE 與其他 ESP8266 型號連線的問題等,請使用者自行搞定!!!
*********************************************************************************

本網頁所使用到的零件可至下面連結訂購:
ESP8266 相關商品可至下面連結訂購:
更多 ESP8266 相關商品,請至分類賣場
*********************************************************************************

開發板在 Arduino IDE 中的設置:
進行下面設置之前,使用必須已經在 Arduino IDE 安裝好 ESP8266 的硬體套件 ( Hardware Package );有購買開發板的使用者,請參閱賣場所提供的套件安裝說明手冊進行安裝!
在 Arduino IDE 的選單 "Tools" 設置下面參數,使用者可以根據需要進行修改 ( 若是沒自行修改過,應該跟下面參數設置一樣 ),一般維持與下面相同的預設值就好
  • Upload Using: "Serial"
  • CPU Frequency: 80 MHz
  • Upload Speed: 460800
  • Port: COM#
    選擇開發板連接的哪一個 COM PORT 號碼

ThingSpeak 的設定:

參考 "初遇 IoT ( Internet of Thing, 物聯網 ) - 使用 Arduino 控制 ESP8266 無線模組上傳資料到 IoT Server ( ThingSpeak )" 網頁,完成下面這三個部分:
  • 申請一個 ThingSpeak 帳號
  • 建立一個給 DHT11 使用的 Channel
  • 取得剛剛建立的 ThingSpeak Channel 的( Write ) API KEY,並手動測試
因為這篇網頁是上篇網頁中的接續,所以使用相同的設定,但資料在測試之前已全部清除!

線路:

比較一下就可以發現!相對於使用 Arduino 板作為微控制器,開發板的接線反而簡化許多。DHT11 只需要三條跳線與一支上拉用的  ( 4.7K ~ 10 K ) 電阻連接到開發板就完成整個佈線,然後將開發板使用手機的 MicroUSB 線與電腦連接就可以開始撰寫與上傳程式。

如下圖。藍線為 DHT11 的第支接腳 ( VCC ) 接至開發板的 3.3V 接腳;黃線為 DHT11 的第支接腳 ( OUT ) 接至開發板的 D8 接腳;綠線為 DHT11 的第支接腳 ( GND ) 接至開發板的 GND 接腳。最後將電阻分別接到 DHT11 的第支與第支接腳就完成整個接線。
實際完成之接線圖
此時要不要先接上 MicroUSB 都可以!

程式碼說明:

下面分別以 HTTP GET 和 HTTP POST 兩個方式,說明如何使用 ESP8266 Arduino IDE 開發板撰寫上傳資料到 ThingSpeak 的程式碼;由於兩個程式碼只差別在上傳的格式,所以只給出其中一份完整的 ( HTTP GET ) 程式,另外一份 ( HTTP POST ) 則只給出差異的部分,請使用者自行修改其中不同之處。

*********************************************************************************.
在 "初遇 IoT ( Internet of Thing, 物聯網 ) - 使用 Arduino 控制 ESP8266 無線模組上傳資料到 IoT Server ( ThingSpeak )" 網頁中所使用的 DHT11 的函式庫只適用於 Arduino 板子,因為沒有根據微控制器調整速度的功能,所以不適用於 ESP8266 為主的微控制器,因此若系統中已經安裝賣場所提供的 DHT11 函式庫,則請先移除或是移動出 {Arduino}/libraries 目錄,或安裝下面提供的另一版本的 DHT11 函式庫
DHT Sensor Library V1.2.0
函式庫的使用可參考下面的範例。

NOTE: 我是移除掉現有的 DHT 函式庫,使用開發板的硬體套件中所包含的 DHT 函式庫,這兩者經過比較都是相同的,安不安裝取決於使用者的選擇,不影響程式碼的編譯!
*********************************************************************************

下面是以 HTTP GET 方法與硬體套件中所帶的 DHT 函式庫所撰寫的 Arduino Sketch,修改至
"初遇 IoT ( Internet of Thing, 物聯網 ) - 使用 Arduino 控制 ESP8266 無線模組上傳資料到 IoT Server ( ThingSpeak )" 網頁中的例子。比較兩者之間的差異,就會發現其中不同之處!好不好使,見"人"見智!
#include "DHT.h"    // 使用 ESP8266 自帶的 DHT11 函式庫
                    // 如果 libraries 已有其他的 DHT 函式庫,請先移除
#include <ESP8266WiFi.h>

//*-- Hardware Serial
#define _baudrate   9600

//*-- DHT11
#define _dhtpin     D8
#define _dhttype    DHT11

// Initialize DHT sensor 
DHT dht11( _dhtpin, _dhttype );
float temperature, humidity;

//*-- IoT Information
#define SSID    "路由器名稱"
#define PASS    "路由器連線密碼"
#define HOST    "api.thingspeak.com" // ThingSpeak IP Address: 184.106.153.149
#define PORT    80
// 使用 GET 傳送資料的格式
// GET /update?key=[THINGSPEAK_KEY]&field1=[data 1]&filed2=[data 2]...;
String GET = "GET /update?key=0123456789ABCDEF";

void setup() {
    Serial.begin( _baudrate );
    Serial.println( "ESP8266 Ready!" );
    // Connecting to a WiFi network
    Serial.print("Connect to ");
    Serial.println( SSID );
    WiFi.begin( SSID, PASS );

    // 持續等待並連接到指定的 WiFi SSID
    while( WiFi.status() != WL_CONNECTED )
    {
        delay(500);
        Serial.print( "." );
    }
    Serial.println( "" );

    Serial.println( "WiFi connected" );
    Serial.println( "IP address: " );
    Serial.println( WiFi.localIP() );
    Serial.println( "" );
    
    // DHT11
    dht11.begin();
    Serial.println( "DHT11 Ready!" );
    delay(2000);
}

void loop() {
    humidity    = dht11.readHumidity();
    temperature = dht11.readTemperature();

    // 確認取回的溫溼度數據可用
    if( isnan( humidity ) || isnan( temperature ) )
    {
        Serial.println( "Failed to read form DHT11" );
    return;
    }
    else
    {
        // DHT11 溫度與濕度傳送      
        Serial.print( "Humidity: " );
        Serial.print( humidity );
        Serial.print( ", Temperature: " );
        Serial.println( temperature );
        updateDHT11();
    }

    // 每隔多久傳送一次資料
    delay( 20000 ); // 20 second
}

void updateDHT11()
{
    // 設定 ESP8266 作為 Client 端
    WiFiClient client;
    if( !client.connect( HOST, PORT ) )
    {
        Serial.println( "connection failed" );
        return;
    }
    else
    {
        // 準備上傳到 ThingSpeak IoT Server 的資料
        // 已經預先設定好 ThingSpeak IoT Channel 的欄位
        // field1:溫度;field2:濕度
        String getStr = GET + "&field1=" + String((int)temperature) + 
                              "&field2=" + String((int)humidity) +
                              " HTTP/1.1\r\n";;
        client.print( getStr );
        client.print( "Host: api.thingspeak.com\n" );
        client.print( "Connection: close\r\n\r\n" );
        
        delay(10);
        //
        // 處理遠端伺服器回傳的訊息,程式碼可以寫在這裡!
        //


        client.stop();
    }
}
程式裡面,拿掉了原先 debug 的串列通訊,取而代之的!是使用硬體串列埠作為訊息(或除錯)用,節省了一個 USB 轉 TTL 模組。

程式中需要注意的及修改的地方,其中

_baudrate 代表的是電腦與開發板的通訊鮑率,可以設定不同的值!

//*-- Hardware Serial
#define _baudrate   9600

SSID PASS 是路由器的名稱與密碼;0123456789ABCDEF 是要傳送到 ThingSpeak 的 Channel 中的 Write API KEY,記得修改成自己的
//*-- IoT Information
#define SSID    "路由器名稱"
#define PASS    "路由器連線密碼"
#define HOST    "api.thingspeak.com" // ThingSpeak IP Address: 184.106.153.149
#define PORT    80
// 使用 GET 傳送資料的格式
// GET /update?key=[THINGSPEAK_KEY]&field1=[data 1]&filed2=[data 2]...;
String GET = "GET /update?key=0123456789ABCDEF";


/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* HTTP POST 修改部分:
//*-- IoT Information
#define SSID    "路由器名稱"
#define PASS    "路由器連線密碼"
#define HOST    "api.thingspeak.com" // ThingSpeak IP Address: 184.106.153.149
#define PORT    80
String APIKEY  = "NAQE1STDCH6ZPKFG";

void updateDHT11()
{
    // 設定 ESP8266 作為 Client 端
    WiFiClient client;
    if( !client.connect( HOST, PORT ) )
    {
        Serial.println( "connection failed" );
        return;
    }
    else
    {
        // 準備上傳到 ThingSpeak IoT Server 的資料
        // 已經預先設定好 ThingSpeak IoT Channel 的欄位
        // field1:溫度;field2:濕度
        String postStr = APIKEY + "&field1=" + String((int)temperature) + \
                                  "&field2=" + String((int)humidity) + "\r\n\r\n";

        client.print( "POST /update HTTP/1.1\n" );
        client.print( "Host: api.thingspeak.com\n" );
        client.print( "Connection: close\n" );
        client.print( "X-THINGSPEAKAPIKEY: "+APIKEY+"\n" );
        client.print( "Content-Type: application/x-www-form-urlencoded\n" );
        client.print( "Content-Length: " );
        client.print( postStr.length() );
        client.print( "\n\n" );
        client.print( postStr );

        client.stop();
    }
}

/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//

上面參數修改好了之後,將開發板接上電腦,並按下 "Upload" 按鈕編譯與上傳程式碼。成功連接和開始傳輸時,就會出現如下輸出畫面直到 100% 並出現 Leaving... 完成上傳
開發板編譯、上傳輸出畫面
打開 Serial Monitor ( 記得選擇程式碼所設定的 _baudrate ) ,再按下板子上面的 RESET1 按鈕,就會看到如下的畫面輸出 ( 開始會有一小段亂碼是正常的,下圖前頭沒有亂碼是嘗試幾次試出來的!):
Serial Monitor 輸出畫面
上傳資料到 ThingSpeak,必須注意,上傳的間隔要在 15 秒以上!(程式每 20 秒上傳一次)

經過一段時間的資料上傳之後,前往 ThingSpeak 所創建的 Channel 中,就會看到類似下面的圖形
ThingSpeak 環境溫濕度記錄圖

結論:

使用 ESP8266 Arduino IDE 開發板來開發物聯網相關應用非常方便!但是相比於 Arduino 板來說,函式庫支援數量相對較低,但持續開發與增加中,長期來說對於開發物聯網原型應用來說,還是具有相當大的吸引力與前景!

另外關於 HTTP POST 與 HTTP GET 上傳的方法,差異在於: GET 速度比較快,但上傳的資料可以被看到;反之使用 POST 用在傳輸隱密性較高且資料量大的情況之下。要用哪一個 ? 使用者自己決定 !

建議使用者能夠比較相關網頁間的程式碼,了解達到相同目的的程式碼之間不同之處,這就是寫這篇網頁的目的!

<< 部落格相關網頁連結 >>


23 則留言:

  1. 請問目前使用 post 方式至 thingspeak 會出現 15 Entries 有連到~ 但是資料無法顯示的狀況 請問有可能是什麼問題~ 謝

    回覆刪除
  2. 如果是過 GET 可以,但 POST 不行,那就檢查一下程式有無打錯的部分 !

    回覆刪除
  3. how i can use Arduino + ESP8266 if use any wire?
    because the wire of Arduino than utilice in COM for the serial print comands AT, really need that, but my problem its than i don´t want any wire in my system, can you help me?
    Pd. your blog it`s awesome.

    回覆刪除
    回覆
    1. If your purpose is using Arduino + ESP8266 that ESP8266 is controlled by AT command.
      If so, check this "http://ruten-proteus.blogspot.tw/2014/11/internet-of-thing-arduino-esp8266.html", or search "ESP8266" tag in blog to find more information.

      刪除
  4. 請問dht-11給我的回應都是nan有可能是什麼問題呢?
    同一顆dht-11在arduino試過沒有問題,esp8266就卡關了,謝謝您。

    回覆刪除
    回覆
    1. 收不到資料就是接線有問題要不然就是接腳定義不對,再詳細檢查看看 !

      刪除
    2. 感謝您,接腳弄錯...謝謝

      刪除
  5. 請問上傳thingspeak的間隔時間一定要在15秒以上嗎 如果我是要1秒上傳20筆 還適用thingspeak嗎

    回覆刪除
    回覆
    1. 根據網站上面要求,只能 15 秒傳送一次;但你應該可以將 20 筆數據一次傳送出去,方法看 thingspeak 上面的說明!

      刪除
  6. 您好 請問 ESP8266WIFI.h 要去哪裡載? arduino uno 也能用嗎?

    回覆刪除
    回覆
    1. 這是 ESP8266 專用的函式庫標頭檔,沒有 ESP8266 不能用。Arduino UNO 基本上只能使用 AT 指令的方式跟 ESP8266 做溝通 (預設的方式),兩者應用的方式不一樣。
      http://ruten-proteus.blogspot.tw/2015/09/esp8266-kits-support-arduino-ide.html

      刪除
    2. 感謝您的回覆
      我是照http://ruten-proteus.blogspot.tw/2014/11/internet-of-thing-arduino-esp8266.html 的接法
      也就是 arduino uno+esp8266,上傳完了,然後我想要在thingspeak 下載data;
      http://ruten-proteus.blogspot.tw/2015/09/iot-esp8266-arduino-retrieve.html
      但是我找不到esp8266wifi.h 載點 而且也在想說是不是 要使用Arduino WiFi Shield 才可以用???

      刪除
    3. 對於 ESP8266 使用的方法,你完全搞錯方向了!
      如果要使用 Arduino UNO + ESP8266 來取得 thingspeak 的資料,請看這篇
      http://ruten-proteus.blogspot.tw/2017/01/esp8266-at-lib-iot-demo-thingspeak.html

      相關資料在部落格上面都有,發問之前請善用搜尋功能!
      http://ruten-proteus.blogspot.tw/2016/08/how-to-ask-a-good-question.html

      刪除
  7. 您好我想要請問一下:
    thingspeak是否可以上傳過去時間的數據?(假設網路斷訊後回復,需上傳斷訊時的資料,目前只有看到利用網頁選擇export csv檔案,但是好像沒有利用ESP8266就可解決的方式?)

    回覆刪除
    回覆
    1. 深入找一下 thingspeak 的文件就會有,只不過需要自己再消化一下,要額外指定 created_at 的欄位在 JSON 字串裡。下面兩個網址,一個是範例程式,另一個是 JSON 格式說明,自己再研究看看!

      刪除
    2. https://www.mathworks.com/help/thingspeak/continuously-collect-data-and-bulk-update-a-thingspeak-channel-using-an-arduino-mkr1000-board-or-an-esp8266-board.html

      https://www.mathworks.com/help/thingspeak/bulk-update-a-channel-feed-1.html

      刪除
    3. 真的很感謝!!我會再研究看看!!

      刪除
  8. 想請問可以一邊傳送資料到thinkspeak 一邊接收另一個thinkspeak資料嗎
    分開我都可以 但是合併再一起 我的sensor資料都是沒感測到

    回覆刪除
    回覆
    1. "部落格相關網頁連結" 裡面有取回 thingspeak 最後一筆資料的程式碼,跟此網頁的程式碼一起融合就可以了!

      刪除
  9. 請問數據可以正常顯示,但上傳到thingspeak只會傳第一筆,不然就是隔很久才傳一筆,可能會是什麼問題

    回覆刪除
    回覆
    1. 請提供 Serial 的輸出訊息!
      輸出斷在哪裡,那裏就是問題所在!

      刪除

留言屬名為"Unknown"或"不明"的用戶,大多這樣的留言都會直接被刪除掉,不會得到任何回覆!

發問問題,請描述清楚你(妳)的問題,別人回答前不會想去 "猜" 問題是什麼?

不知道怎麼發問,請看 [公告] 部落格提問須知 - 如何問問題 !