Camsense X1 + ESP32: đọc LiDAR và hiển thị bản đồ 2D trên trình duyệt
Camsense X1 là cảm biến LiDAR 2D quét 360°. Chỉ với một mạch ESP32 và 3 sợi dây, bạn đọc được dữ liệu quét laser và xem bản đồ thời gian thực ngay trên trình duyệt điện thoại hoặc máy tính — không cần cài phần mềm.
Bài này đi từ đấu dây, cấu trúc gói tin, đến 2 chương trình mẫu hoàn chỉnh
(Arduino .ino và ESP-IDF) đã chạy trên phần cứng thật.
Code mẫu: github.com/dungtsbb/camsense_x1_web
1. Phần cứng và nối dây
Linh kiện
- LiDAR Camsense X1
- Mạch ESP32 DevKit (ESP32-WROOM-32)
- Nguồn 5V ổn định (≥ 500mA) — có thể lấy từ chân
5V/VINcủa ESP32 khi cắm cổng USB tốt.
Đặc điểm của Camsense X1
- Tự động chạy: LiDAR tự quay và gửi dữ liệu ngay khi cấp nguồn 5V — không cần xung PWM hay lệnh khởi động.
- Chỉ cần 3 dây:
5V,GNDvàTX(truyền một chiều từ LiDAR sang vi điều khiển). - Mức logic 3.3V: chân
TXnối thẳng vào GPIO của ESP32, không cần mạch chuyển mức.
Bảng nối chân
| Chân Camsense X1 | Chân ESP32 | Chức năng |
|---|---|---|
| 5V | 5V / VIN | Nguồn cho mạch và mô-tơ quay (~300–320 vòng/phút) |
| GND | GND | Mass chung (bắt buộc) |
| TX | GPIO 16 (RX2) | Dữ liệu UART vào Serial2 của ESP32 |
Mạch ESP32-WROVER (có PSRAM): GPIO 16 và 17 dùng nội bộ cho PSRAM — đổi sang chân khác (ví dụ
GPIO 4hoặcGPIO 18) và sửa hằng sốLIDAR_RX_PINtrong code.
2. Giao thức UART
Camsense X1 truyền liên tục ở UART 115200 bps, 8N1. Mỗi vòng quay 360°, cảm biến gửi khoảng 50 gói tin, mỗi gói 8 điểm đo — tổng cộng ~400 điểm mỗi vòng.
Cấu trúc gói tin 36 byte
Mỗi gói dài đúng 36 byte, bắt đầu bằng header 4 byte cố định
0x55 0xAA 0x03 0x08:
+-------------------+------------+--------------+-------------------------------+--------------+-------------+
| Byte 0 .. 3 | Byte 4..5 | Byte 6..7 | Byte 8 .. 31 | Byte 32..33 | Byte 34..35 |
+-------------------+------------+--------------+-------------------------------+--------------+-------------+
| 0x55 0xAA 0x03 08 | Speed | Start Angle | 8 điểm x (2B Dist + 1B Qual) | End Angle | Checksum |
| (Header) | (2 bytes) | (2 bytes) | (24 bytes) | (2 bytes) | (2 bytes) |
+-------------------+------------+--------------+-------------------------------+--------------+-------------+
Mọi trường nhiều byte theo thứ tự little-endian (byte thấp trước):
uint16_t val = (uint16_t)buf[i] | ((uint16_t)buf[i + 1] << 8);
3. Lưu ý khi giải mã dữ liệu
Ba công thức riêng của Camsense X1 — dùng đúng thì dữ liệu ra chuẩn ngay.
Tốc độ quay
Giá trị rawSpeed (byte 4–5) bằng tần số quay (Hz) nhân 3840. Đổi sang vòng/phút:
RPM = rawSpeed / 64
Khi hoạt động bình thường, RPM nằm trong khoảng 300–330 vòng/phút.
Góc quét
Góc thô (rawStart, rawEnd) lấy mốc 0° tại 0xA000 (40960), mỗi độ là 64
đơn vị:
Góc (độ) = (rawAngle − 0xA000) / 64.0
Thực hiện phép trừ trong miền số nguyên không dấu 16-bit trước khi chia — khi gói tin quét qua mốc 0°, giá trị tự quấn vòng đúng mà không cần xử lý thêm:
float rawToDeg(uint16_t raw) {
return (float)(uint16_t)(raw - 0xA000) / 64.0f;
}
Góc của 8 điểm trong gói (i = 0..7) nội suy tuyến tính giữa góc đầu và góc cuối:
float span = endAngle - startAngle;
if (span < 0.0f) span += 360.0f; // gói vắt qua mốc 360° -> 0°
float step = span / 7.0f;
float angle_i = startAngle + step * i;
Checksum 15-bit
Hai byte cuối (byte 34–35) là tổng dịch trái 1 bit trên 17 word 16-bit đầu tiên (34 byte đầu), sau đó gập 32-bit xuống 15-bit:
uint16_t x1Checksum(const uint8_t *buf, size_t lenBytes) {
uint32_t chk32 = 0;
for (size_t i = 0; i < lenBytes / 2; i++) {
uint16_t word = (uint16_t)buf[2 * i] | ((uint16_t)buf[2 * i + 1] << 8);
chk32 = (chk32 << 1) + word;
}
uint16_t sum = (uint16_t)((chk32 & 0x7FFF) + (chk32 >> 15));
return sum & 0x7FFF;
}
Kiểm checksum giúp loại các gói hỏng do nhiễu đường truyền, và các trường hợp chuỗi byte khoảng cách tình cờ trùng với header.
4. Kiến trúc phần mềm trên ESP32
Ở 115200 baud, Camsense X1 gửi hơn 11.000 byte mỗi giây. Chương trình mẫu tách việc đọc LiDAR và phục vụ web ra hai luồng, để trang web tải nặng đến đâu dữ liệu quét vẫn đầy đủ:
- Task FreeRTOS ưu tiên cao (
lidarTask): chuyên đọc UART2 với bộ đệm 2048 byte, dò header, kiểm checksum và giải mã điểm đo. - Buffer kép:
-
s_building: mảng 360 ô (mỗi ô 1°) đang gom điểm. Khi góc đầu của gói mới nhỏ hơn gói trước — tức vừa quét xong một vòng — toàn bộs_buildingđược chép sangs_completetrong vùng khoátaskENTER_CRITICAL(vài micro giây). -
s_complete: vòng quét hoàn chỉnh, web server đọc và trả về quaGET /scandạng JSON:{"rpm":315,"seq":80,"err":0,"d":[1240,1245,0,890,...]}
-
Mảng d gồm 360 phần tử — phần tử thứ i là khoảng cách (mm) ở góc i độ,
0 là không có vật. Ứng dụng của bạn (Python, Node, app điện thoại…) đọc
trực tiếp từ endpoint này.
5. Chương trình mẫu
Repo camsense_x1_web có 2 bản, chọn theo môi trường quen dùng. Cả hai: ESP32 tự phát WiFi, giao diện radar HTML5 với 3 chế độ vẽ — điểm (point cloud), đa giác (đường bao phòng), tia quét — và đo khoảng cách bằng trỏ chuột.
git clone https://github.com/dungtsbb/camsense_x1_web.git
cd camsense_x1_web
A. Arduino IDE / Arduino CLI
Không cần cài thư viện ngoài. Trong Arduino IDE: mở
arduino/esp32_camsense_x1_radar/esp32_camsense_x1_radar.ino, chọn board
ESP32 Dev Module, Upload. Hoặc dùng Arduino CLI:
arduino-cli compile --fqbn esp32:esp32:esp32 arduino/esp32_camsense_x1_radar
arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32 arduino/esp32_camsense_x1_radar
B. ESP-IDF
cd esp-idf
idf.py set-target esp32
idf.py -p /dev/ttyUSB0 flash monitor
6. Xem kết quả
Sau khi nạp xong:
-
Kết nối điện thoại/máy tính vào WiFi
ESP32_LiDAR_X1(mật khẩu12345678). -
Mở trình duyệt, truy cập
http://192.168.4.1. -
Mở Serial Monitor ở baud
115200để theo dõi trạng thái mỗi 2 giây:vong quet=60 goi sai checksum=0 rpm=312 vong quet=70 goi sai checksum=0 rpm=313 vong quet=80 goi sai checksum=0 rpm=315
Đổi tên và mật khẩu WiFi tại hằng số AP_SSID / AP_PASS đầu file code.
Xử lý sự cố
| Hiện tượng | Cách khắc phục |
|---|---|
vong quet=0, rpm=0 |
Kiểm tra dây TX của LiDAR đã cắm đúng GPIO 16; kiểm tra mô-tơ LiDAR có quay |
Mô-tơ quay giật hoặc rpm dưới 250 |
Nguồn 5V bị sụt áp — dùng cáp USB tốt hoặc cấp nguồn 5V ngoài (nối chung GND) |
goi sai checksum tăng liên tục |
Nối chung GND giữa LiDAR và ESP32; kiểm tra dây TX tiếp xúc chắc chắn |
| Bản đồ bị xoay lệch hướng | Cộng góc bù vào biến rad trong hàm renderMap() của trang HTML theo hướng lắp trên robot |
7. Dùng với ROS2
Với robot chạy ROS2, nối LiDAR vào máy qua mạch USB–UART (TX → RX, 5V, GND) và
dùng driver ros2_camsense_x1
— publish sensor_msgs/LaserScan lên topic /scan:
mkdir -p ~/lidar_ws/src && cd ~/lidar_ws/src
git clone https://github.com/rossihwang/ros2_camsense_x1.git
git clone https://github.com/RoverRobotics-forks/serial-ros2.git
cd ~/lidar_ws && colcon build && source install/setup.bash
sudo chmod 666 /dev/ttyUSB0
ros2 run camsense_x1 camsense_x1_node --ros-args \
--params-file src/ros2_camsense_x1/param/config.yaml
Mở rviz2, đặt Fixed Frame = scan, thêm LaserScan với topic /scan.
Tài liệu cơ khí (bản vẽ lỗ bắt vít, file STEP/STL để thiết kế gá) có tại
Vidicon/camsense-X1.