Xe robot mài nền

17/09/2026
xe-robot-mai-nen

Xe robot mài nền

Tôi đề xuất giao diện điện thoại chia thành 2 khung như sau:

thu nhỏ logo khoảng 100×100 px, sau đó nhúng vào main.cpp. Trên web chỉ hiển thị khoảng 55×55 px ở góc trái trên cùng.

Vì logo GPC hiện đã nhúng trong main.cpp, logo WHP cũng nên làm tương tự. Tôi có thể tạo lại nguyên main.cpp hoàn chỉnh có cả 2 logo, bố cục:

┌──────────────────────────────────────┐
│ ┌──────┐                      ┌──────┐│
│ │ GPC  │    ROBOT CONTROL     │ WHP  ││
│ └──────┘                      └──────┘│
│                                      │
│                 ▲                    │
│               TIẾN                   │
│                                      │
│       ◀ TRÁI    STOP    PHẢI ▶       │
│                                      │
│                 ▼                    │
│                LÙI                   │
│                                      │
│          MANU          AUTO           │
└──────────────────────────────────────┘


┌───────────────────────────────────┐
│              SETUP                │
│                                   │
│ Chạy lệch trái        [   0   ]   │
│ Chạy lệch phải        [   0   ]   │
│ Khoảng cách max       [   0   ]   │
│ Thời gian làm việc max[   0   ]   │
│ Quay góc trái         [  90   ]   │
│ Quay góc phải         [  90   ]   │
│ Khoảng cách L1        [   0   ]   │
│ Khoảng cách L2        [   0   ]   │
│ Khoảng cách cảnh báo  [   0   ]   │
│                                   │
│             [ SAVE ]              │
└───────────────────────────────────┘

Với chạy lệch trái/phải, tôi đề nghị sau này dùng giá trị % hiệu chỉnh tốc độ 2 bánh. Ví dụ đặt chạy lệch trái = 3 thì khi xe có xu hướng lệch trái, thuật toán có thể bù khoảng 3% cho bên phù hợp. Phần này khi có động cơ thực tế chúng ta sẽ hiệu chỉnh.

Các khoảng cách nên thống nhất cm, góc dùng độ, thời gian làm việc dùng phút. Trên giao diện sẽ ghi rõ đơn vị để không nhầm:

 
Chạy lệch trái          [%]
Chạy lệch phải          [%]
Khoảng cách di chuyển   [cm]
Thời gian làm việc      [phút]
Quay góc trái           [°]
Quay góc phải           [°]
Khoảng cách L1          [cm]
Khoảng cách L2          [cm]
Khoảng cách cảnh báo    [cm]

Tôi cũng sẽ thiết kế ngay từ đầu để MANU cho phép dùng 5 nút Tiến/Lùi/Trái/Phải/STOP; còn AUTO khóa các lệnh chạy tay để tránh xung đột.

Nếu đang nói về robot 2 bánh chạy các đường thẳng song song kiểu máy lau/mài nền của bạn, thì không phải chọn 1 trong 3. Ba loại cảm biến làm ba nhiệm vụ khác nhau, và tốt nhất là phối hợp.

Cảm biến Nhiệm vụ chính Với robot của bạn
BNO086 Đo hướng/góc quay của robot Giữ robot chạy thẳng, quay chính xác 90°/180°
Hall/Encoder bánh xe Đo số vòng bánh → quãng đường, tốc độ Biết đã chạy 1 m, 5 m, 10 m; điều khiển hai bánh cân nhau
LiDAR Đo khoảng cách tới tường/vật thể, có thể định vị/map Giữ đường chạy song song, phát hiện vật cản, hiệu chỉnh sai số vị trí

BNO086 không đo quãng đường bánh xe chính xác; encoder/Hall lại bị sai khi bánh trượt; LiDAR cung cấp thông tin môi trường để hiệu chỉnh vị trí. Vì vậy hệ robot di động chính xác thường fusion nhiều cảm biến, thay vì dựa vào một cảm biến duy nhất.

Với máy của bạn, tôi khuyên dùng cả 3

Kiến trúc sẽ như này:

 
              ROBOT
                │
       ┌────────┼────────┐
       ↓        ↓        ↓
    BNO086   Encoder    LiDAR
       │        │        │
       ↓        ↓        ↓
     GÓC      QUÃNG     KHOẢNG CÁCH
    HƯỚNG      ĐƯỜNG     / VỊ TRÍ
       │        │        │
       └────────┼────────┘
                ↓
              ESP32
                ↓
        Điều khiển 2 motor

Ví dụ robot cần chạy 10 m → dịch ngang 50 cm → quay đầu → chạy ngược lại 10 m:

