🚀 ค่าย 3 วัน · Maker + Coding + AI

นวัตกรรมแขนกลอัจฉริยะ
(Smart 3DOF Robotic Arm: From CAD to AI)

เรียนรู้ครบวงจรตั้งแต่การออกแบบชิ้นส่วน 3 มิติด้วย Onshape การจัดหาอุปกรณ์จาก Shopee การพิมพ์ 3 มิติ การประกอบ การเขียนโปรแกรมดึงไลบรารีจาก GitHub จนถึงการใส่สมองกลด้วย AI ท้องถิ่น (Local LLM)

θ1 θ2 θ3
⏱ ระยะเวลา: 3 วัน (วันละ 6–7 ชม.) 🎯 กลุ่มเป้าหมาย: นักเรียน ม.ปลาย / ปวช. / ผู้เริ่มต้น 🛠 โปรเจกต์จริง: terk_arm_esp32_v1
🧪 ทดลอง Kinematics แบบสด 📦 โค้ดบน GitHub 🔌 คู่มือ API
📱 สแกนเปิดเว็บสื่อการสอน https://terk182.github.io/rmutl_robot_arm/

1 ภาพรวมหลักสูตร

🎯 เป้าหมายการเรียนรู้

  • ออกแบบชิ้นส่วน 3 มิติด้วย Onshape
  • จัดหาอุปกรณ์จาก Shopee และทำตารางต้นทุน BOM
  • พิมพ์ 3 มิติและประกอบแขนกลจริง
  • เขียนโปรแกรม ESP32 ดึงไลบรารีจาก GitHub
  • เข้าใจกลศาสตร์แขนกล (3DOF Kinematics)
  • ประยุกต์ใช้ AI เบื้องต้น (Local LLM)

🧩 ผลงานที่นักเรียนได้

  • ชิ้นส่วน Gripper / ถาดวางของที่ออกแบบเอง
  • แขนกล 3 แกนที่ประกอบและใช้งานได้จริง
  • โค้ดที่ถูกปรับแก้จากโปรเจกต์ Open-Source
  • ระบบแขนกลที่สั่งงานด้วย ภาษาไทยผ่าน AI
  • วิดีโอนำเสนอผลงาน (Pitching)

🗺 แผน 3 วัน

  • วัน 1 — โลกของ Maker: ออกแบบ 3 มิติ + จัดหา + ผลิต
  • วัน 2 — โค้ดดิ้ง GitHub + ศาสตร์แห่งการเคลื่อนไหว
  • วัน 3 — สมองกลอัจฉริยะ AI + Mini-Hackathon
⚠️ คำแนะนำผู้สอน: ควรเตรียมชิ้นส่วนโครงสร้างที่พิมพ์ 3 มิติไว้ล่วงหน้า (Pre-printed) อย่างน้อย 1–2 ชุดต่อโต๊ะ เพื่อให้ทุกกลุ่มได้เริ่มประกอบทันทีโดยไม่ต้องรอเครื่องพิมพ์ และสำรองอุปกรณ์ไฟฟ้า (ESP32, มอเตอร์, สายไฟ) เผื่อชำรุดระหว่างค่าย

2 วันที่ 1 — โลกของ Maker: ออกแบบ 3 มิติ, จัดหา และผลิต

DAY 1

เป้าหมาย

นักเรียนสามารถออกแบบชิ้นส่วนของตัวเอง รู้จักแหล่งหาอะไหล่ และเตรียมชิ้นงานพิมพ์ 3 มิติ ได้

🏁 ผลลัพธ์ท้ายวัน: ชิ้นส่วน Gripper / ถาดวางของที่ออกแบบเอง พร้อมพิมพ์ 3 มิติ + ตาราง BOM ที่คำนวณงบประมาณเสร็จเรียบร้อย

ช่วงเช้า · ส่วนที่ 1 · ⏱ 3.5 ชม.📐 การออกแบบด้วย Onshape (Cloud 3D CAD)

  • สมัครบัญชีและทำความรู้จัก UI เบื้องต้น ของ Onshape (ฟรีสำหรับนักเรียน)
  • เรียนรู้คำสั่งพื้นฐาน: Sketch, Dimension, Extrude, Fillet, Hole
  • Mini-Project: ออกแบบ “หัวจับ (Gripper)” หรือ “ถาดวางของ” ที่จะติดที่ปลายแขนกล (End-Effector)
  • โจทย์บังคับ: ต้องมีรูน็อตที่พอดีกับเซอร์โวมอเตอร์ (เช่น M2 / M3, ระยะ 20–25 mm)
💡 เทคนิค: สอนการวัดระยะจริงจาก Gripper สำเร็จรูป แล้วให้ลองวัดกลับไปกลับมา เพื่อสร้างความเข้าใจเรื่อง Tolerance (ค่าเผื่อ) ก่อนสั่งพิมพ์
30

รูป: ตัวอย่างสเก็ตช์ Gripper 2 นิ้วใน Onshape (มีรูน็อต Ø สำหรับยึดกับเซอร์โว)

📖 ดูเพิ่มเติม: Onshape — วิธีเริ่มต้นใช้งานและพื้นฐานการวาด

ช่วงบ่าย · ส่วนที่ 1 · ⏱ 1.5 ชม.🛒 นักจัดซื้อฮาร์ดแวร์ (Shopee Sourcing)

  • เรียนรู้สเปกอุปกรณ์: ESP32, PCA9685, สเต็ปเปอร์มอเตอร์ NEMA 17, เซอร์โวมอเตอร์
  • ทักษะการค้นหาอะไหล่บน Shopee: ใช้คำค้นที่ถูกต้อง, ดูรีวิว, เลือกร้านที่มีของจริง
  • วิธีอ่านสเปกแรงดันไฟ (Voltage) และกระแส (Current) ให้เข้ากับแหล่งจ่ายไฟ
  • ทำตารางต้นทุน BOM (Bill of Materials) — ดูตัวอย่างได้ในหัวข้อ BOM
ℹ️ หมายเหตุ: หากงบจำกัด ให้ใช้สเต็ปเปอร์มอเตอร์ 28BYJ-48 + Driver ULN2003 ทดแทน NEMA 17 แต่โครงสร้างแขนกลในโปรเจกต์นี้ถูกออกแบบมาสำหรับ NEMA 17 เป็นหลัก
฿

รูป: ชิ้นส่วนหลักที่ต้องจัดซื้อ — ESP32, สเต็ปเปอร์, เซอร์โว + งบประมาณ (BOM)

ช่วงบ่าย · ส่วนที่ 2 · ⏱ 1.5 ชม.🖨 การผลิต (Slicing & 3D Printing)

1. Export ไฟล์จาก Onshape

ส่งออกชิ้นส่วน Gripper ที่ออกแบบเป็นไฟล์ STL หรือ STEP

2. โหลดโครงสร้างแขนกลส่วนหลักจาก MakerWorld (Open-Source)

ดาวน์โหลดชิ้นส่วนแขนกล 3 แกนสำเร็จรูปจาก MakerWorld / Printables / Thingiverse เพื่อใช้เป็นโครงสร้างหลัก แล้วนำ Gripper ของตัวเองไปติดที่ปลายแขน

3. นำเข้าโปรแกรม Slicer (เช่น Bambu Studio / Cura / PrusaSlicer)

ตั้งค่า Infill (แนะนำ 20–40% สำหรับชิ้นส่วนรับแรง) และ Support (เปิดเฉพาะจุดที่ยื่นเกิน 45° ที่จำเป็น)

4. สั่งพิมพ์และตรวจชิ้นงาน

เริ่มพิมพ์ชิ้นส่วนพร้อมตรวจคุณภาพ (Support หลุดง่ายไหม? ผิวเรียบไหม? รูน็อตพอดีไหม?) — การประกอบ + เดินสายไฟจะทำต่อในช่วงเช้าของวันที่ 2 เมื่อชิ้นส่วนพิมพ์ครบ

รูป: เครื่องพิมพ์ 3 มิติกำลังพิมพ์ Gripper — ตั้งค่า Infill และ Support ให้ถูกจุดก่อนสั่งพิมพ์

3 📐 Onshape — การติดตั้งและการใช้งานเบื้องต้น

Onshape คือโปรแกรม CAD แบบ Cloud-Native — ไม่ต้องติดตั้งซอฟต์แวร์ใด ๆ เปิดเว็บเบราว์เซอร์แล้วใช้งานได้ทันที ไฟล์ทั้งหมดถูกบันทึกลงคลาวด์อัตโนมัติ และรองรับการทำงานร่วมกันแบบ Real-time (เหมือน Google Docs แต่เป็น 3D CAD) มีบัญชีฟรี และบัญชีนักเรียน (Student Account) ที่ได้ฟีเจอร์เต็มรูปแบบ

📥 วิธีเริ่มต้นใช้งาน (สมัคร + “ติดตั้ง”)

  1. เปิดเว็บ onshape.com แล้วกด Sign Up / Get Started Free — สมัครฟรี ไม่ต้องใช้บัตรเครดิต ได้สิทธิ์ใช้งานทันที
  2. สำหรับนักเรียน: กด Create A Student Account (ผ่านหน้า Education) เพื่อรับสิทธิ์เต็มรูปแบบ — แนะนำให้ผู้สอนสมัครผ่านโปรแกรมการศึกษาเพื่อให้ทั้งห้องได้ใช้ฟีเจอร์ครบ
  3. เข้าใช้งานที่ cad.onshape.com ผ่านเบราว์เซอร์ Chrome / Edge / Firefox (อินเทอร์เน็ตควรเสถียร ประมาณ 10 Mbps ขึ้นไป)
  4. สำหรับมือถือ/แท็บเล็ต: ดาวน์โหลดแอป Onshape จาก App Store (iOS) หรือ Google Play (Android) — ใช้ดูและแก้ไขแบบเบื้องต้นได้
