Ví dụ này cho thấy cách sử dụng nhiều ứng dụng web cùng lúc với thư viện DIYables ESP32 WebApps. Nó trình diễn sự tích hợp của nhiều giao diện web tương tác—như giám sát, điều khiển và liên lạc—trong một dự án duy nhất. Được thiết kế cho nền tảng ESP32, ví dụ này lý tưởng cho việc học cách kết hợp và quản lý nhiều tính năng dựa trên web cùng lúc, cung cấp nền tảng vững chắc cho các dự án IoT tiên tiến.
| 1 | × | mô-đun phát triển ESP-WROOM-32 | | |
| 1 | × | Alternatively, ESP32 Uno-form board | | |
| 1 | × | Alternatively, ESP32 S3 Uno-form board | | |
| 1 | × | USB Cable Type-A to Type-C (for USB-A PC) | | |
| 1 | × | USB Cable Type-C to Type-C (for USB-C PC) | | |
| 1 | × | (Khuyến nghị) Screw Terminal Expansion Board for ESP32 | | |
| 1 | × | (Khuyến nghị) Breakout Expansion Board for ESP32 | | |
| 1 | × | (Khuyến nghị) Power Splitter for ESP32 | | |
Or you can buy the following kits:
| 1 | × | DIYables ESP32 Starter Kit (ESP32 included) | | |
| 1 | × | DIYables Sensor Kit (30 sensors/displays) | | |
| 1 | × | DIYables Sensor Kit (18 sensors/displays) | | |
Hãy làm theo các hướng dẫn này theo từng bước:
Kết nối bo mạch ESP32 với máy tính bằng cáp USB.
Khởi chạy Arduino IDE trên máy tính của bạn.
Chọn bo mạch ESP32 phù hợp (ví dụ ESP32 Dev Module) và cổng COM.
Điều hướng tới biểu tượng Thư viện ở thanh bên trái của Arduino IDE.
Tìm kiếm "DIYables ESP32 WebApps", sau đó tìm thư viện DIYables ESP32 WebApps do DIYables
Nhấp vào nút Cài đặt để cài đặt thư viện.


