ชมรมโดรน

1. ปล่อยสัมภาระด้วยเซอร์โว

เซอร์โว 2 ตัวคุมประตูบอล 4 ช่อง อ่านค่า pulse 1900 / 1000 / 2550 / 490 จากโค้ดของชมรม

ภารกิจทิ้งสัมภาระต้องปล่อยลูกบอลลงแท่นให้ตรง ชุดปล่อยของชมรมใช้ เซอร์โว 2 ตัว แต่มี ประตู 4 ช่อง เพราะเซอร์โวหนึ่งตัวดันประตูได้สองบาน โดยดันไปคนละทิศ

คิดเหมือนประตูบานเลื่อนสองบานที่ผูกกับก้านเดียวกัน ดันก้านไปซ้ายบานหนึ่งเปิด ดันไปขวาอีกบานเปิด ตรงกลางคือปิดทั้งคู่

1. เซอร์โวฟังอะไร

เซอร์โวไม่รู้จักคำว่า "องศา" มันรู้จักแค่ ความกว้างของพัลส์ สายสัญญาณถูกยกเป็น HIGH ทุก 20 มิลลิวินาที ยาวกี่ไมโครวินาที เซอร์โวก็หมุนไปตำแหน่งนั้น

เฟรมสัญญาณเซอร์โว 20 มิลลิวินาทีพัลส์สูง 1000 ไมโครวินาทีกับ 2550 ไมโครวินาที ในเฟรมยาว 20 มิลลิวินาที1 เฟรม = 20,000 µs (ทำซ้ำต่อเนื่อง 1.5 วินาที)HIGH 1000 µsHIGH 2550 µsเริ่มเฟรมเริ่มเฟรมถัดไปส่วนที่เหลือของเฟรมเป็น LOW: delayMicroseconds(20000 − pulse)
พัลส์ยาว 1000 µs กับ 2550 µs ในเฟรม 20 ms เซอร์โวจะไปคนละตำแหน่ง ส่วนที่เหลือของเฟรมเป็น LOW

โค้ดเต็มของการส่งพัลส์อยู่ใน Servo.ino ฟังก์ชันเดียว

void release_servo_angle(uint8_t port_pin, int pulseWidth) {
  uint32_t t = micros();
  while (micros() - t < 1500000) {
    digitalWrite(port_pin, HIGH);
    delayMicroseconds(pulseWidth);
    digitalWrite(port_pin, LOW);
    delayMicroseconds(20000 - pulseWidth);
  }
}

อ่านทีละบรรทัด

  • วนซ้ำ 1.5 วินาที (1,500,000 µs) ให้เซอร์โวมีเวลาไปถึงตำแหน่ง
  • ยกขา HIGH ค้างเท่า pulseWidth แล้วกด LOW ที่เหลือของเฟรม 20,000 µs
  • ฟังก์ชันนี้ บล็อกโปรแกรม ตลอด 1.5 วินาที ระหว่างนั้น Arduino ทำอย่างอื่นไม่ได้

ถ้าสั่งสองตัวพร้อมกัน ใช้ release_dual_servo_angle(pin1, pulse1, pin2, pulse2) ฟังก์ชันนี้ยก HIGH พร้อมกัน ตัวที่พัลส์สั้นกว่าลง LOW ก่อน แล้วรอส่วนต่าง จากนั้นปิดทั้งคู่

2. ใช้พอร์ตไหน

protocol.hpp กำหนดขาของแต่ละพอร์ต ชุดปล่อยบอลใน Drone_Mission.ino ใช้สองพอร์ต

