ชมรมโดรน

4. drone.* คำสั่งแบบอ่านง่าย

wrapper จาก DroneEasy.hpp/.cpp ที่ห่อ pArduino-> ให้สั้นลง พร้อมการเบรกในตัว

ถ้า pArduino-> คือการเขียนใบสั่งยาวๆ ส่งเข้าครัว drone.* ก็คือปุ่มลัดบนจอสั่งอาหาร กดทีเดียวได้ครบชุด ทุกภารกิจของชมรมเขียนด้วย drone.* เป็นหลัก drone เป็นตัวแปรเดียวของคลาส DroneEasy ประกาศไว้ที่ DroneEasy.cpp (DroneEasy drone;)

ลำดับชั้นของคำสั่ง drone.fw()จาก drone.fw ลงไป pArduino แล้วเป็นไบต์ I2Cdrone.fw(250)Drone_Mission.inoชั้นที่เราเขียนทุกวันpArduino->move_forward_cm(250)DroneEasy.cpp + settle(400)ห่อให้สั้น + เบรกต่อท้ายset_direction(1, 2) · delay · posholdprotocol.cppนับเวลาจาก MS_PER_CM_FWDแพ็กเก็ต 6 ไบต์ผ่าน I2Cไปที่ Flight ControllerFC คุมใบพัดเอง
drone.fw(250) ไล่ลงไปทีละชั้น จนกลายเป็นไบต์ที่ส่งไปให้ Flight Controller

1. เดินหน้า ถอยหลัง เลื่อนข้าง: fw bw ml mr

// DroneEasy.cpp
void DroneEasy::settle(uint16_t ms) const {
  pArduino->set_direction(7, 1);
  delay(ms);
}

void DroneEasy::fw(int cm) const { pArduino->move_forward_cm(cm); settle(400); }
void DroneEasy::bw(int cm) const { pArduino->move_backward_cm(cm); settle(400); }
void DroneEasy::ml(int cm) const { pArduino->move_left_cm(cm); settle(400); }
void DroneEasy::mr(int cm) const { pArduino->move_right_cm(cm); settle(400); }

void DroneEasy::sh(int z) const {
  pArduino->set_height(z);
  delay(400);
}

ลองกดดูทีละคำสั่ง ภาพคือสิ่งที่โดรนทำ หลัง บรรทัดนั้นถูกรัน (เริ่มจากโดรนลอยอยู่ที่ 110 ซม.)

กำลังโหลดโดรน 3 มิติ…
drone.fw(150);

ลูกศรแดง = ทิศหัวโดรน · เส้นฟ้า = เส้นทาง · ภาพช่วยเข้าใจ ไม่ใช่สเกลจริง

ไปข้างหน้า 150 ซม.

โดรนเอียงตัวเล็กน้อยแล้วไปข้างหน้า 150 ซม. โค้ดรอ 150 × 15.46 = 2319 ms จากนั้นสั่งเบรกให้ลอยนิ่ง

เวลาจริงบนโดรนประมาณ 2.72 วินาที (ในภาพเร่งให้ดูง่าย)

คำสั่งความหมายทำอะไรจริง
drone.fw(cm)เดินหน้าmove_forward_cm(cm) แล้ว settle(400)
drone.bw(cm)ถอยหลังmove_backward_cm(cm) แล้ว settle(400)
drone.ml(cm)เลื่อนซ้ายmove_left_cm(cm) แล้ว settle(400)
drone.mr(cm)เลื่อนขวาmove_right_cm(cm) แล้ว settle(400)
drone.sh(z)ตั้งความสูง z ซม.set_height(z) แล้วรอ 400 ms
drone.settle(ms)หยุดนิ่งรอset_direction(7, 1) แล้วรอ ms (ค่าตั้งต้น 220)

settle ต่างจากเบรกท้าย move_*_cm ตรงที่ใช้ speed 1 (ช้า) และรอเวลานานกว่า ผลคือโดรนนิ่งจริงก่อนคำสั่งถัดไป

