Ví dụ ESP32 MultipleWebApps Hướng dẫn bảng điều khiển IoT hoàn chỉnh

Tổng quan

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.

ví dụ Arduino với nhiều ứng dụng web - hướng dẫn bảng điều khiển IoT toàn diện.

Tính năng

  • Trang chủ: Trung tâm điều hướng tập trung với liên kết tới tất cả các ứng dụng web
  • Giám sát Web: Giao diện giao tiếp nối tiếp thời gian thực và gỡ lỗi
  • Giao diện trò chuyện: Hệ thống trò chuyện tương tác với khả năng phản hồi từ ESP32
  • Điều khiển chân số: Điều khiển và giám sát tất cả các chân số thông qua web
  • Điều khiển hai thanh trượt: Hai thanh trượt độc lập để điều khiển giá trị tương tự
  • Joystick ảo: Điều khiển vị trí 2D cho các ứng dụng định hướng
  • Quản lý trạng thái thống nhất: Tất cả các giao diện chia sẻ thông tin trạng thái được đồng bộ
  • Cập nhật thời gian thực: Giao tiếp WebSocket để phản hồi tức thì
  • Cấu trúc mẫu: Nền tảng sẵn sàng tùy chỉnh cho các dự án phức tạp

Phần cứng cần chuẩn bị

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)

Các bước nhanh

Hãy làm theo các hướng dẫn này theo từng bước:

  • Nếu đây là lần đầu tiên bạn sử dụng ESP32, hãy tham khảo hướng dẫn ESP32 - Cài Đặt Phần Mềm.
  • 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.
thư viện ESP32 webapps của diyables
  • Bạn sẽ được yêu cầu cài đặt một số phụ thuộc thư viện khác.
  • Nhấn Cài đặt tất cả để cài đặt tất cả các phụ thuộc thư viện.
sự phụ thuộc của diyables ESP32 webapps
  • Trên Arduino IDE, hãy vào Tệp Ví dụ DIYables ESP32 WebApps MultipleWebApps ví dụ, hoặc sao chép mã ở trên và dán nó vào trình soạn thảo của Arduino IDE
