Arduino WebPlotter Example Hướng dẫn Trực quan hóa Dữ liệu Thời gian Thực

Tổng quan

Ví dụ WebPlotter tạo ra một giao diện trực quan hóa dữ liệu thời gian thực có thể truy cập qua bất kỳ trình duyệt web nào. Được thiết kế cho Arduino Uno R4 WiFi và nền tảng giáo dục DIYables STEM V4 IoT với khả năng xử lý dữ liệu nâng cao, tính năng vẽ biểu đồ thời gian thực và tích hợp liền mạch với hệ thống giám sát cảm biến. Hoàn hảo cho việc trực quan hóa dữ liệu cảm biến, debug thuật toán hoặc giám sát hiệu suất hệ thống theo thời gian thực.

Arduino webplotter example - hướng dẫn trực quan hóa dữ liệu thời gian thực

Tính năng

  • Vẽ biểu đồ dữ liệu thời gian thực: Trực quan hóa dữ liệu cảm biến khi nó được truyền từ Arduino
  • Nhiều chuỗi dữ liệu: Vẽ biểu đồ tối đa 8 luồng dữ liệu khác nhau đồng thời
  • Tự động điều chỉnh tỷ lệ: Tự động điều chỉnh tỷ lệ trục Y dựa trên phạm vi dữ liệu
  • Giao diện tương tác: Zoom, pan và phân tích xu hướng dữ liệu
  • Truyền thông WebSocket: Cập nhật tức thì với độ trễ tối thiểu
  • Thiết kế responsive: Hoạt động trên desktop, tablet và thiết bị di động
  • Cấu hình có thể tùy chỉnh: Tiêu đề biểu đồ, nhãn trục và phạm vi có thể điều chỉnh
  • Mở rộng nền tảng: Hiện được triển khai cho Arduino Uno R4 WiFi, nhưng có thể mở rộng cho các nền tảng phần cứng khác. Xem DIYables_WebApps_ESP32

Phần cứng cần thiết

1×Arduino UNO R4 WiFi
1×Alternatively, DIYables STEM V4 IoT
1×(Tùy chọn) DIYables STEM V4 IoT
1×Cáp USB Type-C
1×(Khuyến nghị) Screw Terminal Block Shield for Arduino UNO R4
1×(Khuyến nghị) Breadboard Shield for Arduino UNO R4
1×(Khuyến nghị) Enclosure for Arduino UNO R4
1×(Khuyến nghị) Power Splitter for Arduino UNO R4
1×(Khuyến nghị) Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables STEM V4 IoT Starter Kit (Arduino included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)

Hướng dẫn thiết lập

Các bước nhanh

Làm theo các hướng dẫn này từng bước một:

  • Nếu đây là lần đầu tiên bạn sử dụng Arduino Uno R4 WiFi/DIYables STEM V4 IoT, hãy tham khảo hướng dẫn về Arduino UNO R4 - Cài Đặt Phần Mềm.
  • Kết nối bo mạch Arduino Uno R4/DIYables STEM V4 IoT với máy tính của bạn bằng cáp USB.
  • Khởi động Arduino IDE trên máy tính của bạn.
  • Chọn bo mạch Arduino Uno R4 thích hợp (ví dụ: Arduino Uno R4 WiFi) và cổng COM.
  • Điều hướng đến biểu tượng Libraries trên thanh trái của Arduino IDE.
  • Tìm kiếm "DIYables WebApps", sau đó tìm thư viện DIYables WebApps của DIYables
  • Nhấn nút Install để cài đặt thư viện.
thư viện Arduino UNO R4 diyables webapps
  • Bạn sẽ được yêu cầu cài đặt một số thư viện phụ thuộc khác
  • Nhấn nút Install All để cài đặt tất cả các thư viện phụ thuộc.
thư viện phụ thuộc Arduino UNO R4 diyables webapps
  • Trên Arduino IDE, vào File Examples DIYables WebApps WebPlotter example, hoặc sao chép code trên và dán vào editor của Arduino IDE