เส้นเวลาของ drone.fw(250)สั่งหน้า รอ 3865 มิลลิวินาที เบรกด้วย poshold แล้ว settle 400 มิลลิวินาทีเครื่องบินหน้าอยู่ (delay 3865 ms)250 × 15.46 = 3865settle 400 msset_direction(1,2)poshold(2)dir 7 ความเร็ว 1รวมประมาณ 4.27 วินาทีต่อ fw(250)
drone.fw(250): บินหน้า 3865 ms เบรกด้วย poshold(2) แล้วนิ่งอีก 400 ms รวมราว 4.27 วินาที

2. เขียนต่อกันเป็นขบวน

เขียนต่อกันได้เลยโดยไม่ต้อง delay เอง เพราะแต่ละคำสั่งรอและเบรกให้ในตัว ลองกดดูทีละบรรทัด

กำลังโหลดโดรน 3 มิติ…
drone.fw(250);

ลูกศรแดง = ทิศหัวโดรน · เส้นฟ้า = เส้นทาง · ภาพช่วยเข้าใจ ไม่ใช่สเกลจริง

1ไปข้างหน้า 250 ซม.

โดรนเอียงตัวเล็กน้อยแล้วไปข้างหน้า 250 ซม. โค้ดรอ 250 × 15.46 = 3865 ms จากนั้นสั่งเบรกให้ลอยนิ่ง

เวลาจริงบนโดรนประมาณ 4.27 วินาที (ในภาพเร่งให้ดูง่าย)

drone.fw(250);
drone.ml(255);
drone.mr(480);
drone.bw(8);

3. ตั้งแต่ calibrate ถึงลงจอด

กำลังโหลดโดรน 3 มิติ…
drone.calibration();

ลูกศรแดง = ทิศหัวโดรน · เส้นฟ้า = เส้นทาง · ภาพช่วยเข้าใจ ไม่ใช่สเกลจริง

1calibrate ตั้งศูนย์ไจโร

โดรนนอนนิ่งบนพื้น มอเตอร์ไม่หมุน ไจโรอ่านค่าตอนนิ่งเก็บไว้เป็น "ศูนย์" ห้ามจับหรือขยับจนกว่าจะรอครบ (ชมรมใช้ 3 วินาที)

เวลาจริงบนโดรนประมาณ 3.00 วินาที (ในภาพเร่งให้ดูง่าย)

drone.calibration();             // ตั้งศูนย์
drone.calibrateAndDelay(3000);   // ตั้งศูนย์ + รอ 3000 ms
drone.takeOff();
drone.autoLand();
drone.stopMotor();               // ฉุกเฉิน ตัดมอเตอร์
drone.wait(1000);                // = delay(1000)
drone.poll();                    // ดึงข้อมูลสดจาก FC

4. เลือก speed เอง: move* และ moveFast*

drone.moveForward(100);        // speed 2 เหมือน fw แต่ไม่มี settle(400)
drone.moveLeft(100, 1);        // ช้ากว่า
drone.moveFastForward(243);    // speed 3 ใช้ MS_PER_CM_FWD_FAST ไม่มีเบรก
กลุ่มคำสั่งค่าตั้งต้น speed
ปกติmoveForward moveBackward moveLeft moveRight2
เร็วmoveFastForward moveFastBackward moveFastLeft moveFastRight3

ข้อควรระวัง: ค่า MS_PER_CM_* วัดมาที่ speed ค่าตั้งต้นของกลุ่มนั้น เปลี่ยน speed แล้วระยะจะเพี้ยน ดู ระยะกับเวลา

5. ความสูงและลอยนิ่ง

กำลังโหลดโดรน 3 มิติ…
drone.sh(60);

ลูกศรแดง = ทิศหัวโดรน · เส้นฟ้า = เส้นทาง · ภาพช่วยเข้าใจ ไม่ใช่สเกลจริง

1ตั้งความสูง 60 ซม.

โดรนปรับแรงยกให้ลอยที่ความสูง 60 ซม. จากพื้น ถ้าอยู่ต่ำกว่าจะขึ้น ถ้าสูงกว่าจะลง

เวลาจริงบนโดรนประมาณ 0.40 วินาที (ในภาพเร่งให้ดูง่าย)

