2017年9月26日 星期二

Arduino C on ESP8266 學習筆記 (二) : 在網頁上控制 LED

我在 Instructable 看到下面這篇透過 WiFi 網路控制 LED 的實驗 :

ESP 8266 Wifi Controlled Home Automation

主要是透過 ESP8266WiFi.h 函式庫的支援來連線到一個無線基地台, 並建立一個網頁伺服器, 讓我們可以利用電腦或手機瀏覽器連線到此網頁控制 LED 的亮滅. 關於 ESP8266WiFi.h 函式庫文件參考 :

Arduino/doc/esp8266wifi/

本系列之前的測試紀錄參考 :

使用 Arduino IDE 開發 ESP8266 應用 (一) : 環境設定與韌體上傳

不過上面 Instructable 作者附的程式碼有點怪怪的, 含有一些不該有的 HTML 碼, 而且缺漏了一些資訊, 例如回應網頁上 "Click here to turn ..." 裡面的超連結竟然沒有 href 屬性, 照所貼圖片應該是 href='/LED=ON' 與 href='/LED=OFF' 才對, 我將其修改為如下測試 1 :


測試 1 :  透過 WiFi 控制 LED 

#include <ESP8266WiFi.h>
const char* ssid="H30-L02-webbot";
const char* password="1234567890";
const int LED=2;      // GPIO2
int value=LOW;
WiFiServer server(80);

void setup() {
    Serial.begin(115200);
    delay(10);
    pinMode(LED, OUTPUT);
    digitalWrite(LED, LOW);
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        }
    Serial.println("");
    Serial.println("WiFi connected");
    server.begin();
    Serial.println("Server started");
    Serial.print("Use this URL to connect: ");
    Serial.print("http://");
    Serial.print(WiFi.localIP());
    Serial.println("/");
    }
 
void loop() {
    WiFiClient client=server.available();
    if (!client) {return;}
    Serial.println("New client");
    while (!client.available()) {delay(1);}
    String request=client.readStringUntil('\r');
    Serial.println(request);
    client.flush();
    if (request.indexOf("/LED=ON") != -1) {value=HIGH;}
    if (request.indexOf("/LED=OFF") != -1) {value=LOW;}
    Serial.print("value=");
    Serial.println(value);
    digitalWrite(LED, value);
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("");
    client.println("");
    client.println("");
    client.print("Led pin is now: ");
    if (value==HIGH) {client.print("On");}
    else {client.print("Off");}
    client.println("<br><br>");
    client.println("Click <a href='/LED=ON'>here</a> turn the LED on pin 2 ON<br>");
    client.println("Click <a href='/LED=OFF'>here</a> turn the LED on pin 2 OFF<br>");
    client.println("</p><p>");
    delay(1);
    Serial.println("Client disonnected");
    Serial.println("");
    }

編譯上傳訊息 :

Archiving built core (caching) in: C:\Users\cht\AppData\Local\Temp\arduino_cache_467201\core\core_esp8266_esp8266_generic_CpuFrequency_80,FlashFreq_40,FlashMode_dio,UploadSpeed_115200,FlashSize_512K64,ResetMethod_ck,Debug_Disabled,DebugLevel_None_____ef4920f85b594b4d068baa9c05fdba96.a
草稿碼使用了 230221 bytes (53%) 的程式儲存空間。上限為 434160 bytes。
全域變數使用了 32348 bytes (39%) 的動態記憶體,剩餘 49572 bytes 給區域變數。上限為 81920 bytes 。
Uploading 234368 bytes from C:\Users\cht\AppData\Local\Temp\arduino_build_695446/arduesp_2.ino.bin to flash at 0x00000000
................................................................................ [ 34% ]
................................................................................ [ 69% ]
.....................................................................            [ 100% ]


奇怪了, 程式比較長了, 編譯出來的機器碼為何只有占 53% Flash ? 上次那個簡單的雙 LED 交互閃爍程式短短的就佔 51%? 參考 :

使用 Arduino IDE 開發 ESP8266 應用 (一) : 環境設定與韌體上傳

上傳完成後, 拔掉 GPIO 0 的接地線, 把 ESP-01 重插開機, 打開序列埠監控視窗會看到 ESP8266 已連上 WiFi 基地台並顯示其 IP, 這時打開手機 WiFi 連線同一個無線基地台, 開啟瀏覽器連線 ESP8266 的 IP 就可以看到程式輸出的網頁了, 按 here 超連結即可控制 GPIO 2 外接 LED 的明滅了 :




序列埠監控視窗輸出訊息如下 :

Connecting to H30-L02-webbot
...
WiFi connected
Server started
Use this URL to connect: http://192.168.43.163/
New client
GET / HTTP/1.1
Client disonnected

New client
GET /LED=ON HTTP/1.1
value=1
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value=1
Client disonnected

New client
GET /LED=OFF HTTP/1.1
value=0
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value=0
Client disonnected


接下來我參考上次測試 MicroPython on ESP8266 伺服器的範例, 將上面測試 1 修改為如下測試 2, 把 ESP-01 模組的兩個 GPIO 埠都各接一個 LED + 220 歐姆電阻, 控制網頁改用表格來呈現, 參考 :

MicroPython on ESP8266 (十四) : 網頁伺服器測試


測試 2 :  透過 WiFi 控制 LED (使用表格)

#include <ESP8266WiFi.h>
const char* ssid="H30-L02-webbot";
const char* password="1234567890";
const int LED0=0;      // GPIO0
const int LED2=2;      // GPIO2
int value0=LOW;
int value2=LOW;
WiFiServer server(80);

