โมดูล edge_ai: ถามทะเบียนโมเดล เลือก แล้วอ่านคำตอบ
โมดูล 1 — เริ่มต้น: รันของจริงแล้วแกะดูข้างใน · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร
ใช้สี่คำสั่งหลักของโมดูล edge_ai คือ models, select, result และ stop อ่านคำตอบของโมเดลเป็น dict แปลความ conf กับ CONF_FLOOR และ latency ให้ถูก แล้วรันเมนูหกโมเดลครั้งแรกบน Emulator หรือบอร์ด
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ:
- เรียก edge_ai.models() แล้วอ่านคีย์ index, name, sensor และ labels ของแต่ละโมเดลได้ถูก และอธิบายว่าทำไมควรถามทะเบียนจากเฟิร์มแวร์แทนการ hard-code ชื่อหรือเลขโมเดล
- อธิบายว่า edge_ai.select(n) ยืนยันการสลับโมเดลด้วยการสังเกต (confirm by observation) และห่อการเรียกด้วย try/except OSError ได้
- อ่าน dict จาก edge_ai.result() แล้วบอกได้ว่า label, top, conf, scores, latency_ms และ seq หมายถึงอะไร ตัดสินได้ว่าผลใดเชื่อได้ตาม CONF_FLOOR (0.50) และแปลง latency เป็นจำนวนครั้งต่อวินาทีได้
- รันเมนู Edge AI บน BENTO Emulator หรือบอร์ด เลือกโมเดล กด Load แล้วเห็นคลาสที่ชนะเปลี่ยนตามท่าทางหรือเสียง
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ทบทวนบทเรียน 1.1 ว่าโค้ด MicroPython อยู่บน Cortex-M33 ส่วนโมเดลอยู่บน Cortex-M55 กับ NPU เปิด BENTO IDE ไว้ ถ้ามีบอร์ดให้ต่อสาย USB ให้พร้อม ถ้ายังไม่มีก็ใช้ BENTO Emulator ได้ทั้งบทเรียน
- อุปกรณ์: บอร์ด TESAIoT Dev Kit ที่ลงเฟิร์มแวร์ MicroPython ของ BENTO แล้ว หรือ BENTO Emulator ใน BENTO IDE — บน Emulator คะแนนของโมเดลเป็นค่าจำลองจากเซนเซอร์จำลอง และมีห้าโมเดล (ไม่มี Push Detection)
- เรียนมาก่อน: บทเรียน 1.1 — Edge AI คืออะไร: วงจรชีวิตของข้อมูลห้าขั้นและเป้าหมายที่โมเดลไปรันได้
โมดูล edge_ai คือหน้าต่างเดียวที่เราคุยกับเครื่องยนต์อนุมานบน M55 บทเรียนนี้ใช้แค่สี่คำสั่ง models → select → result → stop
ซึ่งเป็นทั้งเรื่องราวของการรันโมเดล: อ่านทะเบียน เลือกโมเดล อ่านผล แล้วหยุด
edge_ai.models() คืน list ของ dict หนึ่งตัวต่อโมเดล มีคีย์ index (ใช้ตอน select) name (โชว์บนจอ) sensor
(0 = IMU, 1 = RADAR, 2 = MIC) และ labels (คลาสที่โมเดลตอบได้) นิสัยที่ดีคือ ถามฮาร์ดแวร์ก่อน อย่าเดา
ถ้าเฟิร์มแวร์เพิ่มหรือลดโมเดล โค้ดที่อ่านจาก models() จะปรับตามเอง ซึ่งสำคัญมากเพราะบอร์ดกับ Emulator มีจำนวนโมเดลไม่เท่ากัน
edge_ai.select(n) เป็นคำสั่งข้ามคอร์ มันส่งคำสั่งแล้วคอยเช็กว่าเครื่องยนต์สลับจริงหรือยัง (confirm by observation)
ถ้าไม่ยืนยันภายในเวลาที่กำหนดจะโยน OSError เราจึงห่อด้วย try/except OSError เสมอ และ start(n) ทำงานเหมือน select(n)
edge_ai.result() คืนผลล่าสุดเป็น dict หรือ None ถ้ายังไม่มีผล: label คลาสที่ชนะ top ลำดับของคลาสนั้น conf ความมั่นใจ 0..1
scores คะแนนทุกคลาสที่รวมกันได้ 1 latency_ms เวลาที่ NPU ใช้ และ seq ที่เพิ่มขึ้นทุกครั้งที่มีผลใหม่
ในภาษาคณิต คลาสที่ชนะคือ $\arg\max_k s_k$ และความมั่นใจคือ $\max_k s_k$ ค่า CONF_FLOOR = 0.50 คือเส้นที่เฟิร์มแวร์แนะนำ
ต่ำกว่านี้ถือว่าโมเดลยังไม่ชัวร์ เพราะโมเดลตอบเป็นความน่าจะเป็น ไม่ใช่ความจริงเด็ดขาด ส่วน latency แปลงเป็นจำนวนครั้งต่อวินาทีได้ด้วย
$\text{fps} = 1000 / t_{\text{ms}}$ เช่น 4.1 ms ≈ 244 ครั้งต่อวินาที
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”เปิด 12_edge_ai_menu.py ดูก่อนว่าหน้า Edge AI จริงใช้สี่คำสั่งนี้อย่างไร ทาย (Predict) ก่อนรันว่าเลือก Motion แล้วเขย่าบอร์ดจะเกิดอะไร
แล้วค่อยรันเทียบ ไฟล์ที่เราจะเติมเองอยู่ในบทเรียน 1.3
| ไฟล์ | ไฟล์นี้สอน |
|---|---|
| examples/12_edge_ai_menu.py | Edge AI Menu: เลือกและรันโมเดล AI ได้ทุกตัวในเฟิร์มแวร์เดียว (ไม่ต้องต่อเน็ต) |
สไลด์ของบทเรียนนี้อ้างถึงไฟล์ที่อยู่ในบทเรียนอื่นหรือใน shared/ ด้วย:
- m01-onboarding/l03-first-inference-lab/practice/s01_first_inference.py — รันโมเดล Edge AI ตัวแรกของเรา (ฉบับฝึกเติมโค้ด)
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ
-
ทำไมโค้ดในหลักสูตรนี้ถึงอ่านชื่อโมเดลจาก edge_ai.models() แทนการเขียนชื่อหรือเลขโมเดลตายตัว (เลือกหนึ่งข้อ · เป้าหมายข้อ 1)
- ก) เพราะ models() เร็วกว่าการเขียน list เอง
- ข) เพราะเฟิร์มแวร์แต่ละบอร์ดมีโมเดลไม่เท่ากัน ถ้าอ่านจากทะเบียน โค้ดจะปรับตามเองโดยไม่ต้องแก้
- ค) เพราะ select() รับได้เฉพาะชื่อโมเดล
- ง) เพราะ Emulator ไม่มีโมเดลเลย
เฉลย
ข — นิสัย “ถามฮาร์ดแวร์ก่อน อย่าเดา” ทำให้โค้ดชุดเดียวใช้ได้ทั้งบอร์ดหกโมเดลและ Emulator ห้าโมเดล ลำดับที่ต่างกันก็ไม่ทำให้พัง
-
ถ้า edge_ai.select(n) ส่งคำสั่งไปแล้วแต่เครื่องยนต์ไม่สลับภายในเวลาที่กำหนด จะเกิดอะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) select() คืน None เงียบ ๆ แล้วโปรแกรมทำต่อ
- ข) select() โยน OSError เราจึงต้องห่อด้วย try/except OSError
- ค) บอร์ดรีบูตเอง
- ง) โมเดลตัวเดิมถูกลบออกจากทะเบียน
เฉลย
ข — select() ยืนยันด้วยการสังเกตว่าโมเดลที่ active เปลี่ยนจริง ถ้าไม่เห็นก็โยน OSError เพื่อไม่ให้โปรแกรมโกหกว่ากำลังรัน
-
ผลคือ {‘label’: ‘circle’, ‘conf’: 0.41, …} และ CONF_FLOOR = 0.50 ควรทำอย่างไรกับคำตอบนี้ (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)
- ก) เชื่อเลยเพราะ circle ชนะ
- ข) ถือว่ายังไม่ชัวร์ เพราะ conf ต่ำกว่า CONF_FLOOR ยังไม่ควรสั่งการตามคำตอบนี้
- ค) เรียก select() ใหม่ทุกครั้งที่ conf ต่ำ
- ง) คูณ conf ด้วย 2 ให้ผ่านเกณฑ์
เฉลย
ข — argmax เลือกผู้ชนะเสมอแม้คะแนนสูสี CONF_FLOOR คือเกณฑ์ตัดบนค่า conf เชื่อคำตอบก็ต่อเมื่อ conf ≥ 0.50
-
latency_ms = 5 หมายความว่าโมเดลรันได้สูงสุดราวกี่ครั้งต่อวินาที (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)
- ก) 5 ครั้ง
- ข) 50 ครั้ง
- ค) 200 ครั้ง
- ง) 5000 ครั้ง
เฉลย
ค — fps = 1000 / t_ms = 1000 / 5 = 200 ครั้งต่อวินาที เหลือเฟือเมื่อเทียบกับลูปที่อ่านผลทุกราว 180 ms
-
บน BENTO Emulator คุณเลือก Motion Detection กด Load แล้วลากแผ่นเอียงหรือกด Shake ควรเห็นอะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) คลาสที่ชนะเปลี่ยนระหว่าง idle / circle / shaking พร้อมแถบความมั่นใจของทุกคลาส
- ข) รายชื่อโมเดลหายไปจาก dropdown
- ค) หน้าจอขึ้น Push ทุกครั้ง
- ง) ไม่มีอะไรเปลี่ยนจนกว่าจะต่อ WiFi
เฉลย
ก — Motion มีสามคลาส idle circle shaking บน Emulator คะแนนเลียนแบบจากเซนเซอร์จำลอง จึงเปลี่ยนตามการเอียงหรือเขย่าที่เราจำลอง ไม่ต้องใช้เน็ตเลย
- ใน REPL หรือในไฟล์ พิมพ์
edge_ai.models()แล้วจดว่าบอร์ดหรือ Emulator ของคุณมีกี่โมเดล ชื่ออะไร ใช้เซนเซอร์อะไร - รันเมนูบน Emulator (หรือบอร์ด) เลือก Motion Detection กด Load แล้วเห็นคลาสที่ชนะเปลี่ยนเป็น idle / circle / shaking
- ถ้ามีบอร์ด ลองสลับไปโมเดลไมโครโฟนอย่างน้อยหนึ่งตัว แล้วส่งเสียงให้คลาสเปลี่ยน
บทเรียน 1.3 เราจะไล่โค้ดไฟล์ s01_first_inference.py แล้วเติมสี่ช่องเองจนเมนูทำงานครบวงจร
บทเรียนถัดไป: บทเรียน 1.3 — ลงมือทำ: เมนูโมเดลตัวแรกของเรา
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- ถ้าตั้ง CONF_FLOOR ต่ำเกินไปหรือสูงเกินไป แอปของคุณจะผิดพลาดแบบไหน
- ทำไม select() ถึงต้อง “รอดู” ว่าสลับจริง แทนที่จะเชื่อว่าสั่งแล้วสำเร็จ
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
ทำไมโค้ดในหลักสูตรนี้ถึงอ่านชื่อโมเดลจาก edge_ai.models() แทนการเขียนชื่อหรือเลขโมเดลตายตัว (เป้าหมายข้อ 1)
- เพราะ models() เร็วกว่าการเขียน list เอง
- เพราะเฟิร์มแวร์แต่ละบอร์ดมีโมเดลไม่เท่ากัน ถ้าอ่านจากทะเบียน โค้ดจะปรับตามเองโดยไม่ต้องแก้
- เพราะ select() รับได้เฉพาะชื่อโมเดล
- เพราะ Emulator ไม่มีโมเดลเลย
ดูเฉลย
คำตอบ: B. เพราะเฟิร์มแวร์แต่ละบอร์ดมีโมเดลไม่เท่ากัน ถ้าอ่านจากทะเบียน โค้ดจะปรับตามเองโดยไม่ต้องแก้
นิสัย "ถามฮาร์ดแวร์ก่อน อย่าเดา" ทำให้โค้ดชุดเดียวใช้ได้ทั้งบอร์ดหกโมเดลและ Emulator ห้าโมเดล ลำดับที่ต่างกันก็ไม่ทำให้พัง
-
ถ้า edge_ai.select(n) ส่งคำสั่งไปแล้วแต่เครื่องยนต์ไม่สลับภายในเวลาที่กำหนด จะเกิดอะไร (เป้าหมายข้อ 2)
- select() คืน None เงียบ ๆ แล้วโปรแกรมทำต่อ
- select() โยน OSError เราจึงต้องห่อด้วย try/except OSError
- บอร์ดรีบูตเอง
- โมเดลตัวเดิมถูกลบออกจากทะเบียน
ดูเฉลย
คำตอบ: B. select() โยน OSError เราจึงต้องห่อด้วย try/except OSError
select() ยืนยันด้วยการสังเกตว่าโมเดลที่ active เปลี่ยนจริง ถ้าไม่เห็นก็โยน OSError เพื่อไม่ให้โปรแกรมโกหกว่ากำลังรัน
-
ผลคือ {'label': 'circle', 'conf': 0.41, ...} และ CONF_FLOOR = 0.50 ควรทำอย่างไรกับคำตอบนี้ (เป้าหมายข้อ 3)
- เชื่อเลยเพราะ circle ชนะ
- ถือว่ายังไม่ชัวร์ เพราะ conf ต่ำกว่า CONF_FLOOR ยังไม่ควรสั่งการตามคำตอบนี้
- เรียก select() ใหม่ทุกครั้งที่ conf ต่ำ
- คูณ conf ด้วย 2 ให้ผ่านเกณฑ์
ดูเฉลย
คำตอบ: B. ถือว่ายังไม่ชัวร์ เพราะ conf ต่ำกว่า CONF_FLOOR ยังไม่ควรสั่งการตามคำตอบนี้
argmax เลือกผู้ชนะเสมอแม้คะแนนสูสี CONF_FLOOR คือเกณฑ์ตัดบนค่า conf เชื่อคำตอบก็ต่อเมื่อ conf ≥ 0.50
-
latency_ms = 5 หมายความว่าโมเดลรันได้สูงสุดราวกี่ครั้งต่อวินาที (เป้าหมายข้อ 3)
- 5 ครั้ง
- 50 ครั้ง
- 200 ครั้ง
- 5000 ครั้ง
ดูเฉลย
คำตอบ: C. 200 ครั้ง
fps = 1000 / t_ms = 1000 / 5 = 200 ครั้งต่อวินาที เหลือเฟือเมื่อเทียบกับลูปที่อ่านผลทุกราว 180 ms
-
บน BENTO Emulator คุณเลือก Motion Detection กด Load แล้วลากแผ่นเอียงหรือกด Shake ควรเห็นอะไร (เป้าหมายข้อ 4)
- คลาสที่ชนะเปลี่ยนระหว่าง idle / circle / shaking พร้อมแถบความมั่นใจของทุกคลาส
- รายชื่อโมเดลหายไปจาก dropdown
- หน้าจอขึ้น Push ทุกครั้ง
- ไม่มีอะไรเปลี่ยนจนกว่าจะต่อ WiFi
ดูเฉลย
คำตอบ: A. คลาสที่ชนะเปลี่ยนระหว่าง idle / circle / shaking พร้อมแถบความมั่นใจของทุกคลาส
Motion มีสามคลาส idle circle shaking บน Emulator คะแนนเลียนแบบจากเซนเซอร์จำลอง จึงเปลี่ยนตามการเอียงหรือเขย่าที่เราจำลอง ไม่ต้องใช้เน็ตเลย
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"โมดูล edge_ai: ถามทะเบียนโมเดล เลือก แล้วอ่านคำตอบ" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "The edge_ai module: list the models, select one, read its answer" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/edge-ai-developer/m01-onboarding/l02-edge-ai-module/
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA