Bài 6: joystick → esp-now → drone

Thương hiệu: (Đang cập nhật ...) Loại: (Đang cập nhật ...)

Liên hệ
Bài 6: Joystick → ESP-NOW → Drone → Điều khiển Drone bằng tay cầm Sau khi hoàn thành Bài 5 – ESP-NOW: Giao tiếp 2 ESP32, chúng ta đã xây dựng được đường truyền dữ liệu giữa tay cầm ESP32 và Drone ESP32. Ở bài này, hệ thống sẽ tiến thêm một bước quan trọng: Di chuyển joystick → ESP32 đọc giá ...

Bài 6: Joystick → ESP-NOW → Drone → Điều khiển Drone bằng tay cầm

Sau khi hoàn thành Bài 5 – ESP-NOW: Giao tiếp 2 ESP32, chúng ta đã xây dựng được đường truyền dữ liệu giữa tay cầm ESP32 và Drone ESP32.

Ở bài này, hệ thống sẽ tiến thêm một bước quan trọng:

Di chuyển joystick → ESP32 đọc giá trị → xử lý lệnh → truyền ESP-NOW → Drone nhận lệnh → tạo tín hiệu điều khiển.

Đây chính là bước biến một bộ mạch ESP32 thành hệ thống điều khiển Drone bằng tay cầm.


1. Mục tiêu của Bài 6

Sau bài học, học viên cần thực hiện được chuỗi:


JOYSTICK
   ↓
ESP32 TAY CẦM
   ↓
Đọc ADC
   ↓
Calibration
   ↓
Dead Zone
   ↓
Mapping
   ↓
Đóng gói dữ liệu
   ↓
ESP-NOW
   ↓
ESP32 DRONE
   ↓
Giải mã dữ liệu
   ↓
Throttle / Roll / Pitch / Yaw

Ở bài này, trọng tâm là đường truyền điều khiển.

Phần MPU6050 + Motor Mixing + PID/ổn định drone sẽ được triển khai sâu hơn ở Bài 7.


2. Tổng quan hệ thống điều khiển

Tay cầm của Drone Mini ESP32 gồm các thành phần chính:

  • ESP32
  • Joystick
  • Nút nhấn
  • LED/trạng thái
  • Mạch nguồn
  • Các linh kiện hỗ trợ

Joystick tạo ra tín hiệu điện áp thay đổi theo vị trí cần điều khiển.

ESP32 đọc tín hiệu đó thông qua ADC.

Ví dụ:


Joystick
   │
   ├── X → ADC ESP32
   │
   └── Y → ADC ESP32
             │
             ↓
        Xử lý dữ liệu
             │
             ↓
          ESP-NOW
             │
             ↓
        ESP32 Drone


3. Joystick hoạt động như thế nào?

Một joystick analog thông thường có hai trục:


          Y+
          ↑
          │
    X- ←  ●  → X+
          │
          ↓
          Y-

Hai trục tạo ra hai tín hiệu analog:


X → vị trí trái/phải
Y → vị trí lên/xuống

Ngoài ra joystick thường có một nút nhấn:


X axis
Y axis
SW

Tùy thiết kế tay cầm thực tế, cách gán joystick vào Throttle, Roll, Pitch, Yaw có thể khác nhau.

Vì vậy, trong firmware của Drone Mini cần xác định chính xác:


Joystick nào → chức năng nào
Trục X → chức năng nào
Trục Y → chức năng nào

Không nên mặc định theo một chuẩn duy nhất nếu chưa kiểm tra PCB thực tế.


4. ESP32 đọc joystick bằng ADC

Joystick analog tạo ra điện áp.

ESP32 sử dụng ADC để chuyển điện áp thành giá trị số.

Ví dụ:


Điện áp joystick
       ↓
      ADC
       ↓
Giá trị số

Giá trị ADC thực tế phụ thuộc vào ESP32, cấu hình ADC và phiên bản Arduino-ESP32.

Do đó, không nên giả định tuyệt đối rằng mọi board ESP32 đều có cùng một giá trị ADC hoặc cùng độ tuyến tính.

Điều quan trọng là chúng ta xác định được:


MIN
CENTER
MAX

của joystick thực tế.


5. Kiểm tra joystick bằng Serial Monitor

Trước khi truyền ESP-NOW, hãy kiểm tra joystick độc lập.

Ví dụ:


int xValue = analogRead(JOY_X);
int yValue = analogRead(JOY_Y);

Serial.print("X = ");
Serial.print(xValue);