💡 ข้อดีของ Cloud CAD: ไม่ต้องติดตั้ง ใช้ได้ทุกเครื่องที่มีเบราว์เซอร์ ไฟล์ไม่หาย (บันทึกอัตโนมัติทุกครั้ง) แก้แบบพร้อมกันหลายคนได้ และมี Version + Branch ให้ย้อนกลับเวอร์ชันเก่าได้เสมอ

🧭 ทำความรู้จัก UI เบื้องต้น

  • Document (เอกสาร) — “ไฟล์” ของ Onshape ภายในมีหลาย Tab เช่น Parts Studio (ออกแบบชิ้นงาน), Assembly (ประกอบ), Drawing (แบบ 2 มิติ)
  • Feature Toolbar (แถบเครื่องมือด้านบน) — รวมคำสั่งทั้งหมด: Sketch, Extrude, Fillet, Hole…
  • Feature List (รายการด้านซ้าย) — ประวัติขั้นตอนการสร้าง เรียกว่า Feature Tree คลิกย้อนกลับเพื่อแก้ไขได้ทุกเมื่อ
  • View Cube (มุมขวาบน) — หมุนมุมมอง หน้า/หลัง/ซ้าย/ขวา/บน/ล่าง ได้ 1 คลิก
  • การควบคุมเมาส์: คลิกกลางค้าง = หมุนมุมมอง · ล้อเลื่อน = ซูม · คลิกขวาค้าง = เลื่อน (Pan)
  • Mouse Over Toolbar — เอาเมาส์ชี้ที่ไอคอนค้างไว้ จะมีชื่อและคำอธิบายเครื่องมือขึ้นมาให้
cad.onshape.com Feature List Top Plane Sketch 1 Extrude 1 Fillet 1 Hole 1 40 TOP FRONT R

รูป: หน้าจอจำลอง Onshape — Feature Toolbar ด้านบน, Feature Tree ด้านซ้าย, View Cube มุมขวา

🛠 5 ขั้นตอนการใช้งานพื้นฐาน (ใช้ทำ Mini-Project Gripper ได้เลย)

1. สร้าง Document ใหม่

กดปุ่ม + Create → ตั้งชื่อ เช่น My_Gripper → เปิด Tab Parts Studio (หน่วยเริ่มต้นเป็น มม. อยู่แล้ว)

2. วาด Sketch (ร่างแบบ 2 มิติ)

เลือกระนาบ (Plane) เช่น Top Plane → กด Sketch (หรือกด S) → วาดด้วยเครื่องมือ Line / Rectangle / Circle / Arc ตามรูปร่างที่ต้องการ

3. กำหนดขนาดด้วย Dimension

กดเครื่องมือ Dimension (หรือกด D) → คลิกที่เส้น/จุด → ลากออกมาแล้วพิมพ์ตัวเลข (เช่น 20 มม.) → Enter — กรณีทำ Gripper ให้กำหนดรูน็อต Ø3.2 มม. (เผื่อ M3) ให้พอดีกับเซอร์โวมอเตอร์

4. ปิด Sketch แล้ว Extrude (ทำให้เป็น 3 มิติ)

กดเครื่องหมาย ✓ (Check) เพื่อจบ Sketch → กด Extrude (หรือกด E) → เลือกหน้าตัด → ป้อนความหนา (เช่น 8 มม.) → กด ✓

5. เพิ่ม Fillet / Hole แล้ว Export

Fillet (กด F) = ปัดขอบมุมให้เรียบ · Hole = เจาะรูน็อตพร้อมรูปแบบ จากนั้นคลิกขวาที่ชิ้นงาน → Export เลือก STL (สำหรับพิมพ์ 3 มิติ) หรือ STEP (สำหรับแชร์ไฟล์ CAD)

ℹ️ สังเกต: Onshape ไม่มีปุ่ม Save — ทุกอย่างบันทึกลงคลาวด์อัตโนมัติตลอดเวลา อย่าลืมตั้งชื่อ Document และ Feature ต่าง ๆ ให้สื่อความหมาย เพื่อให้ง่ายต่อการส่งงานและการแก้ไขร่วมกัน

⌨️ ทางลัดที่ใช้บ่อย

S Sketch D Dimension E Extrude F Fillet Ctrl+Z ย้อนกลับ Esc ยกเลิกเครื่องมือ

🎓 แหล่งเรียนรู้เพิ่มเติม (ฟรี)

  • Onshape Learning Center — คอร์สฟรีแบบเป็นขั้นตอน: learn.onshape.com
  • Onshape Help Center — คู่มือครบทุกคำสั่ง: cad.onshape.com/help
  • Onshape AI Advisor — ผู้ช่วย AI ในตัว ตอบคำถามได้ทันที (ดูรายละเอียดด้านล่าง)
  • Onshape Forums — กระทู้ถาม–ตอบของชุมชนผู้ใช้ทั่วโลก

🤖 AI ใน Onshape — มี AI Agent ด้วย!

Onshape มี AI ให้ใช้จริง 3 ระดับ — เหมาะกับการสอดแทรกหัวข้อ AI ในค่ายนี้ด้วย:

  • Onshape AI Advisor (beta) — ผู้ช่วย AI ในตัวของ Onshape ตอบคำถามเกี่ยวกับการใช้ CAD ได้ทันที โดยอ้างอิงจากเอกสารทางการของ Onshape (ถามได้ทั้งเรื่อง Sketch, Extrude, การประกอบ ฯลฯ) เข้าถึงได้จากเมนู Help / ไอคอนเครื่องหมายคำถามในโปรแกรม
  • Onshape Labs — AI in CAD — โปรแกรม Early-Access (ทดลองฟีเจอร์ล่วงหน้า) ให้ผู้ใช้ทดสอบฟีเจอร์ AI สำหรับการออกแบบ เช่น AI ช่วยสร้าง/แนะนำฟีเจอร์การขึ้นแบบ
  • FeatureScript MCP Server — ตัวเชื่อมที่เปิดทางให้ AI Agent ภายนอก (เช่น GitHub Copilot, Claude) เข้ามาสร้างหรือแก้ไขโมเดล CAD ได้ด้วยภาษาธรรมชาติหรือโค้ด — เหมือนให้ AI เป็น “ผู้ช่วยออกแบบ” ข้าง ๆ นักเรียน
ℹ️ ใช้ในค่ายได้ยังไง: ให้ผู้เรียนลองถาม AI Advisor เช่น “How do I make a hole for an M3 screw?” หรือ “How to fillet an edge?” — ฝึกทักษะการตั้งคำถาม (Prompt Engineering) ไปพร้อมกับการเรียน CAD และต่อยอดไปสู่หัวข้อ AI ของวันที่ 3 ได้
💡 ข้อควรระวัง: AI อาจตอบผิดได้ (Hallucination) — ควรให้ผู้เรียนตรวจทานคำตอบกับเอกสาร Help จริงเสมอ และสอนว่าการใช้ AI คือการ “เร่งงาน” ไม่ใช่การ “แทนที่ความเข้าใจ”

4 วันที่ 2 — โค้ดดิ้ง GitHub และศาสตร์แห่งการเคลื่อนไหว

DAY 2

เป้าหมาย

ประกอบร่างให้สมบูรณ์ ดึงไลบรารีมาใช้ และเข้าใจกลศาสตร์แขนกล 3 แกน พร้อมปรับโค้ดจาก GitHub ให้แขนกลขยับได้เอง

🏁 ผลลัพธ์ท้ายวัน: แขนกลประกอบครบ + Gripper ของตัวเองติดที่ปลายแขน + โค้ดถูกโหลดลง ESP32 และสั่งให้แขนกลเคลื่อนที่ไปพิกัด X, Y, Z ตามต้องการได้

ช่วงเช้า · ส่วนที่ 1 · ⏱ 1.5 ชม.🔧 ประกอบแขนกล + เดินสายไฟ

  • นำชิ้นส่วนที่พิมพ์เสร็จจากเมื่อวาน (Pre-printed + Gripper ของตัวเอง) มาประกอบโครงสร้างแขนกล 3 แกน
  • ติดGripper ที่ออกแบบเองจาก Onshape เข้ากับปลายแขนกล (End-Effector)
  • เดินสายไฟ (Wiring): ESP32 → A4988 ×3 → NEMA 17 ×3 + Servo Gripper + แหล่งจ่ายไฟ (ดูแผนภาพในหัวข้อ ฮาร์ดแวร์และการเดินสาย)
  • ตรวจสอบการเชื่อมต่อ: สาย STEP/DIR ถูกต้อง, ต่อ GND ร่วมกันทุกบอร์ด

ช่วงเช้า · ส่วนที่ 2 · ⏱ 2 ชม.🌐 โลกของ GitHub + ตั้งค่าโค้ด

  • ทำความรู้จัก GitHub: การค้นหาโปรเจกต์หุ่นยนต์ การดาวน์โหลดโค้ด และการอ่าน README.md
  • ดาวน์โหลดโปรเจกต์ตัวอย่าง: terk182/terk_arm_esp32_v1
  • ติดตั้งไลบรารีที่จำเป็นสำหรับ ESP32 และอัปโหลดเฟิร์มแวร์ (ดูขั้นตอนในหัวข้อ การติดตั้งซอฟต์แวร์)
  • ทดสอบเปิดเครื่อง: เชื่อมต่อ Wi-Fi / AP แล้วเปิดหน้าเว็บควบคุม http://[IP-ESP32]/