/* * DIYables WebApp Library - Multiple WebApps Example * * This example demonstrates multiple web apps of the DIYables WebApp library: * - Home page with links to multiple web apps * - Web Monitor: Real-time serial monitoring via WebSocket * - Web Slider: Dual slider control * - Web Joystick: Interactive joystick control * - Web Rotator: Interactive rotatable disc control * - Web Analog Gauge: Professional circular gauge for sensor monitoring * - Web Table: Two-column data table with real-time updates * - Web Plotter: See WebPlotter example for real-time data visualization * * Features: * - Simplified callback system - no manual command parsing needed * - Automatic state synchronization and JSON handling * - All protocol details handled by the library * - Template for hardware control * * Hardware: ESP32 Boards * * Setup: * 1. Update WiFi credentials below * 2. Upload the sketch to your Arduino * 3. Open Serial Monitor to see the IP address * 4. Navigate to the IP address in your web browser */ #include <DIYables_ESP32_Platform.h> #include <DIYablesWebApps.h> // WiFi credentials - UPDATE THESE WITH YOUR NETWORK const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // Create WebApp server and page instances ESP32ServerFactory factory; DIYablesWebAppServer webAppsServer(factory, 80, 81); DIYablesHomePage homePage; DIYablesWebMonitorPage webMonitorPage; DIYablesWebSliderPage webSliderPage; DIYablesWebJoystickPage webJoystickPage(false, 5); // autoReturn=false, sensitivity=5 DIYablesWebRotatorPage webRotatorPage(ROTATOR_MODE_CONTINUOUS); // Continuous rotation mode (0-360°) DIYablesWebAnalogGaugePage webAnalogGaugePage(0.0, 100.0, "%"); // Range: 0-100%, units: % DIYablesWebTablePage webTablePage; // Variables to track states int currentSlider1 = 64; // Slider 1 value (0-255) int currentSlider2 = 128; // Slider 2 value (0-255) int currentJoystickX = 0; // Current joystick X value (-100 to 100) int currentJoystickY = 0; // Current joystick Y value (-100 to 100) int currentRotatorAngle = 0; // Current rotator angle (0-360°) float currentGaugeValue = 50.0; // Current gauge value (0.0-100.0) void setup() { Serial.begin(9600); delay(1000); // TODO: Initialize your hardware pins here Serial.println("DIYables ESP32 WebApp - Multiple Apps Example"); // Add all web applications to the server webAppsServer.addApp(&homePage); webAppsServer.addApp(&webMonitorPage); webAppsServer.addApp(&webSliderPage); webAppsServer.addApp(&webJoystickPage); webAppsServer.addApp(&webRotatorPage); webAppsServer.addApp(&webAnalogGaugePage); webAppsServer.addApp(&webTablePage); // Add more web apps here (e.g., WebPlotter) // Set 404 Not Found page (optional - for better user experience) webAppsServer.setNotFoundPage(DIYablesNotFoundPage()); // Configure table structure (only attribute names, values will be updated dynamically) 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"); // Start the WebApp server if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) { while (1) { Serial.println("Failed to start WebApp server!"); delay(1000); } } setupCallbacks(); } void setupCallbacks() { // Web Monitor callback - echo messages back webMonitorPage.onWebMonitorMessage([](const String& message) { Serial.println("Web Monitor: " + message); webMonitorPage.sendToWebMonitor("Arduino received: " + message); }); // Web Slider callback - handle slider values webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Store the received values currentSlider1 = slider1; currentSlider2 = slider2; // Print slider values (0-255) without String concatenation Serial.print("Slider 1: "); Serial.print(slider1); Serial.print(", Slider 2: "); Serial.println(slider2); // Update table with new slider values using String() conversion webTablePage.sendValueUpdate("Slider 1", String(slider1)); webTablePage.sendValueUpdate("Slider 2", String(slider2)); // TODO: Add your control logic here based on slider values // Examples: // - Control PWM: analogWrite(LED_PIN, slider1); // - Control servos: servo.write(map(slider1, 0, 255, 0, 180)); // - Control motor speed: analogWrite(MOTOR_PIN, slider2); // Update gauge based on slider1 value (map 0-255 to 0-100) 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)); }); // Handle slider value requests webSliderPage.onSliderValueToWeb([]() { webSliderPage.sendToWebSlider(currentSlider1, currentSlider2); }); // Web Joystick callback - handle joystick movement webJoystickPage.onJoystickValueFromWeb([](int x, int y) { // Store the received values currentJoystickX = x; currentJoystickY = y; // Print joystick position values (-100 to +100) Serial.print("Joystick - X: "); Serial.print(x); Serial.print(", Y: "); Serial.println(y); Serial.print(x); Serial.print(", Y: "); Serial.println(y); // Update table with new joystick values webTablePage.sendValueUpdate("Joystick X", String(x)); webTablePage.sendValueUpdate("Joystick Y", String(y)); // TODO: Add your control logic here based on joystick position // Examples: // - Control motors: if (x > 50) { /* move right */ } // - Control servos: servo.write(map(y, -100, 100, 0, 180)); // - Control LEDs: analogWrite(LED_PIN, map(abs(x), 0, 100, 0, 255)); }); // Handle joystick values requests (when web page loads/reconnects) webJoystickPage.onJoystickValueToWeb([]() { webJoystickPage.sendToWebJoystick(currentJoystickX, currentJoystickY); }); // Web Rotator callback - handle rotation angle changes webRotatorPage.onRotatorAngleFromWeb([](float angle) { // Store the received angle currentRotatorAngle = (int)angle; // Print rotator angle (0-360°) Serial.println("Rotator angle: " + String(angle) + "°"); // Update table with new rotator angle webTablePage.sendValueUpdate("Rotator Angle", String(angle, 0) + "°"); // TODO: Add your control logic here based on rotator angle // Examples: // - Control servo: servo.write(map(angle, 0, 360, 0, 180)); // - Control stepper motor: stepper.moveTo(angle); // - Control directional LED strip: setLEDDirection(angle); }); // Handle analog gauge value requests (when web page loads/reconnects) webAnalogGaugePage.onGaugeValueRequest([]() { webAnalogGaugePage.sendToWebAnalogGauge(currentGaugeValue); }); // Handle table data requests (when web page loads/reconnects) webTablePage.onTableValueRequest([]() { // Send initial values to the table 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() { // Handle WebApp server communications webAppsServer.loop(); // Update table with current uptime every 5 seconds 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); } // Simulate sensor data updates every 3 seconds static unsigned long lastSensorUpdate = 0; if (millis() - lastSensorUpdate > 3000) { lastSensorUpdate = millis(); // Simulate a sensor reading that varies over time float sensorValue = 50.0 + 30.0 * sin(millis() / 10000.0); // Oscillates between 20-80 currentGaugeValue = sensorValue; // Update gauge and table webAnalogGaugePage.sendToWebAnalogGauge(currentGaugeValue); webTablePage.sendValueUpdate("Gauge Value", String(currentGaugeValue, 1) + "%"); } // TODO: Add your main application code here delay(10); }
  • Cấu hình thông tin đăng nhập WiFi trong mã bằng cách cập nhật các dòng này:
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
  • Nhấp vào nút Tải lên trên Arduino IDE để tải mã lên ESP32
  • Mở Serial Monitor
  • Kiểm tra kết quả trên Serial Monitor. Nó trông như hình dưới đây
