ESP8266 Máy chủ Web NodeMCU (WebSocket) với nhiều thanh trượt: Điều khiển độ sáng đèn LED (PWM) Hướng dẫn này chỉ ra cách xây dựng một máy chủ web với bảng ESP8266 NodeMCU hiển thị một trang web có nhiều thanh trượt. Các thanh trượt điều khiển chu kỳ làm việc của các tín hiệu PWM khác nhau để kiểm soát độ sáng của nhiều đèn LED. Thay vì đèn LED, bạn có thể sử dụng dự án này để điều khiển động cơ DC hoặc các thiết bị truyền động khác yêu cầu tín hiệu PWM. Giao tiếp giữa máy khách và ESP8266 được thực hiện bằng giao thức WebSocket. Ngoài ra, bất cứ khi nào có thay đổi, tất cả khách hàng sẽ cập nhật đồng thời các giá trị thanh trượt của họ.
Bạn cũng có thể sửa đổi mã được trình bày trong hướng dẫn này để thêm thanh trượt vào dự án của mình để đặt giá trị ngưỡng hoặc bất kỳ giá trị nào khác mà bạn cần sử dụng trong mã của mình. Đối với dự án này, bo mạch ESP8266 sẽ được lập trình bằng lõi Arduino. Bạn có thể sử dụng Arduino IDE, VS Code với PlatformIO hoặc bất kỳ IDE phù hợp nào khác. Để hiểu rõ hơn về cách thức hoạt động của dự án này, chúng tôi khuyên bạn nên xem các hướng dẫn sau: * Dự án này chỉ ra cách xây dựng một máy chủ web với một thanh trượt, nhưng nó sử dụng các yêu cầu HTTP — trong hướng dẫn này, chúng ta sẽ sử dụng giao thức WebSocket. Chúng tơi có một hướng dẫn tương tự cho bảng ESP32: 1/26
Máy chủ web ESP32 (WebSocket) với nhiều thanh trượt: Điều khiển độ sáng đèn LED (PWM)
Tổng quan dự án Hình ảnh sau đây cho thấy trang web mà chúng ta sẽ xây dựng cho dự án này:
Trang web chứa ba thẻ;
Mỗi thẻ có một đoạn để hiển thị tiêu đề thẻ (Fader 1, Fader 2, Fader 3); Có một thanh trượt phạm vi trong mỗi thẻ mà bạn có thể di chuyển để đặt độ sáng của đèn LED tương ứng; Trong mỗi thẻ, một đoạn khác hiển thị độ sáng LED hiện tại (theo tỷ lệ phần trăm); Khi bạn đặt vị trí mới cho thanh trượt, nó sẽ cập nhật tất cả các máy khách (nếu bạn đã mở nhiều tab trình duyệt web (hoặc nhiều thiết bị), chúng sẽ cập nhật gần như đồng thời bất cứ khi nào có thay đổi).
Nó hoạt động như thế nào? ESP lưu trữ một máy chủ web hiển thị một trang web với ba thanh trượt; Khi bạn đặt vị trí mới cho thanh trượt, máy khách sẽ gửi số thanh trượt và giá trị thanh trượt đến máy chủ thông qua giao thức WebSocket. Ví dụ: nếu bạn đặt thanh trượt số 3 thành vị trí số 40, nó sẽ gửi thông báo này 3s40 đến máy chủ.
2/26
Máy chủ (ESP) nhận số thanh trượt và giá trị tương ứng và điều chỉnh chu kỳ nhiệm vụ PWM cho phù hợp. Ngồi ra, nó cũng thơng báo cho tất cả các máy khách khác với các giá trị thanh trượt hiện tại mới — điều này cho phép chúng tôi cập nhật tất cả các máy khách gần như ngay lập tức.
3/26
ESP8266 xuất tín hiệu PWM với chu kỳ làm việc tương ứng để kiểm soát độ sáng LED. Chu kỳ làm việc 0% có nghĩa là đèn LED tắt hồn tồn, chu kỳ làm việc 50% có nghĩa là đèn LED sáng một nửa và chu kỳ làm việc 100% có nghĩa là đèn LED sáng;
Bất cứ khi nào bạn mở một cửa sổ trình duyệt web mới (đây là khi một máy khách mới kết nối), nó sẽ gửi một tin nhắn đến ESP8266 (cũng thông qua giao thức WebSocket) với thông báo getValues. Khi ESP8266 nhận được thơng báo này, nó sẽ gửi các giá trị thanh trượt hiện tại. Bằng cách này, bất cứ khi nào bạn mở một tab mới, nó ln hiển thị các giá trị hiện tại và cập nhật.
Điều kiện tiên quyết Trước khi tiếp tục với hướng dẫn này, hãy đảm bảo bạn kiểm tra tất cả các điều kiện tiên quyết sau.
1) Các bộ phận cần thiết Để theo dõi dự án này, bạn cần:
4/26
Bảng mạch ESP8266 NodeMCU - đọc Bảng phát triển Wi-Fi ESP8266 tốt nhất Hướng dẫn mua 3x đèn LED Điện trở 3x 220Ohm Breadboard Dây nhảy Bạn không cần ba đèn LED để kiểm tra dự án này, bạn chỉ cần xem kết quả trong Màn hình nối tiếp hoặc sử dụng các thiết bị truyền động khác u cầu tín hiệu PWM để hoạt động. Bạn có thể sử dụng các liên kết trước đó hoặc truy cập trực tiếp vào MakerAdvisor.com/tools để tìm tất cả các phần cho các dự án của mình với giá tốt nhất!
2) Tiện ích bổ sung bảng Arduino IDE và ESP8266 Chúng tơi sẽ lập trình ESP8266 bằng Arduino IDE. Vì vậy, bạn phải cài đặt tiện ích bổ sung ESP8266. Thực hiện theo hướng dẫn tiếp theo nếu bạn chưa có:
Cài đặt bo mạch ESP8266 trong Arduino IDE (Windows, Mac OS X, Linux) Nếu bạn muốn sử dụng VS Code với tiện ích mở rộng PlatformIO, hãy làm theo hướng dẫn tiếp theo để tìm hiểu cách lập trình ESP8266: Bắt đầu với VS Code và PlatformIO IDE cho ESP32 và ESP8266 (Windows, Mac OS X, Linux Ubuntu)
3) Plugin tải lên hệ thống tệp Để tải lên các tệp HTML, CSS và JavaScript cần thiết để xây dựng dự án này lên bộ nhớ flash ESP8266 (LittleFS), chúng tôi sẽ sử dụng một plugin cho trình tải lên hệ thống tệp Arduino IDE: LittleFS. Làm theo hướng dẫn tiếp theo để cài đặt plugin tải lên hệ thống tệp nếu bạn chưa có: Cài đặt ESP8266 NodeMCU LittleFS Filesystem Uploader trong Arduino IDE Nếu bạn đang sử dụng VS Code với tiện ích mở rộng PlatformIO, hãy đọc hướng dẫn sau để tìm hiểu cách tải tệp lên hệ thống tệp: ESP8266 NodeMCU với VS Code và PlatformIO: Tải tệp lên hệ thống tệp (LittleFS)
4) Thư viện Để xây dựng dự án này, bạn cần cài đặt các thư viện sau:
5/26
Bạn có thể cài đặt thư viện đầu tiên bằng Trình quản lý thư viện Arduino. Đi tới Sketch > Include Library > Manage Libraries và tìm kiếm tên thư viện. Các thư viện ESPAsyncWebServer và ESPAsynTCP khơng có sẵn để cài đặt thơng qua Trình quản lý thư viện Arduino, vì vậy bạn cần sao chép các tệp thư viện vào thư mục Thư viện cài đặt Arduino. Ngoài ra, trong Arduino IDE, bạn có thể vào Sketch> Include Library > Add .zip Library và chọn các thư viện bạn vừa tải xuống. Cài đặt thư viện (VS Code + PlatformIO) Nếu bạn đang lập trình ESP8266 bằng PlatformIO, bạn nên thêm các dòng sau vào tệp
platformio.ini để bao gồm các thư viện (cũng thay đổi tốc độ Serial Monitor thành 115200 và đặt hệ thống tệp littleFS): monitor_speed = 115200
board_build.filesystem = littlefs
lib_deps = ESP Async WebServer
arduino-libraries/Arduino_JSON @ 0.1.0
Sơ đồ Nối ba đèn LED với ESP8266. Chúng tôi đang sử dụng GPIO 12 (D6), 13 (D7) và 14 (D5). Bạn có thể sử dụng bất kỳ GPIO phù hợp nào khác.
6/26
Đề xuất đọc: Tham khảo sơ đồ chân ESP8266: Bạn nên sử dụng chân GPIO nào?
Sắp xếp các tệp của bạn Để giữ cho dự án được tổ chức và dễ hiểu hơn, chúng tôi sẽ tạo bốn tệp để xây dựng máy chủ web: Bản phác thảo Arduino xử lý máy chủ web; index.html: để xác định nội dung của trang web;
7/26
Sytle.css: để tạo kiểu cho trang web; script.js: để lập trình hành vi của trang web—xử lý những gì xảy ra khi bạn di
chuyển thanh trượt, gửi, nhận và giải thích các tin nhắn nhận được qua giao thức WebSocket.
Bạn nên lưu các tệp HTML, CSS và JavaScript bên trong một thư mục được gọi là dữ liệu bên trong thư mục phác thảo Arduino, như thể hiện trong sơ đồ trước. Chúng tôi sẽ tải các tệp này lên hệ thống tệp ESP8266 (LittleFS). Bạn có thể tải xuống tất cả các tệp dự án: Tải xuống tất cả các tệp dự án Arduino
Tệp HTML Sao chép nội dung sau vào tệp .html chỉ mục.
Đoạn đầu tiên hiển thị tiêu đề cho thẻ (Fader 1). Bạn có thể thay đổi văn bản thành bất cứ điều gì bạn muốn.
Fader 1
Để tạo thanh trượt trong HTML, bạn sử dụng thẻ <input>. Thẻ <input> chỉ định một trường nơi người dùng có thể nhập dữ liệu. Có rất nhiều loại đầu vào. Để xác định thanh trượt, hãy dùng thuộc tính type với giá trị range. Trong thanh trượt, bạn cũng cần xác định phạm vi tối thiểu và tối đa bằng cách sử dụng các thuộc tính tối thiểu và tối đa (trong trường hợp này là 0 và 100, tương ứng). Bạn cũng cần xác định các thuộc tính khác như: Thuộc tính STEP chỉ định khoảng thời gian giữa các số hợp lệ. Trong trường hợp của chúng tơi, chúng tơi đặt nó thành 1; lớp để tạo kiểu cho thanh trượt (class = "thanh trượt"); id để chúng ta có thể thao tác với giá trị thanh trượt bằng JavaScript (id = "slider1"); thuộc tính onchange để gọi một hàm (updateSliderPWM(this)) khi bạn đặt vị trí mới cho thanh trượt. Hàm này (được định nghĩa trong tệp JavaScript) gửi giá trị thanh trượt hiện tại thông qua giao thức WebSocket đến máy khách. Từ khóa này đề cập đến phần tử thanh trượt HTML. Thanh trượt nằm bên trong một đoạn văn với tên lớp chuyển đổi. Vì vậy, đây là các thẻ thực sự tạo thanh trượt.
max="100" step="1" value ="0" class="slider">
Cuối cùng, có một đoạn văn với thẻ <span>, để chúng ta có thể chèn giá trị thanh trượt hiện tại vào đoạn đó bằng cách tham chiếu đến id của nó (id = "sliderValue1").
Để tạo thêm thanh trượt, bạn cần sao chép tất cả các thẻ HTML tạo thẻ hoàn chỉnh. Tuy nhiên, trước tiên, bạn cần xem xét rằng bạn cần một id duy nhất cho mỗi giá trị thanh trượt và thanh trượt. Trong trường hợp của chúng tơi, chúng tơi có ba thanh trượt với các id sau: slider1, slider2, slider3 và ba trình giữ chỗ cho giá trị thanh trượt với các id sau: sliderValue1, sliderValue2, sliderValue3. Ví dụ: đây là thẻ cho thanh trượt số 2. <div class="card">
Xem mã thô Chúng ta hãy xem nhanh các phần có liên quan của tệp CSS tạo kiểu cho thanh trượt. Trong ví dụ này, chúng ta cần sử dụng tiền tố vendor cho thuộc tính appearance. .slider {
-webkit-appearance: none;
margin: 0 auto;
width: 100%;
height: 15px;
border-radius: 10px;
background: #FFD65C;
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 30px;
height: 30px;
border-radius: 50%;
background: #034078;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 30px;
height: 30px;
border-radius: 50% ;
background: #034078;
cursor: pointer;
}
.switch {
padding-left: 5%;
padding-right: 5%;
}
Tiền tố nhà cung cấp
13/26
Tiền tố của nhà cung cấp cho phép trình duyệt hỗ trợ các tính năng CSS mới trước khi chúng được hỗ trợ đầy đủ. Các trình duyệt được sử dụng phổ biến nhất sử dụng các tiền tố sau: -webkit- Chrome, Safari, các phiên bản Opera mới hơn, hầu hết tất cả các trình duyệt iOS, -moz- Firefox, -o- Phiên bản cũ của Opera, -ms- Microsoft Edge và Internet Explorer. Tiền tố nhà cung cấp là tạm thời. Khi các thuộc tính được hỗ trợ đầy đủ bởi trình duyệt bạn sử dụng, bạn khơng cần chúng. Bạn có thể sử dụng tham chiếu sau để kiểm tra xem thuộc tính bạn đang sử dụng có cần tiền tố hay không: />Chúng ta hãy xem bộ chọn .slider (tạo kiểu cho thanh trượt): .slider {
-webkit-appearance: none;
margin: 0 auto;
width: 100%;
height: 15px;
border-radius: 10px;
background: #FFD65C;outline: none;
}
Đặt -webkit-appearance thành none sẽ ghi đè các kiểu CSS mặc định được áp dụng cho thanh trượt trong trình duyệt Google Chrome, Safari và Android. -webkit-appearance: none;
Đặt lề thành 0 tự động căn chỉnh thanh trượt bên trong vùng chứa chính của nó. margin: 0 auto;
Chiều rộng của thanh trượt được đặt thành 100% và chiều cao thành 15px. Bán kính viền được đặt thành 10px. margin: 0 auto;
width: 100%;
height: 15px;
border-radius: 10px;
Đặt màu nền cho thanh trượt và đặt đường viền thành không có. background: #FFD65C;
outline: none;
Sau đó, định dạng núm điều khiển thanh trượt. Sử dụng -webkit- cho các trình duyệt web Chrome, Opera, Safari và Edge và -moz- cho Firefox.
14/26
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 30px;
height: 30px;
border-radius: 50%;
background: #034078;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 30px;
height: 30px;
border-radius: 50% ;
background: #034078;
cursor: pointer;
}
Đặt thuộc tính -webkit-appearance và appearance thành none để ghi đè các thuộc tính mặc định. -webkit-appearance: none;
appearance: none;
Đặt chiều rộng, chiều cao và bán kính đường viền cụ thể cho trình xử lý. Đặt cùng chiều rộng và chiều cao với bán kính đường viền 50% sẽ tạo ra một vịng trịn. width: 30px;
height: 30px;
border-radius: 50%;
Sau đó, đặt màu cho nền và đặt con trỏ thành con trỏ. background: #034078;
cursor: pointer;
Hãy thoải mái chơi với các thuộc tính thanh trượt để tạo cho nó một cái nhìn khác.
Tệp JavaScript Sao chép nội dung sau vào tập lệnh.js tệp.
15/26
// Complete project details: /> var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onload);
function onload(event) {
initWebSocket();
}
function getValues(){
websocket.send("getValues");
}
function initWebSocket() {
console.log('Trying to open a WebSocket connection…');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
}
function onOpen(event) {
console.log('Connection opened');
getValues();
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
function updateSliderPWM(element) {
var sliderNumber = element.id.charAt(element.id.length-1);
var sliderValue = document.getElementById(element.id).value;
Xem mã thô Dưới đây là danh sách chức năng của mã này: 16/26
khởi tạo kết nối WebSocket với máy chủ; gửi tin nhắn đến máy chủ để nhận các giá trị thanh trượt hiện tại; sử dụng phản hồi để cập nhật các giá trị thanh trượt trên trang web; xử lý trao đổi dữ liệu thông qua giao thức WebSocket. Chúng ta hãy xem mã JavaScript này để xem nó hoạt động như thế nào. Cổng là điểm vào giao diện WebSocket. window.location.hostname lấy địa chỉ trang hiện tại (địa chỉ IP máy chủ web). var gateway = ws://${window.location.hostname}/ws;
Tạo một biến toàn cục mới gọi là websocket. var websocket;
Thêm trình nghe sự kiện sẽ gọi hàm onload khi trang web tải. window.addEventListener('load', onload);
Hàm onload() gọi hàm initWebSocket() để khởi tạo kết nối WebSocket với máy chủ. function onload(event) {
initWebSocket();
}
Hàm initWebSocket() khởi tạo kết nối WebSocket trên cổng được xác định trước đó. Chúng tơi cũng gán một số chức năng gọi lại khi kết nối WebSocket được mở, đóng hoặc khi nhận được tin nhắn.
function initWebSocket() {
console.log('Trying to open a WebSocket connection…');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
}
Lưu ý rằng khi kết nối websocket mở ra, chúng ta sẽ gọi hàm getValues. function onOpen(event) {
console.log('Connection opened');
getValues();
}
Hàm getValues() gửi một thông báo đến máy chủ getValues để lấy giá trị hiện tại của tất cả các thanh trượt. Sau đó, chúng ta phải xử lý những gì xảy ra khi chúng ta nhận được thơng báo đó ở phía máy chủ (ESP8266). function getStates(){
websocket.send("getValues");
}
17/26
Chúng tôi xử lý các tin nhắn nhận được qua giao thức websocket trên hàm onMessage(). function onMessage(event) {
Máy chủ gửi các trạng thái ở định dạng JSON, ví dụ: {
sliderValue1: 20;
sliderValue2: 50;
sliderValue3: 0;
}
Hàm onMessage() chỉ đơn giản là đi qua tất cả các giá trị và đặt chúng vào các vị trí tương ứng trên trang HTML. Hàm updateSliderPWM() chạy khi bạn di chuyển thanh trượt. function updateSliderPWM(element) {
var sliderNumber = element.id.charAt(element.id.length-1);
var sliderValue = document.getElementById(element.id).value;
Hàm này lấy giá trị từ thanh trượt và cập nhật đoạn tương ứng với giá trị phù hợp. Chức năng này cũng gửi tin nhắn đến máy chủ để ESP8266 cập nhật độ sáng LED. websocket.send(sliderNumber+"s"+sliderValue.toString());
Tin nhắn được gửi theo định dạng sau: thanh trượtsốsthanh trượt
Ví dụ: nếu bạn di chuyển thanh trượt số 3 đến vị trí 40, nó sẽ gửi thơng báo sau: 3s40
Bản phác thảo Arduino Sao chép mã sau vào Arduino IDE của bạn hoặc vào tệp chính.cpp nếu bạn đang sử dụng PlatformIO.
18/26
/*
Rui Santos
Complete project details at /> Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.