G terk182/terk_arm_esp32_v1 Public · ESP32 3DOF Robotic Arm terk_arm_esp32_v1.ino RobotArmIK.cpp WebPages.cpp README.md

รูป: ตัวอย่างรีโปโปรเจกต์บน GitHub — ควรอ่าน README.md ก่อนเสมอ

ช่วงบ่าย · ⏱ 3 ชม.🧮 ศาสตร์แห่งการเคลื่อนไหว (3DOF Kinematics)

1. ทฤษฎี (1 ชม.) — จุดหมุน 3 แกน และการแปลงมุม → พิกัด

FK: มุมข้อต่อ → พิกัดปลายแขน · IK: พิกัดปลายแขน → มุมข้อต่อ (ดูสูตรและตัวอย่างในหัวข้อ Kinematics)

2. ทดลองกับ Simulator (30 นาที)

ลองเลื่อนมุม θ1–θ3 ดูตำแหน่งปลายแขน และกดคำนวณ IK ใน Kinematics Simulator

3. ปรับโค้ด + ทดสอบแขนจริง (1.5 ชม.)

นำโค้ดจาก GitHub มาปรับแก้ (Modify) เพื่อสั่งแขนกลไปยังพิกัด X, Y, Z ที่ต้องการ และทดสอบเปิด–ปิด Gripper ที่ออกแบบเอง

XYZ ปลายแขน (x,y,z)

รูป: แขนกล 3 ข้อต่อบนแกน X-Y-Z — เปลี่ยนมุม θ แล้วพิกัดปลายแขนเปลี่ยนตาม

5 วันที่ 3 — สมองกลอัจฉริยะ AI และการประยุกต์ใช้งาน

DAY 3

เป้าหมาย

ยกระดับแขนกลด้วย AI และแข่งขันทักษะการทำภารกิจ

🏁 ผลลัพธ์ท้ายวัน: แขนกลรับคำสั่งภาษามนุษย์ (เช่น “หยิบกระป๋องสีแดงไปทิ้ง”) ผ่าน AI → แปลงเป็นพิกัด → คีบชิ้นงานได้จริง + นำเสนอผลงานได้

ช่วงเช้า · ⏱ 3 ชม.🧠 ติดตั้งสมองกลด้วย Local LLM

  • แนวทางการรันโมเดล AI แบบ Local ออฟไลน์ ด้วย Ollama
  • ทดลองใช้โมเดลภาษา เช่น Typhoon, Qwen หรือ Gemma เพื่อตีความคำสั่งภาษามนุษย์
  • เชื่อมต่อข้อมูลผ่านเครือข่าย Wi-Fi ระหว่าง AI บนคอมพิวเตอร์กับบอร์ด ESP32 เพื่อให้แขนกลทำงานตามคำสั่ง
  • ต่อยอด: ให้แขนกลมองเห็นด้วย VLM (กล้อง + qwen3-vl) — ดูหัวข้อ AI → แขนกล
AI

รูป: สมองกล AI — ตีความภาษามนุษย์แล้วสั่งงานแขนกลผ่าน Wi-Fi

ช่วงบ่าย · ⏱ 3.5 ชม.🏆 Mini-Hackathon “AI Pick & Place”

  • โจทย์ท้าทาย: ใช้ AI รับคำสั่งข้อความ (เช่น “หยิบกระป๋องสีแดงไปทิ้ง”) แปลงเป็นพิกัด แล้วให้แขนกลที่ติด Gripper ของตัวเองไปคีบชิ้นงาน
  • จัดลำดับการทำงาน: ตีความ → คำนวณ IK → เคลื่อนที่ → คีบ → ปล่อย
  • นำเสนอผลงาน (Pitching): เล่าตั้งแต่แนวคิดการออกแบบ Onshape, งบประมาณ Shopee, ไปจนถึงการดัดแปลงโค้ด GitHub และการทำงานร่วมกับ AI

📊 เกณฑ์ให้คะแนน Mini-Hackathon

เกณฑ์รายละเอียดคะแนน
การออกแบบ (Onshape)Gripper ใช้งานได้จริง มีรูน็อตตรงสเปก ออกแบบมีเหตุผล20
งบประมาณ (BOM)ตารางต้นทุนครบถ้วน เลือกอุปกรณ์ตรงสเปก คุ้มค่า15
การปรับโค้ด (GitHub)เข้าใจโค้ดที่นำมาใช้ อธิบายส่วนที่ปรับแก้ได้20
การทำงานของแขนกลคีบ–วางชิ้นงานได้ถูกต้อง แม่นยำ ทันเวลา25
AI Integrationรับคำสั่งภาษาไทยผ่าน Local LLM แล้วแปลงเป็นพิกัดได้10
การนำเสนอ (Pitching)เล่าเรื่องครบวงจร สื่อสารชัดเจน ตอบคำถามได้10

6 🧪 Kinematics Simulator — ลองเล่นได้จริง

จำลองการทำงานของแขนกล 3 แกนจากโปรเจกต์ terk_arm_esp32_v1 (ใช้ค่าจริงจากโค้ด: L1 = 135 mm, L2 = 157 mm, Base = 156.5 mm, End-Effector = 125 mm) เลื่อนมุมข้อต่อเพื่อดูตำแหน่งปลายแขน หรือกรอกพิกัด X, Y, Z แล้วกด คำนวณ IK เพื่อหามุมข้อต่อ

มุมมองด้านข้าง (θ1, θ2) θ3 = หมุนรอบแกน Z

พิกัดปลายแขน (FK)

x = 0 mm  |  y = 0 mm  |  z = 0 mm

คำนวณ Inverse Kinematics (IK)

θ1 = —   θ2 = —   θ3 = —
ℹ️ หลักการ: FK = รู้มุมข้อต่อ → หาตำแหน่งปลายแขน  ·  IK = รู้ตำแหน่งปลายแขน → หามุมข้อต่อ (ใช้ตรีโกณมิติและกฎของโคไซน์)

📐 สูตร Forward Kinematics (FK)

d1 = sin(θ1) × L1        d2 = cos(θ1) × L1
d3 = cos(θ2) × L2        d4 = sin(θ2) × L2

x = cos(θ3) × (d1 + d3 + END)
y = sin(θ3) × (d1 + d3 + END) + WORK_SPACE
z = |(d4 − d2) − BASE|

L1 = 135, L2 = 157, END = 125, BASE = 156.5, WORK_SPACE = 420 (มม.)

🧮 สูตร Inverse Kinematics (IK) — แบบย่อ

r        = |√(x² + (y−WORK_SPACE)²) − END|
theta    = atan2(r, BASE − z)
g        = √(r² + (BASE − z)²)
alpha    = acos((L1² + g² − L2²) / (2·L1·g))
beta     = alpha + theta
theta1   = 180 − beta
theta2   = (180 − free − alpha) + (90 − theta)
theta3   = atan2(y − WORK_SPACE, x)

โดย free = acos((L1² + L2² − g²) / (2·L1·L2)) — กฎของโคไซน์ในสามเหลี่ยมข้อต่อ

📝 ตัวอย่างการคำนวณแบบทีละขั้น

✅ ตัวอย่างที่ 1 — Forward Kinematics (FK)

โจทย์: กำหนดมุมข้อต่อ θ1 = 30°, θ2 = 30°, θ3 = 20° จงหาตำแหน่งปลายแขน (x, y, z)

ขั้นที่ 1 — คำนวณ d1–d4

d1 = sin(30°) × 135 = 0.5000 × 135 =  67.5
d2 = cos(30°) × 135 = 0.8660 × 135 = 116.9
d3 = cos(30°) × 157 = 0.8660 × 157 = 136.0
d4 = sin(30°) × 157 = 0.5000 × 157 =  78.5

ขั้นที่ 2 — ระยะรวมของแขน (ในระนาบข้อต่อ)

d1 + d3 + END = 67.5 + 136.0 + 125 = 328.5

ขั้นที่ 3 — คำนวณพิกัดปลายแขน

x = cos(20°) × 328.5 = 0.9397 × 328.5 = 308.7 mm
y = sin(20°) × 328.5 + 420 = 112.3 + 420 = 532.3 mm
z = |(78.5 − 116.9) − 156.5| = |−194.9| = 194.9 mm
🎯 คำตอบ: ปลายแขนอยู่ที่ (308.7, 532.3, 194.9) มม. — ลองเลื่อน Slider ด้านบนไปที่ θ1=30, θ2=30, θ3=20 แล้วเทียบดูได้

✅ ตัวอย่างที่ 2 — Inverse Kinematics (IK)

โจทย์: ต้องการให้ปลายแขนไปที่พิกัด (150, 300, 100) มม. จงหามุมข้อต่อ θ1, θ2, θ3

ขั้นที่ 1 — ระยะแนวนอน r และมุม θ

base_stant = 156.5 − 100 = 56.5
ระยะรวม   = √(150² + 120²) = √36900 = 192.1
r        = |192.1 − 125| = 67.1
θ        = atan2(67.1, 56.5) = 49.9°

ขั้นที่ 2 — ความยาว g และมุม α

g    = √(67.1² + 56.5²) = √7694 = 87.7
α    = acos((135² + 87.7² − 157²) / (2×135×87.7))
     = acos(0.0536) = 86.9°

ขั้นที่ 3 — มุม β และ free

β    = α + θ = 86.9 + 49.9 = 136.8°
free = acos((135² + 157² − 87.7²) / (2×135×157))
     = acos(0.8299) = 33.9°

ขั้นที่ 4 — มุมข้อต่อทั้งสาม

θ1 = 180 − 136.8 = 43.2°
θ2 = (180 − 33.9 − 86.9) + (90 − 49.9) = 99.3°
θ3 = atan2(300 − 420, 150) = atan2(−120, 150) = −38.7°
🎯 คำตอบ: θ = (43.2°, 99.3°, −38.7°) — ตรวจสอบย้อนกลับด้วย FK ได้ผลลัพธ์ (150.0, 300.0, 99.9) ตรงกับโจทย์ ✓

📖 ตัวอย่างจากแหล่งอ้างอิง: Forward Kinematics ด้วยตรีโกณมิติ

ℹ️ ที่มา: บทความ “Forward Kinematics Calculation for Robotic Arm” โดย Antonius Ringlayer โพสต์บน RobotShop Community (2018) — ลิงก์บทความต้นฉบับ · วิธีที่ใช้คือ ตรีโกณมิติอย่างง่าย (อีก 2 วิธีที่นิยมคือ Denavit–Hartenberg Parameters และ Screw Theory)

📐 ส่วนที่ 1 — 2D FK สำหรับแขนกล 1 DOF

หลักการ: Forward Kinematics (FK) คือการหาตำแหน่งปลายแขนเมื่อรู้มุมข้อต่อ — Inverse Kinematics (IK) คือการหามุมข้อต่อเมื่อรู้ตำแหน่งปลายแขน

ตัวอย่าง: ก้านเดียว l = 10 cm, มุม θ = 45°

cos θ = x / l   →   x = cos 45° × 10 = 7.07 cm
sin θ = y / l   →   y = sin 45° × 10 = 7.07 cm

ตำแหน่งปลายแขน = p(7.07, 7.07) cm — สังเกตว่ามุม 45° ทำให้ x = y

โค้ด Python (จากบทความต้นฉบับ):

import math
def solve_1dof_fk(link, degree):
    x = math.cos(math.radians(degree)) * link
    y = math.sin(math.radians(degree)) * link
    return x, y

x, y = solve_1dof_fk(10, 45)
print("x =", x, " y =", y)
# ผลลัพธ์: x = 7.07  y = 7.07
💡 ข้อสังเกต: ตรีโกณมิติพื้นฐานนี้คือหัวใจของ FK — แขนกล 3 แกนก็แค่แยกคิดทีละมุมแล้วรวมกัน

📐 ส่วนที่ 2 — 3D FK สำหรับแขนกล 3 DOF

โจทย์ต้นฉบับกำหนดค่าให้: l1 = l2 = 10 cm, d2 = 7 cm, θ1 = 60°, θ2 = 30°, θ3 = 140°

ภาพรวมแขนกล 3 DOF มุมมองด้านข้างและด้านบน

รูป: แขนกล 3 DOF — ซ้าย: TOP VIEW (θ1), ขวา: SIDE VIEW (θ2, θ3, z) พร้อมค่าที่กำหนดให้

จากภาพ Side View เราจะหาความสูง z ก่อน แล้วค่อยหาจาก Top View เอาระยะเอื้อมแนวนอน d1 ไปหาพิกัด x, y

มุมมองด้านข้างแขนกล 3 DOF พื้นฐาน

รูป: SIDE VIEW — BASE, ก้าน L1/L2, มุม θ2/θ3, ความสูง z

🧮 ขั้นตอนการคำนวณ 3D FK (ทีละขั้น)

มุมมองด้านข้างพร้อมป้ายทุกค่า

รูป: SIDE VIEW แบบเต็มป้าย — d1…d6, θ4, θ5, 90°, z (ใช้ในขั้นตอนด้านล่าง)

ขั้นที่ 1 — หา d3 (องค์ประกอบแนวตั้งของ L1)

sin θ2 = d3 / l1
   d3 = sin 30° × 10 = 5.0 cm

ขั้นที่ 2 — หามุม θ4 และ θ5

θ4 = 180° − (θ2 + 90°) = 180° − (30° + 90°) = 60°
θ5 = θ3 − θ4 = 140° − 60° = 80°

ขั้นที่ 3 — หา d6 แล้วคำนวณความสูง z

cos θ5 = d6 / l2   →   d6 = cos 80° × 10 = 1.74 cm
   z = d2 + d3 − d6 = 7 + 5.0 − 1.74 = 10.26 cm

ขั้นที่ 4 — หา d4, d5 และระยะเอื้อมแนวนอน d1

d4 = cos θ2 × l1 = cos 30° × 10 = 8.66 cm
   d5 = sin θ5 × l2 = sin 80° × 10 = 9.85 cm
   d1 = d4 + d5 = 8.66 + 9.85 = 18.51 cm

ขั้นที่ 5 — หา x และ y จาก TOP VIEW

มุมมองด้านบนแขนกล
TOP VIEW — θ1 หมุนรอบฐาน
มุมมองด้านบนพร้อม d1
TOP VIEW — d1 = 18.51 cm
x = cos θ1 × d1 = cos 60° × 18.51 = 9.26 cm
   y = sin θ1 × d1 = sin 60° × 18.51 = 16.03 cm
🎯 คำตอบ: ตำแหน่งปลายแขน p(x, y, z) = p(9.26, 16.03, 10.26) cm
⚠️ หมายเหตุเชิงวิศวกร: ในบทความต้นฉบับมีจุดที่คำนวณคลาดเคลื่อนเล็กน้อย (เช่น d3 ≈ 4.9 และ z = 13.6) — ด้านบนเป็นการคำนวณที่ถูกต้อง (d3 = sin 30°×10 = 5.0, z = 10.26) สอนให้ผู้เรียนตรวจทานตัวเลขเสมอ แม้มาจากแหล่งอ้างอิงก็ตาม

📖 ตัวอย่างจากแหล่งอ้างอิง 2: Inverse Kinematics แบบเรขาคณิต (Robohub)

ℹ️ ที่มา: บทความ “Robotics, maths, python: A fledgling computer scientist’s guide to inverse kinematics” โดย Alistair Wick (University of Bristol, 2017) — ลิงก์บทความ · โค้ดเต็มและไฟล์ออกแบบ: github.com/AliShug/EvoArm

🤖 แขนกลตัวอย่าง (3 DOF) และวิธีคิด IK

โครงสร้างแขนกล 3 DOF พร้อมชื่อชิ้นส่วน

รูป: โครงสร้างแขน — Base, Shoulder, Elbow, Wrist, End-Effector พร้อมแกน x/y/z

แขนตัวอย่างมีอิสระ 3 แกน (3 DOF): Swing (หมุนทั้งแขนรอบฐาน), Main (เลื่อนข้อศอกเข้า–ออก), Actuator (เลื่อนปลายแขนขึ้น–ลง) — ข้อดีของแขน 3 DOF คือ ทุกตำแหน่งของปลายแขนมีท่าคำตอบเดียว (unique solution) ทำให้แก้ IK แบบวิเคราะห์ (เรขาคณิต) ได้โดยไม่ต้องใช้การคำนวณเชิงตัวเลขที่ซับซ้อน

การหมุน Swing
Swing — หมุนรอบฐาน
การขยับ Main
Main — ข้อศอกเข้า–ออก
การขยับ Actuator
Actuator — ปลายแขนขึ้น–ลง

🧭 ขั้นตอนที่ 1 — Swing IK (มุมมองจากด้านบน)

มุมมองด้านบน Swing IK แบบกึ่งกลางและเยื้องศูนย์

รูป: “Easy” = จุดหมุนอยู่กึ่งกลาง (ใช้ตรีโกณมิติตรง ๆ) · “Less easy” = จุดหมุนเยื้องศูนย์ (ต้องใช้การค้นหา)

กรณีกึ่งกลาง: หามุมหมุนง่าย ๆ ด้วย atan2 แต่แขนจริงมีระนาบการทำงานเยื้องจากแกนหมุน (ดูภาพขวา) ทำให้ถ้าใช้ตรีโกณมิติตรง ๆ แขนจะชี้เฉไปด้านข้าง

วิธีที่ผู้เขียนใช้: Binary Search (วิธีแบ่งครึ่ง / Bisection Method) — กำหนดขอบบน–ล่างของมุม ตรวจจุดกึ่งกลางว่ามาก/น้อยกว่าเป้าหมาย แล้วลดช่วงลงครึ่งหนึ่งทุกครั้ง 3–5 รอบได้ความแม่นยำต่ำกว่า 0.3° (เพียงพอสำหรับเซอร์โว)

import numpy as np

def normalize(v):
    return v / np.linalg.norm(v)

def signed_angle(A, B):
    """มุมมีเครื่องหมาย: บวก = A หมุนตามเข็มนาฬิกาจาก B (ใช้ dot product)"""
    A, B = normalize(A), normalize(B)
    perp = np.array([-B[1], B[0]])          # เวกเตอร์ตั้งฉากกับ B ไปทางตามเข็มนาฬิกา
    return np.rad2deg(np.arctan2(np.dot(A, perp), np.dot(A, B)))