COM6
Send
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 ==========================================
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • 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:
trang chủ webapp ESP32 diyables với nhiều ứng dụng web
  • 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.

Điều hướng giao diện Web

Bảng điều khiển trang chủ

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

Các URL của ứng dụng

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

Tùy biến sáng tạo - Khơi dậy sự đổi mới của bạn

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.

Cấu hình chân kỹ thuật số

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:

Các pin đầu ra (có thể điều khiển qua Web)

webDigitalPinsPage.enablePin(2, WEB_PIN_OUTPUT); // General purpose output webDigitalPinsPage.enablePin(3, WEB_PIN_OUTPUT); // General purpose output webDigitalPinsPage.enablePin(4, WEB_PIN_OUTPUT); // General purpose output webDigitalPinsPage.enablePin(13, WEB_PIN_OUTPUT); // Built-in LED

Các chân đầu vào (được giám sát qua Web)

webDigitalPinsPage.enablePin(8, WEB_PIN_INPUT); // Sensor input webDigitalPinsPage.enablePin(9, WEB_PIN_INPUT); // Switch input

Cấu hình Joystick

// Create joystick with custom settings // autoReturn=false: Joystick stays at last position when released // sensitivity=5: Only send updates when movement > 5% DIYablesWebJoystickPage webJoystickPage(false, 5);

Các biến trạng thái

Ví dụ duy trì trạng thái đồng bộ trên tất cả các giao diện:

int pinStates[16] = { LOW }; // Track pin states (pins 0-13) int currentSlider1 = 64; // Slider 1 value (0-255) - 25% int currentSlider2 = 128; // Slider 2 value (0-255) - 50% int currentJoystickX = 0; // Joystick X value (-100 to 100) int currentJoystickY = 0; // Joystick Y value (-100 to 100)

Các lệnh trò chuyện tích hợp sẵn

Giao diện trò chuyện bao gồm một số lệnh được lập trình sẵn:

Các Lệnh Cơ Bả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

Các lệnh điều khiển

  • led on - Bật đèn LED tích hợp
  • led off - Tắt đèn LED tích hợp

Phiên trò chuyện ví dụ

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

Ví dụ tích hợp lập trình

Hệ thống điều khiển robot hoàn chỉnh