/* * DIYables WebApp Library - Web Plotter Example * * This example demonstrates the Web Plotter feature: * - Real-time data visualization * - Multiple data series support * - Auto-scaling Y-axis * - Responsive web interface * - WebSocket communication for instant updates * * Hardware: Arduino Uno R4 WiFi or DIYables STEM V4 IoT * * 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 http://[IP_ADDRESS]/webplotter */ #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 UnoR4ServerFactory serverFactory; DIYablesWebAppServer webAppsServer(serverFactory, 80, 81); DIYablesHomePage homePage; DIYablesWebPlotterPage webPlotterPage; // Simulation variables unsigned long lastDataTime = 0; const unsigned long DATA_INTERVAL = 1000; // Send data every 1000ms float timeCounter = 0; void setup() { Serial.begin(9600); delay(1000); // TODO: Initialize your hardware pins and sensors here Serial.println("DIYables WebApp - Web Plotter Example"); // Add home and web plotter pages webAppsServer.addApp(&homePage); webAppsServer.addApp(&webPlotterPage); // Optional: Add 404 page for better user experience webAppsServer.setNotFoundPage(DIYablesNotFoundPage()); // Configure the plotter webPlotterPage.setPlotTitle("Real-time Data Plotter"); webPlotterPage.setAxisLabels("Time (s)", "Values"); webPlotterPage.enableAutoScale(true); webPlotterPage.setMaxSamples(50); // Start the WebApp server if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) { while (1) { Serial.println("Failed to start WebApp server!"); delay(1000); } } // Set up callbacks webPlotterPage.onPlotterDataRequest([]() { Serial.println("Web client requested data"); sendSensorData(); }); Serial.println("\nWebPlotter is ready!"); Serial.println("Usage Instructions:"); Serial.println("1. Connect to the WiFi network"); Serial.println("2. Open your web browser"); Serial.println("3. Navigate to the Arduino's IP address"); Serial.println("4. Click on 'Web Plotter' to view real-time data"); Serial.println("\nGenerating simulated sensor data..."); } void loop() { // Handle web server and WebSocket connections webAppsServer.loop(); // Send sensor data at regular intervals if (millis() - lastDataTime >= DATA_INTERVAL) { lastDataTime = millis(); sendSensorData(); timeCounter += DATA_INTERVAL / 1000.0; // Convert to seconds } } void sendSensorData() { // Generate simulated sensor data // In a real application, replace these with actual sensor readings // Simulated temperature sensor (sine wave with noise) float temperature = 25.0 + 5.0 * sin(timeCounter * 0.5) + random(-100, 100) / 100.0; // Simulated humidity sensor (cosine wave) float humidity = 50.0 + 20.0 * cos(timeCounter * 0.3); // Simulated light sensor (triangle wave) float light = 512.0 + 300.0 * (2.0 * abs(fmod(timeCounter * 0.2, 2.0) - 1.0) - 1.0); // Simulated analog pin reading float analogValue = analogRead(A0); // Send data using different methods: // Method 1: Send individual values (uncomment to use) // webPlotterPage.sendPlotData(temperature); // Method 2: Send multiple values at once webPlotterPage.sendPlotData(temperature, humidity, light / 10.0, analogValue / 100.0); // Method 3: Send array of values (alternative approach) // float values[] = {temperature, humidity, light / 10.0, analogValue / 100.0}; // webPlotterPage.sendPlotData(values, 4); // Method 4: Send raw data string (for custom formatting) // String dataLine = String(temperature, 2) + " " + String(humidity, 1) + " " + String(light / 10.0, 1); // webPlotterPage.sendPlotData(dataLine); // Print to Serial Monitor in Serial Plotter compatible format // Format: Temperature Humidity Light Analog (tab-separated for Serial Plotter) Serial.print(temperature, 1); Serial.print("\t"); Serial.print(humidity, 1); Serial.print("\t"); Serial.print(light / 10.0, 1); Serial.print("\t"); Serial.println(analogValue / 100.0, 2); }
  • Cấu hình thông tin đăng nhập WiFi trong code 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ấn nút Upload trên Arduino IDE để tải code lên Arduino UNO R4/DIYables STEM V4 IoT
  • Mở Serial Monitor
  • Kiểm tra kết quả trên Serial Monitor. Nó sẽ giống như bên dưới
COM6
Send
DIYables WebApp - Web Plotter Example INFO: Added app / INFO: Added app /web-plotter DIYables WebApp Library Platform: Arduino Uno R4 WiFi 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 Plotter: http://192.168.0.2/web-plotter ==========================================
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • Nếu bạn không thấy gì cả, hãy khởi động lại bo mạch Arduino.
  • Ghi lại địa chỉ IP được hiển thị và nhập địa chỉ này vào thanh địa chỉ của trình duyệt web trên smartphone hoặc PC của bạn.
  • Ví dụ: http://192.168.0.2
  • Bạn sẽ thấy trang chủ như hình dưới đây:
