จบชุดบทเรียนนี้เราจะเดินครบ แล้วปิดท้ายด้วยการส่งมอบผลิตภัณฑ์ Edge AI ของทีม:
CONF_FLOOR + debounce + edge-trigger กัน false positives20_capstone.py แล้วออกแบบ Guardian เวอร์ชันของทีมปลายทางของวันนี้: กด Load เฝ้าโมเดล ทำเหตุการณ์เป้าหมาย แล้ว Guardian สั่งการเอง (เสียง + แบนเนอร์ + นับครั้ง) โดยไม่เตือนพร่ำจากพีคหลอก
วันนี้เน้น "ประกอบเป็น + อธิบายการออกแบบได้" ไม่ใช่เขียนของใหม่ — ทุกคำสั่งที่ใช้ เราเจอมาหมดแล้วในชุดบทเรียนก่อน ๆ
ตลอดคอร์สเราสร้าง "ชิ้นส่วน" ทีละชิ้น: logger, ฟิลเตอร์, FFT, โมเดลที่ฝึกเอง, action pipeline วันนี้เอามาต่อเป็น ระบบเดียว
เส้นแบ่งง่ายๆ: เดโมพังเงียบๆ ได้ ผลิตภัณฑ์พังไม่ได้ — มันต้อง "รู้ตัวว่าไม่ชัวร์" และ "ไม่เตือนมั่ว" นี่คือสิ่งที่ capstone ให้คุณพิสูจน์
Guardian ที่จะสร้างวันนี้ ไม่ได้ใช้ของใหม่เลย มันหยิบจากเสาที่เราปูมาทั้งคอร์ส:
เกณฑ์ MVP ของบทเรียน 8.1–8.2 คือ "ข้าม ≥3 เสา" — Guardian ทำครบพอดี และเปิดช่องให้ทีมที่อยากต่อยอดเสียบโมเดลที่ฝึกเอง (เสา Training) หรือ FFT feature (เสา Analysis) เพิ่ม
เราปิดวงพอดี — บทเรียน 1.1–1.3 เริ่มที่ ขั้น Apps (รันโมเดลสำเร็จรูป) วันนี้กลับมาที่ Apps อีกครั้ง แต่คราวนี้เราสร้างได้ทั้งวงจร
ความรู้สึกที่อยากให้คุณมีวันนี้: "เมนู 6 โมเดลในชุดบทเรียนแรกเคยเป็นกล่องดำ ตอนนี้เราเปิดกล่องได้ทุกชั้น และประกอบกล่องของเราเองได้แล้ว"
ก่อนแกะโค้ด ดูปลายทางก่อน นี่คือสิ่งที่ s20_capstone_full.py โชว์เมื่อรัน:
! ALERT ! + เสียงบี๊บ + ตัวนับ alert: N ครั้ง เพิ่มขึ้นจุดที่อยากให้จับ: มันไม่ได้ "เจอปุ๊บเตือนปั๊บ" — มันรอให้มั่นใจพอ แล้วค่อยลงมือ นี่คือความต่างระหว่างเดโมกับผลิตภัณฑ์
หัวใจของ capstone: สามเสาที่เคยอยู่คนละบทเรียน วันนี้ไหลต่อกันในลูปเดียว
สังเกตว่า conf จากโมเดล (Apps) ไม่ได้ถูกใช้ตรงๆ มันวิ่งผ่านเสา Processing ก่อน (กรอง+หน่วง) แล้วค่อยกลายเป็น action — เสาไม่ได้เรียงกันเฉยๆ มัน "ป้อนกันจริง"
หัวใจเดิมจากบทเรียน 1.1–1.3 และ 1.6–1.7 กลับมาครบ: อ่านทะเบียน เลือกโมเดล อ่านผล หยุด แล้วเพิ่ม "ตัดสินใจ + สั่งการ"
| คำสั่ง | ทำอะไรใน Guardian |
|---|---|
edge_ai.models() |
อ่านทะเบียนโมเดล → ทำ dropdown + หา alert_idx |
edge_ai.select(n) |
กด Load → สั่ง CM55 รันโมเดล (ห่อ try/except OSError) |
edge_ai.result() |
อ่าน verdict ล่าสุด {label, top, conf, scores, seq, latency_ms} |
edge_ai.CONF_FLOOR |
เส้นความมั่นใจ 0.50 — ต่ำกว่านี้ "ยังไม่ชัวร์" |
edge_ai.stop() |
ปุ่ม Stop + finally — คืนเครื่องยนต์สู่ idle |
top == alert_idx และ conf ถึงเกณฑ์ ค่อยนับเป็น "เจอ"เรายึด 4 คำสั่งเดิม (
models/select/result/stop) เป็นแกน แล้วห่อชั้นตัดสินใจรอบนอก — โครงนี้คือ pattern ของแอป Edge AI ทุกตัวในโลกจริง
โมเดลตอบความน่าจะเป็น มันกระโดดขึ้นลงได้ทุกเฟรม ถ้าเอา conf ดิบไปตัดสินใจตรงๆ Guardian จะ "เตือนแล้วเงียบ เตือนแล้วเงียบ" น่ารำคาญและไม่น่าเชื่อถือ
conf_ema = dsp.EMA(alpha=EMA_ALPHA) # สร้างครั้งเดียวก่อนลูป
...
conf_s = conf_ema.update(r['conf']) # กรองก่อนเทียบเกณฑ์
sure = conf_s >= edge_ai.CONF_FLOOR
alpha มาก = ตอบไวแต่ยังแกว่ง · alpha น้อย = นิ่งแต่ตอบช้า — นี่คือปุ่มออกแบบที่ทีมต้องเลือกนี่คือเหตุผลที่โมดูล 4 (Analysis) มีอยู่จริง ไม่ใช่ทฤษฎีลอยๆ: ฟิลเตอร์ตัวเดียวกับที่ทำสัญญาณเซนเซอร์ให้สะอาด วันนี้เอามาทำ "ความมั่นใจ" ให้สะอาดด้วย
ตัวกรอง dsp.EMA ที่เราเติมในช่อง 4 มีสูตรบรรทัดเดียว — ผสมค่าปัจจุบันกับ "ความจำ" ที่กรองไว้แล้ว:
อ่านทีละตัวแบบง่ายๆ:
r['conf'])conf_s) เอาไปเทียบ CONF_FLOOREMA_ALPHA โดย ( มาก = เชื่อค่าใหม่มาก, น้อย = เชื่ออดีตมาก)ทำไมสำคัญกับชุดบทเรียนนี้: conf ดิบกระโดดขึ้นลงทุกเฟรม ถ้าเอาไปตัดสินใจตรงๆ Guardian จะเตือนๆ เงียบๆ น่ารำคาญ สูตรนี้ถ่วงอดีตเข้ามาช่วย ทำให้ conf "นิ่ง" ก่อนผ่านด่านตัดสินใจ และเป็นเหตุผลที่ต้องสร้าง conf_ema นอกลูป — เพราะมันต้องเก็บ ข้ามเฟรม ถ้าสร้างใหม่ทุกเฟรมความจำจะถูกล้างทิ้ง
อยากเห็นผลของ ให้ชัด ลองตั้ง
EMA_ALPHA = 0.9เทียบกับ0.2แล้วรัน: 0.9 ตอบไวแต่ยังแกว่ง, 0.2 นิ่งมากแต่ตามช้า — ไม่มีค่าที่ "ถูกที่สุด" มีแต่ค่าที่ "เหมาะกับงานของทีม"
Guardian ไม่ได้ดูแค่คำตอบของโมเดล มันอ่านเซนเซอร์ดิบคู่ขนานไปด้วย เพื่อให้ผู้ใช้ (และตัวมันเอง) รู้ "สถานการณ์รอบตัว"
ax, ay, az = sensors.bmi270.acceleration() # เสา DAQ: อ่านดิบ
mag = (ax*ax + ay*ay + az*az) ** 0.5 # ขนาดเวกเตอร์ความเร่ง
ctx.text("motion: %.1f" % mag) # โชว์เป็นบริบท
mag ~9.8 (แรงโน้มถ่วง) · ถูกจับ/เขย่า mag พุ่งขึ้นการอ่านเซนเซอร์ดิบคือทักษะจากชุดบทเรียน DAQ (โมดูล 2) — capstone เอามาวางข้าง verdict ให้เห็นว่าเสาแรกสุดของวงจรก็ยังมีบทบาทในผลิตภัณฑ์ปลายทาง
ปัญหาใหญ่สุดของ Edge AI ที่ใช้งานจริง ไม่ใช่ "เจอไหม" แต่คือ "เตือนมั่วบ่อยแค่ไหน" Guardian ใช้สามด่านกรองซ้อนกัน:
streak) ตัดพีคหลอกที่โผล่เฟรมเดียวทิ้ง — ต้อง "ยืนยันตัวเอง" หลายครั้งก่อนfired) ยิงครั้งเดียวตอน "เพิ่งเข้าเหตุการณ์" ไม่รัวทุกเฟรมที่ยังเจออยู่สามด่านนี้คือ "วิศวกรรมความน่าเชื่อถือ" — ชุดบทเรียน Apps (บทเรียน 6.3–6.4) ปูเรื่อง debounce มาแล้ว วันนี้เอามาเป็นหัวใจการตัดสินใจของผลิตภัณฑ์
ขนาดเวกเตอร์ความเร่ง (เติมช่อง 2) — ยุบสามแกนเป็นค่าเดียวที่ไม่ขึ้นกับทิศทางบอร์ด:
sensors.bmi270.acceleration() (หน่วย m/s²)เงื่อนไขยิง action (สามด่านของช่อง 5) — ต้องเป็นจริง พร้อมกันทั้งหมด ถึงนับว่า "เจอ":
ทำไมสำคัญ: false positive ส่วนใหญ่ผ่านได้แค่หนึ่งหรือสองด่าน การบังคับ ครบสามคือเหตุผลที่พีคหลอกแวบเดียวไม่ทำให้ Guardian เตือน
ร้อยกลับเข้าสามเสา: เสา DAQ ให้ , เสา Processing ให้ , เสา Apps รวมทุกอย่างเป็น — คณิตสามบรรทัดนี้คือสามเสาในการตัดสินใจครั้งเดียว
capstone ที่ดีต้อง "อธิบายการแลกเปลี่ยนได้" ไม่ใช่แค่ "รันได้" ทุกปุ่มออกแบบมีราคาสองด้าน:
| ปุ่มออกแบบ | ตั้งสูง → | ตั้งต่ำ → | แลกอะไร |
|---|---|---|---|
CONF_FLOOR |
พลาดของจริง (miss) | เตือนมั่ว (false +) | ความไว vs ความแม่น |
HITS_NEEDED |
ตอบช้าลง | เตือนจากพีคหลอก | latency vs false + |
EMA_ALPHA |
ตอบไวแต่แกว่ง | นิ่งแต่หน่วง | ตอบสนอง vs เสถียร |
time.sleep_ms |
ประหยัดไฟ/พลาดจังหวะ | กิน CPU/ไว | พลังงาน vs ความไว |
นี่คือคำถามวิศวกรที่คอร์สฝึกมาทั้งเทอม — "โมเดลตัวนี้ควรอยู่ที่ไหน / ตั้งเกณฑ์เท่าไร / แลกอะไรกับอะไร" capstone คือที่ที่คุณตอบด้วยผลิตภัณฑ์จริง
capstone ไม่ได้เริ่มที่โค้ด มันเริ่มที่ ออกแบบ แล้วค่อยสร้าง แล้วค่อยส่งมอบ — สามจังหวะเดียวกับงานจริง
อย่ากระโดดไป Build เลย — ใช้เวลา 15 นาทีแรกที่ Design ในบันทึกการเรียน (เฝ้าอะไร ทำไม, action คืออะไร, ตั้งเกณฑ์เท่าไรเพราะอะไร) แล้ว Build จะเร็วและตรง
Guardian ยืนบนโมดูลที่เราคุ้นมือแล้วทั้งหมด — ไม่มี API ใหม่ให้จำ มีแต่การเอามาต่อกัน
| โมดูล | ใช้ทำอะไรใน Guardian | เสา |
|---|---|---|
edge_ai |
models / select / result / stop / CONF_FLOOR |
Apps |
dsp |
dsp.EMA(alpha=...) กรองความมั่นใจ |
Processing |
sensors |
sensors.bmi270.acceleration() อ่านบริบทดิบ |
DAQ |
ui / lcd |
Dropdown/Button/Seg7/Bar/Label/Panel + ui.tone + lcd.console |
Apps |
ui.tone(note, wave, vol, ms) เล่นเสียงผ่าน SFX mixer ฝั่ง CM55 — เราใช้ยืนยัน actionถ้าอยากทบทวนคำสั่งไหน เปิด REPL ถามฮาร์ดแวร์ตรงๆ ได้เลย เช่น
import edge_ai; edge_ai.models()— นิสัย "ถามก่อนเดา" จากบทเรียน 1.1–1.3 ยังใช้ได้จนชุดบทเรียนสุดท้าย