1. คำสั่งเดินทางยังไง
โปรโตคอลสามชั้นของ RCSA: serial AB CD LEN, I2C 6 ไบต์ และเฟรมฝูงบิน 0xFA พร้อม CRC-16
เวลาคุณกด "บิน" คำสั่งไม่ได้ไปถึงมอเตอร์ในทีเดียว มันผ่านหลายด่านเหมือนจดหมายที่ผ่านที่ทำการไปรษณีย์หลายแห่ง แต่ละด่านใช้ซองคนละแบบ
หน้านี้เป็นแผนที่รวม อ่านจบจะรู้ว่า "ซอง" แต่ละชั้นหน้าตาเป็นอย่างไร แล้วค่อยไปอ่านรายละเอียดทีละชั้น
ที่มาของข้อมูล
ชั้น 1 และ 3 อ่านจากบันทึก RCSA_PROTOCOL_FULL_NOTES.md ที่สกัดมาจากแอป RCSA 1.0.0 (main.js, lib.min.js) ชั้น 2 อ่านจากโค้ดจริงของชมรม protocol.cpp และ protocol.hpp ภายใน Flight Controller (PID, mixer, การสร้าง PWM ให้ ESC) ไม่มีในไฟล์ใดเลย หน้านี้จึงไม่อ้างอะไรเกี่ยวกับมัน
ชั้น 1: serial ระหว่างคอมพิวเตอร์กับรีโมท
แอป RCSA ส่งคำสั่งไปยังรีโมทผ่านพอร์ต USB เป็นเฟรมโครงเดียวกันทุกคำสั่ง
แอป → รีโมท AB CD LEN PAYLOAD...
รีโมท → แอป DC BA LEN PAYLOAD...AB CDคือสองไบต์หัวเฟรม (0xAB 0xCD) ฝั่งตอบกลับใช้DC BALENคือความยาวของ payload เป็นไบต์- ไบต์แรกของ payload คือ รหัสคำสั่ง ที่เหลือคือพารามิเตอร์
เหมือนซองจดหมาย ที่หน้าซองเขียนว่า "จดหมายจากแอป" (หัวเฟรม) น้ำหนักเท่าไร (LEN) แล้วจึงเป็นเนื้อความ
ขอเวอร์ชัน (version = 13)
- AB[0]
- CD[1]
- 01LEN
- 0Dคำสั่ง 13
สั่งขึ้นบิน (takeOff = 16)
- AB[0]
- CD[1]
- 01LEN
- 10คำสั่ง 16
สั่งลงจอด (autoLand = 17)
- AB[0]
- CD[1]
- 01LEN
- 11คำสั่ง 17
เฟรมที่ซับซ้อนขึ้นมีพารามิเตอร์ต่อท้าย เช่นสั่งความเร็วแนวนอน (vel_control = 27)
vel_control XY: [27, 2, 0, vy, vx, 0]
- AB[0]
- CD[1]
- 06LEN
- 1Bคำสั่ง 27
- 02ชนิด XY
- 00[5]
- VY[6]
- VX[7]
- 00[8]
ค่า VY VX เป็นไบต์หลังแปลงเครื่องหมายแล้ว (ตามบันทึก) ส่วนค่า 16 บิตเช่นมุม setYaw = [18, rotate, angle_lo, angle_hi] ส่งไบต์ต่ำก่อนไบต์สูง (little-endian)
รหัสคำสั่งบางตัว
| รหัส | ชื่อ | ใช้ทำอะไร |
|---|---|---|
1–8 (0x01–0x08) | motor_1…motor_8 | สั่งมอเตอร์ตัวที่ N ตามบันทึก payload คือ [N, speed] |
10 (0x0A) | calibrate | ตั้งศูนย์ |
13 (0x0D) | version | ถามเวอร์ชัน |
14 (0x0E) | get_dataPackage | ขอข้อมูลสถานะ (แอปขอหลังรู้เวอร์ชัน) |
16 (0x10) | takeOff | ขึ้นบิน |
17 (0x11) | autoLand | ลงจอด |
18 (0x12) | set_rotate | หมุนหัว (yaw) |
27 (0x1B) | vel_control | สั่งความเร็ว |
29 (0x1D) | mode_control | สั่งโหมด เช่น ขึ้นบินและค้างความสูง |
30 (0x1E) | pos_control | สั่งตำแหน่ง/ความสูง |
31 (0x1F) | flip | พลิกตัว |
| 100–166 | formation_* | คำสั่งโหมดฝูง |
250 (0xFA) | formation_test | ทดสอบ |
ตารางเต็มมีรหัสหลายสิบตัวในบันทึก ดึงมาเฉพาะที่ใช้ในบทนี้
แอปหาพอร์ตของรีโมทโดยดูรหัสอุปกรณ์ USB สองแบบ คือ CP210x (VID 10C4 / PID EA60) และ CH340 (VID 1A86 / PID 7523)
ชั้น 2: I2C ระหว่าง Arduino กับ Flight Controller
โค้ดที่ชมรมเขียนใน Arduino ไม่ได้ส่งเฟรม AB CD ที่ชั้น 1 มันคุยกับ Flight Controller ด้วย I2C ผ่านแพ็กเก็ต 6 ไบต์ ที่เก็บไว้ในตัวแปร m_i2cData
static char m_i2cData[6];
void Arduino::take_off(void) {
m_i2cData[0]++; // ตัวนับ: บอกว่ามีคำสั่งใหม่
m_i2cData[1] = Arduino::F_ARM; // รหัสคำสั่ง
}ไบต์แรกเป็นตัวนับที่บวกทุกครั้งที่มีคำสั่งใหม่ ไบต์ที่สองคือรหัสคำสั่ง ที่เหลือคือพารามิเตอร์ คำสั่งส่วนใหญ่ของ DroneEasy ลงเอยแบบนี้ รายละเอียดทีละไบต์อยู่ที่ แพ็กเก็ต I2C
ชั้น 3: เฟรมโหมดฝูงบิน
เมื่อควบคุมหลายลำพร้อมกัน เฟรมจะขึ้นต้นด้วยไบต์ 0xFA ตามด้วยข้อมูล และจบด้วย CRC-16 สองไบต์ (ต่ำก่อนสูง) ตัวรับใช้ CRC เช็กว่าข้อมูลไม่เพี้ยนระหว่างทาง รองรับสูงสุด 20 ลำ ดู โหมดฝูงบิน
เทียบสามชั้น
| ชั้น 1 | ชั้น 2 | ชั้น 3 | |
|---|---|---|---|
| เชื่อมอะไร | แอป ↔ รีโมท | Arduino ↔ Flight Controller | สถานี ↔ ฝูงโดรน |
| ช่องทาง | USB serial | I2C (Arduino ที่อยู่ 0x33) | TCP/UDP |
| หัว | AB CD / DC BA | ไม่มี (6 ไบต์ตายตัว) | 0xFA |
| ตรวจความถูกต้อง | ไม่ระบุในบันทึก | ไม่มีในโค้ด | CRC-16 |
| ที่มา | บันทึกโปรโตคอล | protocol.cpp | บันทึกโปรโตคอล |
ลองทำ
- เขียนเฟรมของคำสั่ง
calibrate(รหัส 10) ด้วยมือเป็นเลขฐานสิบหก คำตอบ:AB CD 01 0A - เขียนเฟรม
setYawหมุนขวา (สมมติrotate= 1) 90 องศา เป็นไบต์ คำตอบ: payload12 01 5A 00ดังนั้นAB CD 04 12 01 5A 00(90 =0x005Aส่งไบต์ต่ำ5Aก่อน) - เปิด
protocol.cppดูว่าฟังก์ชันไหนบวกm_i2cData[0]บ้าง แล้วนับว่ามีกี่ฟังก์ชัน
พังตรงไหนบ่อย
- สับสนตารางรหัสสามชุด
takeOffมีรหัส 16 ที่ชั้น 1, รหัส 1 (F_ARM) ที่ชั้น 2 และรหัส 1 ในคำสั่งฝูง (แต่เป็นคนละตาราง) อย่าคัดลอกเลขข้ามชั้น - สลับไบต์ต่ำ/สูง ค่า 16 บิตส่งไบต์ต่ำก่อนเสมอ
- ลืม LEN LEN นับเฉพาะ payload ไม่รวมหัวสองไบต์และตัว LEN เอง
- คิดว่าเปลี่ยนโค้ดแล้วเปลี่ยนการบินได้ทุกอย่าง ส่วนที่ทำให้โดรนเอียงหรือหมุนมอเตอร์อยู่ใน Flight Controller เราสั่งได้แค่ผ่านคำสั่งที่มันเปิดให้
- อ้างตัวเลขภายใน FC ไม่มีค่า PID หรือสูตร mixer ในไฟล์ใด ถ้าไม่มีหลักฐานอย่าเขียนลงรายงาน