บทเรียน 6.4 — ลงมือทำ: action pipeline ที่กัน false positive

Apps II: ท่อสั่งการ (action pipeline) · จาก verdict สู่ action จริง — RGB · เสียง · log

โมดูล 6 — แอป Edge AI

ต่อจากบทเรียน 6.3 — ท่อสั่งการ: CONF_FLOOR, debounce, cooldown และ on_result

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

โครงร่วมของโปรแกรม — ตัวเดิมที่เจอทุกบทเรียน

ก่อนดูไฟล์จริง จำโครง 4 จังหวะจากบทเรียน 1.1–1.3 ไว้ — ชุดบทเรียนนี้ยังเดินตามเป๊ะ ของใหม่แค่ไปแทรกอยู่ใน "ลูป"

1 · import edge_ai · ui · dsp · time 2 · สร้างครั้งเดียว widget + ไฟ RGB + EMA 3 · ลูป (ของใหม่นี่) อ่านผล → ท่อ → action 4 · ui.poll รับปุ่ม back วนกลับ

"สร้างครั้งเดียว" ยังสำคัญเท่าเดิม: ui.Panel ของไฟ RGB และ dsp.EMA สร้างนอกลูป ในลูปแค่ light.color() และ smoother.update() — สร้างซ้ำทุกรอบจอกระพริบและ EMA จะรีเซ็ตตลอด

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

โครงของไฟล์ s16_action_pipeline.py

ทั้งไฟล์อ่านเป็นประโยคเดียว: "เลือกโมเดล → วนอ่านผล → เฟรมนี้เจอเป้าหมายไหม → ครบ debounce+cooldown ไหม → ยิง action"

เลือกโมเดล select() :108 อ่านผล result() :ช่อง 1 hit? ช่อง 2 streak+1 ready = streak≥NEED ready & cooled? :ช่อง 3 fire_action RGB+เสียง+log :ช่อง 4 yes yes no → streak=0 (ไฟฟ้า) ช่อง 1–4 ในไฟล์ฝึก = ด่านของท่อ เรียงตามการไหลนี้

ตัวเลข :108 และ ช่อง 1–4 ชี้จุดที่ต้องเติมในไฟล์ฝึก จำโครงนี้ไว้ เดี๋ยวไล่ดูทีละช่อง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ไล่โค้ด (1) — อ่านผลอนุมาน

ช่องเติมที่ 1: ในลูป ดึงผลล่าสุดมาก่อน เหมือนบทเรียน 1.1–1.3 เป๊ะ — นี่คือปากทางของท่อ

if running:  # (ในไฟล์คือหลังรับปุ่ม)
    # เติม: อ่านผลอนุมานล่าสุดมาเก็บใน r  ->  r = edge_ai.result()
    r = None
    pass
    if r and r['seq'] != last_seq:      # ทำงานเฉพาะตอนมีผลใหม่ (seq เปลี่ยน)
        last_seq = r['seq']
        verdict.text(r['label'] or '-')
        conf.text("conf: %.0f %%" % (r['conf'] * 100))
  • แทน pass ด้วย r = edge_ai.result() — คืน dict (label/conf/scores/seq/...) หรือ None
  • เช็ก seq ก่อนเสมอ วาดจอ + เดินท่อเฉพาะตอนมีผลใหม่ ไม่รัดจอทุกรอบ
  • ถ้าลืมเติม: r เป็น None ตลอด → จอไม่ขึ้นคลาส ท่อไม่เดิน action ไม่ยิง

เหมือนบทเรียน 1.1–1.3 ทุกอย่าง ต่างกันแค่คราวนี้ผลที่อ่านได้กำลังจะถูกส่งเข้าท่อไปตัดสินใจต่อ ไม่ได้จบที่ขึ้นจอ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ไล่โค้ด (2) — ด่านกรอง (false-positive gate)

ช่องเติมที่ 2: ด่านแรกของท่อ — เฟรมนี้นับเป็น "การเจอเป้าหมายจริง" ไหม

# เติม: hit = (r['label'] == TARGET_CLASS and r['conf'] >= edge_ai.CONF_FLOOR)
hit = False
pass

if hit:
    streak += 1
    if streak < NEED_HITS:
        set_light(AMBER, "%d/%d" % (streak, NEED_HITS))
else:
    streak = 0
    set_light(CYAN, "watching")
  • แทน hit = False; pass ด้วยเงื่อนไขสองข้อ and กัน: คลาสตรงเป้าหมาย และ มั่นใจถึงเกณฑ์
  • hit เป็น boolean ของเฟรมเดียว — ยังไม่ยิง แค่ตัดสินว่าเฟรมนี้เข้าข่ายไหม
  • ถ้าลืมกรอง conf: verdict ที่โมเดลเดาแบบไม่มั่นใจก็จะถูกนับด้วย → หลอกง่ายขึ้นมาก