# เริ่มต้นจากมุมคร่าว ๆ (naive) แล้วค้นหาแบบแบ่งครึ่ง
start_theta = np.rad2deg(np.arctan2(goal[1], goal[0]))   # atan2 แก้ quadrant ให้ถูกต้อง
lo, hi = start_theta - 60, start_theta + 60               # ขอบเขตเริ่มต้น
for _ in range(8):                                        # 8 รอบ = แม่นยำมาก
    mid = (lo + hi) / 2
    err = signed_angle(arm_direction(mid), goal - shoulder(mid))
    if err > 0: lo = mid      # มากเกินไป -> ใช้ mid เป็นขอบบน
    else:       hi = mid      # น้อยเกินไป -> ใช้ mid เป็นขอบล่าง
swing = (lo + hi) / 2

ผลลัพธ์ที่ได้จากขั้นนี้ด้วย: ระยะรัศมีจากข้อต่อ Shoulder ถึงปลายแขน (goal_radial) — ใช้ต่อในขั้นตอนที่ 2

goal_radial = np.linalg.norm(goal - shoulder(swing))   # ระยะ 2D บนระนาบการทำงาน

🔺 ขั้นตอนที่ 2 — Plane IK (มุมมองด้านข้าง) หาตำแหน่งข้อศอก

มุมมองด้านข้าง การหาข้อศอกด้วยวงกลมตัดวงกลม

รูป: วงกลม 2 วง (ศูนย์กลางที่ Shoulder รัศมี 148mm = Main arm · ศูนย์กลางที่ Wrist รัศมี = Forearm) — ข้อศอกอยู่ที่จุดตัดบน

เปลี่ยนมาใช้พิกัด 2D ในระนาบการทำงาน (แกน x = ระยะ radial, แกน y = ความสูง) — main arm กับ forearm สร้างสามเหลี่ยมโดยมีข้อศอกอยู่ที่ยอด เนื่องจากข้อศอกอยู่ห่างจาก Shoulder = ความยาว main arm และห่างจาก Wrist = ความยาว forearm เราจึงวาดวงกลม 2 วง แล้วหาจุดตัด — ข้อศอกคือจุดตัดบน (ค่า y มากสุด)

def circle_intersection(c1, r1, c2, r2):
    """จุดตัดของวงกลม 2 วง — คืนจุดบนสุด (y มากสุด) หรือ None ถ้าหาคำตอบไม่ได้"""
    d = np.linalg.norm(c2 - c1)
    if d > r1 + r2:        return None   # วงแยกกัน -> ระยะเอื้อมไม่ถึง
    if d < abs(r1 - r2):   return None   # วงหนึ่งกลืนอีกวง -> โครงสร้างเป็นไปไม่ได้
    a = (r1*r1 - r2*r2 + d*d) / (2*d)
    h = np.sqrt(r1*r1 - a*a)
    p = c1 + a * (c2 - c1) / d
    u = np.array([-(c2[1]-c1[1]), c2[0]-c1[0]]) / d   # ทิศตั้งฉาก
    p1, p2 = p + h*u, p - h*u
    return max(p1, p2, key=lambda v: v[1])            # เลือกข้อศอกตำแหน่งบน

elbow = circle_intersection(shoulder, MAIN_LEN, wrist_goal, FOREARM_LEN)
ℹ️ กรณีที่ไม่มีคำตอบ: ถ้าวงกลมไม่แตะกัน (ระยะเอื้อมไม่ถึง) หรือวงหนึ่งอยู่ข้างในอีกวง → แสดงว่าเป้าหมายนั้นอยู่นอกขอบเขตการทำงานของแขน (Out of Workspace) — ต้องย้ายเป้าหมายใหม่

✅ สรุปแนวคิดของบทความนี้

  • ได้ มุม Swing (ขั้นตอนที่ 1) + ตำแหน่งข้อศอก (ขั้นตอนที่ 2) = ท่าแขนที่สมบูรณ์
  • ถ้าต้องการสามารถแปลงกลับเป็นพิกัด 3D ได้โดยใช้มุม swing + ระนาบการทำงาน
  • แขนจริงอาจมีจุดหมุนเยื้องศูนย์ — การค้นหาแบบ Binary Search ช่วยแก้ได้โดยไม่ต้องนั่งคิดเรขาคณิตยาก ๆ
💡 เปรียบเทียบกับโปรเจกต์ของเรา: แขนของค่ายนี้ (terk_arm_esp32_v1) ใช้สูตรตรีโกณมิติ IK ตรง ๆ ในหัวข้อ Kinematics ด้านบน ส่วนบทความนี้เสนออีกแนวคิดหนึ่ง — การค้นหาแบบแบ่งครึ่ง + เรขาคณิตวงกลม ซึ่งเหมาะกับแขนที่โครงสร้างมีจุดหมุนเยื้องศูนย์ และใช้โค้ด Python + NumPy (pip install numpy) — สอนให้เห็นว่าการแก้ปัญหาเดียวกันมีได้หลายวิธี

🧩 Denavit–Hartenberg (DH) Parameters — วิธีมาตรฐานสากล

🧩 DH Parameters คืออะไร

Denavit–Hartenberg (DH) เป็นวิธีมาตรฐาน (ตีพิมพ์ปี 1955) ในการอธิบายโครงสร้างแขนหุ่นยนต์ ด้วยพารามิเตอร์เพียง 4 ค่าต่อข้อต่อ — ต่างจากตรีโกณมิติที่ต้องคิดเฉพาะโครงสร้าง DH ใช้ได้กับแขนทุกแบบและหลายข้อต่อ (รวมถึงหุ่นยนต์อุตสาหกรรม 6 แกน)

พารามิเตอร์ 4 ตัว สำหรับข้อต่อที่ i:

aᵢ

ระยะตามแกน x (ความยาวก้าน)

αᵢ

มุมบิดรอบแกน x (Link Twist)

dᵢ

ระยะเลื่อนตามแกน z (Offset)

θᵢ

มุมหมุนรอบแกน z — ตัวแปรของข้อต่อหมุน

📋 ตาราง DH ของแขน 3 DOF (ตัวอย่าง)

ข้อต่อ iaᵢ (mm)αᵢ (deg)dᵢ (mm)θᵢ (deg)หมายเหตุ
1 (ฐานหมุน)0−90°156.5θ₁ (ตัวแปร)หมุนรอบแกน Z
21350°0θ₂ (ตัวแปร)ความยาว L1
31570°0θ₃ (ตัวแปร)ความยาว L2

ค่า a, d, α เป็นค่าคงที่ของโครงสร้าง ส่วน θ เป็นตัวแปรที่เปลี่ยนตามข้อต่อหมุน (Revolute)

🧮 เมทริกซ์แปลง (Transformation Matrix) ของ DH

Tᵢ = Rot(z, θᵢ) · Trans(z, dᵢ) · Trans(x, aᵢ) · Rot(x, αᵢ)

    ┌  cosθ   −sinθ·cosα    sinθ·sinα    a·cosθ  ┐
T = │  sinθ    cosθ·cosα   −cosθ·sinα    a·sinθ  │
    │    0        sinα        cosα        d      │
    └    0         0           0          1      ┘

FK ทั้งแขน = T₁ × T₂ × T₃ (คูณเมทริกซ์ต่อกันทุกข้อต่อ) — ตำแหน่งปลายแขน (x, y, z) อยู่ในคอลัมน์สุดท้ายของผลลัพธ์

🐍 โค้ด Python: คำนวณ FK ด้วย DH Parameters

import numpy as np

def dh_transform(a, alpha, d, theta):
    """เมทริกซ์แปลง DH สำหรับหนึ่งข้อต่อ (มุมเป็นเรเดียน)"""
    ct, st = np.cos(theta), np.sin(theta)
    ca, sa = np.cos(alpha), np.sin(alpha)
    return np.array([
        [ct, -st*ca,  st*sa, a*ct],
        [st,  ct*ca, -ct*sa, a*st],
        [0,     sa,    ca,    d ],
        [0,      0,     0,    1 ],
    ])

# ตาราง DH ของแขน 3 DOF (ใช้ค่าจริงจากโปรเจกต์)
dh = [
    {"a": 0,   "alpha": np.deg2rad(-90), "d": 156.5, "theta": np.deg2rad(30)},
    {"a": 135, "alpha": 0,               "d": 0,     "theta": np.deg2rad(45)},
    {"a": 157, "alpha": 0,               "d": 0,     "theta": np.deg2rad(-20)},
]

T = np.eye(4)
for joint in dh:
    T = T @ dh_transform(**joint)

print("ตำแหน่งปลายแขน (x, y, z):", T[:3, 3])
💡 ข้อดีของ DH: ไม่ต้องวาดรูปคิดเรขาคณิตทีละมุม — แค่ใส่ตาราง DH แล้วคูณเมทริกซ์ ใช้ได้กับแขน 3 แกนจนถึง 6 แกนอุตสาหกรรมเหมือนกัน และเป็นพื้นฐานของ ROS / MoveIt
ℹ️ เทียบกับตรีโกณมิติ: ตรีโกณมิติ (หัวข้อด้านบน) ง่ายและเห็นภาพชัด แต่ต้องคำนวณใหม่เมื่อโครงสร้างเปลี่ยน ส่วน DH เป็นระบบมาตรฐานที่อธิบายโครงสร้างด้วยตัวเลข → เหมาะกับแขนซับซ้อนและงานระดับมืออาชีพ

7 🔌 ฮาร์ดแวร์และการเดินสาย