Encoder/Hall xác định robot đã đi được bao nhiêu mét. BNO086 giữ heading, chẳng hạn đường đi đầu tiên là ; nếu lệch thành +1°, ESP32 giảm/tăng tốc hai bánh để kéo về . Đến cuối đường, BNO086 kiểm soát quá trình quay 90° → dịch ngang → quay tiếp 90°. LiDAR đo tường/biên môi trường để kiểm tra robot có thực sự đang chạy song song và hiệu chỉnh sai số tích lũy. Encoder bánh xe vốn có sai số do trượt bánh và sai số kích thước bánh, nên kết hợp IMU và LiDAR sẽ đáng tin cậy hơn.

Nếu muốn làm bản đơn giản trước, tôi sẽ chọn BNO086 + 2 encoder/Hall ở hai bánh. Chưa cần LiDAR. Khi robot đã chạy thẳng và quay đầu ổn định, thêm LiDAR để nâng độ chính xác.

Và lưu ý: Hall ở đây nên hiểu là Hall encoder gắn bánh/motor, chứ không phải một cảm biến Hall đơn lẻ chỉ để phát hiện nam châm.

Với yêu cầu trước đây của bạn là chạy các đường song song cách nhau khoảng 1 thân xe, cấu hình tôi ưu tiên là:

2 encoder bánh + BNO086 + 1 LiDAR phía trước/bên hông.

Nếu bạn cho tôi biết LiDAR bạn định dùng loại 1 điểm (VL53L0X/VL53L1X) hay LiDAR quét 360°, tôi có thể thiết kế luôn thuật toán chạy zíc-zắc phù hợp.

So với các con chúng ta vừa xem

LiDAR Công nghệ Ngoài trời ESP32 Nhận xét cho máy của bạn
YDLIDAR X2 Triangulation ⚠️ Giá rẻ
LDROBOT LD14 Triangulation ⚠️ Dùng được
LDROBOT LD19 dToF ✅ khá Rất đáng chọn
STL-06NBJ TOF ✅ được quảng bá indoor/outdoor ✅ Serial Rất đáng xem

 

MANU: chỉ khi bấm MANU thì 5 nút TIẾN – LÙI – TRÁI – PHẢI – STOP mới điều khiển robot. Code hiện tại đã gần đúng vì khi autoMode=true, các lệnh điều khiển tay đang bị chặn; riêng STOP vẫn hoạt động.

AUTO: khi bấm AUTO, robot sẽ tự chạy theo các thông số trong SETUP.

chu trình AUTO của robot như sau:

ĐƯỜNG 1
Robot ───────────────────────────────►
                                     │
                           gặp cuối đường/vật cản
                                     │
                              quay PHẢI 90°
                                     ↓
                                  đi L1
                                     ↓
                              quay PHẢI 90°
                                     │
◄────────────────────────────────────┘
ĐƯỜNG 2

gặp cuối đường/vật cản
│
↓
quay TRÁI 90°
│
đi L2
│
quay TRÁI 90°
│
└────────────────────────────────────►
ĐƯỜNG 3

→ tiếp tục lặp xen kẽ
PHẢI → PHẢI → TRÁI → TRÁI → PHẢI → PHẢI...

MANU: 5 nút TIẾN / LÙI / TRÁI / PHẢI / STOP hoạt động.

AUTO: 4 nút di chuyển tay bị khóa. Robot tự chạy theo chu trình trên. STOP vẫn hoạt động bất kỳ lúc nào và khi STOP sẽ ga = 0 → đóng phanh → thoát AUTO.

Phần SETUP hiện tại có turnAngleLeft, turnAngleRight, distanceL1, distanceL2, warningDistance, maxDistance, maxWorkTime, nên có thể tận dụng trực tiếp.

Để AUTO chạy thực tế chứ không chỉ chạy theo thời gian, tôi sẽ dùng:

Hall motor → xác định đã đi đủ L1/L2 và quãng đường thẳng.
BNO086 → xác định đã quay đúng ±90° và giữ hướng khi chạy thẳng.
LiDAR 360° → xác định cuối đường/vật cản theo warningDistance.

Một điểm rất hay của cách bạn đặt L1/L2 riêng: nếu robot rộng 50 cm nhưng thực tế đường mài chồng mép 5 cm, ta có thể đặt chẳng hạn L1 = L2 = 45 cm, không phải sửa chương trình.

Tôi đã ghép tiếp vào file hiện tại theo đúng phần cứng bạn xác nhận:

  • BNO086: I2C SDA=21, SCL=22. BNO086 hỗ trợ I²C và SparkFun dùng mặc định địa chỉ 0x4B; Rotation Vector phù hợp để lấy hướng quay/yaw.
  • Hall trái: GPIO34.
  • Hall phải: GPIO35.
  • LDROBOT LD14: TX của LD14 → GPIO16 ESP32, UART 115200, 8N1. LD14 truyền một chiều và tự gửi dữ liệu sau khi hoạt động ổn định.
  • Phanh relay: GPIO27 như trước.
  • Tay ga trái/phải: GPIO25/26.
  • Reverse trái/phải: GPIO32/33.