trang chủ Arduino UNO R4 diyables webapp với ứng dụng web plotter
  • Nhấp vào liên kết Web Plotter, bạn sẽ thấy giao diện người dùng của ứng dụng Web Plotter như bên dưới:
Ứng dụng web plotter Arduino UNO R4 diyables webapp
  • Hoặc bạn cũng có thể truy cập trang trực tiếp bằng địa chỉ IP theo sau bởi /web-plotter. Ví dụ: http://192.168.0.2/web-plotter
  • Quan sát khi Arduino tạo ra dữ liệu cảm biến mô phỏng và vẽ biểu đồ theo thời gian thực. Bạn sẽ thấy nhiều đường màu khác nhau đại diện cho các luồng dữ liệu khác nhau.

Tùy chỉnh sáng tạo - Trực quan hóa dữ liệu của bạn một cách sáng tạo

Biến đổi giao diện vẽ biểu đồ để phù hợp với yêu cầu dự án độc đáo của bạn và tạo ra những trực quan hóa dữ liệu tuyệt đẹp:

Cấu hình nguồn dữ liệu

Thay thế dữ liệu mô phỏng bằng số đọc cảm biến thực tế:

Phương pháp 1: Đọc một cảm biến

void sendTemperatureData() { float temperature = analogRead(A0) * (5.0 / 1023.0) * 100; // Cảm biến nhiệt độ LM35 webPlotterPage.sendPlotData(temperature); }

Phương pháp 2: Nhiều cảm biến

void sendMultipleSensors() { float temperature = readTemperature(); float humidity = readHumidity(); float light = analogRead(A1) / 10.0; float pressure = readPressure(); webPlotterPage.sendPlotData(temperature, humidity, light, pressure); }

Phương pháp 3: Mảng giá trị

void sendSensorArray() { float sensors[6] = { analogRead(A0) / 10.0, // Cảm biến 1 analogRead(A1) / 10.0, // Cảm biến 2 analogRead(A2) / 10.0, // Cảm biến 3 digitalRead(2) * 50, // Trạng thái digital millis() / 1000.0, // Bộ đếm thời gian random(0, 100) // Dữ liệu ngẫu nhiên }; webPlotterPage.sendPlotData(sensors, 6); }

Tùy chỉnh biểu đồ

Tùy chỉnh giao diện biểu đồ

void setupCustomPlot() { webPlotterPage.setPlotTitle("Trạm Giám sát Môi trường"); webPlotterPage.setAxisLabels("Thời gian (phút)", "Số đọc cảm biến"); webPlotterPage.setYAxisRange(0, 100); // Phạm vi trục Y cố định webPlotterPage.setMaxSamples(100); // Hiển thị nhiều điểm dữ liệu hơn }

Cấu hình động

void setupDynamicPlot() { webPlotterPage.setPlotTitle("Giám sát Vườn Thông minh"); webPlotterPage.setAxisLabels("Mẫu #", "Giá trị"); webPlotterPage.enableAutoScale(true); // Tự động điều chỉnh trục Y // Cấu hình callbacks cho các tính năng tương tác webPlotterPage.onPlotterDataRequest([]() { Serial.println("Client đã kết nối - đang gửi dữ liệu ban đầu"); sendInitialDataBurst(); }); }

Xử lý dữ liệu nâng cao

Bộ lọc trung bình trượt

float movingAverage(float newValue) { static float readings[10]; static int index = 0; static float total = 0; total -= readings[index]; readings[index] = newValue; total += readings[index]; index = (index + 1) % 10; return total / 10.0; } void sendFilteredData() { float rawValue = analogRead(A0); float filteredValue = movingAverage(rawValue); webPlotterPage.sendPlotData(rawValue / 10.0, filteredValue / 10.0); }

Ghi log dữ liệu với timestamps

void sendTimestampedData() { unsigned long currentTime = millis() / 1000; float sensorValue = analogRead(A0) / 10.0; // Gửi thời gian và giá trị như các chuỗi dữ liệu riêng biệt webPlotterPage.sendPlotData(currentTime, sensorValue); // Cũng ghi log ra Serial để debug Serial.print("Thời gian: "); Serial.print(currentTime); Serial.print("s, Giá trị: "); Serial.println(sensorValue); }

Ví dụ tích hợp

Giám sát môi trường

#include <DHT.h> #define DHT_PIN 2 #define DHT_TYPE DHT22 DHT dht(DHT_PIN, DHT_TYPE); void sendEnvironmentalData() { float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); float lightLevel = analogRead(A0) / 10.0; if (!isnan(temperature) && !isnan(humidity)) { webPlotterPage.sendPlotData(temperature, humidity, lightLevel); Serial.print("T: "); Serial.print(temperature); Serial.print("°C, H: "); Serial.print(humidity); Serial.print("%, Ánh sáng: "); Serial.println(lightLevel); } }

Phản hồi điều khiển động cơ

void sendMotorData() { int motorSpeed = analogRead(A0); // Biến trở tốc độ int currentDraw = analogRead(A1); // Cảm biến dòng điện int motorPosition = digitalRead(2); // Cảm biến vị trí float speedPercent = (motorSpeed / 1023.0) * 100; float currentAmps = (currentDraw / 1023.0) * 5.0; float positionDegrees = motorPosition * 90; webPlotterPage.sendPlotData(speedPercent, currentAmps, positionDegrees); }

Trực quan hóa bộ điều khiển PID

float setpoint = 50.0; float kp = 1.0, ki = 0.1, kd = 0.01; float integral = 0, previousError = 0; void sendPIDData() { float input = analogRead(A0) / 10.0; float error = setpoint - input; integral += error; float derivative = error - previousError; float output = (kp * error) + (ki * integral) + (kd * derivative); previousError = error; // Vẽ biểu đồ setpoint, input, error và output webPlotterPage.sendPlotData(setpoint, input, error, output); }

Tối ưu hóa hiệu suất

Truyền dữ liệu hiệu quả

unsigned long lastPlotUpdate = 0; const unsigned long PLOT_INTERVAL = 100; // Cập nhật mỗi 100ms void efficientDataSending() { if (millis() - lastPlotUpdate >= PLOT_INTERVAL) { lastPlotUpdate = millis(); // Chỉ gửi dữ liệu trong khoảng thời gian được định nghĩa float value1 = analogRead(A0) / 10.0; float value2 = analogRead(A1) / 10.0; webPlotterPage.sendPlotData(value1, value2); } }

Gửi dữ liệu có điều kiện

float lastSentValue = 0; const float CHANGE_THRESHOLD = 5.0; void sendOnChange() { float currentValue = analogRead(A0) / 10.0; // Chỉ gửi nếu giá trị thay đổi đáng kể if (abs(currentValue - lastSentValue) > CHANGE_THRESHOLD) { webPlotterPage.sendPlotData(currentValue); lastSentValue = currentValue; } }

Ý tưởng dự án

Ứng dụng khoa học

  • Data Logger: Ghi lại nhiệt độ, độ ẩm, áp suất theo thời gian
  • Phân tích rung động: Giám sát dữ liệu accelerometer cho các hệ thống cơ khí
  • Giám sát pH: Theo dõi chất lượng nước trong hệ thống aquaponics
  • Hiệu suất tấm pin mặt trời: Giám sát điện áp/dòng điện ra so với ánh sáng mặt trời

Dự án giáo dục

  • Thí nghiệm vật lý: Trực quan hóa chuyển động con lắc, dao động lò xo
  • Phòng thí nghiệm hóa học: Giám sát tốc độ phản ứng và thay đổi nhiệt độ
  • Nghiên cứu sinh học: Theo dõi cảm biến phát triển thực vật, yếu tố môi trường
  • Toán học: Vẽ biểu đồ hàm số toán học và kết quả thuật toán

Tự động hóa gia đình

  • Giám sát năng lượng: Theo dõi mẫu tiêu thụ điện năng
  • Tự động hóa vườn: Giám sát độ ẩm đất, mức độ ánh sáng
  • Điều khiển HVAC: Trực quan hóa xu hướng nhiệt độ và độ ẩm
  • Hệ thống an ninh: Vẽ biểu đồ hoạt động cảm biến chuyển động

Robot và điều khiển

  • Điều hướng robot: Vẽ biểu đồ dữ liệu vị trí và định hướng
  • Điều khiển động cơ: Giám sát tốc độ, mô-men xoắn và hiệu suất
  • Sensor Fusion: Kết hợp nhiều số đọc cảm biến
  • Quy hoạch đường đi: Trực quan hóa thuật toán di chuyển robot

Khắc phục sự cố

Các vấn đề thường gặp

1. Không có dữ liệu xuất hiện trên biểu đồ

  • Kiểm tra trạng thái kết nối WiFi
  • Xác minh kết nối WebSocket trong console trình duyệt
  • Đảm bảo sendPlotData() đang được gọi thường xuyên
  • Kiểm tra Serial Monitor để tìm thông báo lỗi

2. Biểu đồ xuất hiện giật hoặc bất thường

  • Triển khai lọc dữ liệu (trung bình trượt)
  • Giảm tần suất gửi dữ liệu
  • Kiểm tra nhiễu cảm biến hoặc vấn đề kết nối
  • Xác minh độ ổn định nguồn điện

3. Vấn đề hiệu suất trình duyệt

  • Giảm số mẫu tối đa (setMaxSamples())
  • Giảm tốc độ truyền dữ liệu
  • Đóng các tab trình duyệt khác
  • Sử dụng tăng tốc phần cứng trong trình duyệt

4. Kết nối WebSocket bị ngắt

  • Kiểm tra cường độ tín hiệu WiFi
  • Xác minh cài đặt router (firewall, chặn cổng)
  • Triển khai logic kết nối lại trong code tùy chỉnh
  • Giám sát việc sử dụng bộ nhớ Arduino

Mẹo debug

Bật ghi log chi tiết

void debugPlotterData() { Serial.println("=== Thông tin Debug Plotter ==="); Serial.print("RAM trống: "); Serial.println(freeMemory()); Serial.print("Client đã kết nối: "); Serial.println(server.getConnectedClients()); Serial.print("Tốc độ dữ liệu: "); Serial.println("Mỗi " + String(DATA_INTERVAL) + "ms"); Serial.println("=============================="); }

Tạo dữ liệu thử nghiệm

void generateTestPattern() { static float phase = 0; float sine = sin(phase) * 50 + 50; float cosine = cos(phase) * 30 + 70; float triangle = (phase / PI) * 25 + 25; webPlotterPage.sendPlotData(sine, cosine, triangle); phase += 0.1; if (phase > 2 * PI) phase = 0; }

Tính năng nâng cao

Định dạng dữ liệu tùy chỉnh

void sendFormattedData() { float temp = 25.5; float humidity = 60.3; // Tạo chuỗi dữ liệu định dạng tùy chỉnh String dataLine = String(temp, 1) + "\t" + String(humidity, 1); webPlotterPage.sendPlotData(dataLine); }

Tích hợp với các WebApps khác

void setupMultipleApps() { // Thêm nhiều ứng dụng web server.addApp(new DIYablesHomePage()); server.addApp(new DIYablesWebDigitalPinsPage()); server.addApp(new DIYablesWebSliderPage()); server.addApp(&webPlotterPage); server.addApp(new DIYablesNotFoundPage()); // Cấu hình tương tác giữa các apps webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Sử dụng giá trị slider để điều khiển những gì được vẽ biểu đồ float scaleFactor = slider1 / 255.0; // ... logic vẽ biểu đồ }); }

Điều khiển thời gian thực với vẽ biểu đồ

void controlAndPlot() { // Đọc input điều khiển int targetSpeed = analogRead(A0); // Điều khiển phần cứng analogWrite(9, targetSpeed / 4); // Đầu ra PWM // Đọc phản hồi int actualSpeed = analogRead(A1); int motorCurrent = analogRead(A2); // Vẽ biểu đồ mục tiêu vs thực tế webPlotterPage.sendPlotData( targetSpeed / 4.0, // Tốc độ mục tiêu actualSpeed / 4.0, // Tốc độ thực tế motorCurrent / 10.0 // Lượng dòng tiêu thụ ); }

Các bước tiếp theo

Sau khi thành thạo ví dụ WebPlotter, hãy khám phá:

  1. MultipleWebApps - Kết hợp vẽ biểu đồ với giao diện điều khiển
  2. WebMonitor - Thêm khả năng debugging cùng với vẽ biểu đồ
  3. Ứng dụng tùy chỉnh - Xây dựng công cụ vẽ biểu đồ chuyên dụng của riêng bạn
  4. Phân tích dữ liệu - Triển khai phân tích thống kê dữ liệu được vẽ biểu đồ

Hỗ trợ

Để được trợ giúp thêm:

  • Kiểm tra tài liệu API Reference
  • Truy cập các hướng dẫn DIYables: https://newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-diyables-webapps
  • Diễn đàn cộng đồng Arduino
  • Công cụ debugging WebSocket trong console developer của trình duyệt