void setup() {
    Serial.begin(115200);
    delay(10);
    pinMode(LED0, OUTPUT);
    pinMode(LED2, OUTPUT);  
    digitalWrite(LED0, LOW);
    digitalWrite(LED2, LOW);  
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
        }
    Serial.println("");
    Serial.println("WiFi connected");
    server.begin();
    Serial.println("Server started");
    Serial.print("Use this URL to connect: ");
    Serial.print("http://");
    Serial.print(WiFi.localIP());
    Serial.println("/");
    }
 
void loop() {
    WiFiClient client=server.available();
    if (!client) {return;}
    Serial.println("New client");
    while (!client.available()) {delay(1);}
    String request=client.readStringUntil('\r');
    Serial.println(request);
    client.flush();
    if (request.indexOf("/LED0=ON") != -1) {value0=HIGH;}
    if (request.indexOf("/LED0=OFF") != -1) {value0=LOW;}
    if (request.indexOf("/LED2=ON") != -1) {value2=HIGH;}
    if (request.indexOf("/LED2=OFF") != -1) {value2=LOW;}  
    Serial.print("value0=");
    Serial.println(value0);
    Serial.print("value2=");
    Serial.println(value2);  
    digitalWrite(LED0, value0);
    digitalWrite(LED2, value2);  
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("");
    client.println("");
    client.println("");
    client.println("<br><br>");
    client.println("<h1>ESP8266 Pins</h1>");
    client.println("<table border='1'>");
    client.println("<tr>");
    client.println("<th>Pin</th>");
    client.println("<th>Value</th>");
    client.println("<th>Action</th>");
    client.println("</tr>");
    client.println("<tr>");
    client.println("<td>GPIO 0</td>");
    client.print("<td>");
    client.print(digitalRead(LED0));  
    client.println("</td>");
    client.println("<td><a href='/LED0=ON'>ON</a> <a href='/LED0=OFF'>OFF</a></td>");
    client.println("</tr>");
    client.println("<tr>");
    client.println("<td>GPIO 2</td>");
    client.print("<td>");
    client.print(digitalRead(LED2));  
    client.println("</td>");
    client.println("<td><a href='/LED2=ON'>ON</a> <a href='/LED2=OFF'>OFF</a></td>");
    client.println("</tr>");
    client.println("</table>");
    delay(1);
    Serial.println("Client disonnected");
    Serial.println("");
    }


將程式編譯上傳後拔除 GPIO 0 之接地, GPIO 0/2 接上 LED 重插開機即可.

Archiving built core (caching) in: C:\Users\cht\AppData\Local\Temp\arduino_cache_467201\core\core_esp8266_esp8266_generic_CpuFrequency_80,FlashFreq_40,FlashMode_dio,UploadSpeed_115200,FlashSize_512K64,ResetMethod_ck,Debug_Disabled,DebugLevel_None_____ef4920f85b594b4d068baa9c05fdba96.a
草稿碼使用了 230725 bytes (53%) 的程式儲存空間。上限為 434160 bytes。
全域變數使用了 32524 bytes (39%) 的動態記憶體,剩餘 49396 bytes 給區域變數。上限為 81920 bytes 。
Uploading 234880 bytes from C:\Users\cht\AppData\Local\Temp\arduino_build_695446/arduesp_3.ino.bin to flash at 0x00000000
................................................................................ [ 34% ]
................................................................................ [ 69% ]
......................................................................           [ 100% ]


ESP8266 連上基地台後用手機瀏覽器連線 ESP8266 網址即可看到網頁, 點表格中的 ON/OFF 超連結即可控制兩個 LED 的明滅 :







序列埠監控視窗輸出訊息如下 :

Connecting to H30-L02-webbot
................
WiFi connected
Server started
Use this URL to connect: http://192.168.43.163/

New client
GET /LED0=ON HTTP/1.1
value0=1
value2=0
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value0=1
value2=0
Client disonnected

New client
GET /LED2=ON HTTP/1.1
value0=1
value2=1
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value0=1
value2=1
Client disonnected

New client
GET /LED0=OFF HTTP/1.1
value0=0
value2=1
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value0=0
value2=1
Client disonnected

New client
GET /LED2=OFF HTTP/1.1
value0=0
value2=0
Client disonnected

New client
GET /favicon.ico HTTP/1.1
value0=0
value2=0
Client disonnected


呵呵, 看起來還不錯, 512K Flash 的 ESP-01 雖然在 MicroPython 中沒辦法建立檔案系統而實用性不高, 但用 Arduino IDE 直接編譯原始碼倒是還蠻好用的, 可以用來當作小型物聯網終端控制器.

不過比起有檔案系統的 MicroPython 而言, 使用 Arduino IDE 開發比較麻煩, 每次修改程式都要將 GPIO 0 接地才能更新韌體, 而 MicroPython 只要用 ampy 等工具上傳新的應用程式到檔案系統跟目錄下即可, MicroPython 韌體不用去動它.

參考 :

Android Arduino Wifi Control Devices with ESP8266 Module
Arduino/NTPClient.ino at master · esp8266/Arduino

2 則留言 :

Unknown 提到...

請問版主大大 上述的方法可以用來控制Arduino uno版上的腳位嗎?如果可以要如何連接?

小狐狸事務所 提到...

可以的, 但 Arduino UNO 沒有聯網能力, 必須利用 esp8266 當 wifi 聯網工具, 參考 :
# http://yhhuang1966.blogspot.com/2016/08/arduino.html