พอร์ตช่องที่คุมค่าคงที่
PORT3ช่อง 1 และ 2BALL_SERVO_12_PIN
PORT6ช่อง 3 และ 4BALL_SERVO_34_PIN
เซอร์โว 2 ตัวคุมประตูบอล 4 ช่องPORT3 คุมช่อง 1 และ 2 PORT6 คุมช่อง 3 และ 4 พร้อมค่าพัลส์เปิดของแต่ละช่องเซอร์โว PORT3ช่อง 1เปิด 450µsช่อง 2เปิด 2000µsเซอร์โว PORT6ช่อง 3เปิด 1900µsช่อง 4เปิด 500µsปิดทั้งสองตัว: 1200 µs · เปิดทั้งหมด: 2550 (PORT3) และ 2600 (PORT6)ตัวเลขทั้งหมดอ่านจาก Drone_Mission.ino (BALL_*_US)
เซอร์โวสองตัว ประตูสี่บาน ตัวเลขใต้ช่องคือพัลส์ที่ใช้เปิดช่องนั้น

3. ค่า pulse ในโค้ดมีสองชุด

ในโฟลเดอร์ drone_sanam5 มีค่า pulse ปรากฏสองชุด ที่ไม่เหมือนกัน ดูทั้งสองชุดให้ชัดก่อนแก้อะไร

Servo.ino · README.ino · Test_ball.inoDrone_Mission.ino (ที่ภารกิจใช้)
ปิด19001200 (BALL_12_CLOSE_US, BALL_34_CLOSE_US)
ช่อง 11000450
ช่อง 225502000
ช่อง 31000 (PORT6)1900
ช่อง 42550 (PORT6)500
เปิดทั้งหมด490 (drop_payload_all4) หรือ 25502550 (PORT3) และ 2600 (PORT6)

เลข 1900 จึงมีความหมายไม่เหมือนกัน ในชุดแรกคือ "ปิด" ในชุดหลังคือ "เปิดช่อง 3" ชุดแรกเขียนไว้ให้ทดสอบทีละพอร์ต ส่วนชุดหลังคือชุดที่ setupDroneMissionMode() ใช้ตอนเริ่มต้น (มันเรียก close_all_ball_gate() ซึ่งใช้ 1200)

อย่าผสมสองชุด

ถ้าเรียก release_servo_angle(PORT3, 1900) ในโค้ดภารกิจ ประตูจะไม่ปิดเหมือนที่ README บอก เพราะตำแหน่งปิดของชุดภารกิจคือ 1200 ดูว่าไฟล์ไหนเป็นต้นทางของค่านั้นก่อนคัดลอก

4. ขั้นตอนปล่อยจริง (ดูภาพก่อน แล้วอ่านโค้ดตามลำดับ)

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

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

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

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

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

ลดความสูงเหลือ 45 ซม. ปล่อยบอล แล้วลงจอด

ภารกิจไม่ได้เรียก release_servo_angle ตรงๆ แต่ห่อเป็นชื่อที่อ่านง่ายใน Drone_Mission.ino

void open_pair_ch1_ch4() {
  drone.servoReleaseDual(
    BALL_SERVO_12_PIN, BALL_CH1_OPEN_US,
    BALL_SERVO_34_PIN, BALL_CH4_OPEN_US);
}

void mission_drop_ch1_ch4() {
  open_pair_ch1_ch4();
  delay(MISSION_DROP_WAIT_MS);   // 300 ms
  close_all_ball_gate();
  delay(MISSION_CLOSE_WAIT_MS);  // 100 ms
}

ปล่อยเป็นคู่ ช่อง 1 กับ 4 หรือ ช่อง 2 กับ 3 ตัวแปร payload_round10 ในโค้ดอธิบายไว้ว่า 0 = ปล่อยช่อง 1&4 และ 1 = ปล่อยช่อง 2&3 ซึ่งตรงกับตัวจำลองบนเว็บนี้ที่ตั้งแท่นฝั่งซ้ายเป็นประตู 1&4 และฝั่งขวาเป็น 2&3

ลองนับเวลาหนึ่งครั้งที่ปล่อย เพราะฟังก์ชัน servo บล็อก 1.5 วินาทีต่อครั้ง

เปิดคู่      1.5 วินาที
รอ           0.3 วินาที   (MISSION_DROP_WAIT_MS)
ปิดทุกช่อง   1.5 วินาที
รอ           0.1 วินาที   (MISSION_CLOSE_WAIT_MS)
รวม         ≈ 3.4 วินาที ต่อการปล่อยหนึ่งครั้ง