thêm 2 nút điều khiển để bật máy mài kích dương và máy hút ở 2 góc trái/phải cùng hàng với nút lùi. 2 nút này cũng dùng manu/auto đều điều khiển được. Khi bấm nút stop thì 2 nút này cũng off. Chạy auto sẽ luôn bật 2 nút này.

Đã thêm đúng yêu cầu vào code đang chạy ổn:

  • GPIO18 → MÁY MÀI, kích dương HIGH = ON.
  • GPIO19 → MÁY HÚT, kích dương HIGH = ON.
  • Hai nút nằm cùng hàng với nút LÙI: MÁY MÀI | LÙI | MÁY HÚT.
  • MANU: bật/tắt độc lập hai thiết bị.
  • AUTO: khi bắt đầu AUTO, máy mài + máy hút tự động ON. Hai nút vẫn có thể điều khiển.
  • Bấm STOP ở MANU hoặc AUTO → xe dừng/phanh và MÁY MÀI + MÁY HÚT đều OFF.
  • Khi khởi động ESP32, cả hai đầu ra mặc định LOW/OFF.

Khoảng cách di chuyển max: đi thẳng đến tối đa khoảng cách đó thì quay đầu. Thời gian làm việc Max: máy hoạt động đến từng đó thời gian thì stop, chỉ áp dụng khi chạy auto, Hiển thị thời gian làm việc đếm lùi dưới dòng tốc độ.

Đã sửa theo đúng logic bạn yêu cầu:

  • Khoảng cách di chuyển MAX: chỉ áp dụng khi AUTO đang chạy thẳng. Ví dụ đặt 1000 cm, xe đi thẳng đủ 10 m thì coi như đến cuối đường và thực hiện chu trình quay đầu giống khi LiDAR phát hiện cuối đường. Sang đường mới, bộ đếm khoảng cách được tính lại từ 0.
  • Thời gian làm việc MAX: chỉ tính từ lúc bấm AUTO. Hết thời gian → xe STOP + phanh + máy mài OFF + máy hút OFF. MANU không bị giới hạn bởi thời gian này.
  • Ngay dưới dòng TỐC ĐỘ đã thêm:
    THỜI GIAN LÀM VIỆC: 29:59
    và đếm lùi liên tục. Khi không chạy AUTO hiển thị --:--.

chưa lắp cảm biến và bánh xe, khi bấm auto thì thời gian chưa đếm lùi

Đúng. Trường hợp này khả năng cao AUTO thực tế chưa được ESP32 chấp nhận, vì code hiện tại chỉ startAuto() khi bnoReady == true. Bạn chưa lắp BNO086 nên nhấn AUTO bị trả về "BNO086 chưa sẵn sàng", do đó autoStartMs chưa bắt đầu và đồng hồ vẫn --:--.

Tôi sẽ sửa logic để giai đoạn test chưa lắp cảm biến vẫn bấm AUTO và đồng hồ đếm lùi bình thường. Khi lắp cảm biến sau, ta bật lại điều kiện an toàn BNO/Hall.

trong code đã có, chức năng BNO086 đã làm được gì

Trong code hiện tại, BNO086 đã được dùng chủ yếu để đo góc quay của robot, đặc biệt phục vụ việc quay trái/phải chính xác khi chạy AUTO.

Cụ thể nó đang làm các việc sau:

  1. Đọc góc hướng Yaw của robot liên tục:
 
bno086.serviceBus();
float yawRad = bno086.getYaw();
currentYawDeg = yawRad * 180.0f / PI;

Ví dụ robot đang hướng 20°, sau khi quay thành 110° → code xác định robot đã quay khoảng 90°.

  1. Khi AUTO đến cuối đường, code lưu góc hiện tại:
 
autoTurnStartYaw = currentYawDeg;

Sau đó cho hai bánh quay ngược chiều nhau để robot quay tại chỗ.

  1. Trong lúc quay, BNO086 liên tục kiểm tra:
 
fabsf(angleDiff(currentYawDeg, autoTurnStartYaw))

Khi đạt turnAngleRight hoặc turnAngleLeft, ví dụ 90°, code dừng quay. Vì vậy giá trị trong SETUP:

  • Quay góc trái = 90°
  • Quay góc phải = 90°