รายการอุปกรณ์หลักของแขนกลในโปรเจกต์ terk_arm_esp32_v1 พร้อมขา GPIO ที่ใช้จริงในโค้ด

12V Power จ่ายไฟมอเตอร์ Buck 12V→5V ไฟ ESP32 + Servo ESP32 Wi-Fi + Web Server Servo Gripper G17G16 G18G5 G21G19 A4988 #1 DIR | STEP A4988 #2 DIR | STEP A4988 #3 DIR | STEP NEMA 17 #1 ข้อต่อ 1 (Z) NEMA 17 #2 ข้อต่อ 2 NEMA 17 #3 ข้อต่อ 3 สัญญาณ GPIO 12V 5V สายมอเตอร์

รูป: แผนภาพการเดินสายไฟ — ESP32 → A4988 ×3 → NEMA 17 ×3 + Servo Gripper + แหล่งจ่ายไฟ (GND ต้องต่อร่วมกันทุกบอร์ด)

🧠 ESP32

สมองหลัก ควบคุมมอเตอร์ 3 ตัว + Gripper + Web Server (Wi-Fi) มีโหมด AP (SSID: RobotArmAP_04)

⚙️ สเต็ปเปอร์มอเตอร์ ×3

NEMA 17 ขับด้วย AccelStepper + MultiStepper สำหรับการเคลื่อนที่แบบประสานงาน

🖐 Gripper Servo

เซอร์โวควบคุมการเปิด–ปิดหัวจับ (0° = คีบ, 180° = ปล่อย) ขับด้วยไลบรารี ESP32Servo

🎛 PCA9685

โมดูลขับ PWM 16 ช่อง ใช้ควบคุมเซอร์โวหลายตัว พร้อมไลบรารีจาก GitHub

🔌 Power Supply

12V สำหรับสเต็ปเปอร์ + 5V สำหรับ ESP32/เซอร์โว ระวังเรื่องกระแสรวม (ดูหัวข้อ BOM)

📡 OTA Update

อัปเดตเฟิร์มแวร์ผ่าน Wi-Fi ได้ ไม่ต้องเสียบสาย — เหมาะสำหรับการแข่งในค่าย

🔗 ตารางขา GPIO (จากโค้ดจริง)

อุปกรณ์ฟังก์ชันGPIO (โค้ด)หมายเหตุ
Stepper 1 (ข้อต่อฐาน Z)DIR / STEP17 / 16AccelStepper stepper1(1, 17, 16)
Stepper 2 (ข้อต่อกลาง)DIR / STEP18 / 5AccelStepper stepper2(1, 18, 5)
Stepper 3 (ข้อต่อปลาย)DIR / STEP21 / 19AccelStepper stepper3(1, 21, 19)
Gripper ServoPWMกำหนดในโค้ดไลบรารี ESP32Servo
Wi-FiAP/STA—AP: RobotArmAP_04 / STA: SSID ในโค้ด
⚠️ ข้อควรระวัง: ต่อขา STEP/DIR ผ่าน Driver (A4988 / DRV8825) ห้ามต่อมอเตอร์เข้ากับ GPIO โดยตรง ตรวจสอบแรงดัน VMOT ของ Driver ให้ตรงกับมอเตอร์ และต่อขา GND ร่วมกันทุกบอร์ด

8 💻 ซอฟต์แวร์ — โครงสร้างโปรเจกต์และวิธีติดตั้ง

📁 โครงสร้างโปรเจกต์ terk_arm_esp32_v1

terk_arm_esp32_v1/
├── terk_arm_esp32_v1.ino   # เฟิร์มแวร์หลัก
├── Constants.h             # ค่าคงที่ (π, AP name...)
├── RobotArmIK.h / .cpp     # FK + IK
├── WebPages.h / .cpp       # หน้าเว็บควบคุม (HTML/CSS/JS)
├── API_Examples.md         # เอกสารตัวอย่าง API
├── test_compile.ino        # ไฟล์ทดสอบคอมไพล์
└── build/                  # โฟลเดอร์ build

🛠 วิธีติดตั้งซอฟต์แวร์ (Arduino IDE)

  1. ติดตั้ง Arduino IDE (เวอร์ชัน 2.x)
  2. เพิ่มบอร์ด ESP32: File → Preferences → Additional boards URLs ใส่ https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  3. ติดตั้งบอร์ด esp32 by Espressif Systems ผ่าน Boards Manager
  4. ติดตั้งไลบรารีใน Library Manager: AccelStepper, ESP32Servo, Adafruit PWM Servo Driver (PCA9685)
  5. ดาวน์โหลดโปรเจกต์จาก GitHub (Code → Download ZIP) แล้วแตกไฟล์
  6. เปิด terk_arm_esp32_v1.ino แก้ค่า ssid/password ให้เป็น Wi-Fi ของตัวเอง
  7. เลือกบอร์ด ESP32 Dev Module และพอร์ต COM ที่ถูกต้อง แล้วกด Upload
💡 OTA: หลังโหลดครั้งแรกผ่านสายแล้ว ครั้งต่อไปสามารถอัปเดตผ่านหน้าเว็บ /ota ได้โดยไม่ต้องใช้สาย

🌐 หน้าเว็บควบคุมบน ESP32

แขนกลมี Web Server ในตัว (พอร์ต 80) เข้าใช้งานผ่านเบราว์เซอร์ที่ http://[IP-ESP32]/ ประกอบด้วยโหมด:

🎯 XYZ Mode — ป้อนพิกัด X,Y,Z แล้วแขนกลคำนวณ IK ให้อัตโนมัติ 🔧 Joint Mode — ควบคุมมุม θ1, θ2, θ3 ตรง ๆ 🖐 Gripper — เปิด/ปิดหัวจับ 0–180° 📜 G-code — ส่งชุดคำสั่งแบบลำดับ ⚙️ Setup — ปรับค่าคาลิเบรชัน (บันทึกลง EEPROM)

การเคลื่อนที่ใช้ Trajectory Planning — สร้างจุดขั้นกลาง (interpolation) แล้วป้อนเข้าคิวคำสั่ง commandQueue เพื่อให้ข้อต่อทั้ง 3 ขยับพร้อมกันอย่างนุ่มนวล

9 🔌 API Reference — สั่งงานแขนกลด้วยโปรแกรม

แขนกลเปิด API แบบ HTTP (ไม่ต้องมี Authentication) — เหมาะสำหรับต่อกับ AI, Python, หรือเว็บแอป
Base URL: http://[ESP32_IP]/api/  ·  รูปแบบตอบกลับ: JSON

MethodEndpointพารามิเตอร์คำอธิบาย
POST/api/movex, y, z, speed, accelerationเคลื่อนปลายแขนไปพิกัด X, Y, Z (มม.)
POST/api/jointtheta1, theta2, theta3, speed, accelerationหมุนข้อต่อไปยังมุม (องศา)
POST/api/gripperpositionตั้ง Gripper 0–180°
GET/api/status—ดูตำแหน่ง มุมข้อต่อ สถานะคิว Wi-Fi IP
POST/api/gcodegcodeส่งชุดคำสั่ง G-code (หลายบรรทัดได้)
POST/api/home—กลับตำแหน่ง Home
POST/api/zero—ตั้งศูนย์ / Calibrate
GET/api/docs—หน้าเอกสาร API ในตัว
ℹ️ Content-Type: ใช้ application/x-www-form-urlencoded สำหรับ POST — รองรับ CORS สำหรับเว็บแอป

🐍 ตัวอย่าง Python — Pick & Place

import requests, time

robot = "http://192.168.1.100"   # เปลี่ยนเป็น IP ของ ESP32

def api(ep, data=None):
    r = requests.post(f"{robot}/api/{ep}", data=data)
    print(ep, "→", r.json()["message"])

# 1. ไปยังตำแหน่งหยิบชิ้นงาน
api("move", {"x": 100, "y": 100, "z": 50, "speed": 1000})
time.sleep(2)
# 2. ลดแขนลง
api("move", {"x": 100, "y": 100, "z": 10})
time.sleep(1)
# 3. คีบชิ้นงาน (Gripper ปิด = 0°)
api("gripper", {"position": 0})
time.sleep(1)
# 4. ยกขึ้น แล้วไปทิ้งที่ตำแหน่งใหม่
api("move", {"x": 100, "y": 100, "z": 50})
time.sleep(1)
api("move", {"x": 200, "y": 200, "z": 50})
time.sleep(2)
api("move", {"x": 200, "y": 200, "z": 10})
time.sleep(1)
# 5. ปล่อยชิ้นงาน (Gripper เปิด = 180°)
api("gripper", {"position": 180})
print("✅ Pick & Place เสร็จสิ้น")

📜 ตัวอย่าง G-code

# เคลื่อนที่ไปพิกัด (XYZ x y z delay)
XYZ 100 100 50 1000
# คีบชิ้นงาน
GPON
# หน่วงเวลา 500 ms
DELAY 500
# ย้ายไปตำแหน่งทิ้ง
XYZ 200 200 50 1000
# ปล่อยชิ้นงาน
GPOFF

ส่งผ่าน POST /api/gcode ด้วยพารามิเตอร์ gcode — ระบบจะแยกทีละบรรทัดแล้วเข้าคิวสั่งงานตามลำดับ

10 🤖 AI → แขนกล (Local LLM + Wi-Fi)