Serial.print(" | Y = ");
Serial.println(yValue);

Di chuyển joystick và quan sát Serial Monitor.

Ví dụ kết quả có thể dạng:


X = 2040 | Y = 2018
X = 2500 | Y = 2020
X = 3100 | Y = 2025
X = 1500 | Y = 2010

Các giá trị trên chỉ là ví dụ minh họa.

GPIO và giá trị ADC phải lấy theo đúng mạch tay cầm đang sử dụng.


6. Tại sao cần Calibration?

Joystick thực tế hiếm khi có:


MIN = 0
CENTER = chính giữa tuyệt đối
MAX = giá trị tối đa

Ví dụ joystick ở giữa có thể đọc:


X = 2037
Y = 1989

thay vì một giá trị lý tưởng.

Nếu không calibration, drone có thể nhận thấy joystick đang lệch dù người dùng không tác động.

Vì vậy cần xác định:


X_MIN
X_CENTER
X_MAX

Y_MIN
Y_CENTER
Y_MAX


7. Dead Zone – vùng chết của joystick

Đây là kỹ thuật rất quan trọng đối với tay điều khiển drone.

Giả sử joystick đang ở giữa:


          Y
          ↑
          │
       ┌──┼──┐
       │  │  │
───────┼──●──┼──────→ X
       │     │
       └─────┘

Do nhiễu ADC, giá trị có thể dao động nhẹ:


1995
2002
1998
2007
2001

Nếu không có Dead Zone, hệ thống có thể hiểu rằng người dùng liên tục ra lệnh điều khiển.

Ta tạo một vùng nhỏ quanh vị trí trung tâm:


       ┌─────────┐
       │ Dead    │
       │  Zone   │
       │    ●    │
       └─────────┘

Nếu joystick nằm trong vùng này:


Control = 0


8. Hàm xử lý Dead Zone

Ví dụ:


int applyDeadZone(int value, int center, int deadZone)
{
    if (abs(value - center) <= deadZone) {
        return 0;
    }

    return value - center;
}

Ví dụ:


Center = 2048
Dead Zone = 80

Các giá trị:


1980 → 0
2010 → 0
2048 → 0
2080 → 0
2150 → giá trị điều khiển

Giá trị Dead Zone cần được điều chỉnh dựa trên joystick thực tế.


9. Mapping joystick thành dữ liệu điều khiển

Sau khi đọc ADC, chúng ta cần chuyển đổi dữ liệu sang một phạm vi dễ xử lý.

Ví dụ:


ADC
 ↓
Calibration
 ↓
Dead Zone
 ↓
Mapping
 ↓
-1000 ... +1000

Có thể sử dụng:


int controlValue = map(
    adcValue,
    ADC_MIN,
    ADC_MAX,
    -1000,
    1000
);

Tuy nhiên, đối với vùng trung tâm, nên xử lý riêng để đảm bảo joystick trở về gần 0.


10. Xác định 4 kênh điều khiển

Drone cơ bản có bốn nhóm lệnh:

Kênh Chức năng
Throttle Tăng/giảm lực nâng
Roll Nghiêng trái/phải
Pitch Nghiêng trước/sau
Yaw Xoay quanh trục đứng

Mô hình:


             PITCH
               ↑
               │
               │
ROLL  ←────────┼────────→ ROLL
               │
               ↓
             PITCH

              YAW
               ↻

Trong tay cầm, các trục joystick sẽ được ánh xạ vào những kênh này.

Ví dụ minh họa:


Joystick trái Y → Throttle
Joystick trái X → Yaw

Joystick phải X → Roll
Joystick phải Y → Pitch

Đây chỉ là một cách bố trí.

Firmware thực tế phải được thiết lập theo đúng hướng joystick trên tay cầm của bạn.


11. Đảo chiều joystick

Một vấn đề rất thường gặp là:

Di chuyển joystick lên nhưng giá trị lại giảm.

Ví dụ:


Joystick ↑
     ↓
ADC giảm

Trong trường hợp này cần đảo chiều:


value = -value;

Hoặc thay đổi phạm vi mapping.

Ví dụ:


int pitch = map(
    yValue,
    ADC_MAX,
    ADC_MIN,
    -1000,
    1000
);

Việc này rất quan trọng vì chiều điều khiển sai có thể khiến drone phản ứng ngược với mong muốn.


12. Tạo gói dữ liệu điều khiển

Sau khi xử lý joystick, chúng ta tạo packet.

Ví dụ:


struct DroneControl {

    int16_t throttle;
    int16_t roll;
    int16_t pitch;
    int16_t yaw;

    uint8_t arm;
    uint8_t button1;

    uint32_t counter;
};

Ví dụ dữ liệu:


Throttle = 300
Roll     = -120
Pitch    = 80
Yaw      = 0
Arm      = 1
Counter  = 1250

Packet này sẽ được gửi qua ESP-NOW.


13. Luồng dữ liệu hoàn chỉnh

Toàn bộ quá trình tại tay cầm:


        JOYSTICK
           ↓
      analogRead()
           ↓
      Calibration
           ↓
       Dead Zone
           ↓
        Mapping
           ↓
   Throttle/Roll/Pitch/Yaw
           ↓
      DroneControl
           ↓
        ESP-NOW

Đây là phần quan trọng nhất của Bài 6.


14. Gửi packet qua ESP-NOW

Sau khi tạo packet:


DroneControl control;

control.throttle = throttle;
control.roll     = roll;
control.pitch   = pitch;
control.yaw      = yaw;

control.arm      = armState;
control.button1  = buttonState;

control.counter++;

Sau đó gửi packet tới ESP32 Drone.

Với Arduino-ESP32 hiện nay, cách triển khai ESP-NOW nên sử dụng API phù hợp với phiên bản ESP32 core đang cài đặt.

Về mặt kiến trúc:


DroneControl
     ↓
ESP-NOW Peer
     ↓
ESP32 Drone


15. ESP32 Drone nhận packet

Ở phía Drone:


ESP-NOW Receiver
       ↓
Nhận DroneControl
       ↓
Kiểm tra dữ liệu
       ↓
Kiểm tra timeout
       ↓
Lưu giá trị điều khiển

Ví dụ:


RX:
Throttle = 500
Roll     = 100
Pitch    = -50
Yaw      = 20

Các giá trị này chưa nên đưa trực tiếp vào motor một cách đơn giản.

Chúng cần đi qua tầng điều khiển của drone.


16. Tách hệ thống thành các tầng

Một firmware drone nên được thiết kế theo từng tầng.


┌─────────────────────────┐
│      USER INPUT         │
│      Joystick           │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│      ESP-NOW RX         │
│      Communication      │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│     Control Command     │
│ Throttle/Roll/Pitch/Yaw │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│      IMU / MPU6050      │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│    Control Algorithm    │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│      Motor Mixing       │
└───────────┬─────────────┘
            ↓
┌─────────────────────────┐
│       4 Motors           │
└─────────────────────────┘

Bài 6 chủ yếu hoàn thiện từ Joystick đến Control Command.


17. Không nên điều khiển motor trực tiếp từ joystick

Một lỗi thiết kế phổ biến là:


Joystick
   ↓
PWM Motor

Cách này quá đơn giản đối với một hệ thống quadcopter ổn định.

Kiến trúc phù hợp hơn:


Joystick
   ↓
Lệnh người điều khiển
   ↓
MPU6050
   ↓
Thuật toán điều khiển
   ↓
Motor Mixing
   ↓
Motor

Joystick đưa ra mong muốn của người điều khiển.

MPU6050 cung cấp trạng thái thực tế của drone.

Bộ điều khiển sẽ kết hợp hai thông tin này.


18. Failsafe trong Bài 6

Tay cầm có thể mất kết nối.

Drone phải biết khi nào packet cuối cùng được nhận.

Ví dụ:


uint32_t lastPacketTime;

Mỗi khi nhận packet:


lastPacketTime = millis();

Sau đó kiểm tra:


if (millis() - lastPacketTime > FAILSAFE_TIMEOUT) {

    // Chuyển sang trạng thái an toàn

}

Mục tiêu:


Mất tín hiệu
    ↓
Timeout
    ↓
Failsafe
    ↓
Không tiếp tục sử dụng
lệnh điều khiển cũ

Đây là phần bắt buộc cần kiểm thử trước khi bay.


19. Arming – cho phép hệ thống hoạt động

Không nên để motor hoạt động ngay khi drone vừa cấp nguồn.

Có thể thiết kế trạng thái:


DISARM
   ↓
Nhận lệnh ARM
   ↓
Kiểm tra điều kiện
   ↓
ARM

Ví dụ:


Power ON
   ↓
DISARM
   ↓
Kiểm tra ESP-NOW
   ↓
Kiểm tra MPU6050
   ↓
Joystick ở trạng thái an toàn
   ↓