drone.setHeight(110);            // set_height ไม่รอ
drone.holdHeight(110, 2);        // set_height แล้ว poshold(2)
drone.smoothSetHeight(120);      // ค่อยๆ ขยับทีละ 10 ซม. (step 10, delay 200)
drone.posHold();                 // poshold(2)
drone.direction(5, 3);           // set_direction(5, 3) ทิศอะไรก็ได้
drone.up(3, 300);                // ขึ้น speed 3 รอ 300 ms
drone.down(3, 300);              // ลง speed 3 รอ 300 ms
uint16_t h = drone.heightCm();   // ความสูงล่าสุดจาก get_height_cm()
  • sh(z) เหมาะกับท่อนที่ต้องรอให้ถึงก่อนไปต่อ ส่วน setHeight(z) ส่งแล้วไปต่อทันที
  • drone.up และ drone.down ค่าตั้งต้น speed คือ 3 (ต่างจาก pArduino->up ที่ใช้ 2) และไม่หยุดเอง
  • heightCm() ต้องเรียก drone.poll() ก่อนจึงได้ค่าล่าสุด

6. คำสั่งอื่นที่ห่อไว้ครบ

drone.เรียก pArduino->
rotate()rotate()
flip()flip() (ว่างเปล่า)
circle360()circle_360()
jump() และ jumpEnd()jump() และ jump_end()
picture()picture()
videoBegin() และ videoEnd()video_begin() และ video_end()
motor(num, speed)motor(num, speed)
setPos(x, y)set_pos(x, y)
setYaw(rotate, angle)set_yaw(rotate, angle)
raw()คืน *pArduino ไว้เรียกเมธอดที่ไม่มีใน wrapper

7. ตัวช่วยวัดระยะ: mToCm และ moveTimeDir

uint16_t cm = DroneEasy::mToCm(2.5f);   // 250 (แปลงเมตรเป็นซม. ปัดเศษ)

drone.moveTimeDir(1, 100, 15.46f);      // dir 1 หน้า 100 ซม. ใช้ 15.46 ms/cm

moveTimeDir(dir, cm, ms_per_cm, speed) ให้ใส่ค่า ms/cm เอง แล้วเบรกด้วย set_direction(7, 1) และรอ 220 ms เหมาะกับการลองค่าใหม่โดยไม่ต้องแก้ config.hpp ใช้ตอนวัดตามหน้า ระยะกับเวลา

8. ปุ่มรีโมท

drone.onKey1(handler);    // ถึง onKey14
drone.onKey(5, handler);  // เลขปุ่มตรงๆ

อ่านต่อที่ ปุ่มรีโมท คำสั่งเซอร์โว ปล่อยบอล และยิง (servoRelease, swipeLeftS1, dropPayload, reachShootHeightStable ฯลฯ) ห่อไว้ใน DroneEasy เหมือนกัน แต่อธิบายในหมวดกลไก เช่น ปล่อยสัมภาระ

ลองทำ

  1. เขียนบรรทัดบินสี่เหลี่ยมจัตุรัสด้านละ 100 ซม. ด้วย fw mr bw ml
  2. เทียบ drone.fw(100) กับ drone.moveForward(100) ต่างกันกี่ ms ต่อครั้ง (ตอบ: ต่างกันที่ settle(400) คือ 400 ms)
  3. เขียน drone.moveTimeDir(1, 100, 15.46f) แล้วเทียบระยะที่ได้กับ fw(100)

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

  • เรียก drone.up() โดยไม่ตามด้วย posHold() โดรนไต่ต่อไม่หยุด
  • ใช้ moveFast* แล้วโดรนไหลเลย ไม่มีเบรกท้ายคำสั่ง ต้องใส่ drone.settle() เอง
  • สับสน sh กับ setHeight ตัวแรกรอ 400 ms ตัวหลังไม่รอ
  • ใช้ชื่อสั้นผิดตัวพิมพ์ เขียน Fw ตัวพิมพ์ใหญ่ หรือ setheight ตัวเล็กหมด จะ compile ไม่ผ่าน ชื่อต้องตรงกับ DroneEasy.hpp ทุกตัวอักษร

On this page