#include <Servo.h> // Hardware definitions 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() { // Initialize hardware panServo.attach(SERVO_PAN); tiltServo.attach(SERVO_TILT); pinMode(MOTOR_LEFT_PWM, OUTPUT); pinMode(MOTOR_RIGHT_PWM, OUTPUT); // ... WebApp setup code ... setupRobotCallbacks(); } void setupRobotCallbacks() { // Use joystick for robot movement webJoystickPage.onJoystickValueFromWeb([](int x, int y) { // Convert joystick to tank drive int leftSpeed = y + (x / 2); int rightSpeed = y - (x / 2); leftSpeed = constrain(leftSpeed, -100, 100); rightSpeed = constrain(rightSpeed, -100, 100); // Apply speed limits from sliders leftSpeed = map(leftSpeed, -100, 100, -currentSlider1, currentSlider1); rightSpeed = map(rightSpeed, -100, 100, -currentSlider1, currentSlider1); // Control motors analogWrite(MOTOR_LEFT_PWM, abs(leftSpeed)); analogWrite(MOTOR_RIGHT_PWM, abs(rightSpeed)); Serial.println("Robot - Left: " + String(leftSpeed) + ", Right: " + String(rightSpeed)); }); // Use sliders for camera pan/tilt control webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Slider 1 controls maximum speed, Slider 2 controls camera tilt 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) + "°"); }); // Use digital pins for special functions webDigitalPinsPage.onPinWrite([](int pin, int state) { switch (pin) { case 2: // Headlights digitalWrite(pin, state); Serial.println("Headlights " + String(state ? "ON" : "OFF")); break; case 3: // Horn/Buzzer if (state) { // Trigger buzzer sequence digitalWrite(pin, HIGH); delay(200); digitalWrite(pin, LOW); } break; case 4: // Emergency stop if (state) { analogWrite(MOTOR_LEFT_PWM, 0); analogWrite(MOTOR_RIGHT_PWM, 0); Serial.println("EMERGENCY STOP ACTIVATED"); } break; } }); // Enhanced chat commands for robot control 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; } // Default response for unknown commands chatPage.sendToChat("Robot commands: stop, center camera, speed"); }); }

Hệ thống điều khiển nhà thông minh

// Home automation pin assignments 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() { // Configure home automation pins 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); // Digital pins for room lighting control 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")); // Send notification to chat String message = room + " lights turned " + String(state ? "ON" : "OFF"); chatPage.sendToChat(message); }); // Sliders for fan and AC control webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Slider 1 controls fan speed (0-255) analogWrite(FAN_CONTROL, slider1); // Slider 2 controls AC intensity (0-255) analogWrite(AC_CONTROL, slider2); Serial.println("Fan: " + String(map(slider1, 0, 255, 0, 100)) + "%, " + "AC: " + String(map(slider2, 0, 255, 0, 100)) + "%"); }); // Enhanced chat commands for home control 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; } // Default home automation help chatPage.sendToChat("Home commands: all lights on/off, temperature, security"); }); } void loop() { server.loop(); // Monitor home security sensors static bool lastMotion = false; static bool lastDoor = false; bool currentMotion = digitalRead(MOTION_SENSOR); bool currentDoor = digitalRead(DOOR_SENSOR); // Send alerts for security events 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); }

Dự án Khoa học Giáo dục

// Science experiment control system 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() { // Sliders for temperature and stirring control webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Slider 1 controls target temperature (mapped to heating/cooling) int targetTemp = map(slider1, 0, 255, 20, 80); // 20-80°C range // Slider 2 controls stirrer speed analogWrite(STIRRER_MOTOR, slider2); // Simple temperature control logic int currentTemp = readTemperature(); if (currentTemp < targetTemp) { analogWrite(HEATING_ELEMENT, 200); // Heat on analogWrite(COOLING_FAN, 0); // Fan off } else if (currentTemp > targetTemp + 2) { analogWrite(HEATING_ELEMENT, 0); // Heat off analogWrite(COOLING_FAN, 255); // Fan on } else { analogWrite(HEATING_ELEMENT, 0); // Both off (maintain) analogWrite(COOLING_FAN, 0); } Serial.println("Target: " + String(targetTemp) + "°C, Current: " + String(currentTemp) + "°C"); }); // Chat interface for experiment control and data 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) { // Begin experiment sequence chatPage.sendToChat("🔬 Experiment started! Monitoring conditions..."); return; } if (msg.indexOf("stop") >= 0) { // Emergency stop 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"); }); // Monitor for automatic data logging 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() { // Read temperature sensor (example implementation) int sensorValue = analogRead(TEMP_SENSOR_PIN); return map(sensorValue, 0, 1023, 0, 100); // Convert to temperature } float readPH() { // Read pH sensor (example implementation) int sensorValue = analogRead(PH_SENSOR_PIN); return map(sensorValue, 0, 1023, 0, 14) / 10.0; // Convert to pH }