สังเกตว่า streak เพิ่มเมื่อ hit และรีเซ็ตเป็น 0 ทันทีที่ไม่ hit — บรรทัดเล็กๆ นี้แหละที่ล้างยอดแหลมเดี่ยวทิ้ง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ไล่โค้ด (3) — เงื่อนไข debounce + cooldown

ช่องเติมที่ 3: ด่านตัดสินว่า "ยิงได้หรือยัง" — ต้องผ่านทั้ง debounce และ cooldown

now = time.ticks_ms()
cooled = time.ticks_diff(now, last_fire) >= COOLDOWN_MS   # พ้นช่วงเว้นแล้วไหม
ready = streak >= NEED_HITS                               # จับครบต่อเนื่องหรือยัง
# เติม: should_fire = ready and cooled
should_fire = False
pass
if should_fire:
    ...
  • แทน should_fire = False; pass ด้วย should_fire = ready and cooled
  • ready มาจาก debounce (ด่าน 2 นับ streak) · cooled มาจาก cooldown (ด่าน 3 นับเวลา) — ต้องจริงทั้งคู่
  • ready กับ cooled เตรียมไว้ให้แล้ว หน้าที่ของช่องนี้คือ "and" มันเข้าด้วยกัน

ถ้าเอา cooled ออก เหลือแค่ ready: พอคลาสเป้าหมายค้างยาว จะยิงรัวทุกครั้งที่ streak ครบ — cooldown คือตัวเว้นจังหวะ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ไล่โค้ด (4) — ยิง action

ช่องเติมที่ 4: ปลายท่อ — เมื่อผ่านครบทุกด่าน สั่งการจริงแล้วรีเซ็ตให้พร้อมรอบใหม่

if should_fire:
    # เติม: fire_action(r['conf']); last_fire = now; streak = 0
    pass
  • แทน pass ด้วยสามคำสั่ง: fire_action(r['conf']) (ยิง RGB+เสียง+log) · last_fire = now (เริ่มนับ cooldown ใหม่) · streak = 0 (ล้าง streak รอบใหม่)
  • fire_action() เตรียมไว้ให้แล้ว ข้างในทำ 3 ช่องทางครบ — ช่องนี้แค่ "เรียกใช้ + เก็บกวาดสถานะ"
  • ถ้าลืม last_fire = now: cooldown ไม่ถูกรีเซ็ต จะยิงรัวทันทีในเฟรมถัดไป

สามบรรทัดนี้คือ "จบหนึ่งเหตุการณ์": สั่งการ · ตั้งนาฬิกาเว้นช่วง · เคลียร์ตัวนับ พร้อมเริ่มเฝ้ารอบใหม่

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ลงมือทำ — เติมช่องว่างทั้ง 4 จุด

เปิด s16_action_pipeline.py มี pass วางไว้ 4 จุด = 4 ด่านของท่อเรียงตามการไหล

# ด่านของท่อ เติมด้วย ถ้าลืม
1 อ่านผล r = edge_ai.result() จอไม่ขึ้นคลาส ท่อไม่เดิน
2 กรอง hit = (r['label'] == TARGET_CLASS and r['conf'] >= edge_ai.CONF_FLOOR) streak ไม่ขยับ ไม่มีวันยิง
3 debounce+cooldown should_fire = ready and cooled should_fire False ตลอด ไม่ยิง
4 action fire_action(r['conf']); last_fire = now; streak = 0 ผ่านด่านแต่ไม่สั่งการ (หรือยิงรัว)

ขั้นตอน:

  1. ไล่หา # เติม: ทีละจุด แทน pass ตามคำใบ้
  2. กด Run (Emulator) หรือ Program to Device (บอร์ด) เลือก Cough (หรือ Motion เพื่อทดสอบง่าย)
  3. ทำเสียง/ท่าให้ค้าง — ดูไฟไล่ ฟ้า → เหลือง → แดง + เสียง + log ถ้าไอแวบเดียวแล้วยิง แปลว่า debounce ยังไม่ทำงาน กลับไปเช็กช่อง 2–3

สี่ช่องนี้คือ 4 ด่านของท่อเป๊ะ — เติมครบเมื่อไร คุณจะมี action pipeline ที่กัน false positive ได้จริง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

หน้าตาจริงตอนรัน — บน BENTO Edge AI Emulator

