Ví dụ WebSlider cung cấp hai điều khiển slider độc lập có thể truy cập qua trình duyệt web. Được thiết kế cho Arduino Uno R4 WiFi và DIYables STEM V4 IoT - nền tảng giáo dục với khả năng analog nâng cao, tính năng điều khiển chính xác, và các module giáo dục tích hợp để học PWM và điện tử analog. Mỗi slider cung cấp giá trị từ 0-255, làm cho chúng hoàn hảo cho điều khiển PWM, điều chỉnh độ sáng, điều khiển tốc độ động cơ, và bất kỳ ứng dụng nào yêu cầu giá trị điều khiển tương tự analog.
| 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) | | |
Thực hiện theo các hướng dẫn từng bước:
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 phù hợp (ví dụ: Arduino Uno R4 WiFi) và cổng COM.
Điều hướng đến biểu tượng Libraries ở thanh bên 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.


#include <DIYablesWebApps.h>
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
UnoR4ServerFactory serverFactory;
DIYablesWebAppServer webAppsServer(serverFactory, 80, 81);
DIYablesHomePage homePage;
DIYablesWebSliderPage webSliderPage;
int slider1Value = 64;
int slider2Value = 128;
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("DIYables WebApp - Web Slider Example");
webAppsServer.addApp(&homePage);
webAppsServer.addApp(&webSliderPage);
webAppsServer.setNotFoundPage(DIYablesNotFoundPage());
if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) {
while (1) {
Serial.println("Failed to start WebApp server!");
delay(1000);
}
}
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
Serial.println("Slider 1: " + String(slider1) + ", Slider 2: " + String(slider2));
});
webSliderPage.onSliderValueToWeb([]() {
webSliderPage.sendToWebSlider(slider1Value, slider2Value);
Serial.println("Web client requested values - Sent: Slider1=" + String(slider1Value) + ", Slider2=" + String(slider2Value));
});
}
void loop() {
webAppsServer.loop();
delay(10);
}
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
DIYables WebApp - Web Slider Example
INFO: Added app /
INFO: Added app /web-slider
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 Slider: http://192.168.0.2/web-slider
==========================================
Nếu bạn không thấy gì, hãy khởi động lại bo mạch Arduino.
Ghi nhớ đị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 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:
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-slider. Ví dụ: http://192.168.0.2/web-slider
Thử di chuyển hai slider để điều khiển các giá trị analog (0-255) và quan sát phản hồi thời gian thực trong Serial Monitor.
Cấu hình vị trí ban đầu của slider:
int slider1Value = 64;
int slider2Value = 128;
Giao diện slider cung cấp:
Slider 1: Slider điều khiển đầu tiên với hiển thị giá trị (0-255)
Slider 2: Slider điều khiển thứ hai với hiển thị giá trị (0-255)
Hiển thị Giá trị: Giá trị số thời gian thực cho cả hai slider
Nút Preset: Truy cập nhanh đến các giá trị thông dụng (0%, 25%, 50%, 75%, 100%)
Nhấn và Kéo: Nhấn vào tay cầm slider và kéo để điều chỉnh giá trị
Nhấn Vị trí: Nhấn bất kỳ đâu trên track slider để nhảy đến giá trị đó
Điều khiển Tinh: Sử dụng chuyển động chuột nhỏ để điều chỉnh chính xác
Chạm và Kéo: Chạm tay cầm slider và kéo đến vị trí mới
Chạm Vị trí: Chạm trên track slider để đặt giá trị
Điều khiển Mượt: Kéo bằng ngón tay cung cấp thay đổi giá trị mượt mà
Mỗi slider cung cấp:
Giá trị Tối thiểu: 0 (0% - tắt hoàn toàn)
Giá trị Tối đa: 255 (100% - cường độ tối đa)
Độ phân giải: 256 bước rời rạc (độ chính xác 8-bit)
Tương thích PWM: Sử dụng trực tiếp với hàm analogWrite()
void setup() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
Serial.println("Slider 1: " + String(slider1) + ", Slider 2: " + String(slider2));
});
}
const int LED1_PIN = 9;
const int LED2_PIN = 10;
void setup() {
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
analogWrite(LED1_PIN, slider1Value);
analogWrite(LED2_PIN, slider2Value);
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
analogWrite(LED1_PIN, slider1);
analogWrite(LED2_PIN, slider2);
Serial.println("LED1 Brightness: " + String(slider1) +
", LED2 Brightness: " + String(slider2));
});
}
#include <Servo.h>
Servo servo1, servo2;
void setup() {
servo1.attach(9);
servo2.attach(10);
servo1.write(map(slider1Value, 0, 255, 0, 180));
servo2.write(map(slider2Value, 0, 255, 0, 180));
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
int angle1 = map(slider1, 0, 255, 0, 180);
int angle2 = map(slider2, 0, 255, 0, 180);
servo1.write(angle1);
servo2.write(angle2);
Serial.println("Servo1: " + String(angle1) + "°, Servo2: " + String(angle2) + "°");
});
}
const int MOTOR1_PWM = 9;
const int MOTOR1_DIR1 = 2;
const int MOTOR1_DIR2 = 3;
const int MOTOR2_PWM = 10;
const int MOTOR2_DIR1 = 4;
const int MOTOR2_DIR2 = 5;
void setup() {
pinMode(MOTOR1_PWM, OUTPUT);
pinMode(MOTOR1_DIR1, OUTPUT);
pinMode(MOTOR1_DIR2, OUTPUT);
pinMode(MOTOR2_PWM, OUTPUT);
pinMode(MOTOR2_DIR1, OUTPUT);
pinMode(MOTOR2_DIR2, OUTPUT);
digitalWrite(MOTOR1_DIR1, HIGH);
digitalWrite(MOTOR1_DIR2, LOW);
digitalWrite(MOTOR2_DIR1, HIGH);
digitalWrite(MOTOR2_DIR2, LOW);
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
analogWrite(MOTOR1_PWM, slider1);
analogWrite(MOTOR2_PWM, slider2);
int speed1Percent = map(slider1, 0, 255, 0, 100);
int speed2Percent = map(slider2, 0, 255, 0, 100);
Serial.println("Motor1: " + String(speed1Percent) + "%, " +
"Motor2: " + String(speed2Percent) + "%");
});
}
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;
void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
int redValue = slider1;
int blueValue = slider2;
int greenValue = (slider1 + slider2) / 2;
analogWrite(RED_PIN, redValue);
analogWrite(GREEN_PIN, greenValue);
analogWrite(BLUE_PIN, blueValue);
Serial.println("RGB - R:" + String(redValue) +
" G:" + String(greenValue) +
" B:" + String(blueValue));
});
}
class SliderSmoother {
private:
int currentValue = 0;
int targetValue = 0;
unsigned long lastUpdate = 0;
const int SMOOTH_RATE = 5;
public:
void setTarget(int target) {
targetValue = target;
}
int getCurrentValue() {
return currentValue;
}
bool update() {
if (millis() - lastUpdate > 10) {
bool changed = false;
if (currentValue < targetValue) {
currentValue = min(currentValue + SMOOTH_RATE, targetValue);
changed = true;
} else if (currentValue > targetValue) {
currentValue = max(currentValue - SMOOTH_RATE, targetValue);
changed = true;
}
lastUpdate = millis();
return changed;
}
return false;
}
};
SliderSmoother smoother1, smoother2;
void setup() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
smoother1.setTarget(slider1);
smoother2.setTarget(slider2);
});
}
void loop() {
server.loop();
bool changed1 = smoother1.update();
bool changed2 = smoother2.update();
if (changed1 || changed2) {
analogWrite(9, smoother1.getCurrentValue());
analogWrite(10, smoother2.getCurrentValue());
}
}
void setupThresholdControl() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
const int LOW_THRESHOLD = 85;
const int MEDIUM_THRESHOLD = 170;
if (slider1 < LOW_THRESHOLD) {
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
} else if (slider1 < MEDIUM_THRESHOLD) {
digitalWrite(2, HIGH);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
} else {
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
}
analogWrite(9, slider2);
});
}
const int PRESETS[][2] = {
{0, 0},
{64, 128},
{128, 128},
{255, 128},
{255, 255}
};
void applyPreset(int presetNumber) {
if (presetNumber >= 0 && presetNumber < 5) {
slider1Value = PRESETS[presetNumber][0];
slider2Value = PRESETS[presetNumber][1];
analogWrite(9, slider1Value);
analogWrite(10, slider2Value);
webSliderPage.sendToWebSlider(slider1Value, slider2Value);
Serial.println("Applied preset " + String(presetNumber) +
": " + String(slider1Value) + ", " + String(slider2Value));
}
}
void setupPresetSystem() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
analogWrite(9, slider1);
analogWrite(10, slider2);
});
}
void loop() {
server.loop();
static bool lastButton = false;
bool currentButton = digitalRead(7);
if (currentButton && !lastButton) {
static int currentPreset = 0;
applyPreset(currentPreset);
currentPreset = (currentPreset + 1) % 5;
}
lastButton = currentButton;
}
const int LED_STRIP_PIN = 6;
const int NUM_LEDS = 30;
void setupLEDStrip() {
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
uint8_t brightness = slider1;
uint8_t hue = slider2;
Serial.println("LED Strip - Brightness: " + String(brightness) +
", Hue: " + String(hue));
});
}
const int FAN1_PIN = 9;
const int FAN2_PIN = 10;
void setupFanControl() {
pinMode(FAN1_PIN, OUTPUT);
pinMode(FAN2_PIN, OUTPUT);
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
int fan1Speed = (slider1 > 50) ? map(slider1, 50, 255, 100, 255) : 0;
int fan2Speed = (slider2 > 50) ? map(slider2, 50, 255, 100, 255) : 0;
analogWrite(FAN1_PIN, fan1Speed);
analogWrite(FAN2_PIN, fan2Speed);
Serial.println("Fan1: " + String(map(fan1Speed, 0, 255, 0, 100)) + "%, " +
"Fan2: " + String(map(fan2Speed, 0, 255, 0, 100)) + "%");
});
}
const int VOLUME1_PIN = 9;
const int VOLUME2_PIN = 10;
void setupAudioControl() {
pinMode(VOLUME1_PIN, OUTPUT);
pinMode(VOLUME2_PIN, OUTPUT);
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
slider1Value = slider1;
slider2Value = slider2;
float volume1 = pow(slider1 / 255.0, 2) * 255;
float volume2 = pow(slider2 / 255.0, 2) * 255;
analogWrite(VOLUME1_PIN, (int)volume1);
analogWrite(VOLUME2_PIN, (int)volume2);
Serial.println("Volume1: " + String((int)volume1) +
", Volume2: " + String((int)volume2));
});
}
1. Sliders không phản hồi
Kiểm tra kết nối WebSocket trong console của trình duyệt
Xác minh kết nối mạng giữa thiết bị và Arduino
Refresh trang trình duyệt để reset kết nối
Kiểm tra Serial Monitor để tìm lỗi kết nối
2. Giá trị không đạt phạm vi đầy đủ
Xác minh cài đặt phạm vi slider trong giao diện web
Kiểm tra vấn đề ánh xạ giá trị trong hàm callback
Kiểm tra với các trình duyệt hoặc thiết bị khác nhau
3. Điều khiển giật hoặc không ổn định
Triển khai làm mịn giá trị cho thay đổi dần dần
Kiểm tra vấn đề độ trễ mạng
Thêm debouncing cho thay đổi giá trị nhanh
4. Output PWM không hoạt động
Xác minh chân hỗ trợ PWM (kiểm tra sơ đồ chân Arduino)
Đảm bảo analogWrite() được gọi với số chân chính xác
Kiểm tra kết nối phần cứng và yêu cầu tải