🧠 ขั้นตอนติดตั้ง Ollama (Local AI บนเครื่อง)

  1. ดาวน์โหลดและติดตั้ง Ollama จากเว็บไซต์
  2. เปิด Terminal แล้วโหลดโมเดลภาษาไทย: ollama pull typhoon-instruct (หรือ qwen2.5 / gemma2)
  3. ทดสอบ: ollama run typhoon-instruct "สวัสดี"
  4. เชื่อมคอมพิวเตอร์กับ Wi-Fi เดียวกับ ESP32 (หรือให้ ESP32 ต่อ AP เดียวกัน)
⚠️ ข้อควรรู้: โมเดล Local ทำงานออฟไลน์ ไม่ต้องใช้อินเทอร์เน็ต — แต่คอมพิวเตอร์กับ ESP32 ต้องอยู่ใน เครือข่ายเดียวกัน จึงจะคุยกันได้

� ขั้นตอนการทำงาน AI → แขนกล

"หยิบกระป๋อง สีแดงไปทิ้ง" Ollama (LLM) Typhoon / Qwen JSON x,y,z,gripper Wi-Fi /api/move แขนกล

รูป: AI ตีความคำสั่งภาษาไทย → แปลงเป็น JSON → ส่งผ่าน Wi-Fi → ESP32 ขยับแขนกลทำงาน

�🐍 โค้ดตัวอย่าง: “หยิบกระป๋องสีแดงไปทิ้ง”

import requests, subprocess, json, re

ESP32 = "http://192.168.1.100"     # IP ของแขนกล

def ask_ai(prompt):
    r = subprocess.run(["ollama", "run", "typhoon-instruct", prompt],
                       capture_output=True, text=True)
    return r.stdout.strip()

# 1) ให้ AI แปลงคำสั่งภาษาคน → JSON พิกัด
text = "หยิบกระป๋องสีแดงไปทิ้ง"
prompt = f"""แขนกล 3DOF ทำงานบนพื้นที่ x=0..300, y=0..400, z=0..250 มม.
กระป๋องสีแดงอยู่ที่ x=100,y=100,z=50 และถังขยะอยู่ที่ x=250,y=250,z=50
ตอบเป็น JSON เดียวเท่านั้น: {{"x":..,"y":..,"z":..,"gripper":0}}   (gripper 0=คีบ 180=ปล่อย)
คำสั่ง: {text}"""
out = ask_ai(prompt)

# 2) แยก JSON ออกจากคำตอบ แล้วส่งไปแขนกล
m = re.search(r'\{.*\}', out, re.S)
data = json.loads(m.group(0))
print("🤖 AI ตีความได้:", data)

# 3) สั่งแขนกลทำงาน
requests.post(f"{ESP32}/api/move", data={"x": data["x"], "y": data["y"], "z": data["z"]})
requests.post(f"{ESP32}/api/gripper", data={"position": data["gripper"]})
print("✅ แขนกลทำงานตามคำสั่ง AI แล้ว!")
💡 แนวคิดการออกแบบ: แทนที่จะให้ AI คำนวณพิกัดเอง ให้ AI เลือกพิกัดจากชุดที่กำหนดไว้ล่วงหน้า (รู้พิกัดชิ้นงาน/จุดทิ้ง) จะแม่นยำและปลอดภัยกว่า — AI ทำหน้าที่ “เข้าใจภาษา” ส่วนแขนกลทำหน้าที่ “คำนวณและเคลื่อนที่”

👁️ ระดับถัดไป: ให้แขนกล “มองเห็น” ด้วย VLM / VLA

นอกจาก AI ที่ “ฟังคำสั่ง” แล้ว เรายังเพิ่ม AI ที่ “มองเห็น” ได้ — ใช้กล้องเว็บแคม (Webcam) + โมเดล Vision Language Model (VLM) ให้แขนกลหาตำแหน่งชิ้นงานจากภาพได้เอง โดยไม่ต้องบอกพิกัดล่วงหน้า

  • VLM (Vision–Language Model) — โมเดลที่เข้าใจทั้งภาพและข้อความ เช่น qwen3-vl, minicpm-v4.5, llava (รันผ่าน Ollama ได้เลย) — ถามได้ว่า “กระป๋องสีแดงอยู่ตรงไหนในภาพ?” แล้วได้พิกัดพิกเซลกลับมา
  • VLA (Vision–Language–Action) — โมเดลหุ่นยนต์แบบ End-to-End (เช่น OpenVLA, RT-2, π0) ที่รับภาพ + คำสั่ง แล้วออกการเคลื่อนที่ของมอเตอร์โดยตรง — ยังเป็นงานวิจัยขั้นสูง เหมาะสำหรับผู้เรียนที่อยากต่อยอด

สถาปัตยกรรมที่แนะนำสำหรับค่าย: กล้อง → VLM หาตำแหน่งชิ้นงาน → แปลงพิกเซลเป็นพิกัด X, Y, Z → ส่ง /api/move (ใช้ IK ที่เรียนมาแล้ว — เหมาะกับงานจริงและปลอดภัยกว่า VLA แบบเต็มรูปแบบ)

📷 กล้อง VLM qwen3-vl พิกัด px x_px, y_px แปลงพิกัด X, Y, Z แขนกลหยิบงาน

รูป: แขนกลมองเห็นด้วย VLM — กล้องจับภาพ → โมเดลหาตำแหน่ง → แปลงพิกัด → สั่งแขนกล

🐍 โค้ดตัวอย่าง: “มองเห็นกระป๋องแดงแล้วหยิบ”

import requests, base64, json, re, cv2

# 1) ถ่ายภาพจากกล้องเว็บแคม (OpenCV)
cap = cv2.VideoCapture(0)
ok, frame = cap.read()
cap.release()
_, buf = cv2.imencode(".jpg", frame)
b64 = base64.b64encode(buf).decode()

# 2) ถาม VLM ผ่าน Ollama API ให้หาตำแหน่งกระป๋องในภาพ
r = requests.post("http://localhost:11434/api/generate", json={
    "model": "qwen3-vl",   # หรือ minicpm-v4.5 / llava
    "prompt": 'ในภาพนี้มีกระป๋องสีแดง 1 ใบ '
              'ตอบเป็น JSON: {"x_px":..,"y_px":..} (กึ่งกลางวัตถุเป็นพิกเซล)',
    "images": [b64],
    "stream": False,
})
out = r.json()["response"]
m = re.search(r'\{.*\}', out, re.S)
px = json.loads(m.group(0))
print("📍 VLM เห็นชิ้นงานที่พิกเซล:", px)

# 3) แปลงพิกเซล -> พิกัดแขนกล (ต้องคาลิเบรตกล้องก่อน) แล้วสั่งงาน
x = int(px["x_px"] * 0.5)          # ตัวอย่างการแมปพิกัด
y, z = 300, 80
requests.post("http://192.168.1.100/api/move", data={"x": x, "y": y, "z": z})
print("✅ แขนกลเคลื่อนไปหยิบชิ้นงานที่มองเห็น")
⚠️ ข้อควรระวัง: ต้องคาลิเบรตกล้องก่อนใช้งานจริง (จับคู่พิกเซลกับพิกัดแขนกล) และ VLM อาจตรวจจับพลาดได้ — ให้ผู้เรียนตรวจสอบและลองซ้ำ 2–3 ครั้ง เพื่อฝึกทักษะการแก้ปัญหาแบบวิศวกร

11 🎮 Reinforcement Learning + การเทรนใน Simulator (MuJoCo / Isaac Sim)

ต่อยอดจากแขนกลของเรา — นอกจากการควบคุมด้วยสูตร Kinematics แล้ว ยังมีอีกแนวทางคือ ให้ AI เรียนรู้การควบคุมเองด้วย Reinforcement Learning (RL) โดยเทรนในโลกจำลอง (Simulator) ก่อน แล้วค่อยนำไปใช้กับแขนจริง (Sim-to-Real)

🧠 RL เบื้องต้นใน 1 นาที

Agent 🤖 Policy π(a|s) Environment 🌍 MuJoCo / Isaac Sim Action State + Reward
  • Agent — สมอง/Policy ที่จะเรียนรู้ (เช่น แขนกล)
  • Environment — โลกที่ Agent อยู่ (ฟิสิกส์ใน Simulator)
  • State (s) — สิ่งที่ Agent เห็น (มุมข้อต่อ, ตำแหน่งเป้าหมาย)
  • Action (a) — สิ่งที่ Agent สั่ง (แรงบิด / มุมมอเตอร์)
  • Reward (r) — คะแนนตอบแทน (เข้าใกล้เป้า = บวก, ชนอะไร = ลบ)

Agent เล่นซ้ำหลายพันรอบ (Episode) เพื่อปรับ Policy ให้ได้คะแนนรวมสูงสุด — เหมือนการฝึกสุนัขด้วยขนม!

🛡️ ทำไมต้องเทรนใน Simulator ก่อน (Sim-to-Real)

⚡ เร็ว

ซิมรันเร็วหลายร้อยเท่าของเวลาจริง — เทรนเป็นล้านรอบได้ในไม่กี่ชั่วโมง

🛡️ ปลอดภัย

ไม่ต้องกลัวแขนพัง/ชนของจริง ตอนที่ยัง Trial & Error ช่วงแรก

💰 ถูก

ไม่ต้องใช้อุปกรณ์หลายชุด — รันขนานได้หลายพัน Environment บน GPU

⚠️ ข้อควรระวัง: มีช่องว่างระหว่างซิมกับของจริง (Sim-to-Real Gap) เช่น แรงเสียดทาน ความหน่วงของมอเตอร์ — ควรสุ่มค่าพารามิเตอร์ในซิม (Domain Randomization) เพื่อให้ Policy ทนทานเมื่อไปใช้งานจริง