Kỹ thuật tích phân nâng cao

Đồng bộ trạng thái

void synchronizeAllStates() { // Ensure all interfaces show current state webSliderPage.sendToWebSlider(currentSlider1, currentSlider2); webJoystickPage.sendToWebJoystick(currentJoystickX, currentJoystickY); // Update all pin states for (int pin = 0; pin <= 13; pin++) { if (webDigitalPinsPage.isPinEnabled(pin)) { webDigitalPinsPage.updatePinState(pin, pinStates[pin]); } } Serial.println("All interface states synchronized"); }

Giao tiếp giữa các giao diện

void setupCrossInterfaceCommunication() { // Joystick position affects slider maximum values webJoystickPage.onJoystickValueFromWeb([](int x, int y) { // Calculate distance from center float distance = sqrt(x*x + y*y); // Limit slider maximum based on joystick distance if (distance > 50) { // Reduce maximum slider values when joystick is far from center int maxValue = map(distance, 50, 100, 255, 128); // You could implement dynamic slider limiting here } }); // Pin states affect available chat commands 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"); } }); }

Khắc phục sự cố

Các vấn đề phổ biến

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
  1. 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ụ

Chiến lược gỡ lỗi

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("========================"); }

Các mẫu dự án

Mẫu điều khiển công nghiệp

  • Các chân số kỹ thuật số cho điều khiển máy móc
  • Các thanh trượt để điều khiển tốc độ/nhiệt độ
  • Joystick cho các hệ thống định vị
  • Trò chuyện cho báo cáo trạng thái và lệnh
  • Màn hình để ghi dữ liệu

Mẫu Phòng thí nghiệm Giáo dục

  • Các thanh trượt cho tham số thí nghiệm
  • Các chân số để điều khiển thiết bị
  • Trò chuyện cho sinh viên tương tác
  • Màn hình để thu thập dữ liệu
  • Giám sát cảm biến thời gian thực

Mẫu tự động hóa gia đình

  • Các chân số để điều khiển chiếu sáng và thiết bị.
  • Các thanh trượt để điều chỉnh độ sáng và kiểm soát khí hậu.
  • Giám sát an ninh thông qua các chân đầu vào.
  • Chat cho các lệnh bằng giọng nói.
  • Giám sát trạng thái hệ thống và ghi log.

Mẫu Phát triển Robot

  • Joystick để điều khiển chuyển động
  • Các thanh trượt để điều chỉnh tốc độ và vị trí của servo
  • Các chân số cho tín hiệu từ cảm biến
  • Chat cho giao diện lệnh
  • Màn hình để gỡ lỗi và thu thập dữ liệu từ xa

Tối ưu hóa Hiệu Suất

Quản lý bộ nhớ

void optimizeMemoryUsage() { // Disable unused interfaces to save memory // server.addApp(&homePage); // Always keep home page // server.addApp(&webMonitorPage); // Keep for debugging // server.addApp(&chatPage); // Optional // server.addApp(&webDigitalPinsPage); // Based on project needs // server.addApp(&webSliderPage); // Based on project needs // server.addApp(&webJoystickPage); // Based on project needs }

Điều khiển tần suất cập nhật

void controlUpdateFrequency() { static unsigned long lastSlowUpdate = 0; static unsigned long lastFastUpdate = 0; // Fast updates for critical controls (10ms) if (millis() - lastFastUpdate > 10) { // Update joystick and emergency controls lastFastUpdate = millis(); } // Slow updates for monitoring (1000ms) if (millis() - lastSlowUpdate > 1000) { // Update sensor readings and status lastSlowUpdate = millis(); } }

Các bước tiếp theo

Sau khi làm chủ ví dụ MultipleWebApps:

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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

Hỗ trợ

Để đượ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!