ก่อนลงมือ ดูหน้าเมนู Edge AI บน Emulator ที่คุ้นกันตั้งแต่โมดูล 1: dropdown · ปุ่ม Load/Stop · การ์ดผล · แถบคะแนนต่อคลาส

หน้า Edge AI บน BENTO Emulator: dropdown เลือกโมเดล Motion Detection ปุ่ม Load และ Stop คลาสที่ชนะ idle เวลาอนุมาน และแถบความมั่นใจของ idle circle shaking

จอ emulator ที่รันได้จริงบนเบราว์เซอร์ (BENTO Edge AI Emulator) — ไฟล์ของบทเรียนนี้ใช้การ์ดผลกับแถบแบบเดียวกัน แล้วเพิ่มการ์ดไฟ RGB กับ log เข้ามา

สังเกตแถบคะแนนแต่ละคลาส — พอเราเติมท่อครบ 4 ด่านแล้วรัน การ์ดไฟในหน้าของเราจะไล่สีฟ้า → เหลือง → แดง ให้เห็นกับตา

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ลงมือ (1) — รันบน BENTO Emulator

ไม่มีบอร์ดก็เริ่มได้ทันที:

  1. เปิด ide.tesaiot.dev (BENTO Emulator) ในเบราว์เซอร์
  2. เปิดไฟล์ s16_action_pipeline.py
  3. กด Run — จะเห็นการ์ดผล + ไฟ RGB + แถบคะแนนแต่ละคลาส
  4. ตั้งต้นโมเดลเป็น Motion (MODEL_KEYWORD="Motion", TARGET_CLASS="shaking") เพราะเขย่าจำลองง่ายกว่าไอ — แล้วเขย่าค้างดูไฟไล่สี
  5. ลองปรับ NEED_HITS เป็น 1 แล้ว 5 สังเกตว่ายิงง่าย/ยากต่างกันแค่ไหน

Motion/shaking เหมาะกับการซ้อมที่บ้านเพราะควบคุมได้ด้วยมือ พอเข้าใจท่อแล้วค่อยสลับไป Cough ตอนอยู่กับบอร์ดจริง + ไมค์

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ลงมือ (2) — รันบนบอร์ด BENTO จริง

บนบอร์ดจริงใช้ไมค์จริง เสียงจริง:

  1. เสียบบอร์ด เปิดไฟล์ใน BENTO IDE กด Program to Device
  2. ใช้ค่าตั้งต้น Cough (TARGET_CLASS="cough") — ไอใส่ไมค์ให้ต่อเนื่องหน่อย
  3. สังเกตว่าไอ แค้กเดียวสั้นๆ มักไม่ยิง แต่ไอเป็นชุด 2–3 ครั้งติดจะดันไฟเป็นแดง
  4. ดู log ในคอนโซล: ALERT #n ... conf ...% พร้อมจำนวนครั้ง
  5. ในฉบับเต็ม ลองไอค้างยาวๆ ดูตัวเลข blocked เพิ่มขึ้น — นั่นคือ cooldown กำลังกันยิงซ้ำ

โมเดลเสียงแบบ Ready-Model (Cough/Alarm/Siren) มีขีดจำกัดจำนวนครั้งการอนุมานต่อการบูต ถ้าผลนิ่งให้รีบูตบอร์ด — ไม่ใช่โค้ดเราพัง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

จูน pipeline — sensitivity แลกกับ false positive

หัวใจเชิงวิศวกรรมของชุดบทเรียนนี้ ไม่มีค่าที่ "ถูก" ตายตัว ทุกค่าคือการแลกเปลี่ยน คุณต้องเลือกให้เหมาะกับงาน

ไว (ยิงง่าย) เข้ม (ยิงยาก) NEED_HITS=1 false positive เยอะ NEED_HITS=3 จุดกลางที่ใช้ได้ NEED_HITS=6 พลาดของจริงบ่อย
  • NEED_HITS สูง = เตือนผิดน้อย แต่พลาดเหตุการณ์สั้นๆ ของจริง (เช่น ไอครั้งเดียว)
  • CONF_FLOOR สูง = เชื่อเฉพาะที่มั่นใจมาก แต่เหตุการณ์คลุมเครือจะหลุด
  • COOLDOWN_MS ยาว = ไม่รบกวนซ้ำ แต่ถ้าเกิดเหตุจริงสองครั้งติดในช่วงเว้น จะเห็นแค่ครั้งเดียว
  • เครื่องมือวัดว่าจูนดีไหม: นับ false positive (ยิงทั้งที่ไม่มีเหตุ) เทียบ false negative (มีเหตุแต่ไม่ยิง)