ARM

Trong thiết kế thực tế, điều kiện ARM cần được xây dựng rõ ràng và kiểm thử kỹ.


20. Kiểm tra joystick trước khi kết nối motor

Một bài test rất quan trọng:


Controller
     ↓
ESP-NOW
     ↓
Drone
     ↓
Serial Monitor

Không gắn cánh quạt.

Di chuyển joystick và quan sát:


Throttle : 0 → 1000
Roll     : -1000 → +1000
Pitch    : -1000 → +1000
Yaw      : -1000 → +1000

Khi joystick trở về giữa:


Roll  ≈ 0
Pitch ≈ 0
Yaw   ≈ 0

Nếu các giá trị không về gần trung tâm, cần quay lại bước Calibration + Dead Zone.


21. Kiểm tra chiều điều khiển

Đây là bước không được bỏ qua.

Ví dụ:


Joystick phải
      ↓
Roll +
      ↓
Drone phải phản ứng đúng

Nếu:


Joystick phải
      ↓
Roll -

thì cần đảo chiều phần mềm.

Tương tự với:

  • Pitch
  • Yaw
  • Throttle

Không nên thử bay khi chưa xác nhận đúng chiều của tất cả kênh điều khiển.


22. Kiểm tra mất kết nối

Thực hiện:


1. Bật Controller
2. Bật Drone
3. Kết nối ESP-NOW
4. Kiểm tra packet
5. Tắt Controller
6. Quan sát Drone

Drone phải chuyển sang trạng thái an toàn theo thiết kế Failsafe.

Sau đó kiểm tra lại:


Controller ON
      ↓
Kết nối lại
      ↓
Nhận packet
      ↓
Hệ thống hoạt động


23. Một vòng điều khiển hoàn chỉnh

Khi hệ thống phát triển hoàn thiện, vòng điều khiển sẽ gần giống:


          NGƯỜI ĐIỀU KHIỂN
                 │
                 ↓
             Joystick
                 │
                 ↓
         ESP32 Controller
                 │
                 ↓
             ESP-NOW
                 │
                 ↓
           ESP32 Drone
                 │
        ┌────────┴────────┐
        ↓                 ↓
    Lệnh bay           MPU6050
        │                 │
        └────────┬────────┘
                 ↓
         Control Algorithm
                 ↓
           Motor Mixing
                 ↓
          M1 M2 M3 M4

Đây là kiến trúc nền tảng của một hệ thống quadcopter điều khiển bằng tay cầm.


24. Các lỗi thường gặp

Lỗi 1: Joystick bị rung

Nguyên nhân:

  • Nhiễu ADC
  • Joystick không về chính giữa tuyệt đối
  • Chưa có Dead Zone

Giải pháp:


Calibration
+
Dead Zone
+
Filtering nếu cần


Lỗi 2: Joystick điều khiển ngược

Kiểm tra:


X direction
Y direction

Sau đó đảo chiều trong mapping nếu cần.


Lỗi 3: Drone không nhận packet

Kiểm tra:

  • MAC Address
  • Peer
  • Channel
  • ESP-NOW initialization
  • Wi-Fi mode
  • Packet structure

Lỗi 4: Packet nhận không ổn định

Kiểm tra:

  • Nguồn cấp ESP32
  • Channel
  • Khoảng cách
  • Tần suất gửi
  • Nhiễu RF
  • Firmware

Lỗi 5: Mất kết nối nhưng drone vẫn giữ lệnh cũ

Kiểm tra ngay:


FAILSAFE TIMEOUT

Không được để drone tiếp tục sử dụng command cũ vô thời hạn.


25. Bài thực hành

Thực hành 1 – Đọc joystick

Hiển thị:


X
Y
SW

trên Serial Monitor.


Thực hành 2 – Calibration

Xác định:


X_MIN
X_CENTER
X_MAX

Y_MIN
Y_CENTER
Y_MAX


Thực hành 3 – Dead Zone

Thiết lập vùng trung tâm để joystick không tạo lệnh ngoài ý muốn.


Thực hành 4 – Mapping

Chuyển joystick thành:


Throttle
Roll
Pitch
Yaw


Thực hành 5 – ESP-NOW

Gửi packet:


Throttle
Roll
Pitch
Yaw
Arm
Counter

từ Controller sang Drone.


Thực hành 6 – Failsafe

Tắt Controller và kiểm tra Drone có chuyển sang trạng thái an toàn hay không.


 

popup

Số lượng:

Tổng tiền: