Bài viết này hướng dẫn các bạn các bước xây dựng ESP8266 thành một Web Server có thể điều khiển 2 ngõ ra LED. ESP8266 Web Server có thể truy cập từ bất cứ thiết bị nào có sẵn một trình duyệt, trong mạng Wifi local.
Mục Lục
Cài đặt môi trường lập trình ESP8266 Web Server trên Arduino IDE
1. Download và cài đặt Arduino IDE trên máy của bạn.
2. Cài đặt ESP8266 add-on trên Arduino IDE, File > Preferences
3. Nhập chuỗi http://arduino.esp8266.com/stable/package_esp8266com_index.json vào mục “Additional Board Manager URLs” sau đó chọn “OK”.
4. Chọn Tools > Board > Boards Manager…
5. Tìm kiếm ESP8266 và chọn cài đặt “esp8266 by ESP8266 Community”.
6. Tools > Board, sau đó chọn loại board ESP8266 của bạn và khởi động lại Arduino IDE.
Code ESP8266 Web Server
Copy đoạn code dưới đây vào Sketch và thay đổi các thông số cho phù hợp.
// Load Wi-Fi library #include <ESP8266WiFi.h> // Replace with your network credentials const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; // Set web server port number to 80 WiFiServer server(80); // Variable to store the HTTP request String header; // Auxiliar variables to store the current output state String output5State = "off"; String output4State = "off"; // Assign output variables to GPIO pins const int output5 = 5; const int output4 = 4; // Current time unsigned long currentTime = millis(); // Previous time unsigned long previousTime = 0; // Define timeout time in milliseconds (example: 2000ms = 2s) const long timeoutTime = 2000; void setup() { Serial.begin(115200); // Initialize the output variables as outputs pinMode(output5, OUTPUT); pinMode(output4, OUTPUT); // Set outputs to 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("."); } // Print local IP address and start web server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); } void loop(){ WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client currentTime = millis(); previousTime = currentTime; while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected currentTime = millis(); if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // turns the GPIOs on and off 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); } // Display the HTML web page 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 to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences 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>"); // Web Page Heading client.println("<body><h1>ESP8266 Web Server</h1>"); // Display current state, and ON/OFF buttons for GPIO 5 client.println("<p>GPIO 5 - State " + output5State + "</p>"); // If the output5State is off, it displays the ON button 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>"); } // Display current state, and ON/OFF buttons for GPIO 4 client.println("<p>GPIO 4 - State " + output4State + "</p>"); // If the output4State is off, it displays the ON button 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>"); // The HTTP response ends with another blank line client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } }
Thay đổi thông tin về Wifi nhà bạn tại đây
const char* ssid = ""; const char* password = "";
Nạp Sketch vào board
Cắm board của bạn vào máy tính và chọn đúng COM port. Sau đó chọn Upload để nạp, khi nạp xong bạn sẽ nhận được “Done uploading.”
Nguyên lí mạch test ESP8266 Web Server
Yêu cầu:
- ESP8266 12-E
- 2x LEDs
- 2x Resistors (220 hoặc 330 ohms)
- Breadboard
- Jumper
Kết nối mạch như hình vẽ sau đây – kết nối chân GPIO4 (D2) và GPIO5 (D1) tới 2 LED.
Chạy thử
Sau khi Upload sketch chọn Serial monitor (baud 115200) và quan sát.
Cấp phát địa chỉ IP
Lưu lại IP này để có thể truy cập từ trình duyệt của bạn.
Truy cập Web Server do ESP8266 tạo ra
Mở một trình duyệt bất kỳ, sau đó nhập địa chỉ IP đã lưu ở trên
Tại của sổ Serial Monitor bạn sẽ thấy thông tin HTTP Request của bạn, trong trường hợp này là Trình duyệt.
Điểu khiển trên Web Server thông qua ESP8266
Trên giao diên Web Server, bấm chọn GPIO5 ON. ESP sẽ nhận được môt Request tại /5/on và bật sáng LED
Trang thái LED cũng sẽ được cập nhật trên giao diện ESP8266 Web Server.
Thử điều khiển GPIO4 tương tự nhự vậy.
Chi tiết Code
Đầu tiên chúng ta cần khai báo thư viện ESP8266WiFi.
setup()
Hàm setup() chỉ chạy một lần duy nhất. Đầu tiên, chúng ta khai báo tốc độ baud của Serial.
Serial.begin(115200);
Khai báo các chân tương ứng là ngõ ra.
pinMode(output5, OUTPUT); pinMode(output4, OUTPUT); digitalWrite(output5, LOW); digitalWrite(output4, LOW);
Hàm WiFi.begin(ssid, password), ESP sẽ bắt đầu kết nối Wifi. Sẽ mất một chút thời gian để ESP được cấp phát IP.
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."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin();
loop()
Trong loop() chúng ta lập trình sự kiện xảy ra khi có một kết nối được tạo.
ESP luôn lắng nghe kết nối.
WiFiClient client = server.available();
Khi có một kết nối tới, ESP sẽ lưu các thông tin lại. Các lệnh thực hiện trong while() sẽ tiếp tục đến khi Client mất kết nối.
if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println();
Tiếp theo chúng ta xử lý việc điều khiển chân GPIO tưng ứng với nút được nhấn.
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); }
Và sau đó lưu lại trạng thái nút nhấn để phản hồi với Client.
Hiển thị trang HTML
Để hiên thị trên trình duyệt ESP8266 sẽ gửi các Response dưới dạng chỗi HTML. Trang web sẽ được gửi tới Client dùng hàm client.println().
Trang web luôn bắt đầu với thẻ:
<!DOCTYPE html><html>
Sử dụng Style trên Web Server
Khai báo Style cho button
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
Màu sắc, kích thước, …
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;}");
Khai báo cho nút nhấn OFF
client.println(".button2 {background-color: #77878A;}</style></head>");
Khai báo header của trang web
client.println("<h1>ESP8266 Web Server</h1>");
Hiển thị các nút nhấn và trạng thái
Sau khi nhấn, trạng thái các nút nhấn thay đổi sẽ được lưu lại và được..
client.println("<p>GPIO 5 - State " + output5State + "</p>");
…phản hồi tới Client
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>"); }
Ngắt kết nối đến Web Server
Khi Respone kết thúc, ESP ngắt kết nối và xóa các biến lưu trữ.
// Clear the header variable header = ""; // Close the connection client.stop();
Tổng kết
Bài viết đã hướng dẫn các bạn xây dựng và tùy biến một Web Server trên ESP8266. Hy vọng các bạn có thể ứng dụng kiến thức từ bài viết vào các dự án của mình.
Đừng quên theo dõi các bài hướng dẫn ESP8266 và ESP32 trên ESPITEK.
Chúc các bạn thành công!
anh ơi! em muốn thêm một nút nhấn phải làm sao ạ, tổng cộng là 3 nút nhấn. em cảm ơn ạ
Chào bạn, bạn theo dõi code mẫu có đoạn dưới: đây là đoạn code tạo ra 1 giao diện nút nhấn, để tạo thêm nút bạn chỉ cần copy và thay đổi tên nút mới.
Nhớ thêm các biến cho nút thứ 3 nhé !
em chào anh ,a cho e hỏi khi em nạp code xong mở monitor lên nó cứ load chứ k hiện IP là e sai ở đâu ạ ,em cảm ơn