ชมรมโดรน

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) ไม่มีในไฟล์ใดเลย หน้านี้จึงไม่อ้างอะไรเกี่ยวกับมัน

โปรโตคอลสามชั้นของโดรน RCSAชั้นแรก serial ระหว่างคอมพิวเตอร์กับรีโมท ชั้นสอง I2C ระหว่าง Arduino กับ Flight Controller ชั้นสาม เฟรมฝูงบินขึ้นต้นด้วย 0xFA1คอมพิวเตอร์แอป RCSAรีโมทUSB serialAB CD LEN …DC BA LEN …2บอร์ด Arduinoที่อยู่ I2C 0x33Flight Controllerที่อยู่ I2C 0x346 ไบต์ [n, F_*, …]8 ไบต์ (ความสูง …)3สถานีฝูงบินTCP / UDPโดรนหลายลำสูงสุด 20 ลำ0xFA … CRC lo hitelemetry 0xFA …
สามชั้น: คอมพิวเตอร์คุยกับรีโมทด้วย serial · Arduino คุยกับ Flight Controller ด้วย I2C · โหมดฝูงบินใช้เฟรมที่ขึ้นต้นด้วย 0xFA

ชั้น 1: serial ระหว่างคอมพิวเตอร์กับรีโมท

แอป RCSA ส่งคำสั่งไปยังรีโมทผ่านพอร์ต USB เป็นเฟรมโครงเดียวกันทุกคำสั่ง

แอป → รีโมท   AB CD LEN PAYLOAD...
รีโมท → แอป   DC BA LEN PAYLOAD...
  • AB CD คือสองไบต์หัวเฟรม (0xAB 0xCD) ฝั่งตอบกลับใช้ DC BA
  • LEN คือความยาวของ payload เป็นไบต์
  • ไบต์แรกของ payload คือ รหัสคำสั่ง ที่เหลือคือพารามิเตอร์

เหมือนซองจดหมาย ที่หน้าซองเขียนว่า "จดหมายจากแอป" (หัวเฟรม) น้ำหนักเท่าไร (LEN) แล้วจึงเป็นเนื้อความ

ขอเวอร์ชัน (version = 13)

  1. AB[0]
  2. CD[1]
  3. 01LEN
  4. 0Dคำสั่ง 13

สั่งขึ้นบิน (takeOff = 16)

  1. AB[0]
  2. CD[1]
  3. 01LEN
  4. 10คำสั่ง 16

สั่งลงจอด (autoLand = 17)

  1. AB[0]
  2. CD[1]
  3. 01LEN
  4. 11คำสั่ง 17

เฟรมที่ซับซ้อนขึ้นมีพารามิเตอร์ต่อท้าย เช่นสั่งความเร็วแนวนอน (vel_control = 27)

vel_control XY: [27, 2, 0, vy, vx, 0]

  1. AB[0]
  2. CD[1]
  3. 06LEN
  4. 1Bคำสั่ง 27
  5. 02ชนิด XY
  6. 00[5]
  7. VY[6]
  8. VX[7]
  9. 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–166formation_*คำสั่งโหมดฝูง
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 serialI2C (Arduino ที่อยู่ 0x33)TCP/UDP
หัวAB CD / DC BAไม่มี (6 ไบต์ตายตัว)0xFA
ตรวจความถูกต้องไม่ระบุในบันทึกไม่มีในโค้ดCRC-16
ที่มาบันทึกโปรโตคอลprotocol.cppบันทึกโปรโตคอล

ลองทำ

  1. เขียนเฟรมของคำสั่ง calibrate (รหัส 10) ด้วยมือเป็นเลขฐานสิบหก คำตอบ: AB CD 01 0A
  2. เขียนเฟรม setYaw หมุนขวา (สมมติ rotate = 1) 90 องศา เป็นไบต์ คำตอบ: payload 12 01 5A 00 ดังนั้น AB CD 04 12 01 5A 00 (90 = 0x005A ส่งไบต์ต่ำ 5A ก่อน)
  3. เปิด protocol.cpp ดูว่าฟังก์ชันไหนบวก m_i2cData[0] บ้าง แล้วนับว่ามีกี่ฟังก์ชัน

พังตรงไหนบ่อย

  • สับสนตารางรหัสสามชุด takeOff มีรหัส 16 ที่ชั้น 1, รหัส 1 (F_ARM) ที่ชั้น 2 และรหัส 1 ในคำสั่งฝูง (แต่เป็นคนละตาราง) อย่าคัดลอกเลขข้ามชั้น
  • สลับไบต์ต่ำ/สูง ค่า 16 บิตส่งไบต์ต่ำก่อนเสมอ
  • ลืม LEN LEN นับเฉพาะ payload ไม่รวมหัวสองไบต์และตัว LEN เอง
  • คิดว่าเปลี่ยนโค้ดแล้วเปลี่ยนการบินได้ทุกอย่าง ส่วนที่ทำให้โดรนเอียงหรือหมุนมอเตอร์อยู่ใน Flight Controller เราสั่งได้แค่ผ่านคำสั่งที่มันเปิดให้
  • อ้างตัวเลขภายใน FC ไม่มีค่า PID หรือสูตร mixer ในไฟล์ใด ถ้าไม่มีหลักฐานอย่าเขียนลงรายงาน

On this page