được thực hiện dựa vào BNO086, chứ không dựa vào thời gian quay động cơ.

  1. Nó được dùng cho cả hai lần quay trong một chu kỳ chuyển làn:
    quay phải 90° → chạy L1 → quay phải 90°, rồi lần sau quay trái 90° → chạy L2 → quay trái 90°.
  2. thêm cho chức năng giữ hướng khi chạy thẳng:

    Bắt đầu đường → ghi Yaw mục tiêu → trong khi chạy liên tục so sánh Yaw hiện tại với Yaw mục tiêu → lệch trái thì chỉnh tốc độ hai bánh → lệch phải thì chỉnh ngược lại.

Như vậy BNO086 sẽ đảm nhiệm 2 nhiệm vụ: quay đúng góc 90° + giữ đường chạy thẳng, còn Hall đảm nhiệm đo quãng đường MAX/L1/L2, và LD14 đảm nhiệm phát hiện vật cản/cuối đường.

chưa lắp cảm biến và bánh xe, khi bấm auto thì thời gian chưa đếm lùi

Đúng. Trường hợp này khả năng cao AUTO thực tế chưa được ESP32 chấp nhận, vì code hiện tại chỉ startAuto() khi bnoReady == true. Bạn chưa lắp BNO086 nên nhấn AUTO bị trả về "BNO086 chưa sẵn sàng", do đó autoStartMs chưa bắt đầu và đồng hồ vẫn --:--.

Tôi sẽ sửa logic để giai đoạn test chưa lắp cảm biến vẫn bấm AUTO và đồng hồ đếm lùi bình thường. Khi lắp cảm biến sau, ta bật lại điều kiện an toàn BNO/Hall.

Tôi sẽ thêm ngay dưới chữ SETUP hai ô:

 
          SETUP

┌──────────────┐   ┌──────────────┐
│  HALL TRÁI   │   │  HALL PHẢI   │
│      0       │   │      0       │
└──────────────┘   └──────────────┘

Hai giá trị này sẽ được ESP32 đọc liên tục và web tự cập nhật, hoàn toàn độc lập với MANU/AUTO/STOP. Vì vậy kể cả xe dừng, bạn quay bánh bằng tay thì số Hall vẫn thay đổi.

Tuy nhiên cần xác định “số Hall” bạn muốn hiển thị là gì, vì động cơ BLDC Hall thường có 3 dây tín hiệu HA/HB/HC. Có hai cách:

  • Bộ đếm xung Hall: hiện tổng số xung của bánh trái và bánh phải. Quay bánh → số tăng liên tục, kể cả quay bằng tay.
  • Tốc độ từ Hall: hiện RPM hoặc số xung/giây; khi dừng sẽ về 0.

Sau khi nạp code

Web sẽ hoạt động độc lập như sau:

 
Hall trái
GPIO34
   │
   └── RISING
          │
          ▼
 hallLeftCount
          │
          ▼
       /hall
          │
        Wi-Fi
          │
          ▼
       Điện thoại
          │
          ▼
      HALL TRÁI
        1256


Hall phải
GPIO35
   │
   └── RISING
          │
          ▼
 hallRightCount
          │
          ▼
       /hall
          │
          ▼
      HALL PHẢI
        1249

 

 

Sau đó mới nối Hall qua chia áp:

 
Hall 4.8V
   │
  4.7k
   │
   ├──── GPIO25/26
   │
  10k
   │
  GND

Như vậy tín hiệu 4,8 V được hạ xuống khoảng 3,27 V.

 

Bánh còn lại giống hệt với GPIO14:

Thêm tụ 104 chạy ổn luôn nhưng phải lắp chân tụ sát với esp32 xuống GND
Tín hiệu Hall
     │
    4.7k
     │
     ├──────────── GPIO14
     │       │
    10k     100nF
     │       │
    GND     GND
    
    

Nếu tín hiệu Hall HIGH khoảng 4,8 V, cặp 4.7k + 10k còn có tác dụng chia xuống khoảng:

4.8×104.7+10≈3.27V4.8\times\frac{10}{4.7+10}\approx3.27V

rất phù hợp cho ESP32.

 

Trường hợp này dùng chế độ WIFI_AP_STA: ESP32 vừa phát Wi-Fi riêng để điện thoại kết nối trực tiếp, vừa kết nối router. Hai cách đều truy cập cùng một giao diện điều khiển robot.

Kết quả sẽ là:

                     ESP32 ROBOT
                    /           \
                   /             \
          WiFi AP trực tiếp      WiFi Router
          ROBOT_ESP32                │
               │                     │
          Điện thoại             Điện thoại
               │                     │
       192.168.4.1          192.168.x.xxx

Cách 1 – đứng gần xe, không cần router: điện thoại kết nối:

WiFi: ROBOT_ESP32
Pass: 12345678

rồi mở:

http://192.168.4.1

