4. จูนเซอร์โวด้วยองศา
แปลงองศา 0–180 เป็นความกว้างพัลส์ ด้วย Servo_Degree.ino และเลิกจำเลข µs ด้วยมือ
หน้าก่อนหน้าสั่งเซอร์โวด้วยตัวเลขอย่าง 1000 และ 2550 ซึ่งเป็นความกว้างพัลส์ในหน่วยไมโครวินาที คนที่ไม่ได้ตั้งค่ามาเองอ่านแล้วไม่รู้ว่าประตูอยู่ตรงไหน Servo_Degree.ino แก้เรื่องนี้ด้วยการให้สั่งเป็น องศา แล้วแปลงเป็นพัลส์ให้
เหมือนสั่งก๊อกน้ำว่า "เปิดครึ่งหนึ่ง" แทนที่จะบอก "หมุนสามรอบครึ่ง" ต้นทางยังเป็นพัลส์เหมือนเดิม แค่มีตัวแปลงคั่น
1. ช่วงของเซอร์โวชุดนี้
ค่าปลายสองข้างอยู่บนสุดของไฟล์ เป็นค่า calibrate ของกลไกชุดนี้
const int SERVO_DEGREE_MIN = 0;
const int SERVO_DEGREE_MAX = 180;
const int SERVO_DEGREE_MIN_PULSE = 490; // pulse ที่ 0°
const int SERVO_DEGREE_MAX_PULSE = 2550; // pulse ที่ 180°
int servo_degree_to_pulse(int angle) {
angle = constrain(angle, SERVO_DEGREE_MIN, SERVO_DEGREE_MAX);
return map(angle, SERVO_DEGREE_MIN, SERVO_DEGREE_MAX,
SERVO_DEGREE_MIN_PULSE, SERVO_DEGREE_MAX_PULSE);
}constrain ตัดองศาให้อยู่ใน 0–180 ก่อน แล้ว map ย่อช่วงเส้นตรง สูตรเทียบเท่ากับ
pulse = 490 + องศา × (2550 − 490) / 180
= 490 + องศา × 11.44map ของ Arduino คำนวณด้วยจำนวนเต็ม เศษถูกตัดทิ้ง ผลขององศาที่ชมรมใช้ในโค้ดจึงเป็น
| องศา | ตัวแปรใน config.hpp | pulse ที่คำนวณ | ค่า pulse ตรงๆ ในไฟล์เดียวกัน |
|---|---|---|---|
| 62° | S_LEFT_ANGLE | 1199 µs | S_LEFT = 1200 |
| 88° | S_CLOSE_ANGLE | 1497 µs | S_CLOSE = 1500 |
| 132° | S_RIGHT_ANGLE | 2000 µs | S_RIGHT = 2000 |
| 90° | ตัวอย่างในคอมเมนต์ | 1520 µs |
คู่ค่าห่างกันไม่เกิน 3 µs ชวนให้เชื่อว่าสองชุดตัวเลขถูกเลือกให้ตรงกัน ผู้เขียนโค้ดไม่ได้บันทึกไว้ตรงๆ นี่คือข้อสังเกตจากตัวเลข
2. ลองเครื่องคิดเลข
เครื่องคิดเลขตั้งต้นที่ 500–2500 ซึ่งเป็นค่ามาตรฐานทั่วไป ให้พิมพ์ 490 และ 2550 ในสองช่องล่างให้ตรงกับชุดของชมรมก่อน
90° → พัลส์ 1500 µs (1.50 ms)
ลองใส่ 62, 88, 132 ดูว่าตรงกับตารางข้างบน (เครื่องคิดเลขปัดเป็นจำนวนเต็มต่างจาก map เล็กน้อย บางค่าอาจต่างกัน 1 µs)
3. เรียกใช้
ฟังก์ชันที่ห่อไว้ให้ใช้ต่อได้ทันทีมี 4 ตัว
release_servo_degree(PORT3, 90); // ตัวเดียว
release_dual_servo_degree(PORT3, 62, PORT6, 132); // สองตัวพร้อมกัน
release_servo_degree_custom(PORT3, 90, 600, 2400); // กำหนดช่วง pulse เองตัว _custom ไว้สำหรับเซอร์โวที่ปลายช่วงไม่เท่ากับ 490–2550 ส่ง pulse_min และ pulse_max ของตัวนั้นไปเอง และมี release_dual_servo_degree_custom สำหรับสองตัวต่างรุ่น ฟังก์ชันทั้งหมดเรียกต่อไปที่ release_servo_angle จึงบล็อก 1.5 วินาทีเหมือนกัน ผ่าน DroneEasy ก็ใช้ได้ เช่น drone.servoAngle(SHOOT1_PIN, S_LEFT_ANGLE)
4. จูนอย่างเป็นระบบ
ใช้ลำดับนี้ ซึ่งสอดคล้องกับคำแนะนำใน README.ino (ปรับทีละ 25–50 µs ทดสอบทีละช่องก่อนรวม)
- ถอดของที่เซอร์โวดันออก หรือถอดใบพัด ไม่มีใครถือโดรนที่ต่อแบตระหว่างจูน
- สั่ง
release_servo_degree(PORT3, 0)แล้วดูว่าก้านไปสุดข้างหรือชนขอบ ถ้าชน ให้เพิ่มSERVO_DEGREE_MIN_PULSEทีละ 25 - สั่ง 180° ทำแบบเดียวกันกับ
SERVO_DEGREE_MAX_PULSE - สั่ง 90° ต้องอยู่กลางจริง ถ้าไม่ใช่ แปลว่าเส้นไม่ตรงกลางพอดี
- จดองศาของตำแหน่ง "ปิด" "เปิด" ของแต่ละกลไกเป็นค่าคงที่ที่มีชื่อ (แบบ
S_LEFT_ANGLE) แล้วเรียกจากชื่อเสมอ
ลองทำ
- คำนวณด้วยมือว่า 45° ได้กี่ µs จากสูตร 490 + 45 × 11.44 แล้วเทียบกับเครื่องคิดเลข
- เขียนฟังก์ชันกลับด้าน
pulse_to_degreeที่แปลง µs เป็นองศา (คำใบ้: ใช้mapแต่สลับช่วง) แล้วลองกับ 1200, 1500, 2000 - ถ้ากลไกใหม่ใช้ช่วง 600–2400 ให้ใช้
release_servo_degree_custom(PORT3, 90, 600, 2400)แล้วตรวจว่าได้ 1500 µs
พังตรงไหนบ่อย
- ช่วงเริ่มต้นของเครื่องคิดเลขไม่ใช่ของเรา ลืมเปลี่ยนเป็น 490/2550 ได้ผลต่างหลายสิบ µs
- ใช้
Servo_Degreeกับพอร์ตที่ไม่ได้ตั้งpinModeเซอร์โวนิ่ง ดูว่าDroneEasy::beginDefault()ตั้งให้พอร์ตนั้นแล้ว - ปรับปลายช่วงจนกลไกชน เซอร์โวดันสุดแล้วสั่น ทำให้ร้อนและกินกระแส ถอยกลับ 25–50 µs
- องศาเกิน 180
constrainตัดให้เป็น 180 เงียบๆ โดยไม่เตือน ถ้าสั่ง 200 จะได้ 180 - คิดว่าแปลงกลับได้ โค้ดนี้แปลงทางเดียวจากองศาเป็นพัลส์ ไม่มีตัวอ่านองศาจากเซอร์โว
- ลืมว่าบล็อก ทุกฟังก์ชันนี้ใช้เวลา 1.5 วินาที ดูงบเวลาของภารกิจ