本課程是一個循序漸進的指南,顯示了如何建置一個獨立的ESP8266 Web Server來控制兩個輸出(兩個LED)。該ESP8266 NodeMCU Web Server具有行動回應能力,可通過您本地網絡中的瀏覽器用任何設備對其進行存取。
如果您想了解更多有關ESP8266模塊的信息,請先閱讀我的ESP8266 WiFi模塊入門指南。
本教程介紹了兩種構建Web服務器的方法:
- 第1部分:使用Arduino IDE建立Web Server
- 第2部分:使用NodeMCU韌體建立Web Server
這裡我們先只介紹第1部分的開發方式,第2部分之後有機會再來介紹給大家。
文章目錄標題
第1部分:使用ARDUINO IDE建立Web Server
準備Arduino IDE
2. 然後,您需要為Arduino IDE安裝ESP8266插件。為此,請轉到檔案>偏好設定。
3. 輸入http://arduino.esp8266.com/stable/package_esp8266com_index.json進入“額外的開發板管理員網址”字段,如下圖所示。然後,點擊“確定”按鈕。
4. 轉到工具>開發板>開發板管理員…
5. 向下滾動,選擇ESP8266開發板選單,並安裝“ ESP8266 Community的esp8266 ”,如下圖所示。
6.轉到工具>開發板,然後選擇您的ESP8266開發板。然後,重新打開Arduino IDE。
程式碼
將以下程式碼複製到您的Arduino IDE,但尚未上傳。您需要進行一些更改以使其適合您。
/*********
Terry Lee
完整說明請參閱 http://honeststore.com.tw
*********/
// 載入Wi-Fi資料庫
#include <ESP8266WiFi.h>
// 將下列ssid及pass替換為您的網絡憑據
const char* ssid = "替換成你的SSID";
const char* password = "替換成你的PASSWORD";
// 設定web server端口為80 port
WiFiServer server(80);
// 設定變數header為HTTP請求值
String header;
// 輔助變數存儲當前輸出狀態
String output5State = "off";
String output4State = "off";
// 將輸出變數分配給GPIO引腳
const int output5 = 5;
const int output4 = 4;
// 當前時間
unsigned long currentTime = millis();
// 前次時間
unsigned long previousTime = 0;
// 定義暫時時間以毫秒為單位 (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
Serial.begin(115200);
// 將輸出變數初始化為輸出PIN引腳模式
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// 將輸出設定為LOW低電位
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// 列出得到的區域端IP及啟動web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // 傾聽clients傳入的值
if (client) { // 假如有一個新的client端連線,
Serial.println("New Client."); // 在序列端口中印出訊息
String currentLine = ""; // 設定String儲存從客戶端傳入的數據
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // 當client端連線時,持續循環{}內動作 currentTime = millis(); if (client.available()) { // 如果有客戶端讀取的字節 char c = client.read(); // 閱讀一個字元, 然後 Serial.write(c); // 印出到序列顯示器 header += c; if (c == '\n') { // 如果字元是換行符號 // 如果當前行為空白,則您可以連續兩個換行符號 // 這是client端HTTP請求的結束,所以發送回應: if (currentLine.length() == 0) { // HTTP標頭始終以回應代碼開始 (e.g. HTTP/1.1 200 OK) // 和content-type,使客戶知道即將到來,然後是一個空白行 client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html; charset=utf-8"); client.println("Connection: close"); client.println(); // 打開和關閉GPIO if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
// 顯示HTML網頁
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS 格式的ON/OFF按鍵
// 隨時更改背景顏色和字體大小屬性
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// 網頁標題
client.println("<body><h1>ESP8266 Web Server</h1>");
// 顯示當前狀態,以及GPIO 5的開/關按鍵狀態
client.println("<p>GPIO 5 - State " + output5State + "</p>");
// 如果output5State狀態是關閉,則按鍵會顯示ON
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// 顯示當前狀態,以及GPIO 4的開/關按鍵狀態
client.println("<p>GPIO 4 - State " + output4State + "</p>");
// 如果output4State狀態是關閉,則按鍵會顯示ON
if (output4State=="off") {
client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// HTTP回應以隔一行結尾
client.println();
// 跳出循環
break;
} else { // 如果你有一個換行符號,就清空currentLine變數值
currentLine = "";
}
} else if (c != '\r') { // 如果您有其他任何訊息,但不是回車字符,
currentLine += c; // 則將其值加到currentLine變數尾端
}
}
}
// 清除標題變數
header = "";
// 關閉連接
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
您需要使用網絡憑證修改以下兩個變數,以使ESP8266可以與路由器建立連接。
// 將下列ssid及pass替換為您的網絡憑據
const char* ssid = "替換成你的SSID";
const char* password = "替換成你的PASSWORD";
上傳草稿圖
如果您使用的是ESP-12E NodeMCU套件,則上傳草稿圖非常簡單,因為它具有內建的編程器。將您的板子插入電腦。確保選擇了正確的開發板和COM端口。
然後,點擊Arduino IDE中的上傳按鈕,等待幾秒鐘,直到看到消息“ 儲存完畢”。在左下角。
原理圖
所需零件:
- ESP8266 12-E
- 2個LED
- 2個電阻 (220或330歐姆均可)
- 麵包板
- 跳線
如下圖所示,將兩個LED連接到ESP8266 –一個LED連接到 GPIO 4 (D2),另一個 GPIO 5 (D1)。
測試Web Server
找到ESP IP地址
按下ESP8266 RESET按鈕,它將在序列監視器上輸出ESP IP地址
複製該IP地址,因為您需要它來存取Web Server。
存取Web Server
打開瀏覽器,輸入ESP IP地址,您將看到以下頁面。當您在ESP IP地址上請求時,此頁面由ESP8266發送。
如果看一下序列監視器,您可以看到背景情況。ESP從新客戶端(在本例中為您的瀏覽器)接收HTTP請求。
您還可以查看有關HTTP請求的其他信息-這些字段稱為HTTP標頭字段,它們定義HTTP事務的操作參數。
測試Web服務器
讓我們測試一下Web Server。點擊按鈕GPIO 5上。ESP在/ 5 / on URL上收到請求,然後將LED 5點亮。
LED狀態也會在網頁上更新。
測試 GPIO 4 按鈕並檢查它是否以類似的方式工作。
程式碼如何工作
// 載入Wi-Fi資料庫
#include <ESP8266WiFi.h>
如前所述,您需要在雙引號內中輸入您的ssid和密碼。
const char* ssid = "";
const char* password = "";
然後,將Web Server端口設為80。
// 設定web server端口為80 port
WiFiServer server(80);
接下來建立一個變數來存儲HTTP請求的標頭:
String header;
接下來,建立輔助變數以存儲輸出取得的當前狀態。如果要增加更多輸出並保存其狀態,則需要建立更多變數。
// 輔助變數存儲當前輸出狀態
String output5State = "off";
String output4State = "off";
您還需要為每個輸出分配一個GPIO。這裡我們使用GPIO 4 (D2)和 GPIO 5(D1)。您也可以使用任何其他合適的GPIO。
// 將輸出變數分配給GPIO引腳
const int output5 = 5;
const int output4 = 4;
setup()
接著,讓我們進入 setup()。在setup()中,該函數只會在ESP第一次啟動時運行一次。首先,出於調試目的,我們以115200的鮑率啟動序列通信。
Serial.begin(115200);
接著將GPIO定義為OUTPUT,並將其設置為LOW。
// 將輸出變數初始化為輸出PIN引腳模式
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// 將輸出設定為LOW低電位
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
以下幾行開始與Wi-Fi連接 WiFi.begin(ssid,密碼),等待連接成功,然後在序列監視器中印出ESP IP地址。
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// 列出得到的區域端IP及啟動web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
loop()
在loop() 裡,我們編程當新客戶端與Web Server建立連接時會發生什麼。 ESP始終通過下列該行程式碼監聽傳入的客戶端輸出狀態值:
WiFiClient client = server.available(); // 傾聽clients傳入的值
收到客戶的請求後,首先將儲存傳入的數據。只要客戶端保持連接,隨後的while循環將一直運行。我們不建議您更改程式碼以下的部分,除非您確實知道自己要做什麼。
if (client) { // 假如有一個新的client端連線,
Serial.println("New Client."); // 在序列端口中印出訊息
String currentLine = ""; // 設定String儲存從客戶端傳入的數據
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // 當client端連線時,持續循環{}內動作
currentTime = millis();
if (client.available()) { // 如果有客戶端讀取的字節
char c = client.read(); // 閱讀一個字元, 然後
Serial.write(c); // 印出到序列顯示器
header += c;
if (c == '\n') { // 如果字元是換行符號
// 如果當前行為空白,則您可以連續兩個換行符號
// 這是client端HTTP請求的結束,所以發送回應:
if (currentLine.length() == 0) {
// HTTP標頭始終以回應代碼開始 (e.g. HTTP/1.1 200 OK)
// 和content-type,使客戶知道即將到來,然後是一個空白行
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html; charset=utf-8");
client.println("Connection: close");
client.println();
if and else語句的下一部分檢查在網頁中按下了哪個按鈕,並對應地控制輸出。如前所述,我們會根據所按下的按鈕在不同的URL上發出請求。
// 打開和關閉GPIO
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
例如,如果您按了 GPIO 5“開啟”按鈕,URL更改為ESP IP地址,後跟/ 5 / ON,我們在HTTP標頭上收到該信息。因此,我們可以檢查標題是否包含表達式GET / 5 / on。 如果包含,則程式碼在序列監視器上印出一條消息,更改 output5State 變數打開,並打開LED。 其他按鈕也是如此運作。因此,如果要增加更多輸出控制,則應修改代程式碼的這一部分。
顯示HTML網頁
接下來需要做的是生成網頁。ESP8266將通過一些HTML文本向瀏覽器發送響應以顯示網頁。
該網頁使用 client.println()功能。您應該輸入要發送給客戶端的參數。
您應該始終發送的第一個text是下列這一行,表示我們正在發送HTML。
<!DOCTYPE html><html>
然後,以下行使網頁在任何Web瀏覽器中都回應。
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
下一個用於防止與網站圖標相關的請求。
client.println("<link rel=\"icon\" href=\"data:,\">");
網頁樣式
接下來,我們有一些CSS用來設置按鈕和網頁外觀的樣式。我們選擇Helvetica字體,定義要顯示為區塊並在中心對齊的內容。
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
我們使用一些屬性來設置按鈕樣式,以定義顏色,大小,邊框等。
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
然後,我們定義第二個按鈕的樣式,具有我們先前定義的按鈕的所有屬性,但是具有不同的顏色。是關閉按鈕的樣式。
client.println(".button2 {background-color: #77878A;}</style></head>");
設置網頁第一個標題
在下一行中,設置網頁的第一個標題,您可以將此text更改為任意內容。
// 網頁標題
client.println("<body><h1>ESP8266 Web Server</h1>");
顯示按鈕及其對應狀態
然後,寫一個段落來顯示 GPIO 5當前狀態。如您所見,我們使用output5State 變數,以便在此變數更改時狀態立即更新。
client.println("<p>D1(GPIO 5) - 狀態 " + output5State + "</p>");
然後,根據GPIO的當前狀態,顯示開或關按鈕。
if (output5State=="off") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">開</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">關</button></a></p>");
}
GPIO 4也是一樣的解析。
斷開連接
最後,當回應結束時,我們清除header變量,並使用以下命令停止與客戶端的連接 client.stop()。
// 清除標題變數
header = "";
// 關閉連接
client.stop();
更進一步
您可以控制一個繼電器來控制幾乎所有的電子設備,而不必控制兩個LED 。
要建立Web Server以顯示感測器讀數,您可以閱讀以下教程:
- ESP8266 DHT溫濕度Web服務器(Arduino IDE)
- ESP8266 DS18B20 Temperature Web Server(Arduino IDE)
另外,如果您想使用MicroPython對ESP8266進行編程,則可以閱讀以下教程:ESP32 / ESP8266 MicroPython Web Server –控制輸出
如果您喜歡ESP8266,請確保您了解我們有關ESP8266的家庭自動化課程。
謝謝閱讀。
您好我正在學習做專題,想請問作者可以借我看程式碼嗎?
不好意思,沒辦法~