Cách 2 – qua router: ESP32 và điện thoại cùng kết nối router. Serial Monitor sẽ báo ví dụ:

===== WIFI ROUTER =====
Da ket noi Router!
STA IP: 192.168.0.115

thì điện thoại mở:

http://192.168.0.115

Cả 192.168.4.1192.168.0.115 đều vào cùng một WebServer server(80), nên các chức năng TIẾN/LÙI/TRÁI/PHẢI/STOP, AUTO/MANU, Hall, BNO086, LiDAR... không cần viết lại.

==========================
ESP32 ROBOT
==========================
BNO086: NOT FOUND
LD14: UART 115200 STARTED

===== WIFI AP =====
SSID: ROBOT_ESP32
AP IP: 192.168.4.1

Dang ket noi Router: linhkiendientu
..
===== WIFI ROUTER =====
Da ket noi Router!
STA IP: 192.168.0.123
RSSI: -45 dBm
WEB SERVER STARTED

 

 

Nếu mục tiêu là biết bánh đang quay tiến hay lùi, thì mỗi bánh chỉ cần 2 tín hiệu Hall là đủ. Không bắt buộc dùng cả 3 Hall A/B/C của động cơ BLDC.

Và vì bạn vừa phát hiện nhiễu, tôi khuyên mỗi đường Hall đưa vào ESP32 đều gắn tụ 104 (100 nF) như đường hiện tại đã chạy ổn định, đồng thời bảo đảm điện áp HIGH không vượt mức an toàn của GPIO ESP32.

Các GPIO thường dùng tốt cho interrupt gồm GPIO 4, 5, 13, 14, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33, 34, 35, 36, 39.

Với ESP32 DevKit V1:

GPIO Dùng Hall Ghi chú
25 ✅ Rất tốt Ưu tiên
26 ✅ Rất tốt Ưu tiên
27 Dùng được
14 Dùng được nếu đang trống
13 Dùng được
4 Có thể dùng nhưng là chân boot-strapping
16 Dùng được
17 Dùng được- nhiễu
34 ⚠️ Chân hiện tại, đang nghi lỗi
35 Dùng được
36 ⚠️ Input-only, không pull-down
39 ⚠️ Input-only, không pull-down

 

4 Hall 13/14/34/35 →  quãng đường  → STOP lưu vị trí → vẫn tương thích AUTO + BNO086 + web hiện tại.

 

tạo thêm 4 ô cùng kiểu với HALL TRÁI/HALL PHẢI:

  • QUÃNG ĐƯỜNG — cm hoặc m đã di chuyển.
  • THỜI GIAN AUTO — thời gian đã hoạt động kể từ lúc bấm AUTO.
  • VẬT PHÍA TRƯỚC — khoảng cách từ LiDAR LD14.
  • GÓC HƯỚNG — góc từ BNO086.

 

Như vậy SETUP sẽ thành bố cục:

┌───────────────┐  ┌───────────────┐
│   HALL TRÁI   │  │   HALL PHẢI   │
│      125      │  │      127      │
└───────────────┘  └───────────────┘

┌───────────────┐  ┌───────────────┐
│ QUÃNG ĐƯỜNG   │  │ THỜI GIAN AUTO│
│    325.4      │  │     12:35     │
│      cm       │  │  đã hoạt động │
└───────────────┘  └───────────────┘

┌───────────────┐  ┌───────────────┐
│VẬT PHÍA TRƯỚC │  │  GÓC HƯỚNG  │
│     86.5      │  │     2.4°      │
│      cm       │  │    BNO086     │
└───────────────┘  └───────────────┘

 

 

“GÓC HƯỚNG” và dùng Yaw của BNO086.

Quy ước cho robot:

 
Khởi động / bắt đầu AUTO     =    0°
Quay PHẢI                    =   + góc
Quay TRÁI                    =   - góc

                 0°
                 ↑
                 │
       -90° ←   XE   → +90°

              ±180°
                 ↓

Giá trị luôn giới hạn:

 
-180° ... 0° ... +180°

 

sửa thêm cho tôi khi chạy thẳng hay lùi thì điều khiển để 2 hall luôn bằng nhau

Quan trọng với AUTO + BNO086

Code của bạn đã có BNO086 giữ hướng khi AUTO chạy thẳng. Không nên để BNO và Hall cùng tự do chỉnh hai motor theo hai thuật toán độc lập, vì chúng có thể “đánh nhau”.

ư

Tôi sẽ tổ chức theo kiểu:

Tốc độ cơ sở
     ↓
CÂN HALL
giữ 2 bánh đi gần bằng quãng đường
     ↓
BNO086
hiệu chỉnh nhỏ để robot giữ đúng hướng
     ↓
Motor trái / Motor phải

