ESP32 Bluetooth Joystick Example Hướng Dẫn Giao Diện Điều Khiển 2D Tương Tác
Tổng Quan
Ví dụ Bluetooth Joystick cung cấp bộ điều khiển joystick 2D tương tác có thể truy cập thông qua ứng dụng DIYables Bluetooth STEM. Được thiết kế cho board ESP32 với hỗ trợ cả BLE (Bluetooth Low Energy) và Classic Bluetooth. Joystick gửi giá trị tọa độ X và Y theo thời gian thực từ -100 đến +100, lý tưởng cho điều khiển robot, điều khiển động cơ, định vị servo và bất kỳ ứng dụng nào cần đầu vào hướng.
Ví dụ này hỗ trợ hai chế độ Bluetooth:
ESP32 BLE (Bluetooth Low Energy): Hoạt động trên cả Android và iOS
ESP32 Classic Bluetooth: Chỉ hoạt động trên Android. iOS không hỗ trợ Classic Bluetooth. Sử dụng BLE nếu bạn cần hỗ trợ iOS.
Tính Năng
Điều Khiển 2D: Trục X và Y với giá trị từ -100 đến +100
Cập Nhật Thời Gian Thực: Cập nhật vị trí tức thì qua giao tiếp Bluetooth
Tùy Chọn Tự Động Về Tâm: Có thể cấu hình tự động về vị trí trung tâm (0, 0)
Độ Nhạy Điều Chỉnh: Cấu hình ngưỡng chuyển động tối thiểu để lọc các thay đổi nhỏ
Tương Thích Robot: Giá trị dễ dàng ánh xạ đến đầu vào driver động cơ
BLE & Classic Bluetooth: Chọn chế độ Bluetooth phù hợp với dự án của bạn
Đa Nền Tảng: Chế độ BLE hoạt động trên cả Android và iOS; Classic Bluetooth hoạt động trên Android
Tùy Chọn Tiết Kiệm Điện: Chế độ BLE tiêu thụ ít điện hơn Classic Bluetooth
Kết nối board ESP32 với máy tính của bạn bằng cáp USB.
Mở Arduino IDE trên máy tính.
Chọn board ESP32 và cổng COM phù hợp.
Điều hướng đến biểu tượng Libraries ở thanh bên trái của Arduino IDE.
Tìm kiếm "DIYables Bluetooth", sau đó tìm thư viện DIYables Bluetooth của DIYables
Nhấp nút Install để cài đặt thư viện.
Bạn sẽ được hỏi về việc cài đặt một số thư viện phụ thuộc khác
Nhấp nút Install All để cài đặt tất cả thư viện phụ thuộc.
Chọn một trong hai chế độ Bluetooth dưới đây tùy thuộc vào nhu cầu của bạn:
Code ESP32 Classic Bluetooth (chỉ hoạt động với ứng dụng trên Android)
Lưu ý: Classic Bluetooth KHÔNG được hỗ trợ trên iOS. Nếu bạn cần hỗ trợ iOS, hãy sử dụng code BLE dưới đây.
Trong Arduino IDE, đi đến File Examples DIYables Bluetooth Esp32Bluetooth_Joystick, hoặc sao chép code trên và dán vào trình soạn thảo của Arduino IDE
/* * DIYables Bluetooth Library - ESP32 Classic Bluetooth Joystick Example * Works with DIYables Bluetooth STEM app on Android * Note: Classic Bluetooth is NOT supported on iOS. Use BLE examples for iOS support. * * This example demonstrates the Bluetooth Joystick feature: * - Interactive joystick control via Bluetooth * - Real-time X/Y coordinate values (-100 to +100) * - Control pins based on joystick position * * Compatible Boards: * - ESP32 (all variants with Classic Bluetooth) * - ESP32-WROOM-32 * - ESP32-DevKitC * - ESP32-WROVER * * Note: Select "Huge APP (3MB No OTA/1MB SPIFFS)" partition scheme * in Arduino IDE: Tools > Partition Scheme * * Setup: * 1. Upload the sketch to your ESP32 * 2. Open Serial Monitor (115200 baud) to see connection status * 3. Use DIYables Bluetooth App to connect and control the joystick * * Tutorial: https://diyables.io/bluetooth-app * Author: DIYables */#include <DIYables_BluetoothServer.h>#include <DIYables_BluetoothJoystick.h>#include <platforms/DIYables_Esp32Bluetooth.h>// Create Bluetooth instancesDIYables_Esp32Bluetooth bluetooth("ESP32_Joystick");DIYables_BluetoothServer bluetoothServer(bluetooth);// Create Joystick app instance// Configure with autoReturn=false and sensitivity=5 (minimum 5% change to trigger updates)DIYables_BluetoothJoystick bluetoothJoystick(false, 5);// Variables to store current joystick valuesint currentJoystickX = 0;int currentJoystickY = 0;voidsetup() {Serial.begin(115200);delay(1000);Serial.println("DIYables Bluetooth - ESP32 Joystick Example");// TODO: initialize your hardware pins here// Initialize Bluetooth server with platform-specific implementation bluetoothServer.begin();// Add joystick app to server bluetoothServer.addApp(&bluetoothJoystick);// Set up connection event callbacks bluetoothServer.setOnConnected([]() {Serial.println("Bluetooth connected!"); }); bluetoothServer.setOnDisconnected([]() {Serial.println("Bluetooth disconnected!"); });// Set up joystick callback for position changes bluetoothJoystick.onJoystickValue([](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);// 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: ledcWrite(channel, map(abs(x), 0, 100, 0, 255));// - Send commands to other devices via Serial, I2C, SPI, etc. });// Optional: Handle requests for current joystick values (when app loads) bluetoothJoystick.onGetConfig([]() {// Send the stored joystick values back to the app bluetoothJoystick.send(currentJoystickX, currentJoystickY);Serial.print("App requested values - Sent: X=");Serial.print(currentJoystickX);Serial.print(", Y=");Serial.println(currentJoystickY); });// You can change configuration at runtime:// bluetoothJoystick.setAutoReturn(false); // Disable auto-return// bluetoothJoystick.setSensitivity(10.0); // Only send updates when joystick moves >10% (less sensitive)Serial.println("Waiting for Bluetooth connection...");}voidloop() {// Handle Bluetooth server communications bluetoothServer.loop();// TODO: Add your main application code heredelay(10);}
Nhấp nút Upload trên Arduino IDE để upload code lên ESP32
Mở Serial Monitor
Kiểm tra kết quả trên Serial Monitor. Nó trông như thế này:
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
DIYables Bluetooth - ESP32 Joystick Example
Waiting for Bluetooth connection...
Ln 11, Col 1
ESP32 Dev Module on COM15
2
Code ESP32 BLE (hoạt động với ứng dụng trên cả Android và iOS)
Trong Arduino IDE, đi đến File Examples DIYables Bluetooth Esp32BLE_Joystick, hoặc sao chép code trên và dán vào trình soạn thảo của Arduino IDE
/* * DIYables Bluetooth Library - ESP32 BLE Joystick Example * Works with DIYables Bluetooth STEM app on Android and iOS * * This example demonstrates the Bluetooth Joystick feature: * - Interactive joystick control via Bluetooth * - Real-time X/Y coordinate values (-100 to +100) * - Control pins based on joystick position * * Compatible Boards: * - ESP32-WROOM-32 * - ESP32-DevKitC * - ESP32-WROVER * - ESP32-S3 * - ESP32-C3 * - Any ESP32 board supporting BLE * * Note: Select "Huge APP (3MB No OTA/1MB SPIFFS)" partition scheme * in Arduino IDE: Tools > Partition Scheme * * Setup: * 1. Upload the sketch to your ESP32 * 2. Open Serial Monitor (115200 baud) to see connection status * 3. Use DIYables Bluetooth App to connect and control the joystick * * Tutorial: https://diyables.io/bluetooth-app * Author: DIYables */#include <DIYables_BluetoothServer.h>#include <DIYables_BluetoothJoystick.h>#include <platforms/DIYables_Esp32BLE.h>// BLE Configurationconst char* DEVICE_NAME = "ESP32BLE_Joystick";const char* SERVICE_UUID = "19B10000-E8F2-537E-4F6C-D104768A1214";const char* TX_UUID = "19B10001-E8F2-537E-4F6C-D104768A1214";const char* RX_UUID = "19B10002-E8F2-537E-4F6C-D104768A1214";// Create Bluetooth instancesDIYables_Esp32BLE bluetooth(DEVICE_NAME, SERVICE_UUID, TX_UUID, RX_UUID);DIYables_BluetoothServer bluetoothServer(bluetooth);// Create Joystick app instanceDIYables_BluetoothJoystick bluetoothJoystick(false, 5);// Variables to store current joystick valuesint currentJoystickX = 0;int currentJoystickY = 0;voidsetup() {Serial.begin(115200);delay(1000);Serial.println("DIYables Bluetooth - ESP32 BLE Joystick Example");// Initialize Bluetooth server with platform-specific implementation bluetoothServer.begin();// Add joystick app to server bluetoothServer.addApp(&bluetoothJoystick);// Set up connection event callbacks bluetoothServer.setOnConnected([]() {Serial.println("Bluetooth connected!"); }); bluetoothServer.setOnDisconnected([]() {Serial.println("Bluetooth disconnected!"); });// Set up joystick callback for position changes bluetoothJoystick.onJoystickValue([](int x, int y) { currentJoystickX = x; currentJoystickY = y;Serial.print("Joystick - X: ");Serial.print(x);Serial.print(", Y: ");Serial.println(y);// TODO: Add your control logic here based on joystick position }); bluetoothJoystick.onGetConfig([]() { bluetoothJoystick.send(currentJoystickX, currentJoystickY);Serial.print("App requested values - Sent: X=");Serial.print(currentJoystickX);Serial.print(", Y=");Serial.println(currentJoystickY); });Serial.println("Waiting for Bluetooth connection...");}voidloop() { bluetoothServer.loop();delay(10);}
Nhấp nút Upload trên Arduino IDE để upload code lên ESP32
Mở Serial Monitor
Kiểm tra kết quả trên Serial Monitor. Nó trông như thế này:
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
DIYables Bluetooth - ESP32 BLE Joystick Example
Waiting for Bluetooth connection...
Ln 11, Col 1
ESP32 Dev Module on COM15
2
Ứng Dụng Di Động
Cài đặt ứng dụng DIYables Bluetooth trên smartphone của bạn: Android | iOS
Nếu bạn đang sử dụng code ESP32 Classic Bluetooth, bạn cần ghép nối ESP32 với điện thoại Android trước khi mở ứng dụng:
Đi đến Cài Đặt > Bluetooth trên điện thoại
Đảm bảo Bluetooth đã được bật
Điện thoại của bạn sẽ quét các thiết bị có sẵn
Tìm và nhấn "ESP32_Joystick" trong danh sách thiết bị có sẵn
Xác nhận yêu cầu ghép nối (không cần PIN)
Đợi cho đến khi nó hiển thị "Paired" dưới tên thiết bị
Nếu bạn đang sử dụng code ESP32 BLE, không cần ghép nối. Chỉ cần tiến hành bước tiếp theo.
Mở ứng dụng DIYables Bluetooth
Khi mở ứng dụng lần đầu tiên, nó sẽ yêu cầu quyền. Vui lòng cấp các quyền sau:
Quyền Nearby Devices (Android 12+) / Bluetooth (iOS) - cần thiết để quét và kết nối với thiết bị Bluetooth
Quyền Location (chỉ Android 11 trở xuống) - được yêu cầu bởi các phiên bản Android cũ để quét thiết bị BLE
Đảm bảo Bluetooth đã được bật trên điện thoại của bạn
Trên màn hình chính, nhấn nút Connect. Ứng dụng sẽ quét cả thiết bị BLE và Classic Bluetooth.
Tìm và nhấn thiết bị của bạn trong kết quả quét để kết nối:
Cho Classic Bluetooth: nhấn "ESP32_Joystick"
Cho BLE: nhấn "ESP32BLE_Joystick"
Sau khi kết nối, ứng dụng tự động quay về màn hình chính. Chọn ứng dụng Joystick từ menu ứng dụng.
Lưu ý: Bạn có thể nhấn biểu tượng cài đặt trên màn hình chính để ẩn/hiện các ứng dụng trên màn hình chính. Để biết thêm chi tiết, xem Hướng Dẫn Sử Dụng DIYables Bluetooth App.
Di chuyển joystick theo bất kỳ hướng nào để gửi giá trị tọa độ X/Y
Bây giờ hãy nhìn lại Serial Monitor trên Arduino IDE. Bạn sẽ thấy:
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
Di chuyển joystick trong ứng dụng và xem các giá trị X/Y theo thời gian thực trong Serial Monitor
Tùy Chỉnh Sáng Tạo - Điều Chỉnh Code Cho Dự Án Của Bạn
Cấu Hình Auto-Return và Sensitivity
Thiết lập hành vi joystick với các tham số constructor:
// Tạo instance ứng dụng Joystick// Tham số: autoReturn (bool), sensitivity (float - % thay đổi tối thiểu để kích hoạt cập nhật)DIYables_BluetoothJoystick bluetoothJoystick(false, 5);// Hoặc thay đổi trong thời gian chạy:bluetoothJoystick.setAutoReturn(true); // Bật auto-return về tâmbluetoothJoystick.setSensitivity(10.0); // Chỉ gửi cập nhật khi joystick di chuyển >10%// Đọc cấu hình hiện tại:bool autoReturn = bluetoothJoystick.getAutoReturn();float sensitivity = bluetoothJoystick.getSensitivity();
Xử Lý Thay Đổi Vị Trí Joystick
Sử dụng callback onJoystickValue() để nhận tọa độ X/Y:
bluetoothJoystick.onJoystickValue([](int x, int y) {// x từ -100 (trái) đến +100 (phải)// y từ -100 (xuống) đến +100 (lên)Serial.print("X: ");Serial.print(x);Serial.print(", Y: ");Serial.println(y);// TODO: Thêm logic điều khiển của bạn ở đây});
Xử Lý Yêu Cầu Cấu Hình Từ Ứng Dụng
Khi ứng dụng kết nối và mở màn hình Joystick, nó yêu cầu cấu hình joystick từ ESP32. Bạn có thể sử dụng callback onGetConfig() để gửi giá trị joystick hiện tại cho ứng dụng tại thời điểm đó:
bluetoothJoystick.onGetConfig([]() {// Được gọi khi ứng dụng yêu cầu cấu hình joystick// Gửi giá trị joystick hiện tại để ứng dụng hiển thị đúng bluetoothJoystick.send(currentJoystickX, currentJoystickY);Serial.println("Ứng dụng yêu cầu cấu hình - đã gửi giá trị hiện tại");});
Gửi Giá Trị Đến Ứng Dụng
Bạn có thể gửi giá trị tọa độ joystick từ ESP32 đến ứng dụng:
// Gửi giá trị tọa độ X/Y đến ứng dụngbluetoothJoystick.send(currentJoystickX, currentJoystickY);// Gửi tin nhắn văn bảnbluetoothJoystick.send("Joystick đã được hiệu chỉnh");
Xử Lý Sự Kiện Kết Nối
Bạn có thể phát hiện khi ứng dụng kết nối hoặc ngắt kết nối với ESP32:
// Được gọi khi ứng dụng kết nối với ESP32bluetoothServer.setOnConnected([]() {Serial.println("Bluetooth đã kết nối!"); bluetoothJoystick.send(currentJoystickX, currentJoystickY);});// Được gọi khi ứng dụng ngắt kết nối với ESP32bluetoothServer.setOnDisconnected([]() {Serial.println("Bluetooth đã ngắt kết nối!");// Dừng động cơ khi mất kết nối stopAllMotors();});// Kiểm tra trạng thái kết nối ở bất cứ đâu trong codeif (bluetoothServer.isConnected()) {// Làm gì đó chỉ khi đã kết nối}
Cách Sử Dụng Joystick
Điều Khiển Giao Diện Ứng Dụng
Giao diện joystick trong ứng dụng DIYables Bluetooth cung cấp:
Bảng Joystick Ảo: Chạm và kéo để điều khiển vị trí
Hiển Thị Giá Trị X: Hiển thị vị trí ngang hiện tại (-100 đến +100)
Hiển Thị Giá Trị Y: Hiển thị vị trí dọc hiện tại (-100 đến +100)
Phạm Vi Giá Trị
Joystick cung cấp:
Trục X: -100 (hoàn toàn trái) đến 0 (giữa) đến +100 (hoàn toàn phải)
Trục Y: -100 (hoàn toàn xuống) đến 0 (giữa) đến +100 (hoàn toàn lên)
Vị Trí Trung Tâm: (0, 0) khi joystick ở trạng thái nghỉ
constint MOTOR_LEFT_PWM = 16;constint MOTOR_LEFT_DIR1 = 18;constint MOTOR_LEFT_DIR2 = 19;constint MOTOR_RIGHT_PWM = 17;constint MOTOR_RIGHT_DIR1 = 21;constint MOTOR_RIGHT_DIR2 = 22;voidsetup() {// Cấu hình chân động cơpinMode(MOTOR_LEFT_PWM, OUTPUT);pinMode(MOTOR_LEFT_DIR1, OUTPUT);pinMode(MOTOR_LEFT_DIR2, OUTPUT);pinMode(MOTOR_RIGHT_PWM, OUTPUT);pinMode(MOTOR_RIGHT_DIR1, OUTPUT);pinMode(MOTOR_RIGHT_DIR2, OUTPUT); bluetoothJoystick.onJoystickValue([](int x, int y) {// Differential drive: kết hợp X (rẽ) và Y (tốc độ)int leftSpeed = constrain(y + x, -100, 100);int rightSpeed = constrain(y - x, -100, 100);// Đặt hướng và tốc độ động cơ tráiif (leftSpeed >= 0) {digitalWrite(MOTOR_LEFT_DIR1, HIGH);digitalWrite(MOTOR_LEFT_DIR2, LOW); } else {digitalWrite(MOTOR_LEFT_DIR1, LOW);digitalWrite(MOTOR_LEFT_DIR2, HIGH); }analogWrite(MOTOR_LEFT_PWM, map(abs(leftSpeed), 0, 100, 0, 255));// Đặt hướng và tốc độ động cơ phảiif (rightSpeed >= 0) {digitalWrite(MOTOR_RIGHT_DIR1, HIGH);digitalWrite(MOTOR_RIGHT_DIR2, LOW); } else {digitalWrite(MOTOR_RIGHT_DIR1, LOW);digitalWrite(MOTOR_RIGHT_DIR2, HIGH); }analogWrite(MOTOR_RIGHT_PWM, map(abs(rightSpeed), 0, 100, 0, 255));Serial.print("Trái: ");Serial.print(leftSpeed);Serial.print("%, Phải: ");Serial.print(rightSpeed);Serial.println("%"); });}
Điều Khiển Servo Pan-Tilt
#include <ESP32Servo.h>Servo panServo; // Ngang (trục X)Servo tiltServo; // Dọc (trục Y)constint PAN_PIN = 13;constint TILT_PIN = 14;voidsetup() { panServo.attach(PAN_PIN); tiltServo.attach(TILT_PIN); panServo.write(90); // Vị trí giữa tiltServo.write(90); bluetoothJoystick.onJoystickValue([](int x, int y) {// Ánh xạ giá trị joystick (-100 đến +100) sang góc servo (0 đến 180)int panAngle = map(x, -100, 100, 0, 180);int tiltAngle = map(y, -100, 100, 0, 180); panServo.write(panAngle); tiltServo.write(tiltAngle);Serial.print("Pan: ");Serial.print(panAngle);Serial.print("°, Tilt: ");Serial.print(tiltAngle);Serial.println("°"); });}
Chỉ Thị Hướng LED Matrix
// 4 LED chỉ hướngconstint LED_UP = 16;constint LED_DOWN = 17;constint LED_LEFT = 18;constint LED_RIGHT = 19;constint THRESHOLD = 30; // Giá trị joystick tối thiểu để kích hoạt LEDvoidsetup() {pinMode(LED_UP, OUTPUT);pinMode(LED_DOWN, OUTPUT);pinMode(LED_LEFT, OUTPUT);pinMode(LED_RIGHT, OUTPUT); bluetoothJoystick.onJoystickValue([](int x, int y) {// Bật LED dựa trên hướng joystickdigitalWrite(LED_UP, y > THRESHOLD ? HIGH : LOW);digitalWrite(LED_DOWN, y < -THRESHOLD ? HIGH : LOW);digitalWrite(LED_RIGHT, x > THRESHOLD ? HIGH : LOW);digitalWrite(LED_LEFT, x < -THRESHOLD ? HIGH : LOW);// Hiển thị hướng trong SerialStringdirection = "";if (y > THRESHOLD) direction += "LÊN ";if (y < -THRESHOLD) direction += "XUỐNG ";if (x > THRESHOLD) direction += "PHẢI ";if (x < -THRESHOLD) direction += "TRÁI ";if (direction == "") direction = "GIỮA";Serial.println("Hướng: " + direction); });}
Kỹ Thuật Lập Trình Nâng Cao
Bộ Lọc Dead Zone
constint DEAD_ZONE = 15; // Bỏ qua giá trị joystick trong phạm vi ±15bluetoothJoystick.onJoystickValue([](int x, int y) {// Áp dụng bộ lọc dead zoneint filteredX = (abs(x) > DEAD_ZONE) ? x : 0;int filteredY = (abs(y) > DEAD_ZONE) ? y : 0;// Sử dụng giá trị đã lọc để điều khiển controlMotors(filteredX, filteredY);});
bluetoothJoystick.onJoystickValue([](int x, int y) {// Tính độ lớn (khoảng cách từ tâm, 0-100)float magnitude = sqrt(x * x + y * y); magnitude = constrain(magnitude, 0, 100);// Tính góc theo độ (0° = phải, 90° = lên)float angle = atan2(y, x) * 180.0 / PI;Serial.print("Độ lớn: ");Serial.print(magnitude, 1);Serial.print(", Góc: ");Serial.print(angle, 1);Serial.println("°");// Sử dụng độ lớn cho tốc độ và góc cho hướngintspeed = map((int)magnitude, 0, 100, 0, 255);// Áp dụng vào phần cứng...});