🦾 MuJoCo — ฟิสิกส์เอนจินโอเพนซอร์ส (Google DeepMind)

  • ฟรี + Open Source ติดตั้งง่ายด้วย pip install mujoco
  • ฟิสิกส์รวดเร็ว แม่นยำ เหมาะกับงาน Contact-rich (การคีบจับ)
  • ฟอร์แมตโมเดล MJCF (XML) — เขียน/แก้โมเดลแขนด้วยมือได้
  • เชื่อมกับ Gymnasium + Stable-Baselines3 (PPO) ได้ทันที
  • มีโมเดลสำเร็จรูปใน MuJoCo Menagerie (รวมแขนกลหลายรุ่น)
# pip install mujoco gymnasium stable-baselines3
import gymnasium as gym
from stable_baselines3 import PPO

# แขนกล 2 ข้อต่อใน MuJoCo (Reacher: เอื้อมถึงเป้า)
env = gym.make("Reacher-v5")

# เทรนด้วย PPO (Proximal Policy Optimization)
model = PPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=200_000)
model.save("reacher_policy")

# ทดสอบ Policy ที่เทรนแล้ว
env = gym.make("Reacher-v5", render_mode="human")
obs, _ = env.reset()
for _ in range(500):
    action, _ = model.predict(obs, deterministic=True)
    obs, reward, terminated, truncated, _ = env.step(action)
    if terminated or truncated:
        obs, _ = env.reset()

🎮 NVIDIA Isaac Sim + Isaac Lab — ระดับโรงงาน

  • Simulator บน NVIDIA Omniverse — ภาพสมจริงด้วย RTX, ฟิสิกส์บน GPU
  • นำเข้าโมเดลได้จาก URDF / MJCF / Onshape / CAD → แปลงเป็น USD
  • Isaac Lab = เฟรมเวิร์ก Robot Learning (โอเพนซอร์ส) — มี 30+ สภาพแวดล้อมสำเร็จรูป, หุ่นยนต์ 16+ รุ่น
  • รองรับ RL หลายไลบรารี: RSL-RL, SKRL, RL Games, Stable-Baselines3
  • เซนเซอร์สมจริง: RTX Camera, LiDAR, Depth, IMU — เหมาะกับงาน Perception
  • ข้อจำกัด: ต้องมี GPU NVIDIA RTX และติดตั้งหนัก (หลาย GB)
# Isaac Lab: เทรนแขน Franka ให้เอื้อมถึงเป้า (ตัวอย่างคำสั่ง)
./isaaclab.sh -p scripts/reinforcement_learning/rsl_rl/train.py \
    --task Isaac-Reach-Franka-v0 --num_envs 4096
💡 Isaac Lab ล่าสุด (2026): เวอร์ชัน 3.0 (Beta) ใช้กับ Isaac Sim 6.x — รองรับการเทรนแบบ Multi-Agent, Imitation Learning และทำงานกับเอนจิน Newton (โอเพนซอร์สใหม่จาก NVIDIA + Google DeepMind + Disney) ได้ด้วย

⚖️ เปรียบเทียบ MuJoCo vs Isaac Sim — เลือกใช้ตัวไหน?

หัวข้อMuJoCoNVIDIA Isaac Sim + Isaac Lab
ลิขสิทธิ์ฟรี + Open Source (DeepMind)ฟรี (Isaac Lab: Apache 2.0)
ความสมจริงภาพพื้นฐาน (OpenGL)Photorealistic (RTX / Omniverse)
ความเร็ว / ขนาดเบา เร็ว รันบน CPU ได้GPU-accelerated รันหลายพัน Env พร้อมกัน
ฟอร์แมตโมเดลMJCF, URDFUSD, URDF, MJCF, Onshape, CAD
เซนเซอร์พื้นฐานRTX Camera, LiDAR, Depth, IMU ฯลฯ
RL FrameworkGymnasium + Stable-Baselines3RSL-RL, SKRL, RL Games, SB3
ฮาร์ดแวร์ขั้นต่ำCPU/GPU ทั่วไปต้องมี GPU NVIDIA RTX
เหมาะกับมือใหม่, เรียน RL, ทดสอบไอเดียเร็วงานใหญ่, Sim-to-Real, Perception

🚀 ต่อยอดกับแขนกลของค่าย

  1. สร้างโมเดลแขนกลใน Onshape → Export เป็น URDF (หรือใช้ปลั๊กอิน Onshape-to-URDF)
  2. โหลดเข้า MuJoCo (เบา เริ่มต้นเร็ว) หรือ Isaac Sim (สมจริง) เพื่อทดสอบฟิสิกส์
  3. นิยาม Reward: “เข้าใกล้เป้า / คีบจับสำเร็จ = +” “ชนพื้น / เกินขอบเขต = −”
  4. เทรนด้วย PPO จนได้ Policy ที่คีบ–วางชิ้นงานได้
  5. Export Policy แล้วนำไปรันบน ESP32 (หรือคอมพิวเตอร์) สั่งผ่าน /api/move ที่มีอยู่แล้ว
💡 แนวคิด: RL ไม่ได้มาแทนที่ Kinematics — โดยทั่วไปยังใช้ IK กำหนดเป้าหมาย แล้วให้ RL เรียนรู้ “การควบคุมละเอียด” (เช่น หนีบของนุ่ม, หลบสิ่งกีดขวาง) — ทั้งสองอย่างใช้คู่กันได้

📘 การตั้งค่า PPO Policy สำหรับแขนกล 3DOF

เจาะลึกการตั้งค่า PPO ที่สำคัญ — Actor–Critic, Runner, Algorithm, Observation/Action Space และ Distillation — อธิบายทีละพารามิเตอร์ พร้อมค่าที่แนะนำสำหรับแขนกลของเรา:

ค่าที่แนะนำสำหรับแขนกล 3DOF (terk_arm):

obs    = [θ1, θ2, θ3, gripper, target_x, target_y, target_z]   (7)
action = [Δθ1, Δθ2, Δθ3, gripper]                                (4)
actor_hidden_dims = [128, 64]   critic_hidden_dims = [128, 64]
clip_param = 0.2   entropy_coef = 0.005   init_noise_std = 1.0
💡 ขั้นตอน: เทรน PPO ใน MuJoCo / Isaac Lab → distill เป็น student ขนาดเล็ก → export policy.onnx → แปลงเป็น C → รันบน ESP32 → สั่งงานผสานกับ /api/move ที่มีอยู่แล้ว

12 🧾 ตาราง BOM (Bill of Materials) — ตัวอย่างต้นทุน

ตารางตัวอย่างสำหรับ 1 ชุด ให้ปรับราคาตามจริงที่หาได้จาก Shopee ในวันที่เรียน (ราคาประมาณการเท่านั้น — ใช้เป็น แบบฟอร์ม ให้ผู้เรียนกรอกเอง)

#รายการจำนวนสเปกโดยย่อราคา/ชิ้น (บาท)รวม (บาท)
1ESP32 DevKit / SuperMini1Wi-Fi + Bluetooth, 3.3V——
2สเต็ปเปอร์มอเตอร์ NEMA 1731.8°/step, 12V, ~0.4A——
3Driver A4988 / DRV88253สำหรับขับสเต็ปเปอร์——
4เซอร์โว Gripper (MG996R/SG90)1สำหรับหัวจับ——
5PCA9685 (โมดูล PWM)116 ช่อง ควบคุมเซอร์โว——
6แหล่งจ่ายไฟ 12V1กระแสเพียงพอสำหรับมอเตอร์ทั้งหมด——
7Buck Converter 12V→5V1จ่ายไฟให้ ESP32/เซอร์โว——
8ชิ้นส่วนพิมพ์ 3 มิติ1 ชุดโครงสร้าง + Gripper (MakerWorld + ออกแบบเอง)——
9สกรู/น็อต M2, M31 ชุดสำหรับยึดข้อต่อและ Gripper——
10สายไฟ + Jumper + แผงต่อวงจร1 ชุดสำหรับเดินสายไฟ——
รวมทั้งชุด___________ บาท
ℹ️ กิจกรรม: ให้ผู้เรียนค้นหาราคาจริงบน Shopee แล้วกรอกลงตาราง พร้อมคำนวณผลรวมและเปรียบเทียบงบประมาณ — ฝึกทักษะการจัดซื้อและการอ่านสเปกอุปกรณ์

13 📚 เอกสารและแหล่งเรียนรู้เพิ่มเติม

🔗 ลิงก์สำคัญ

🏠 ทบทวนความรู้ประจำวัน

💡 วันที่ 1: Sketch/Extrude คืออะไร? Infill ต่างจาก Support อย่างไร? BOM คืออะไร?
💡 วันที่ 2: FK กับ IK ต่างกันยังไง? ถ้าเพิ่ม θ1 ปลายแขนจะขยับแบบใด? ทำไมต้องอ่าน README?
💡 วันที่ 3: Local LLM กับ Cloud AI ต่างกันอย่างไร? ปลอดภัยกว่าตรงไหน? จะทำให้ AI ตีความผิดพลาดน้อยลงได้ยังไง?

📱 แชร์เว็บสื่อการสอนนี้

สแกน QR ด้านล่างเพื่อเปิดเว็บไซต์บนมือถือ — แชร์ให้เพื่อน หรือพิมพ์ติดห้องเรียนได้เลย

https://terk182.github.io/rmutl_robot_arm/