Hall đảm nhiệm đồng bộ hai bánh, còn BNO086 đảm nhiệm giữ hướng thực tế.

Với Hall hiện tại chỉ đếm tăng, cách này dùng được cho cả TIẾN và LÙI, vì khi chạy lùi số xung Hall vẫn tăng. Không cần Hall xác định chiều; code đã biết robot đang được lệnh tiến hay lùi.

 

hướng nhìn của robot:

 
        PHÍA TRƯỚC
            180°
             ↑

   TRÁI     GIỮA      PHẢI
190°-220° 170°-190° 150°-140°

 

Giữ GIỮA 170°–190°, chỉ mở rộng hai bên thành:

  • PHẢI: 140°–170°
  • GIỮA: 170°–190°
  • TRÁI: 190°–220°

tổng vùng quan sát phía trước là 80°, từ 140° → 220°, tâm vẫn là 180°:

               180°
                ↑
          HƯỚNG ROBOT

       TRÁI    GIỮA     PHẢI
     190-220  170-190  140-170
        30°     20°      30°

 

Khoảng cách cảnh báo là khoảng cách stop hoạt động của xe đi tiến trong manu và auto. các chức năng đi lùi, rẽ trái, phải vẫn hoạt động được.

Đúng. Ta sửa logic để “Khoảng cách cảnh báo” chỉ khóa chuyển động TIẾN khi LiDAR phát hiện vật cản trong vùng phía trước.

Cụ thể:

 
TIẾN MANU   → gặp vật cản → STOP
TIẾN AUTO   → gặp vật cản → STOP / xử lý tránh vật theo AUTO
LÙI         → vẫn được phép
RẼ TRÁI     → vẫn được phép
RẼ PHẢI     → vẫn được phép
STOP        → luôn được phép

 

Thứ tự này là đúng:

 
LD14
 ↓
updateLD14()
 ↓
updateObstacleSafety()
 ↓
phát hiện <= Khoảng cách cảnh báo
 ↓
throttleStop()
brakeOn()

-------------------------------------------------

hiện tại mỗi lần chạy, bên phải lệch so với bên trái 4 xung, vài lần chạy thành lệch nhiều, trong setup có ô Chạy lệch trái và Chạy lệch phải , hãy thêm chức năng chạy tiến và lùi được công thêm số xung này trước khi tiến / lùi

Nếu muốn đúng yêu cầu mới, đổi ý nghĩa hai ô thành:

 
BÙ HALL TRÁI (xung)
BÙ HALL PHẢI (xung)

và giá trị:

 
Trái = 0
Phải = 4

Trường hợp thực tế của bạn

Nếu sau mỗi lần chạy:

 
Hall trái tăng: 100
Hall phải tăng: 96

tức bánh phải thường thiếu 4 xung, thì đặt:

 
BÙ HALL TRÁI = 0
BÙ HALL PHẢI = 4

Hall Sync sẽ nhìn thành:

 
Trái thực tế: 100 + 0 = 100
Phải thực tế:  96 + 4 = 100

Nhưng có một điểm quan trọng: nếu mục tiêu của bạn là bánh phải thực sự phải chạy thêm 4 xung trước khi kết thúc mỗi đoạn, thì cách cộng vào phép so sánh ở trên lại làm bộ điều khiển coi 96 + 4 = 100không bắt bánh phải chạy thêm.

tôi sẽ sửa theo hướng thứ hai: khi bắt đầu TIẾN/LÙI, bánh bị thiếu sẽ được chạy bù 4 xung trước, sau đó mới cho hai bánh chạy đồng thời và Hall Sync từ 0–0. Cách đó phù hợp hơn với hiện tượng lệch tích lũy bạn đang gặp

Sửa motorForward()

Trình tự mới:

 
Bấm TIẾN
   ↓
bánh phải chạy trước 4 xung
   ↓
dừng bánh phải
   ↓
reset Hall Sync = 0 : 0
   ↓
2 bánh cùng TIẾN
   ↓
Hall Sync giữ 2 bánh bằng nhau

-----------------------------------------------

 

đường kính bánh xe 16cm, 30 xung = 1 vòng, tính khoảng cách cho tôi theo cm

Với bánh xe đường kính 16 cm, 30 xung Hall = 1 vòng:

Chu vi bánh xe:

C=πD=3.1416×16≈50.27 cmC = \pi D = 3.1416 \times 16 \approx 50.27\text{ cm}

Vậy 1 xung tương ứng:

50.27/30≈1.676 cm50.27 / 30 \approx \mathbf{1.676\text{ cm}}

Công thức tính khoảng cách:

Khoảng caˊch (cm)=Soˆˊ xung×1.676\boxed{\text{Khoảng cách (cm)} = \text{Số xung} \times 1.676}

