🚀 เริ่มต้นใช้งาน RazorRobot Simulator
แพลตฟอร์มจำลองหุ่นยนต์และการเขียนโปรแกรมเสมือนจริง รองรับทั้ง Block-based Programming และ C++ (Arduino Style)
หน้าจอจำลองถูกแบ่งออกเป็น 2 ฝั่งหลักเพื่อความสะดวกในการเรียนรู้และทดสอบโปรแกรม:
| ฟังก์ชัน | หน้าที่และการทำงาน | ตัวอย่างบล็อกที่เหมาะสม |
|---|---|---|
| void setup() | ทำงาน เพียง 1 ครั้ง เมื่อกดปุ่ม RUN เหมาะสำหรับการตั้งค่าเริ่มต้น, รอสัญญาณ หรือการวิ่งภารกิจแบบสเต็ปขั้นตอน | MOVE (กำหนดเวลา), หน่วงเวลา, หมุนในที่, ยิงปล่อยกล่อง |
| void loop() | ทำงาน วนซ้ำตลอดเวลา ไม่รู้จบ เหมาะสำหรับการอ่านเซนเซอร์เส้น, ตรวจจับสิ่งกีดขวาง หรือการเขียนเงื่อนไขตัดสินใจ | MOVE_LOOP (ไม่บล็อกเวลา), ถ้า...ให้ทำ (if), อ่านเซนเซอร์เส้น |
⏱️ หมวดบล็อค TIME (เวลาและการหน่วงเวลา)
คู่มือการใช้งานบล็อคในแถบสีฟ้า (TIME) สำหรับคนเริ่มต้น — เข้าใจง่าย ใช้งานได้ทันที
- บล็อค "หน่วงเวลา (delay)": ใช้เมื่อต้องการสั่งให้หุ่นยนต์ "รอ" ก่อนทำคำสั่งถัดไป
- บล็อค "millis()": ใช้เหมือน "นาฬิกาจับเวลา" ดูว่าหุ่นยนต์วิ่งไปกี่วินาทีแล้ว
สั่งให้สมองกลของหุ่นยนต์ "หยุดรอชั่วคราว" ตามเวลาที่ใส่ในช่อง ก่อนที่จะข้ามไปทำงานบล็อคถัดไปที่ต่ออยู่ด้านล่าง
การสั่ง "หน่วงเวลา" ไม่ได้แปลว่าหุ่นยนต์จะหยุดวิ่ง!
ในขณะที่โปรแกรมกำลังรอ มอเตอร์จะยังคงหมุนทำงานตามคำสั่งล่าสุดที่สั่งไว้ก่อนหน้า
- ถ้าอยากให้วิ่งไปข้างหน้า 1 วินาทีแล้วหยุด: ต้องต่อบล็อค
[เดินหน้า fd(80)]➔[หน่วง 1000 ms]➔[หยุดมอเตอร์ ao()] - ถ้าอยากให้หุ่นยนต์ยืนอยู่นิ่งๆ เพื่อรอ: ต้องสั่งบล็อค
[หยุดมอเตอร์ ao()]ก่อน แล้วจึงตามด้วยบล็อค[หน่วง ... ms]
📝 ตัวอย่างโค้ด C++ ที่โปรแกรมแปลงออกมา:
fd(80); // สั่งมอเตอร์เดินหน้าความเร็ว 80%
delay(1000); // หน่วงเวลา 1000 ms (หุ่นยนต์จะวิ่งไปข้างหน้านาน 1 วินาที)
ao(); // สั่งดับมอเตอร์ทุกตัวเพื่อหยุดสนิท
เปรียบเสมือน "นาฬิกาจับเวลา" ในตัวหุ่นยนต์ ทันทีที่เรากดปุ่ม RUN ปุ๊บ นาฬิกานี้จะเริ่มนับเวลาตั้งแต่ 0, 1, 2, 3... มิลลิวินาที สะสมขึ้นเรื่อยๆ ตลอดเวลาที่หุ่นยนต์กำลังทำงาน
millis() > 3000) หรือนำไปเก็บใส่ตัวแปร
🎯 ประโยชน์ที่นิยมใช้ในการแข่งขันจริง:
🔁 หมวดบล็อค LOOP (การวนซ้ำและการควบคุมลูป)
คู่มือการใช้งานบล็อคในแถบสีเขียว (LOOP) สำหรับคนเริ่มต้น — สั่งให้หุ่นยนต์ทำงานซ้ำๆ ได้อย่างง่ายดาย
- กลุ่มวนซ้ำ: สั่งให้ทำซ้ำแบบไม่รู้จบ, ทำซ้ำตามเงื่อนไข, หรือทำซ้ำตามจำนวนรอบ
- กลุ่มหยุด/ข้าม: สั่งเบรกออกจากลูปทันที หรือสั่งข้ามไปรอบถัดไป
📦 กลุ่มที่ 1: บล็อควนซ้ำ (Looping)
คำสั่งอะไรก็ตามที่นำมาใส่ไว้ในช่องของบล็อคนี้ หุ่นยนต์จะ ทำซ้ำไปเรื่อยๆ ตลอดเวลาไม่มีวันหยุด จนกว่าผู้ใช้จะกดปุ่มสีแดง Reset หรือ Stop
🎯 เหมาะสำหรับ: นำไปวางใน void setup() เพื่อสร้างระบบเดินตามเส้น หรือระบบเดินหลบกำแพงอัตโนมัติ
while (true) {
// คำสั่งข้างในนี้จะทำงานวนรอบไม่รู้จบ
}
หุ่นยนต์จะตรวจดูก่อนว่าเงื่อนไขในช่องด้านบน "ยังเป็นจริงอยู่ไหม?" ถ้าจริง จะลงไปทำคำสั่งในช่อง 1 รอบ แล้วกลับขึ้นมาตรวจเงื่อนไขใหม่เรื่อยๆ จนกว่าเงื่อนไขจะกลายเป็นเท็จ จึงจะยอมหลุดออกจากลูป
• เงื่อนไข:
ระยะทางเซนเซอร์หน้า > 15 cm• คำสั่งข้างใน:
เดินหน้า fd(80)• ผลลัพธ์: หุ่นยนต์จะวิ่งเดินหน้าไปเรื่อยๆ "ขณะที่" ด้านหน้ายังโล่งอยู่ แต่พอวิ่งไปใกล้กำแพงจนเหลือน้อยกว่า 15 cm ปุ๊บ หุ่นยนต์จะหยุดทำคำสั่งในลูปทันที!
สั่งให้หุ่นยนต์ทำงานข้างในวนไปเรื่อยๆ "จนกระทั่งเจอเหตุการณ์เป้าหมาย" แล้วจึงหยุด (เข้าใจง่ายเหมือนคำพูดมนุษย์ เช่น "เดินหน้าไปเรื่อยๆ จนกว่าจะเจอเส้นดำ")
• เงื่อนไข:
เซนเซอร์เส้น A0 < 500 (เจอเส้นดำ)• คำสั่งข้างใน:
เดินหน้า fd(60)• ผลลัพธ์: หุ่นยนต์จะวิ่งตรงไปเรื่อยๆ จนกระทั่งเซนเซอร์แตะโดนเส้นดำปุ๊บ จะหลุดออกจากลูปทันที เพื่อไปทำคำสั่งเลี้ยวหรือหยุดในขั้นตอนต่อไป
สั่งให้คำสั่งภายในทำงานซ้ำตามจำนวนตัวเลขที่ระบุ เช่น ใส่เลข 4 ก็จะทำงานวนข้างใน 4 รอบเป๊ะๆ แล้วจบการทำงาน
🎯 ตัวอย่างการใช้จริง: สั่งยิงปล่อยลูกบาศก์ภารกิจ 4 ลูกลงโซนภารกิจ โดยใส่คำสั่ง [ยิงกล่อง kickF()] ไว้ข้างในลูป 4 รอบ
for (int count = 0; count < 4; count++) {
kickF(); // ยิงปล่อยกล่องภารกิจด้านหน้า
delay(200);
}
วนซ้ำโดยมี "ตัวแปร" (เช่น ตัวแปร i) คอยนับตัวเลขจากค่าเริ่มต้นไปถึงค่าสิ้นสุด และเพิ่มค่าขึ้นทีละสเต็ปในแต่ละรอบ
🎯 ตัวอย่างการใช้จริง: การเร่งความเร็วมอเตอร์อย่างนุ่มนวล (Soft Start) เช่น เริ่มจากความเร็ว 20 ไปถึง 100 เพิ่มทีละ 10
// เร่งความเร็วจาก 20% ถึง 100% ทีละ 10%
for (int i = 20; i <= 100; i += 10) {
fd(i);
delay(100);
}
🛑 กลุ่มที่ 2: บล็อคหยุด / ข้ามลูป (Loop Control)
| บล็อคคำสั่ง | โค้ด C++ | หน้าที่และการทำงาน |
|---|---|---|
| break out of loop | break; |
เบรกฉุกเฉิน: กระโดดออกจากลูปทันที ไม่ทำคำสั่งที่เหลือ และไม่วนรอบต่อไปอีก (มักใช้คู่กับเงื่อนไข if ถ้า... ภายในลูป) |
| continue with next iteration | continue; |
ข้ามรอบปัจจุบัน: ข้ามคำสั่งที่เหลือด้านล่างในรอบนี้ แล้วกระโดดขึ้นไปเริ่มต้นวนรอบใหม่ทันที |
🧭 1. ระบบทิศทางและบล็อคคำสั่งเคลื่อนที่ (Heading & Motion Guide)
คู่มือระบบพิกัดองศาไจโรสโคป (Gyro Heading) การกำหนดทิศทางเดินหน้า/ถอยหลัง และการใช้งานบล็อคควบคุมการเคลื่อนที่ขั้นสูง (MOVE / DIFF / SPIN) ใน RazorIDE
ใน RazorRobot Simulator และการแข่งขันหุ่นยนต์จริง ระบบจะอ้างอิงทิศทางสนามด้วยมุมองศาเข็มทิศสัมบูรณ์ (0°–360°) โดยการเลือกใช้ "หน้าหุ่นยนต์" หรือ "หลังหุ่นยนต์" เป็นแกนนำทาง จะมีองศาที่สอดคล้องกันดังนี้:
| ทิศทางในสนาม | 🤖 ใช้หน้าหุ่นยนต์เดิน (Front) | 🔙 ใช้หลังหุ่นยนต์เดิน (Rear) | คำอธิบายพฤติกรรม |
|---|---|---|---|
| ⬆️ ขึ้นบน (ทิศเหนือ) | 0 องศา (ตรงขึ้น) | 180 องศา | หุ่นยนต์วิ่งมุ่งหน้าขึ้นสู่ด้านบนของสนาม |
| ➡️ ไปทางขวา (ทิศตะวันออก) | 90 องศา (เลี้ยวขวา) | 270 องศา | หุ่นยนต์เคลื่อนที่เบนออกไปทางขวามือของสนาม |
| ⬇️ ลงล่าง (ทิศใต้) | 180 องศา (ตรงลง) | 0 องศา | หุ่นยนต์เคลื่อนที่มุ่งลงสู่ด้านล่างของสนาม |
| ⬅️ ไปทางซ้าย (ทิศตะวันตก) | 270 องศา (เลี้ยวซ้าย) | 90 องศา | หุ่นยนต์เคลื่อนที่เบนออกไปทางซ้ายมือของสนาม |
⚡ เจาะลึก 3 บล็อคคำสั่งการเคลื่อนที่หลักของ RAZOR-S3
สั่งให้หุ่นยนต์วิ่งตรงไปยังมุมองศาเป้าหมาย โดยระบบจะใช้เซนเซอร์ไจโรสโคปและสมการ PID คอยคำนวณปรับแต่งความเร็วมอเตอร์ซ้าย-ขวาแบบเรียลไทม์ ทำให้หุ่นยนต์วิ่งเป็นเส้นตรงได้อย่างสมบูรณ์แบบ แม้พื้นสนามจะลื่นหรือมีแรงสั่นสะเทือน
| พารามิเตอร์ | ค่าเริ่มต้น | หน้าที่และการปรับแต่ง |
|---|---|---|
| แกนนำ / องศา | หน้า · 0° | เลือกแกนอ้างอิง (หน้า/หลัง) และมุมองศาเป้าหมายในสนาม (0–360°) |
| ความเร็วต้น | 20% | ความเร็วขณะเริ่มออกตัว ช่วยป้องกันไม่ให้ล้อหมุนฟรีและลดแรงกระชาก |
| speed | 30% | ความเร็วหลักในการเคลื่อนที่ (ปรับเพิ่มได้ถึง 100% ตามความชำนาญ) |
| time | 500 ms | ระยะเวลาที่ต้องการให้วิ่ง (มิลลิวินาที: 1000 ms = 1 วินาที) |
| KP / KI / KD | 1 / 0 / 0.05 | พารามิเตอร์ควบคุม PID ดึงหุ่นให้ตรง ค่าเริ่มต้นถูกปรับจูนมาอย่างเหมาะสมแล้ว |
| เร่ง / ชะลอ | 0 / 0 ms | ช่วงเวลา Soft-start เร่งความเร็วขึ้น และ Soft-stop ชะลอความเร็วก่อนหยุด |
สั่งให้หุ่นยนต์เลี้ยวโค้งเข้าหามุมองศาเป้าหมายด้วยการหักความเร็วสองล้อให้ต่างกัน (ล้อด้านในโค้งหมุนช้า ล้อด้านนอกโค้งหมุนเร็ว) ทำให้เข้าโค้งได้อย่างนุ่มนวลและรักษาความเร็วไว้ได้ต่อเนื่อง
| พารามิเตอร์ | ค่าเริ่มต้น | หน้าที่และการปรับแต่ง |
|---|---|---|
| ทิศ / องศา | 90° | มุมองศาเป้าหมายที่ต้องการเลี้ยวไปหา |
| เร็วสุด / ช้าสุด | 80 / 20 | ความเร็วสูงสุดของล้อนอกโค้ง และความเร็วต่ำสุดของล้อในโค้ง |
| หยุดที่ | 3 ° | ระยะความคลาดเคลื่อนที่ยอมรับได้ (เช่น 3° หมายถึงเลี้ยวถึง 87°–93° ถือว่าสำเร็จ) |
| timeout | 2000 ms | เวลาตัดการทำงานอัตโนมัติหากหุ่นยนต์ติดขัดหรือชนขอบสนาม |
สั่งให้หุ่นยนต์หมุนเปลี่ยนทิศทาง ณ จุดเดิมโดยที่ตำแหน่งกึ่งกลางหุ่นไม่ขยับ (ล้อสองฝั่งหมุนสวนทางกัน) ระบบจะเลือกทิศทางการหมุนที่สั้นที่สุดไปยังองศาเป้าหมายโดยอัตโนมัติ
| พารามิเตอร์ | ค่าเริ่มต้น | หน้าที่และการปรับแต่ง |
|---|---|---|
| ทิศ / องศา | 90° | องศาเป้าหมายที่ต้องการหมุนไปหา |
| เร็วสุด / ช้าสุด | 80 / 30 | ความเร็วในการหมุนตัว (ระบบจะค่อยๆ ชะลอเมื่อใกล้ถึงมุมเพื่อกันการหมุนเลย) |
| หยุดที่ / timeout | 3° / 2000 ms | ค่าความคลาดเคลื่อนที่ยอมรับได้ และเวลาตัดการหมุนอัตโนมัติ |
🔁 2. บล็อค MOVE_LOOP (เดินเกาะทิศใน loop แบบไม่บล็อกเวลา)
เรียนรู้วิธีสั่งให้หุ่นยนต์วิ่งตรงด้วยไจโร พร้อมกับอ่านเซนเซอร์และตัดสินใจตลอดเวลาใน void loop()
บล็อค
MOVE ปกติจะสั่งให้หุ่นยนต์ "วิ่งตามเวลา" (เช่น วิ่ง 2 วินาที) ซึ่งในระหว่าง 2 วินาทีนั้น สมองกลจะไม่ยอมอ่านเซนเซอร์เส้นหรือตรวจจับกำแพงเลยบล็อค MOVE_LOOP จึงถูกสร้างขึ้นมาเพื่อให้หุ่นยนต์ "วิ่งตรงด้วยไจโรทีละสเต็ปสั้นๆ" ทำให้เราสามารถอ่านค่าเซนเซอร์เส้นไปพร้อมๆ กันได้ในลูป!
สั่งคำนวณไจโร PID และขับมอเตอร์เพื่อรักษาทิศทาง 1 สเต็ป โดยไม่หยุดรอเวลา เหมาะสำหรับการวางไว้ใน void loop() หรือในลูป forever / repeat while
| พารามิเตอร์ | ค่าเริ่มต้น | หน้าที่และการปรับแต่ง |
|---|---|---|
| ทิศ / องศา | หน้า · 0° | มุมองศาที่ต้องการให้หุ่นยนต์วิ่งเกาะทิศไปเรื่อยๆ |
| ความเร็วต้น / speed | 30 / 60 | ความเร็วเริ่มต้น และความเร็วปกติในการเคลื่อนที่ |
| KP / KD | 1 / 0 | ค่าน้ำหนัก PID ดึงหุ่นให้ตรงตามองศา |
ใช้สั่งรีเซ็ตตัวเร่งความเร็วเริ่มต้น (Start Speed) เมื่อเปลี่ยนทิศทางใหม่หรือเริ่มรอบการวิ่งครั้งใหม่
ตัวอย่างการเขียนโค้ดสั่งให้หุ่นยนต์วิ่งตรงไปข้างหน้าด้วย MOVE_LOOP แล้วตรวจจับเซนเซอร์เส้น A0 ตลอดเวลา เมื่อเจอเส้นดำจะหยุดและเลี้ยวทันที:
void setup() {
// ตั้งค่าเริ่มต้น
}
void loop() {
// ตรวจสอบว่าเซนเซอร์ A0 เจอเส้นดำหรือยัง (ค่าน้อยกว่า 500 คือสีดำ)
if (analogRead(A0) < 500) {
ao(); // หยุดมอเตอร์ทันทีเมื่อเจอเส้นดำ
delay(200);
razorSpin(1, 90, 80, 30, 3, 2000); // หมุนตัวไปทางขวา 90 องศา
} else {
// หากยังไม่เจอเส้นดำ ให้วิ่งเกาะทิศ 0 องศาต่อไป
razorMoveLoop(1, 0, 30, 60, 1.0, 0.0);
}
}
📦 3. ระบบกลไกยิงปล่อยลูกบาศก์ (Cube Launcher)
คู่มือการใช้งานระบบยิงปล่อยกล่องภารกิจสำหรับ Quick Box Drop Challenge และ Wall Tracking Rescue
บล็อคคำสั่งยิงกล่องอยู่ในแถบเครื่องมือสีส้ม MOTOR หรือพิมพ์คำสั่งภาษา C++ ได้โดยตรง:
ยิงปล่อยลูกบาศก์หน้าC++:
kickF();
ยิงปล่อยลูกบาศก์หลังC++:
kickB();
kickF() ให้ต่อบล็อค หน่วงเวลา 200–300 ms เพื่อให้ลูกบาศก์ตกถึงพื้นสนิทrepeat [N] times ครอบคำสั่งยิง เพื่อปล่อยกล่อง 2–4 ลูกติดต่อกันได้ทันที📝 ตัวอย่างโค้ด: ขับไปหน้าโซน 1 ➔ ยิงกล่อง ➔ วิ่งเข้าเส้นชัย
void setup() {
// 1. วิ่งตรง 1 วินาทีไปจอดหน้าโซนเขียว
razorMove(1, 0, 60, 1000, 1.0, 0.0, 0.05, 0, 0, 20);
ao();
delay(200);
// 2. ยิงปล่อยลูกบาศก์ด้านหน้า 1 ลูก
kickF();
delay(300); // หน่วงเวลาให้กล่องตกถึงพื้น
// 3. เลี้ยวขวา 90 องศา แล้ววิ่งเข้าเส้นชัย Finish
razorSpin(1, 90, 80, 30, 3, 2000);
razorMove(1, 90, 70, 1500, 1.0, 0.0, 0.05, 0, 0, 20);
ao();
}
void loop() {}
📡 4. ระบบเซนเซอร์ตรวจจับเส้น & พิน A0–A3 (Line Sensors)
คู่มือการอ่านค่าเซนเซอร์แสงและตำแหน่งพิน A0–A3 บนหุ่นยนต์ RAZOR-S3 สำหรับตรวจจับเส้นดำและเส้นตัด
RAZOR-S3 ติดตั้งเซนเซอร์ตรวจจับเส้นแบบอินฟราเรด (IR Line Sensors) จำนวน 4 พินหลักที่ใช้งานบ่อยที่สุด:
| พิน (Pin) | ตำแหน่งบนตัวหุ่น | หน้าที่และการประยุกต์ใช้ |
|---|---|---|
| A0 | ด้านหน้า - ฝั่งซ้าย | ตรวจจับเส้นดำฝั่งซ้ายหน้า / เช็คเส้นตัดร่วมกับ A1 |
| A1 | ด้านหน้า - ฝั่งขวา | ตรวจจับเส้นดำฝั่งขวาหน้า / เช็คเส้นตัดร่วมกับ A0 |
| A2 | ด้านหลัง - ฝั่งซ้าย | ตรวจจับเส้นดำขณะถอยหลัง (ใช้ร่วมกับโหมดหลังหุ่นยนต์เดิน) |
| A3 | ด้านหลัง - ฝั่งขวา | ตรวจจับเส้นดำขณะถอยหลัง (ใช้ร่วมกับโหมดหลังหุ่นยนต์เดิน) |
เมื่อใช้คำสั่ง analogRead(A0) ค่าที่ส่งกลับมาจะมีค่าตั้งแต่ 0 ถึง 1023:
analogRead(A0) < 500➔ แปลว่า "เจอเส้นดำ หรือ หลุมตก"analogRead(A0) >= 500➔ แปลว่า "ยังอยู่บนพื้นสีขาว"
(A0 < 500) || (A1 < 500)ถ้าหน้าซ้าย หรือ หน้าขวา แตะโดนเส้นดำ
(A0 < 500) && (A1 < 500)เมื่อทั้งหน้าซ้าย และ หน้าขวา โดนเส้นดำพร้อมกัน
ตัวอย่างโค้ด: เดินหน้าค้นหาเส้นตัดสี่แยกแล้วหยุดสนิท
void setup() {
// วิ่งเดินหน้าด้วยความเร็ว 60%
fd(60);
// วนรอจนกระทั่งทั้ง A0 และ A1 เจอเส้นดำพร้อมกัน
while (!(analogRead(A0) < 500 && analogRead(A1) < 500)) {
delay(5); // หน่วงเวลาอ่านซ้ำสั้นๆ
}
// เมื่อถึงเส้นตัด ให้หยุดและดับมอเตอร์
ao();
}
void loop() {}
📚 5. ตารางคำสั่ง C++ ทั้งหมดของ RAZOR-S3
สรุปรายการฟังก์ชัน C++ (Arduino Style) ทั้งหมดที่รองรับบนหุ่นยนต์ RAZOR-S3 พร้อมพารามิเตอร์และตัวอย่างการใช้งาน
| ฟังก์ชัน C++ | พารามิเตอร์ (Parameters) | หน้าที่และการทำงาน |
|---|---|---|
| razorMove(...) | (dir, angle, spd, timeMs, kp, ki, kd, rampUp, rampDown, startSpeed) |
วิ่งตรงล็อคทิศทาง Gyro PID (บล็อกเวลา): หุ่นวิ่งตรงตามองศา angle (0–360°) ด้วยความเร็ว spd เป็นเวลา timeMs มิลลิวินาที |
| razorMoveLoop(...) | (dir, angle, startSpeed, spd, kp, kd) |
วิ่งตรงล็อคทิศทางใน loop (ไม่บล็อกเวลา): ขับเคลื่อนและแก้ทิศทางทีละสเต็ป ต้องเรียกซ้ำใน loop() เพื่อให้อ่านเซนเซอร์ระหว่างทางได้ |
| razorMoveLoopReset() | - | รีเซ็ตตัวเร่งความเร็วของ MOVE_LOOP: เรียกเมื่อต้องการเริ่มรอบการวิ่งใหม่ |
| razorDiff(...) | (dir, angle, maxSpd, minSpd, stopAt, timeoutMs) |
ดิฟเลี้ยวโค้ง (Differential Turn): ล้อนอกหมุนเร็ว ล้อในหมุนช้า เพื่อเลี้ยวโค้งเข้าหามุม angle อย่างนุ่มนวล |
| razorSpin(...) | (dir, angle, maxSpd, minSpd, stopAt, timeoutMs) |
หมุนตัวในที่ (Spin / Pivot Turn): ล้อสองฝั่งหมุนสวนทางกันเพื่อหมุนตัว ณ จุดเดิมไปยังมุม angle |
| ฟังก์ชัน C++ | พารามิเตอร์ | หน้าที่และการทำงาน |
|---|---|---|
| kickF() | - | ยิงปล่อยลูกบาศก์ด้านหน้า: ปล่อยกล่องภารกิจด้านหน้า 1 ลูก (ควรหน่วงเวลา delay(300); ตามหลัง) |
| kickB() | - | ยิงปล่อยลูกบาศก์ด้านหลัง: ปล่อยกล่องภารกิจด้านหลัง 1 ลูก |
| ฟังก์ชัน C++ | พารามิเตอร์ | หน้าที่และการทำงาน |
|---|---|---|
| fd(spd) | spd (0 ถึง 100) |
สั่งขับเคลื่อน เดินหน้า ทั้ง 2 ฝั่งด้วยความเร็ว spd% |
| bk(spd) | spd (0 ถึง 100) |
สั่งขับเคลื่อน ถอยหลัง ทั้ง 2 ฝั่งด้วยความเร็ว spd% |
| sl(spd) / sr(spd) | spd (0 ถึง 100) |
เลี้ยวซ้าย / เลี้ยวขวา แบบล้อเดียว (ล้อฝั่งเลี้ยวจะหยุด) |
| tl(spd) / tr(spd) | spd (0 ถึง 100) |
หมุนตัวกลับซ้าย / ขวา (ล้อสองฝั่งหมุนสวนทางกัน) |
| motor(ch, spd) | ch (1=ซ้าย, 2=ขวา), spd (-100 ถึง 100) |
สั่งมอเตอร์แยกข้างอิสระ (ค่าบวก = เดินหน้า, ค่าลบ = ถอยหลัง) |
| motorL(spd) / motorR(spd) | spd (-100 ถึง 100) |
สั่งมอเตอร์ฝั่งซ้าย / มอเตอร์ฝั่งขวา |
| ao() / stop_motor() | - | หยุดมอเตอร์ทุกตัว: เบรกและตัดกระแสมอเตอร์ทันที |
| ฟังก์ชัน C++ | ค่าที่ส่งกลับ (Return) | หน้าที่และการทำงาน |
|---|---|---|
| analogRead(pin) | 0 – 1023 (ตัวเลข) |
อ่านค่าเซนเซอร์เส้น A0 (หน้าซ้าย), A1 (หน้าขวา), A2 (หลังซ้าย), A3 (หลังขวา) — ต่ำกว่า 500 = เจอเส้นดำ |
| sonarF() / sonarB() | เซนติเมตร (cm) |
อ่านระยะวัดวัตถุ/กำแพงด้านหน้า (Front) / ด้านหลัง (Back) |
| sonarL() / sonarR() | เซนติเมตร (cm) |
อ่านระยะวัดวัตถุ/กำแพงด้านซ้าย (Left) / ด้านขวา (Right) |
| getGyro() | 0.0 – 359.9° |
อ่านมุมองศาปัจจุบันของหุ่นยนต์จากเซนเซอร์ไจโร (Auto-Zero 0° ตอนเริ่มรัน) |
| gyroZero() | - | รีเซ็ตมุมอ้างอิงไจโร ณ จุดปัจจุบันให้เป็น 0° |
| ฟังก์ชัน C++ | พารามิเตอร์ | หน้าที่และการทำงาน |
|---|---|---|
| delay(ms) | ms (มิลลิวินาที) |
หยุดรอเวลาที่ระบุ (1000 ms = 1 วินาที) มอเตอร์จะยังคงทำงานตามคำสั่งล่าสุด |
| millis() | - (คืนค่า unsigned long) |
คืนค่าเวลาสะสมนับตั้งแต่เริ่มกดปุ่ม RUN (มิลลิวินาที) ใช้สำหรับจับเวลา |
| Beep(freq, dur) | freq (Hz), dur (ms) |
สั่งให้ลำโพง Buzzer ส่งเสียงตามความถี่และระยะเวลาที่กำหนด |
| Serial.println(msg) | ข้อความ / ตัวแปร | พิมพ์ค่าหรือข้อความออกทางหน้าต่าง Terminal / Serial Monitor |
⚡ เจาะลึกบล็อกพิเศษ: RAZORS3 MOVE (ล็อคทิศทางด้วย Gyro + PID)
บล็อกคำสั่งที่ทรงพลังที่สุดของ RAZOR-S3 ช่วยให้หุ่นวิ่งตรงเป๊ะตามองศาที่กำหนด ไม่เอียง ไม่เป๋ แม้พื้นจะลื่นหรือมีแรงเหวี่ยง
// เทียบเท่าคำสั่ง C++:
razorMove(1, 0, 60, 1000, 1.0, 0.0, 0.05, 200, 200, 30);
| พารามิเตอร์ | ชนิด/ค่า | ค่าแนะนำ | คำอธิบายหน้าที่ & เหตุผลที่ต้องใช้ (Why & How) |
|---|---|---|---|
| DIR | Dropdown | เดินหน้า (1) | ทิศทางขับเคลื่อน: เลือกระหว่าง เดินหน้า (1) หรือ ถอยหลัง (-1) |
| ANGLE / ทิศ | องศา 0–360 | ↑ 0° | องศาอ้างอิงของสนามที่ต้องการล็อค: โดยระบบจะยึดทิศทางตอนกด RUN เป็น 0° (↑=0°, →=90°, ↓=180°, ←=270°) หุ่นจะคอยปรับล้อให้วิ่งตรงตามแนวทิศนี้ตลอดเวลา |
| STARTSPD | Number (0–100) | 20 |
ความเร็วตอนเริ่มออกตัว (Soft Start Initial Speed):
💡 ใช้ทำไม: ถ้าสั่งให้หุ่นออกตัวที่ความเร็วสูงทันที (เช่น 80) ล้อจะฟรีและหุ่นจะสะบัดเสียทิศ การตั้งค่านี้ไว้ที่ 20–30 ช่วยให้ออกตัวนุ่มนวลและตรงเป๊ะ
|
| SPD | Number (0–100) | 30 | ความเร็วสูงสุดในการวิ่ง: ความเร็วที่หุ่นยนต์จะวิ่งไปถึงหลังจากช่วงเร่งเครื่อง |
| TIME | ms (มิลลิวินาที) | 1000 ms | ระยะเวลาที่ต้องการให้วิ่ง: 1,000 ms = 1 วินาที เมื่อครบเวลาหุ่นจะหยุดมอเตอร์ให้อัตโนมัติ |
| KP | Decimal | 1.0 |
Proportional Gain (ความไวในการแก้ทิศทาง):
💡 ใช้ทำไม: ยิ่งตั้งค่ามาก หุ่นจะยิ่งดึงตัวกลับมาตรงทิศเร็ว แต่ถ้าตั้งมากเกินไป หุ่นจะวิ่งส่ายเป็นงู (แนะนำ 0.8 – 1.5)
|
| KI | Decimal | 0.0 | Integral Gain (การชดเชยค่าสะสม): ปกติสำหรับระบบขับเคลื่อนพื้นเรียบให้ตั้งค่าเป็น 0.0 |
| KD | Decimal | 0.05 |
Derivative Gain (ตัวหน่วงการสะบัด / แดมเปอร์):
💡 ใช้ทำไม: ช่วยเบรกและหยุดอาการส่ายเมื่อหุ่นวิ่งด้วยความเร็วสูง ทำให้การวิ่งนิ่งและเสถียรที่สุด (แนะนำ 0.02 – 0.1)
|
| RAMPUP | ms (มิลลิวินาที) | 100–300 ms |
เวลาในการเร่งความเร็ว (Soft-Start Ramp):
💡 ใช้ทำไม: ระยะเวลาที่หุ่นจะค่อยๆ ไต่ความเร็วจาก
STARTSPD ขึ้นไปหา SPD ช่วยไม่ให้หุ่นกระชากตอนออกตัว |
| RAMPDOWN | ms (มิลลิวินาที) | 100–300 ms |
เวลาในการชะลอความเร็ว (Soft-Stop Ramp):
💡 ใช้ทำไม: ระยะเวลาที่หุ่นจะค่อยๆ ผ่อนความเร็วลงก่อนหยุดเมื่อใกล้ครบเวลา ช่วยให้หยุดได้นิ่งสนิท ไม่ลื่นไถลเลยเป้าหมาย
|
🔁 บล็อก MOVE_LOOP & MOVE_LOOP reset (เดินแบบไม่บล็อกเวลา)
เมื่อต้องการให้หุ่นเดินไปข้างหน้า พร้อมกับอ่านค่าเซนเซอร์เพื่อตัดสินใจตลอดเวลา (เช่น เดินไปเรื่อยๆ จนกว่าจะเจอเส้นดำ แล้วค่อยหยุด) ต้องใช้บล็อกชุดนี้!
// ตัวอย่างการใช้ใน loop() เพื่อวิ่งไปหยุดที่เส้นดำ:
void setup() {
razorMoveLoopReset(); // รีเซ็ตค่า PID ก่อนเริ่มรอบใหม่
}
void loop() {
// ถ้าเจอเส้นดำที่เซนเซอร์หน้า (A0 หรือ A1 < 300) ให้หยุด
if (analogRead(A0) < 300 || analogRead(A1) < 300) {
ao(); // หยุดมอเตอร์
while(1); // หยุดการทำงาน
} else {
razorMoveLoop(1, 0, 30, 60, 1.0, 0.05); // เดินคุมทิศ 1 จังหวะ
}
}
🔄 การหมุนในที่ (Spin) vs การเลี้ยวแบบดิฟ (Differential Turn)
การทำงาน: ล้อซ้ายและล้อขวาหมุนสวนทิศทางกัน ทำให้ตัวหุ่นหมุนอยู่กับจุดเดิม
- SMAX (ความเร็วสูงสุด): แนะนำ 70–80
- SMIN (ความเร็วต่ำสุด): แนะนำ 25–30 (ชะลอเมื่อใกล้ถึงมุม)
- THR (มุมยอมรับ): เช่น 3° เมื่อเหลือมุมน้อยกว่า 3° จะตัดจบ
- TIMEOUT: เวลาป้องกันการหมุนค้าง (เช่น 2000 ms)
การทำงาน: ล้อข้างหนึ่งดัน ล้ออีกข้างแตะเบาๆ ทำให้เกิดการเลี้ยวแบบตีวงโค้ง
- DIR: หน้า (TurnF_S) หรือ หลัง (TurnB_S)
- จุดเด่น: เข้าโค้งได้นุ่มนวล ไม่สะบัด เหมาะกับการเลี้ยวเข้าโซน
- SMAX / SMIN: ควบคุมความเร็วในการตีวง
- THR: มุมยอมรับสำหรับหยุดการเลี้ยว
📦 ภารกิจ Quick Box Drop (การยิงปล่อยลูกบาศก์)
ในการแข่งขัน Quick Box Drop เมื่อหุ่นยนต์วิ่งเข้าไปอยู่ในพื้นที่ Drop Zone 1, 2, 3 หรือ 4 สามารถสั่งปล่อยลูกบาศก์เพื่อทำคะแนนได้ด้วยคำสั่ง:
| คำสั่ง C++ | บล็อกในระบบ | การทำงาน |
|---|---|---|
| kick_front() | เครื่องยิง ยิงลูกบาศก์หน้า | ปล่อยลูกบาศก์ด้านหน้าตัวหุ่นลงในโซนทำคะแนน |
| kick_back() | เครื่องยิง ยิงลูกบาศก์หลัง | ปล่อยลูกบาศก์ด้านหลังตัวหุ่นลงในโซนทำคะแนน |
💡 ตัวอย่างโปรแกรมภารกิจจริง (Mission Code Recipes)
void setup() {
// 1. วิ่งตรงไปข้างหน้า (ทิศ 0°) ด้วยความเร็ว 70 เป็นเวลา 1500 ms
razorMove(1, 0, 70, 1500, 1.0, 0.0, 0.05, 200, 200, 30);
// 2. ยิงปล่อยลูกบาศก์ด้านหน้าลงใน Drop Zone
kick_front();
delay(500);
// 3. หมุนตัวกลับหลัง 180° อยู่กับที่
razorTurn(1, 180, 80, 30, 3, 2000);
// 4. วิ่งตรงกลับมา (ล็อคทิศทาง 180°) เป็นเวลา 1500 ms
razorMove(1, 180, 70, 1500, 1.0, 0.0, 0.05, 200, 200, 30);
// 5. หยุดมอเตอร์สนิท
ao();
}
void loop() {
// จบภารกิจ ไม่ต้องทำอะไรใน loop
}
| คำสั่ง C++ | บล็อกในระบบ | การทำงาน |
|---|---|---|
| gripClose() | แขนคีบ หนีบกระป๋อง | สั่งให้แขนคีบหนีบจับวัตถุ/กระป๋องที่อยู่ด้านหน้า |
| gripOpen() | แขนคีบ อ้าแขนคีบ | สั่งให้อ้าแขนคีบเพื่อปล่อยหรือเตรียมจับวัตถุ |
ด้านหน้า 8 ตัว (A0–A7) สำหรับเดินหน้าตามเส้น และด้านหลัง 8 ตัว (A8–A15) สำหรับถอยหลังตามเส้นด้วยระบบ PID ความแม่นยำสูง
ใช้คำสั่ง linePID(speed, kp, kd) ในการเกาะเส้นอย่างเรียบเนียนโดยไม่หลุดโค้ง
| คำสั่ง C++ | การทำงาน |
|---|---|
| gripLeftClose() / gripLeftOpen() | หนีบ / ปล่อย มือคีบข้างซ้าย |
| gripRightClose() / gripRightOpen() | หนีบ / ปล่อย มือคีบข้างขวา |
| handOffLeftToRight() | ส่งกระป๋องจากมือซ้ายข้ามไปมือขวาอัตโนมัติ |
| readColor() | อ่านค่าสีของวัตถุที่มือคีบจับอยู่ (คืนค่า 'red', 'green', 'blue', 'yellow', 'black') |
📚 ตารางคำสั่ง C++ ทั้งหมด (API Cheat Sheet)
สรุปรายการฟังก์ชัน C++ มาตรฐานที่สามารถเรียกใช้งานได้ใน RazorSIM
| คำสั่ง | พารามิเตอร์ | การทำงาน |
|---|---|---|
| fd(speed) | 0 ถึง 100 | เดินหน้าความเร็วเท่ากันทั้งสองล้อ |
| bk(speed) | 0 ถึง 100 | ถอยหลังความเร็วเท่ากันทั้งสองล้อ |
| tl(speed) / tr(speed) | 0 ถึง 100 | เลี้ยวซ้าย / เลี้ยวขวา (ล้อเดียวหมุน) |
| sl(speed) / sr(speed) | 0 ถึง 100 | หมุนซ้าย / หมุนขวาอยู่กับที่ (ล้อสองข้างหมุนสวนกัน) |
| fd2(speedL, speedR) | -100 ถึง 100 | ควบคุมความเร็วแยกอิสระล้อซ้ายและล้อขวา (ค่าลบ = ถอยหลัง) |
| ao() | — | หยุดมอเตอร์ทุกตัวทันที (All Off) |
| delay(ms) | มิลลิวินาที | หน่วงเวลาการทำงาน (1000 ms = 1 วินาที) |
| คำสั่ง | ค่าที่คืนกลับ | การทำงาน |
|---|---|---|
| analogRead(pin) | 0 ถึง 1023 | อ่านค่าเซนเซอร์เส้น (ค่าน้อย < 300 = เจอดำ / ค่ามาก > 700 = พื้นขาว) |
| readSonar(dir) | ระยะทาง cm | อ่านระยะทางจาก Sonar/TOF (เช่น 'front', 'back', 'left', 'right') |
| getGyro() | องศา 0–360 | อ่านมุมองศาปัจจุบันของหุ่นยนต์จากเซนเซอร์ไจโร |