คำถามวิศวกรจริง: "งานนี้พลาดแบบไหนแพงกว่ากัน?" เตือนไฟไหม้พลาดของจริงไม่ได้เลย (ต้องไว) · เตือนขโมยพร่ำเพรื่อคนจะเลิกสนใจ (ต้องเข้ม) — ค่าพวกนี้คือการตัดสินใจเชิงออกแบบ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

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

อยากเข้าใจ debounce · false positive · hysteresis ให้ลึกขึ้น ลองตามลิงก์เหล่านี้ (เปิดดูได้ตามสะดวก):

วิดีโอ (ลิงก์ — ของเจ้าของช่องแต่ละคน)

ภาพ / เอกสารอ้างอิง

วิดีโอ/ภาพภายนอกเป็นของเจ้าของต้นฉบับ ใช้เพื่อการศึกษา อ้างอิงลิงก์ต้นทาง — เราไม่ได้ฝังหรือทำซ้ำ เพียงชี้ทางไปอ่านต่อ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ชัยชนะที่เห็นได้ + MVP ของชุดบทเรียนนี้

ชัยชนะที่เห็นได้ของชุดบทเรียนนี้ · verdict ของโมเดลจุดชนวน action จริง (ไฟแดง + เสียง + log) — และ "ไอแวบเดียว" ยิงไม่ได้

MVP ของบทเรียน 6.3–6.4 (เกณฑ์ผ่านของชุดบทเรียน): คุณต่อ action pipeline แบบ debounce ได้ — คลาสเป้าหมาย (เช่น cough) ที่จับได้ต่อเนื่องจุดชนวน action จริง ส่วนสัญญาณกระพริบสั้นๆ ถูกกันไว้ ไม่ยิง

  • ทำบน Emulator หรือ บอร์ดจริง ก็ได้ (โค้ดชุดเดียวกัน)
  • อธิบายได้ว่าท่อ 4 ด่านแต่ละด่านกันอะไร และจูน NEED_HITS/COOLDOWN_MS แล้วพฤติกรรมเปลี่ยนยังไง

"ยิง action ได้" ไม่ใช่แค่ "ไฟติด" — คุณต้องแสดงให้เห็นว่า pipeline ปฏิเสธ สัญญาณปลอมได้ด้วย นั่นคือส่วนที่ยากและมีค่าจริง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

บันไดช่วยเหลือ — ใบ้ → เริ่มจากโครง → เฉลย → ฉบับเต็ม

ถ้าติด ให้ไต่บันไดนี้ทีละขั้น อย่าเพิ่งกระโดดไปดูเฉลย เพราะของจะเข้าหัวตอนที่คุณพยายามเองก่อน:

  • ใบ้ — คำใบ้อยู่ในคอมเมนต์ # เติม: ทั้ง 4 จุดในไฟล์ฝึก + ตารางด่านของท่อหน้าที่แล้ว บอกว่าแต่ละช่องเติมอะไร
  • เริ่มจากโครง — s16_action_pipeline.py มีโครงครบทั้งไฟล์ (widget/ไฟ RGB/fire_action เตรียมไว้แล้ว) เหลือแค่ 4 บรรทัดของท่อ
  • เฉลย — s16_action_pipeline.py เติมครบพร้อมคอมเมนต์อธิบายทุกด่าน (อ่านให้เข้าใจ ปิดไฟล์ แล้วพิมพ์เอง)
  • ฉบับเต็ม — s16_action_pipeline_full.py เพิ่ม dsp.EMA smoothing · ไฟ RGB 4 สถานะ · on_result log การเปลี่ยนคลาส · ตัวนับ blocked

ลองเขียนเองให้สุดก่อนนะ ถ้าติดจริงๆ ค่อยเปิดเฉลยดูทีละด่าน แล้วกลับมาพิมพ์เอง — เดี๋ยวเราค่อย ๆ แกะไปด้วยกัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

เชื่อมโยงรากฐาน — วันนี้เราแตะอะไรไปบ้าง

action pipeline ตัวเดียวซ่อนแนวคิดที่ใช้ต่อได้ทั้งงาน Edge AI จริง:

ฝั่ง Edge AI / ระบบ

  • verdict → action — ผลของโมเดลไม่ได้จบที่จอ มันจุดชนวนการกระทำในโลกจริง
  • false-positive handling — เกราะ 3 ชั้น (conf floor · debounce · cooldown) คือหัวใจที่แยก demo ออกจากของใช้งาน
  • event vs poll — on_result (callback) กับ result() (poll) เหมาะกับงานคนละแบบ เลือกให้ถูก
  • smoothing — dsp.EMA จาก โมดูล 3 (Processing) กลับมาใช้กด verdict ที่กระตุก