Ví dụ: 30 xung = 50.27 cm, 100 xung ≈ 167.55 cm, 2000 xung ≈ 3351 cm = 33.51 m.

------------------------------------------------

 

AUTO đang chạy theo kiểu ziczac/lawn-mower, với chu trình như sau.

 
BẤM AUTO
   ↓
Bật máy mài + máy hút
   ↓
TIẾN THẲNG
   ↓
BNO086 giữ hướng
   ↓
┌─────────────────────────────┐
│ Có vật cản trong khoảng     │
│ cảnh báo LiDAR              │
│           HOẶC              │
│ đạt Khoảng cách MAX         │
└──────────────┬──────────────┘
               ↓
             STOP
               ↓ 400 ms
        QUAY PHẢI 90°
               ↓
          TIẾN L1
               ↓
        QUAY PHẢI 90°
               ↓
          TIẾN THẲNG
               ↓
          gặp cuối đường
               ↓
        QUAY TRÁI 90°
               ↓
          TIẾN L2
               ↓
        QUAY TRÁI 90°
               ↓
          TIẾN THẲNG
               ↓
       lặp PHAI ↔ TRÁI

1. Khi bấm AUTO

startAuto() thực hiện:

 
autoMode = true;
autoState = AUTO_FORWARD;
autoTurnRight = true;

Sau đó lấy hướng hiện tại của BNO086 làm , reset quãng đường, bật:

 
accessoriesOn();   // máy mài + máy hút

rồi gọi:

 
motorForward();
captureAutoHeading();

Nghĩa là lần đầu AUTO luôn bắt đầu bằng đi thẳng, và lần quay đầu tiên là bên phải.

2. Khi chạy thẳng

Ở trạng thái:

 
AUTO_FORWARD

AUTO liên tục kiểm tra hai điều kiện:

 
frontObstacle()

hoặc:

 
roadCm >= maxDistance

Chỉ cần một trong hai xảy ra → xe STOP và chuẩn bị quay.

LiDAR hiện kiểm tra cả 3 vùng TRÁI + GIỮA + PHẢI. Chỉ cần một vùng có vật ở khoảng cách nhỏ hơn:

 
warningDistance

là được coi là gặp vật cản.

3. BNO086 đang giữ hướng

Trong AUTO_FORWARDAUTO_SHIFT, code gọi:

 
updateAutoHeadingHold();

khoảng 25 lần/giây.

Nó so sánh:

 
currentYawDeg

với:

 
autoHeadingTargetDeg

rồi tăng/giảm điện áp hai bánh:

 
leftV  = baseV - correction;
rightV = baseV + correction;

Thông số hiện tại:

 
HEADING_KP = 0.018
HEADING_DEADBAND = 0.8°
HEADING_MAX_CORR_V = 0.45V

Tức BNO086 đang thực sự tham gia chỉnh lệch trái/phải khi chạy thẳng.

4. Khi gặp cuối đường

AUTO STOP trước:

 
motorStop();

đợi:

 
400 ms

sau đó quay tại chỗ bằng BNO086.

Lần đầu:

 
Quay PHẢI → turnAngleRight

mặc định hiện tại là:

 
turnAngleRight = 90;

Nó không quay theo thời gian mà đo góc BNO:

 
fabs(angleDiff(...)) >= target

đủ 90° mới dừng.

5. Sau đó chạy L1

Sau lần quay phải thứ nhất:

 
→ chạy thẳng L1

Mặc định:

 
distanceL1 = 100 cm

Khoảng cách này được tính bằng Hall:

 
getShiftDistanceCm()

Khi đạt L1 → STOP → lại quay phải 90°.

Sau đó bắt đầu đường thẳng tiếp theo.

6. Cuối đường tiếp theo đổi sang trái

Sau khi hoàn thành một lượt phải, code:

 
autoTurnRight = !autoTurnRight;

nên lượt tiếp theo:

 
Quay TRÁI
→ đi L2
→ quay TRÁI
→ đi thẳng

Sau đó lại đổi thành phải.

Vì vậy đường đi là:

 
↑ ↑ ↑
│ │ │
│ └─┐
│   │
└─┐ │
  │ │

đúng kiểu quét ziczac mặt nền.

7. Thời gian AUTO

Code cũng kiểm tra:

 
maxWorkTime

mặc định hiện tại:

 
30 phút

Khi hết thời gian:

 
stopAuto();

→ dừng xe + tắt máy mài + máy hút.

Trong code hiện tại, nút AUTO bị khóa nếu BNO086 chưa sẵn sàng.