สี่แท่นก็ราว 13.6 วินาที ตัวเลขนี้คำนวณจากค่าในโค้ด ไม่ได้จับเวลาจริง ต้องเผื่อไว้ในงบ 150 วินาที

5. ฟังก์ชันปล่อยตามรอบใน Servo.ino

Servo.ino มีชุดฟังก์ชันที่เลือกการปล่อยตามหมายเลขรอบ (round) เพื่อไม่ต้องเขียนเลขซ้ำ

ฟังก์ชันรอบ 0รอบ 1รอบ 2รอบ 3
drop_payload_by_round05PORT3 → 1000PORT6 → 1000PORT3 → 2550PORT6 → 2550
drop_payload_by_round10คู่ PORT3 1000 · PORT6 1000คู่ 2550คู่ 1000คู่ 2550
drop_payload_by_round_allคู่ 1000คู่ 2550ไม่มีไม่มี

และ drop_payload_all4() เปิดสุดที่ 490 รอ 300 ms แล้วกลับมาที่ 1900

void drop_payload_all4() {
  release_dual_servo_angle(PORT6, 490, PORT3, 490);
  delay(300);
  release_dual_servo_angle(PORT6, 1900, PORT3, 1900);
}

ถ้าเขียนด้วย DroneEasy เรียกผ่านชื่อสั้น ๆ ได้เลย เช่น drone.dropPayloadRound05(0) หรือ drone.servoReleaseDual(PORT3, 1000, PORT6, 1000)

ลองทำ

  1. เปิด Test_ball.ino อ่านลำดับใน test_release_the_ball() ทีละบรรทัด เดาก่อนว่าประตูไหนจะขยับ แล้วค่อยรันกับชุดบนโต๊ะ (ถอดใบพัดก่อนเสมอ)
  2. ลองเลื่อนค่าเปิดช่อง 1 (450) ขึ้นทีละ 25 แล้วดูว่าประตูเปิดกว้างขึ้นหรือแคบลง จดค่าที่บอลหลุดครบพอดี
  3. คำนวณเวลาปล่อยทั้ง 4 แท่นของท่า T เมื่อใช้ mission_drop_ch1_ch4 สองครั้งและ mission_drop_ch2_ch3 สองครั้ง ว่าเหลือเวลาบินกี่วินาทีจาก 150
  4. ดูโดรนปล่อยบอลในตัวจำลอง
ดูตัวอย่างปล่อยบอลในตัวจำลอง

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

  • ประตูไม่ปิดสนิท บอลหลุดระหว่างบิน ปรับค่าปิด (1200 ในชุดภารกิจ) ทีละ 25–50 ตามที่ README.ino แนะนำ
  • เซอร์โวสั่นแล้วร้อน ค่า pulse ต่ำหรือสูงเกินช่วงที่กลไกไปถึงได้ เซอร์โวดันชนขอบ คอมเมนต์ในโค้ดเขียนไว้ว่าค่าต่ำไปทำให้เซอร์โวดันสุดแล้วสั่น
  • ใช้ค่าผิดชุด คัดลอก 1900 จาก README ไปใช้ในโค้ดภารกิจ แล้วประตูช่อง 3 เปิดเอง
  • ลืม pinMode ถ้าขาไม่ได้เป็น OUTPUT เซอร์โวนิ่ง setupDroneMissionMode() ตั้ง PORT3 กับ PORT6 ไว้แล้ว อย่าลบ
  • นับเวลาไม่ครบ ฟังก์ชัน servo บล็อกทีละ 1.5 วินาที หลายครั้งรวมกันกินงบเวลาจากที่คิดไว้
  • เปิดคู่ผิดคู่ ปล่อยช่อง 1&4 ที่แท่นซ้ายแล้วค่อยปล่อย 2&3 ที่แท่นขวา ถ้าสลับ บอลจะลงผิดแท่น

อ่านต่อที่ การจูนเซอร์โวด้วยองศา เพื่อเลิกจำเลข µs ด้วยมือ

On this page