ฝั่ง MicroPython / โครงโปรแกรม

  • โครงร่วมเดิม — import → สร้างครั้งเดียว → ลูป → ui.poll (ของใหม่แทรกในลูป)
  • แยก fire_action() ออกมา — ตรรกะ "จะทำอะไรตอนยิง" แก้ที่เดียว ไม่ปนกับ debounce
  • time.ticks_ms/ticks_diff — วัดเวลาอย่างถูกต้อง รับมือ overflow
  • เก็บกวาดตอนจบ — finally: on_result(None); stop() คืนเครื่องสู่สถานะที่รู้แน่

ทั้งหมดนี้คือ "หลังบ้าน" ที่ทำให้แอป Edge AI น่าเชื่อถือพอจะปล่อยให้คนใช้จริง — ชุดบทเรียนถัดไป (บทเรียน 6.5–6.6) เราจะต่อปลายท่อออกเน็ต

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

ใช้จริงที่ไหน — action pipeline ในโลกจริง

ทุกอุปกรณ์ Edge AI ที่ขายได้ มี pipeline แบบนี้ซ่อนอยู่หลังบ้าน หลักการเดียวกับที่เราต่อวันนี้เป๊ะ:

เครื่องตรวจการล้ม (IMU) verdict "fall" ต้องค้างจริง ไม่ใช่แค่วางโทรศัพท์แรงๆ debounce กันแจ้งเตือนปลอม → ญาติไม่ตกใจฟรี action: โทรฉุกเฉิน (ยิงพลาดไม่ได้ทั้งสองทาง) ตรวจเสียงไอ/เสียงเตือน (MIC) ไอครั้งเดียวไม่นับ ต้องเป็นชุด → debounce + cooldown log ทุกครั้งพร้อมเวลา → หมอดูแนวโน้มย้อนหลังได้ action: บันทึก + แจ้งเตือน (คือ Cough วันนี้) สวิตช์ไฟตามการมีคน (RADAR) คนเดินผ่านแวบเดียวไม่เปิดไฟ → ต้องอยู่จริง cooldown กันไฟกระพริบตอนคนขยับไปมา action: เปิดรีเลย์ไฟ ร่วมกัน — ชั้นตัดสินใจ ทุกงานมี verdict → กรอง → debounce → cooldown → action ต่างกันแค่ปลายท่อ (เสียง/รีเลย์/เน็ต) และค่าจูน 6.5–6.6 ต่อปลายท่อออก WiFi/MQTT

ท่อ 4 ด่านที่เราต่อวันนี้ ไม่ใช่ของสมมติ — มันคือชั้นที่ทำให้ Edge AI ในตลาด "เชื่อถือได้" เราแค่ต่อมันด้วยมือตัวเองในไม่กี่บรรทัด

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0

งานทำเอง + สรุปบทเรียน

งานทำเอง (ท้ายบทเรียน):

  1. เติม s16_action_pipeline.py ให้ครบทั้ง 4 ช่อง รันได้จริง (Emulator หรือบอร์ด)
  2. จูน NEED_HITS อย่างน้อย 3 ค่า (เช่น 1, 3, 6) จดว่าแต่ละค่ายิงง่าย/ยากต่างกันแค่ไหน และเกิด false positive กี่ครั้ง
  3. หาสัญญาณที่ ควรถูกกัน (เช่น ไอแวบเดียว / ขยับผ่านเร็วๆ) แล้วยืนยันว่า pipeline กันมันได้จริง อธิบายว่าด่านไหนกัน

ใบ้ข้อ 3 — สัญญาณสั้นๆ ที่หลุด CONF_FLOOR ได้ จะถูกด่าน debounce (streak) จับไว้ เพราะมันไม่ค้างต่อเนื่อง ลองดูตัวเลข streak ตอนนั้นว่าขึ้นถึงเท่าไรแล้วรีเซ็ต

วันนี้เราได้: เข้าใจ verdict → action · เห็นปัญหา false positive จริง · ต่อเกราะ 3 ชั้น (conf floor · debounce · cooldown) + smoothing · แยก event (on_result) กับ poll · สั่งการ 3 ช่อง (RGB · เสียง · log)

ชุดบทเรียนถัดไป (บทเรียน 6.5–6.6) เราจะ รวม verdict กับเซนเซอร์ดิบ (sensor fusion) แล้วส่ง action ออกเน็ตด้วย WiFi/MQTT — ปลายท่อของวันนี้จะยื่นไปถึงคลาวด์ เจอกันครับ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก Edge AI Developer (รศ.วิรุฬห์ ศรีบริรักษ์, BUU) · CC BY-NC 4.0