Trong handleMode() đang có:

 
if(mode=="auto"){
    if(!bnoReady){
      server.send(503,"text/plain; charset=utf-8","BNO086 chưa sẵn sàng");
      return;
    }
    startAuto();
    Serial.println("MODE = AUTO");
}else{

Vì bạn đã tháo/comment BNO nên:

 
bnoReady = false;

→ chương trình return ngay → startAuto() không chạy → máy mài/hút vẫn OFF → MODE vẫn MANU.

Sửa ngay chỗ này

Thay toàn bộ handleMode() bằng:

 
void handleMode()
{
  String mode = server.arg("mode");

  if(mode == "auto")
  {
    // TAM THOI KHONG KIEM TRA BNO086
    // if(!bnoReady){
    //   server.send(503,"text/plain; charset=utf-8","BNO086 chưa sẵn sàng");
    //   return;
    // }

    startAuto();
    Serial.println("MODE = AUTO");
  }
  else
  {
    stopAuto();
    Serial.println("MODE = MANU");
  }

  server.send(200,"text/plain","OK");
}

Sau sửa, bấm AUTO thì ít nhất Serial phải xuất hiện:

 
MAY MAI: ON
MAY HUT: ON
AUTO: FORWARD
MODE = AUTO

và web phải chuyển:

 
MODE = AUTO
MAY MAI: ON
MAY HUT: ON

Nhưng còn một vấn đề tiếp theo

Trong startAuto() vẫn có:

 
motorForward();
captureAutoHeading();

Tạm thời comment BNO:

 
motorForward();

// TAM TAT BNO086
// captureAutoHeading();

Serial.println("AUTO: FORWARD");

Và trong updateAuto() còn phần quay 90° dựa vào currentYawDeg. Nếu chỉ sửa handleMode() thì AUTO sẽ bắt đầu chạy được, nhưng đến cuối đường lúc cần quay 90° sẽ không hoạt động đúng vì không có BNO.

---------------------------------------------------

trong setup, Thêm 2 ô nhập đặt dưới Thời gian làm việc MAX, Khoảng cách di chuyển: 15cm và ô Thời gian dừng: 5 giây, Khi bấm auto thì xe tiến 15cm và dừng 5 giây, cứ lặp lại như vậy, các nội dung khác giữ nguyên

Với yêu cầu này, tôi khuyên không sửa cấu trúc AUTO hiện tại, chỉ thêm một cơ chế “tiến ngắt quãng” vào trạng thái chạy thẳng:

 
AUTO
→ tiến 15 cm
→ STOP 5 giây
→ tiến tiếp 15 cm
→ STOP 5 giây
→ lặp lại...

LiDAR, Hall Sync, khoảng cách MAX, thời gian MAX, L1/L2, máy mài/hút và các chức năng AUTO khác vẫn giữ nguyên.

 

Thay Cảm biến BNO086 bằng Mpu6050, thay LiDAR bằng cảm biến siêu âm JSN-SR04T

Có thể thay thành:

  • BNO086 → MPU6050 để lấy góc hướng/yaw tương đối.
  • LD14 → JSN-SR04T để đo một khoảng cách phía trước.
  • Giữ nguyên Hall, AUTO ngắt quãng, Web, máy mài/hút.
  • Vì JSN-SR04T chỉ đo phía trước, giao diện LiDAR 3 vùng nên đổi thành “CẢM BIẾN TRƯỚC” một giá trị.

Tuy nhiên có một điểm quan trọng: MPU6050 không có từ kế, nên yaw sẽ bị trôi theo thời gian, không ổn định tuyệt đối như BNO086. Với robot của bạn, Hall vẫn nên giữ nhiệm vụ cân hai bánh khi chạy thẳng; MPU6050 chủ yếu dùng để đo góc quay tương đối 90° trong thời gian ngắn.

Đặc biệt không nên để MPU6050 và Hall cùng liên tục sửa DAC khi xe chạy thẳng, vì hai bộ điều khiển có thể “đánh nhau”. Chạy thẳng hiện tại nên để Hall Sync làm chính; MPU6050 dùng cho góc quay.

Tôi có thể sửa trực tiếp toàn bộ file 2745 dòng bạn vừa gửi thành bản MPU6050 + JSN-SR04T, đồng thời đổi giao diện Web từ LiDAR TRÁI/GIỮA/PHẢI thành CẢM BIẾN TRƯỚC, giữ nguyên các phần còn lại

Lưu ý ECHO của JSN-SR04T thường là mức 5 V. Không đưa trực tiếp vào ESP32. Dùng chia áp, ví dụ:

JSN ECHO
   |
  4.7k
   |
   +-------- GPIO17 ESP32
   |
  10k
   |
  GND

TRIG từ GPIO16 → TRIG JSN có thể điều khiển trực tiếp.

 

Bình luận
Nội dung này chưa có bình luận, hãy gửi bình luận đầu tiên của bạn.
VIẾT BÌNH LUẬN CỦA BẠN