#include <DIYables_ESP32_Platform.h>
#include <DIYablesWebApps.h>
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
ESP32ServerFactory factory;
DIYablesWebAppServer webAppsServer(factory, 80, 81);
DIYablesHomePage homePage;
DIYablesWebMonitorPage webMonitorPage;
DIYablesWebSliderPage webSliderPage;
DIYablesWebJoystickPage webJoystickPage(false, 5);
DIYablesWebRotatorPage webRotatorPage(ROTATOR_MODE_CONTINUOUS);
DIYablesWebAnalogGaugePage webAnalogGaugePage(0.0, 100.0, "%");
DIYablesWebTablePage webTablePage;
int currentSlider1 = 64;
int currentSlider2 = 128;
int currentJoystickX = 0;
int currentJoystickY = 0;
int currentRotatorAngle = 0;
float currentGaugeValue = 50.0;
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("DIYables ESP32 WebApp - Multiple Apps Example");
webAppsServer.addApp(&homePage);
webAppsServer.addApp(&webMonitorPage);
webAppsServer.addApp(&webSliderPage);
webAppsServer.addApp(&webJoystickPage);
webAppsServer.addApp(&webRotatorPage);
webAppsServer.addApp(&webAnalogGaugePage);
webAppsServer.addApp(&webTablePage);
webAppsServer.setNotFoundPage(DIYablesNotFoundPage());
webTablePage.addRow("Arduino Status");
webTablePage.addRow("WiFi Connected");
webTablePage.addRow("Uptime");
webTablePage.addRow("Slider 1");
webTablePage.addRow("Slider 2");
webTablePage.addRow("Joystick X");
webTablePage.addRow("Joystick Y");
webTablePage.addRow("Rotator Angle");
webTablePage.addRow("Gauge Value");
if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) {
while (1) {
Serial.println("Failed to start WebApp server!");
delay(1000);
}
}
setupCallbacks();
}
void setupCallbacks() {
webMonitorPage.onWebMonitorMessage([](const String& message) {
Serial.println("Web Monitor: " + message);
webMonitorPage.sendToWebMonitor("Arduino received: " + message);
});
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
Serial.print("Slider 1: ");
Serial.print(slider1);
Serial.print(", Slider 2: ");
Serial.println(slider2);
webTablePage.sendValueUpdate("Slider 1", String(slider1));
webTablePage.sendValueUpdate("Slider 2", String(slider2));
currentGaugeValue = map(slider1, 0, 255, 0, 100);
webAnalogGaugePage.sendToWebAnalogGauge(currentGaugeValue);
char gaugeStr[16];
snprintf(gaugeStr, sizeof(gaugeStr), "%.1f%%", currentGaugeValue);
webTablePage.sendValueUpdate("Gauge Value", String(gaugeStr));
});
webSliderPage.onSliderValueToWeb([]() {
webSliderPage.sendToWebSlider(currentSlider1, currentSlider2);
});
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
currentJoystickX = x;
currentJoystickY = y;
Serial.print("Joystick - X: ");
Serial.print(x);
Serial.print(", Y: ");
Serial.println(y);
Serial.print(x);
Serial.print(", Y: ");
Serial.println(y);
webTablePage.sendValueUpdate("Joystick X", String(x));
webTablePage.sendValueUpdate("Joystick Y", String(y));
}
});
webJoystickPage.onJoystickValueToWeb([]() {
webJoystickPage.sendToWebJoystick(currentJoystickX, currentJoystickY);
});
webRotatorPage.onRotatorAngleFromWeb([](float angle) {
currentRotatorAngle = (int)angle;
Serial.println("Rotator angle: " + String(angle) + "°");
webTablePage.sendValueUpdate("Rotator Angle", String(angle, 0) + "°");
});
webAnalogGaugePage.onGaugeValueRequest([]() {
webAnalogGaugePage.sendToWebAnalogGauge(currentGaugeValue);
});
webTablePage.onTableValueRequest([]() {
webTablePage.sendValueUpdate("Arduino Status", "Running");
webTablePage.sendValueUpdate("WiFi Connected", "Yes");
webTablePage.sendValueUpdate("Uptime", "0 seconds");
webTablePage.sendValueUpdate("Slider 1", String(currentSlider1));
webTablePage.sendValueUpdate("Slider 2", String(currentSlider2));
webTablePage.sendValueUpdate("Joystick X", String(currentJoystickX));
webTablePage.sendValueUpdate("Joystick Y", String(currentJoystickY));
webTablePage.sendValueUpdate("Rotator Angle", String(currentRotatorAngle) + "°");
webTablePage.sendValueUpdate("Gauge Value", String(currentGaugeValue, 1) + "%");
});
}
void loop() {
webAppsServer.loop();
static unsigned long lastUptimeUpdate = 0;
if (millis() - lastUptimeUpdate > 5000) {
lastUptimeUpdate = millis();
unsigned long uptimeSeconds = millis() / 1000;
String uptimeStr = String(uptimeSeconds) + " seconds";
if (uptimeSeconds >= 60) {
uptimeStr = String(uptimeSeconds / 60) + "m " + String(uptimeSeconds % 60) + "s";
}
webTablePage.sendValueUpdate("Uptime", uptimeStr);
}
static unsigned long lastSensorUpdate = 0;
if (millis() - lastSensorUpdate > 3000) {
lastSensorUpdate = millis();
float sensorValue = 50.0 + 30.0 * sin(millis() / 10000.0);
currentGaugeValue = sensorValue;
webAnalogGaugePage.sendToWebAnalogGauge(currentGaugeValue);
webTablePage.sendValueUpdate("Gauge Value", String(currentGaugeValue, 1) + "%");
}
delay(10);
}
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
DIYables WebApp - Multiple Apps Example
INFO: Added app /
INFO: Added app /web-monitor
INFO: Added app /web-slider
INFO: Added app /web-joystick
INFO: Added app /web-rotator
INFO: Added app /web-gauge
INFO: Added app /web-table
DIYables WebApp Library
Platform: ESP32
Network connected!
IP address: 192.168.0.2
HTTP server started on port 80
Configuring WebSocket server callbacks...
WebSocket server started on port 81
WebSocket URL: ws://192.168.0.2:81
WebSocket server started on port 81
==========================================
DIYables WebApp Ready!
==========================================
📱 Web Interface: http://192.168.0.2
🔗 WebSocket: ws://192.168.0.2:81
📋 Available Applications:
🏠 Home Page: http://192.168.0.2/
📊 Web Monitor: http://192.168.0.2/web-monitor
🎚️ Web Slider: http://192.168.0.2/web-slider
🕹️ Web Joystick: http://192.168.0.2/web-joystick
🔄 Web Rotator: http://192.168.0.2/web-rotator
⏲️ Web Analog Gauge: http://192.168.0.2/web-gauge
📊 Web Table: http://192.168.0.2/web-table
==========================================
Nếu bạn không nhìn thấy gì, khởi động lại mạch ESP32.
Ghi chú địa chỉ IP hiển thị, và nhập địa chỉ này vào thanh địa chỉ của trình duyệt web trên điện thoại thông minh hoặc máy tính của bạn.
Ví dụ: http://192.168.0.2
Bạn sẽ thấy trang chủ với tất cả các ứng dụng web như hình bên dưới:
Nhấp vào bất kỳ liên kết ứng dụng web nào (Chat, Web Monitor, Web Digital Pins, Web Slider, Web Joystick, v.v.), bạn sẽ thấy giao diện người dùng (UI) của ứng dụng web tương ứng.
Hoặc bạn cũng có thể truy cập trực tiếp từng trang bằng địa chỉ IP kèm theo đường dẫn của ứng dụng. Ví dụ: http://192.168.0.2/chat, http://192.168.0.2/web-monitor, v.v.
Khám phá tất cả các ứng dụng web: thử trò chuyện với Arduino, theo dõi đầu ra serial, điều khiển các chân số kỹ thuật số, điều chỉnh các thanh trượt, và sử dụng joystick ảo để trải nghiệm đầy đủ các tính năng của giao diện web tích hợp.
Trang chủ đóng vai trò là trung tâm điều khiển của bạn với các liên kết đến tất cả các ứng dụng:
Giám sát Web: /webmonitor - Giao diện giao tiếp nối tiếp
Trò chuyện: /chat - Nhắn tin tương tác với Arduino
Chân số kỹ thuật số: /digital-pins - Điều khiển và giám sát các chân
Thanh trượt Web: /webslider - Hai thanh trượt điều khiển tín hiệu tương tự
Joystick Web: /webjoystick - Giao diện điều khiển vị trí 2D
Truy cập trực tiếp từng giao diện:
http://[ARDUINO_IP]/ # Home page
http://[ARDUINO_IP]/webmonitor # Serial monitor interface
http://[ARDUINO_IP]/chat # Chat interface
http://[ARDUINO_IP]/digital-pins # Pin control
http://[ARDUINO_IP]/webslider # Slider controls
http://[ARDUINO_IP]/webjoystick # Joystick control
Ví dụ toàn diện này cung cấp nền tảng cho các dự án sáng tạo của bạn. Thay đổi và điều chỉnh các cấu hình dưới đây để xây dựng các ứng dụng IoT tuyệt vời phù hợp với tầm nhìn độc đáo của bạn.
Ví dụ này đã cấu hình trước các chân cụ thể cho các mục đích khác nhau:
webDigitalPinsPage.enablePin(2, WEB_PIN_OUTPUT);
webDigitalPinsPage.enablePin(3, WEB_PIN_OUTPUT);
webDigitalPinsPage.enablePin(4, WEB_PIN_OUTPUT);
webDigitalPinsPage.enablePin(13, WEB_PIN_OUTPUT);
webDigitalPinsPage.enablePin(8, WEB_PIN_INPUT);
webDigitalPinsPage.enablePin(9, WEB_PIN_INPUT);
DIYablesWebJoystickPage webJoystickPage(false, 5);
Ví dụ duy trì trạng thái đồng bộ trên tất cả các giao diện:
int pinStates[16] = { LOW };
int currentSlider1 = 64;
int currentSlider2 = 128;
int currentJoystickX = 0;
int currentJoystickY = 0;
Giao diện trò chuyện bao gồm một số lệnh được lập trình sẵn:
hello - Phản hồi chào hỏi thân thiện
time - Hiển thị thời gian hoạt động của ESP32 tính bằng giây
status - Báo cáo trạng thái ESP32 và trạng thái đèn LED
help - Liệt kê các lệnh có sẵn
User: hello
ESP32: Hello! I'm your Arduino. How can I help you?
User: led on
ESP32: Built-in LED is now ON!
User: time
ESP32: I've been running for 1245 seconds.
User: status
ESP32: Status: Running smoothly! LED is ON
#include <Servo.h>
const int MOTOR_LEFT_PWM = 9;
const int MOTOR_RIGHT_PWM = 10;
const int SERVO_PAN = 11;
const int SERVO_TILT = 12;
const int LED_STRIP_PIN = 6;
Servo panServo, tiltServo;
void setup() {
panServo.attach(SERVO_PAN);
tiltServo.attach(SERVO_TILT);
pinMode(MOTOR_LEFT_PWM, OUTPUT);
pinMode(MOTOR_RIGHT_PWM, OUTPUT);
setupRobotCallbacks();
}
void setupRobotCallbacks() {
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
int leftSpeed = y + (x / 2);
int rightSpeed = y - (x / 2);
leftSpeed = constrain(leftSpeed, -100, 100);
rightSpeed = constrain(rightSpeed, -100, 100);
leftSpeed = map(leftSpeed, -100, 100, -currentSlider1, currentSlider1);
rightSpeed = map(rightSpeed, -100, 100, -currentSlider1, currentSlider1);
analogWrite(MOTOR_LEFT_PWM, abs(leftSpeed));
analogWrite(MOTOR_RIGHT_PWM, abs(rightSpeed));
Serial.println("Robot - Left: " + String(leftSpeed) + ", Right: " + String(rightSpeed));
});
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
int panAngle = map(currentJoystickX, -100, 100, 0, 180);
int tiltAngle = map(slider2, 0, 255, 0, 180);
panServo.write(panAngle);
tiltServo.write(tiltAngle);
Serial.println("Camera - Pan: " + String(panAngle) + "°, Tilt: " + String(tiltAngle) + "°");
});
webDigitalPinsPage.onPinWrite([](int pin, int state) {
switch (pin) {
case 2:
digitalWrite(pin, state);
Serial.println("Headlights " + String(state ? "ON" : "OFF"));
break;
case 3:
if (state) {
digitalWrite(pin, HIGH);
delay(200);
digitalWrite(pin, LOW);
}
break;
case 4:
if (state) {
analogWrite(MOTOR_LEFT_PWM, 0);
analogWrite(MOTOR_RIGHT_PWM, 0);
Serial.println("EMERGENCY STOP ACTIVATED");
}
break;
}
});
chatPage.onChatMessage([](const String& message) {
String msg = message;
msg.toLowerCase();
if (msg.indexOf("stop") >= 0) {
analogWrite(MOTOR_LEFT_PWM, 0);
analogWrite(MOTOR_RIGHT_PWM, 0);
chatPage.sendToChat("Robot stopped!");
return;
}
if (msg.indexOf("center camera") >= 0) {
panServo.write(90);
tiltServo.write(90);
chatPage.sendToChat("Camera centered!");
return;
}
if (msg.indexOf("speed") >= 0) {
String response = "Current max speed: " + String(map(currentSlider1, 0, 255, 0, 100)) + "%";
chatPage.sendToChat(response);
return;
}
chatPage.sendToChat("Robot commands: stop, center camera, speed");
});
}
const int LIVING_ROOM_LIGHTS = 2;
const int BEDROOM_LIGHTS = 3;
const int KITCHEN_LIGHTS = 4;
const int FAN_CONTROL = 9;
const int AC_CONTROL = 10;
const int MOTION_SENSOR = 8;
const int DOOR_SENSOR = 9;
void setupHomeAutomation() {
pinMode(LIVING_ROOM_LIGHTS, OUTPUT);
pinMode(BEDROOM_LIGHTS, OUTPUT);
pinMode(KITCHEN_LIGHTS, OUTPUT);
pinMode(FAN_CONTROL, OUTPUT);
pinMode(AC_CONTROL, OUTPUT);
pinMode(MOTION_SENSOR, INPUT);
pinMode(DOOR_SENSOR, INPUT_PULLUP);
webDigitalPinsPage.onPinWrite([](int pin, int state) {
digitalWrite(pin, state);
String room;
switch (pin) {
case 2: room = "Living Room"; break;
case 3: room = "Bedroom"; break;
case 4: room = "Kitchen"; break;
default: room = "Pin " + String(pin); break;
}
Serial.println(room + " lights " + String(state ? "ON" : "OFF"));
String message = room + " lights turned " + String(state ? "ON" : "OFF");
chatPage.sendToChat(message);
});
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
analogWrite(FAN_CONTROL, slider1);
analogWrite(AC_CONTROL, slider2);
Serial.println("Fan: " + String(map(slider1, 0, 255, 0, 100)) + "%, " +
"AC: " + String(map(slider2, 0, 255, 0, 100)) + "%");
});
chatPage.onChatMessage([](const String& message) {
String msg = message;
msg.toLowerCase();
if (msg.indexOf("all lights on") >= 0) {
digitalWrite(LIVING_ROOM_LIGHTS, HIGH);
digitalWrite(BEDROOM_LIGHTS, HIGH);
digitalWrite(KITCHEN_LIGHTS, HIGH);
chatPage.sendToChat("All lights turned ON!");
return;
}
if (msg.indexOf("all lights off") >= 0) {
digitalWrite(LIVING_ROOM_LIGHTS, LOW);
digitalWrite(BEDROOM_LIGHTS, LOW);
digitalWrite(KITCHEN_LIGHTS, LOW);
chatPage.sendToChat("All lights turned OFF!");
return;
}
if (msg.indexOf("temperature") >= 0) {
String response = "Fan: " + String(map(currentSlider1, 0, 255, 0, 100)) + "%, " +
"AC: " + String(map(currentSlider2, 0, 255, 0, 100)) + "%";
chatPage.sendToChat(response);
return;
}
if (msg.indexOf("security") >= 0) {
bool motion = digitalRead(MOTION_SENSOR);
bool door = digitalRead(DOOR_SENSOR);
String status = "Motion: " + String(motion ? "DETECTED" : "CLEAR") +
", Door: " + String(door ? "CLOSED" : "OPEN");
chatPage.sendToChat(status);
return;
}
chatPage.sendToChat("Home commands: all lights on/off, temperature, security");
});
}
void loop() {
server.loop();
static bool lastMotion = false;
static bool lastDoor = false;
bool currentMotion = digitalRead(MOTION_SENSOR);
bool currentDoor = digitalRead(DOOR_SENSOR);
if (currentMotion != lastMotion) {
if (currentMotion) {
chatPage.sendToChat("🚨 MOTION DETECTED!");
webMonitorPage.sendToWebMonitor("Security Alert: Motion detected");
}
lastMotion = currentMotion;
}
if (currentDoor != lastDoor) {
String status = currentDoor ? "CLOSED" : "OPENED";
chatPage.sendToChat("🚪 Door " + status);
webMonitorPage.sendToWebMonitor("Security: Door " + status);
lastDoor = currentDoor;
}
delay(10);
}
const int HEATING_ELEMENT = 9;
const int COOLING_FAN = 10;
const int STIRRER_MOTOR = 11;
const int TEMP_SENSOR_PIN = A0;
const int PH_SENSOR_PIN = A1;
void setupScienceExperiment() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
int targetTemp = map(slider1, 0, 255, 20, 80);
analogWrite(STIRRER_MOTOR, slider2);
int currentTemp = readTemperature();
if (currentTemp < targetTemp) {
analogWrite(HEATING_ELEMENT, 200);
analogWrite(COOLING_FAN, 0);
} else if (currentTemp > targetTemp + 2) {
analogWrite(HEATING_ELEMENT, 0);
analogWrite(COOLING_FAN, 255);
} else {
analogWrite(HEATING_ELEMENT, 0);
analogWrite(COOLING_FAN, 0);
}
Serial.println("Target: " + String(targetTemp) + "°C, Current: " + String(currentTemp) + "°C");
});
chatPage.onChatMessage([](const String& message) {
String msg = message;
msg.toLowerCase();
if (msg.indexOf("data") >= 0) {
int temp = readTemperature();
float ph = readPH();
String data = "Temperature: " + String(temp) + "°C, pH: " + String(ph, 2);
chatPage.sendToChat(data);
return;
}
if (msg.indexOf("start") >= 0) {
chatPage.sendToChat("🔬 Experiment started! Monitoring conditions...");
return;
}
if (msg.indexOf("stop") >= 0) {
analogWrite(HEATING_ELEMENT, 0);
analogWrite(COOLING_FAN, 0);
analogWrite(STIRRER_MOTOR, 0);
chatPage.sendToChat("⚠️ Experiment stopped - all systems OFF");
return;
}
chatPage.sendToChat("Science commands: data, start, stop");
});
webMonitorPage.onWebMonitorMessage([](const String& message) {
if (message == "log") {
int temp = readTemperature();
float ph = readPH();
String logEntry = String(millis()) + "," + String(temp) + "," + String(ph, 2);
webMonitorPage.sendToWebMonitor(logEntry);
}
});
}
int readTemperature() {
int sensorValue = analogRead(TEMP_SENSOR_PIN);
return map(sensorValue, 0, 1023, 0, 100);
}
float readPH() {
int sensorValue = analogRead(PH_SENSOR_PIN);
return map(sensorValue, 0, 1023, 0, 14) / 10.0;
}
void synchronizeAllStates() {
webSliderPage.sendToWebSlider(currentSlider1, currentSlider2);
webJoystickPage.sendToWebJoystick(currentJoystickX, currentJoystickY);
for (int pin = 0; pin <= 13; pin++) {
if (webDigitalPinsPage.isPinEnabled(pin)) {
webDigitalPinsPage.updatePinState(pin, pinStates[pin]);
}
}
Serial.println("All interface states synchronized");
}
void setupCrossInterfaceCommunication() {
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
float distance = sqrt(x*x + y*y);
if (distance > 50) {
int maxValue = map(distance, 50, 100, 255, 128);
}
});
webDigitalPinsPage.onPinWrite([](int pin, int state) {
if (pin == 2 && state == HIGH) {
chatPage.sendToChat("📢 System armed - additional commands available");
} else if (pin == 2 && state == LOW) {
chatPage.sendToChat("📢 System disarmed - limited commands only");
}
});
}
1. Một số giao diện không tải được
Kiểm tra xem tất cả ứng dụng có được thêm vào máy chủ trong quá trình thiết lập không
Xác nhận kết nối WebSocket trong bảng điều khiển trình duyệt
Đảm bảo đủ bộ nhớ cho tất cả các giao diện
Nêu ra những bất nhất giữa các giao diện
Triển khai các hàm gọi lại đồng bộ trạng thái
Sử dụng các biến toàn cục dùng chung để theo dõi trạng thái
Gọi các hàm đồng bộ sau các thay đổi trạng thái lớn
3. Vấn đề hiệu suất với nhiều giao diện
Giảm tần suất cập nhật cho các giao diện không quan trọng
Triển khai cập nhật có chọn lọc dựa trên giao diện đang hoạt động
Cân nhắc vô hiệu hóa các giao diện chưa sử dụng cho các dự án cụ thể
4. Giới hạn bộ nhớ
Giám sát RAM có sẵn bằng Serial.print(freeMemory())
Vô hiệu hóa các giao diện không được sử dụng khi bộ nhớ bị giới hạn
Tối ưu hóa các hàm gọi lại để giảm thiểu bộ nhớ tiêu thụ
void debugSystemState() {
Serial.println("=== System State Debug ===");
Serial.println("Free Memory: " + String(freeMemory()) + " bytes");
Serial.println("Digital Pins:");
for (int pin = 0; pin <= 13; pin++) {
if (webDigitalPinsPage.isPinEnabled(pin)) {
Serial.println(" Pin " + String(pin) + ": " + String(pinStates[pin] ? "HIGH" : "LOW"));
}
}
Serial.println("Sliders: " + String(currentSlider1) + ", " + String(currentSlider2));
Serial.println("Joystick: X=" + String(currentJoystickX) + ", Y=" + String(currentJoystickY));
Serial.println("========================");
}
void optimizeMemoryUsage() {
}
void controlUpdateFrequency() {
static unsigned long lastSlowUpdate = 0;
static unsigned long lastFastUpdate = 0;
if (millis() - lastFastUpdate > 10) {
lastFastUpdate = millis();
}
if (millis() - lastSlowUpdate > 1000) {
lastSlowUpdate = millis();
}
}
Sau khi làm chủ ví dụ MultipleWebApps:
Tùy chỉnh cho Dự án của bạn: Loại bỏ các giao diện không được sử dụng và thêm logic đặc thù cho dự án
Thêm cảm biến: Tích hợp các giá trị cảm biến thực tế để giám sát đầu vào
Triển khai an toàn: Thêm các công tắc dừng khẩn cấp và khóa an toàn
Tạo lệnh tùy chỉnh: Mở rộng giao diện trò chuyện bằng các lệnh tùy chỉnh cho dự án
Thêm ghi dữ liệu: Sử dụng trình giám sát web cho lưu trữ dữ liệu vĩnh viễn
Tối ưu hóa cho thiết bị di động: Kiểm tra và tối ưu hóa cho việc sử dụng trên thiết bị di động
Để được trợ giúp thêm:
Kiểm tra tài liệu ví dụ riêng lẻ (Chat_Example.txt, WebMonitor_Example.txt, v.v.)
Xem lại tài liệu tham khảo API
Truy cập các hướng dẫn DIYables: https://esp32io.com/tutorials/diyables-esp32-webapps
Diễn đàn cộng đồng ESP32
Ví dụ toàn diện này cung cấp nền tảng cho hầu như bất kỳ dự án ESP32 được điều khiển qua web. Bắt đầu với mẫu này và tùy chỉnh nó cho nhu cầu cụ thể của bạn!