บทเรียน 6.2 — ลงมือทำ: แอปโฟกัสของเราเอง

Apps I: 6 โมเดล กับ edge_ai API · สร้าง "แอปโฟกัสโมเดลเดียว" ของคุณเอง

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

ต่อจากบทเรียน 6.1 — หกโมเดลกับ edge_ai API: แอปที่โฟกัสโมเดลเดียว

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

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

ไม่มีบอร์ดก็เริ่มได้ ซ้อมโครงแอปบน Emulator ได้เลย (โมเดลเสียงบน Emulator เป็นค่าจำลอง ลูกบิด POTEN ดันคลาสเหตุการณ์ขึ้นได้แต่ยังไม่ชนะ unlabelled ตัวนับจึงยังไม่ขยับ):

  1. เปิด ide.tesaiot.dev (BENTO Emulator) ในเบราว์เซอร์
  2. เปิด 16_edge_ai_sound_events.py กด Run ดูเมนูเสียงสามโมเดลก่อน (ของจริงที่จะแกะ)
  3. จากนั้นเปิด s15_apps.py — นี่คือแอปโฟกัส Cough ที่เราจะเติม
  4. เติมสี่ช่องให้ครบ กด Run หมุนลูกบิด POTEN แล้วดูแถบสองคลาสขยับ ถ้าอยากเห็นตัวนับทำงานบน Emulator ให้เล็งโมเดล Motion ชั่วคราว (TARGET_KEYWORDS = ("motion",), TARGET_CLASS = "shaking") แล้วกดปุ่ม Shake
  5. ตัวนับกับเสียงไอจริงต้องลองบนบอร์ด ลองเสียงอื่นที่ไม่ใช่ไอ ดูว่าตัวนับ ไม่ขยับ (เพราะ conf ไม่ถึงเกณฑ์ หรือคลาสไม่ตรง)

Emulator ใช้เซนเซอร์เสียง จำลอง แต่ API เหมือนบอร์ดจริงทุกบรรทัด — ซ้อมโครงแอปที่บ้านได้ แล้วมายืนยันด้วยไมค์จริงบนบอร์ด

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

หน้าจอ BENTO Edge AI Emulator

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

จอ emulator ที่รันได้จริงในเบราว์เซอร์ — เปิด ide.tesaiot.dev แล้วกด Run ได้เลย ไม่ต้องมีบอร์ด API ทุกบรรทัดเหมือนบอร์ดจริง จึงซ้อมแอปโฟกัสที่บ้านก่อน แล้วมายืนยันด้วยไมค์จริงบนบอร์ด

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

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

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

  1. เสียบบอร์ดเข้าคอมด้วยสาย USB
  2. เปิด s15_apps.py ใน BENTO IDE กด Program to Device
  3. บนจอขึ้นแอปโฟกัส Cough: การ์ด verdict + การ์ดตัวนับ + แถบสองคลาส
  4. ไอใกล้ไมค์ (หรือเปิดคลิปเสียงไอ) หลายครั้ง ดูคลาส cough ชนะ + ตัวนับเพิ่ม
  5. ถ้าผลค้างนิ่ง (seq ไม่ขยับ) ให้ รีบูตบอร์ด — ถึงขีด eval ของ Ready-Model แล้ว

จุดที่ควรสังเกต: ตัวนับจะเพิ่ม หนึ่งต่อการไอหนึ่งครั้ง ไม่ใช่พรวดหลายที เพราะโค้ดนับเฉพาะขอบขาขึ้น ถ้าเห็นมันพรวด แปลว่าเงื่อนไข not was_target หายไป

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

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

ทั้งไฟล์อ่านเป็นประโยคเดียว: "เล็งโมเดล cough → สร้างการ์ด → เริ่มรัน → วนอ่านผล เอาคลาสขึ้นจอ นับเมื่อเจอ → ออกก็หยุด"

เล็งโมเดล find_model :53 สร้างการ์ด Panel+Seg7+Bar :62 เริ่มรัน select :88 (เติม) ออก → finally stop :125 อ่านผล + verdict result/verdict :96 (เติม) นับเมื่อเจอ is_target :112 (เติม) + CONF_FLOOR วนอ่านผลทุก 150 ms แถวล่าง = สิ่งที่เกิดในลูปทุกครั้งที่มีผลใหม่

เลขบรรทัด (:88, :96, :112) ชี้จุดที่คุณต้องเติมในไฟล์ฝึก — สามจุดหลัก แต่มีสี่ช่อง # เติม: (result กับ verdict อยู่ใกล้กัน)

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

ไล่โค้ด (1) — เล็งโมเดลด้วยตัวแปรบนหัวไฟล์

ส่วนบนสุดของไฟล์คือ "แผงตั้งค่า" ที่ทำให้รีทาร์เก็ตง่าย เปลี่ยนที่นี่ที่เดียวก็ได้แอปโมเดลอื่น:

TARGET_KEYWORDS = ("cough",)   # คีย์เวิร์ดหาชื่อโมเดล
TARGET_CLASS    = "cough"       # ชื่อคลาสที่ถือว่า "ตรวจเจอ"
TARGET_SENSOR   = edge_ai.SENSOR_MIC

model = find_model(TARGET_KEYWORDS, TARGET_SENSOR)
labels = model['labels']       # เช่น ['unlabelled', 'cough']
  • TARGET_KEYWORDS บอก find_model() ว่าจะหาโมเดลชื่ออะไร · TARGET_CLASS บอกว่าคลาสไหนคือ "เจอ"
  • แยกสองค่านี้ออกจากกันเพราะ ชื่อโมเดล กับ ชื่อคลาส ไม่เหมือนกัน เช่น โมเดลชื่อ "Siren Detection" แต่คลาสคือ sirens
  • บรรทัดพวกนี้ให้ไว้แล้วในไฟล์ฝึก — งานของคุณคือสี่ช่องด้านล่าง

ออกแบบให้ "จุดที่ต้องแก้ตอนรีทาร์เก็ต" รวมอยู่บนหัวไฟล์ทั้งหมด เป็นนิสัยที่ดีมาก คนอ่านโค้ดต่อจะรู้ทันทีว่าปรับอะไรได้ตรงไหน โดยไม่ต้องไล่ทั้งไฟล์

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

ไล่โค้ด (2) — ช่องเติมที่ 1: เริ่มรัน

ช่องเติมที่ 1: ก่อนเข้าลูป สั่งให้โมเดลเป้าหมายเริ่มรัน (ครั้งเดียว ไม่มีปุ่ม Load):

try:
    # เติม: เริ่มรันโมเดลเป้าหมายตัวเดียว ด้วย edge_ai.select(model['index'])
    pass
    lcd.console('<span class=ok> เริ่มฟัง %s…</span>' % model['name'])

    while True:
        ...
  • แทน pass ด้วย edge_ai.select(model['index']) — ใช้ model['index'] ที่ find_model() หามาให้
  • ต่างจาก บทเรียน 1.1–1.3: ที่นี่ select() อยู่ ก่อนลูป ไม่ใช่ในปุ่ม เพราะแอปโฟกัสรู้อยู่แล้วว่าจะรันอะไร
  • ทั้งก้อนอยู่ใน try เพราะ select() โยน OSError ได้ ถ้า M55 ไม่ยืนยันการสลับ

ถ้าลืมเติมช่องนี้: แอปเปิดได้ การ์ดขึ้นครบ แต่ result() จะคืน None ตลอด เพราะไม่มีโมเดลไหนถูกสั่งให้รันเลย — ตัวนับจะไม่มีวันขยับ

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

ไล่โค้ด (3) — ช่องเติมที่ 2+3: อ่านผล + คลาสที่ชนะ

ช่องเติมที่ 2 และ 3: หัวใจของลูป อ่านผลแล้วเอาคลาสที่ชนะขึ้นจอ:

# เติม: อ่านผลอนุมานล่าสุดมาเก็บใน r  ->  r = edge_ai.result()
r = None
pass
if r and r['seq'] != last_seq:
    last_seq = r['seq']
    # เติม: แสดงคลาสที่ชนะบนจอ ด้วย verdict.text(r['label'] or '-')
    pass
    conf.text("conf: %.0f %%" % (r['conf'] * 100))
    lat.text("latency: %.1f ms" % r['latency_ms'])
  • ช่อง 2: แทน pass ด้วย r = edge_ai.result() (ลบ r = None ทิ้ง หรือปล่อยไว้ก็ได้ เพราะจะถูกทับ)
  • ช่อง 3: แทน pass ด้วย verdict.text(r['label'] or '-')
  • เช็ก seq ก่อนเสมอ วาดจอเฉพาะตอนมีผลใหม่ — เหมือน บทเรียน 1.1–1.3 เป๊ะ

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

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

ไล่โค้ด (4) — ช่องเติมที่ 4: เงื่อนไขตรวจเจอ

ช่องเติมที่ 4: ของใหม่ของชุดบทเรียนนี้ ต่อ verdict เข้ากับ action (การนับ):

# เติม: แทน False ด้วยเงื่อนไขตรวจเจอจริง
#       r['label'] == TARGET_CLASS and r['conf'] >= edge_ai.CONF_FLOOR
is_target = False
if is_target and not was_target:
    hits += 1
    hits_lbl.text(str(hits))
    lcd.console('<span class=ok> เจอ %s ครั้งที่ %d</span>' % (TARGET_CLASS, hits))
was_target = is_target
  • แทน False ด้วย r['label'] == TARGET_CLASS and r['conf'] >= edge_ai.CONF_FLOOR
  • สองเงื่อนไขต้องเป็นจริงพร้อมกัน: คลาสตรงเป้า และมั่นใจถึงเกณฑ์
  • not was_target คือกุญแจของ "ขอบขาขึ้น" — นับหนึ่งต่อการเจอหนึ่งครั้ง

ลองผิดดูก็ได้เพื่อเรียนรู้: ถ้าเติมแค่ r['label'] == TARGET_CLASS (ตัด conf ทิ้ง) แล้วส่งเสียงมั่วๆ คุณจะเห็นตัวนับเด้งทั้งที่ไม่ได้ไอ — นั่นคือ false positive ที่ CONF_FLOOR มีไว้กัน

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

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

เปิด s15_apps.py มี # เติม: วางไว้ 4 จุด (สามจุดหลักของ edge_ai + หนึ่ง action):

# จุด เติมด้วย ถ้าลืม
1 ก่อนลูป edge_ai.select(model['index']) แอปเปิดได้ แต่ result เป็น None ตลอด
2 ในลูป r = edge_ai.result() จอไม่ขึ้นคลาสเลย
3 มีผลใหม่ verdict.text(r['label'] or '-') แถบขยับ แต่ตัวใหญ่ไม่เปลี่ยน
4 ตรวจเจอ r['label']==TARGET_CLASS and r['conf']>=edge_ai.CONF_FLOOR ตัวนับไม่ขยับ (หรือเด้งมั่ว)

ขั้นตอน:

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

สามช่องแรกคือ pattern เดิมจาก บทเรียน 1.1–1.3 (select/result/verdict) — ช่องที่ 4 คือก้าวใหม่จริงของคุณ: การเปลี่ยน "ผล" ให้กลายเป็น "การกระทำ"

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

รีทาร์เก็ตเป็น cough / alarm / siren

MVP วันนี้ต้องมีแอป อย่างน้อยสองตัว ข่าวดีคือรีทาร์เก็ตใช้เวลาไม่ถึงนาที เปลี่ยนแค่สองบรรทัดบนหัวไฟล์แล้วเซฟเป็นไฟล์ใหม่:

# s15_alarm_app.py — แค่เปลี่ยนสองบรรทัดนี้
TARGET_KEYWORDS = ("alarm",)
TARGET_CLASS    = "alarm"

# s15_siren_app.py — โมเดลชื่อ Siren แต่คลาสสะกด sirens (มี s)
TARGET_KEYWORDS = ("siren",)
TARGET_CLASS    = "sirens"
  • โครงทั้งไฟล์ ไม่ต้องแตะ — find_model() หาโมเดลใหม่ให้เอง, แถบคลาสปรับตาม labels ที่ได้มา
  • ระวังจุดเดียว: TARGET_CLASS ต้องสะกดตรงกับ label จริง (Siren → sirens มี s) เช็กด้วย edge_ai.models() ใน REPL ก่อน
  • เซฟเป็น s15_cough_app.py / s15_alarm_app.py / s15_siren_app.py — นี่คือ "แอปต่อโมเดล" ที่หลักสูตรตั้งเป้าไว้

นี่คือผลตอบแทนของการออกแบบให้ตัวแปรอยู่บนหัวไฟล์: โมเดลหนึ่งแม่แบบ กลายเป็นสามแอปได้ในไม่กี่นาที — คุณเพิ่งสร้าง "ตระกูลแอป" ของตัวเอง

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

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

อยากเข้าใจ argmax / softmax / edge AI ให้ลึกขึ้น ลองดูจากช่องที่อธิบายเห็นภาพ:

วิดีโอ (ภาษาอังกฤษ อธิบายเข้าใจง่าย)

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

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

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

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

ชัยชนะที่เห็นได้ของชุดบทเรียนนี้ · แอปโฟกัสที่คุณสร้างเอง รันโมเดลเดียว แล้ว "นับ" ขึ้นจริงเมื่อเจอเสียงเป้าหมาย

MVP ของบทเรียน 6.1–6.2 (เกณฑ์ผ่านของชุดบทเรียน): คุณสร้าง แอปโฟกัสต่อโมเดล ที่ UI สะอาด — เล็งโมเดลด้วย find_model(), โชว์ verdict + แถบทุกคลาส + latency, และมี action หนึ่งอย่าง (ตัวนับ) ที่ทำงานจริงเมื่อคลาสเป้าหมายข้าม CONF_FLOOR

  • ทำบน Emulator หรือ บอร์ดจริง ก็ได้ (โค้ดชุดเดียวกัน)
  • รีทาร์เก็ตได้อย่างน้อย สองโมเดล (เช่น Cough + Alarm) โดยแก้แค่ตัวแปรบนหัวไฟล์
  • อธิบายได้ว่าทำไมต้องเช็ก CONF_FLOOR ก่อนนับ และทำไมต้องนับเฉพาะ "ขอบขาขึ้น"

"แอปที่สร้างเอง" ไม่ใช่แค่ "รันแล้วมีตัวเลข" — คุณต้องบอกได้ว่า action ของคุณเชื่อ verdict ตอนไหน และกันนับเฟ้ออย่างไร นั่นคือหัวใจของ Apps

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

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

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

  • ใบ้ — คำใบ้อยู่ในคอมเมนต์ # เติม: ทั้ง 4 จุดในไฟล์ฝึก + ตารางช่องเติมหน้าที่แล้ว
  • เริ่มจากโครง — s15_apps.py มีโครงครบทั้งไฟล์ เหลือแค่ 4 จุดให้เติม
  • เฉลย — s15_apps.py เติมครบพร้อมคอมเมนต์อธิบายทุกช่อง (อ่านให้เข้าใจ ปิดไฟล์ แล้วพิมพ์เอง)
  • ฉบับเต็ม — s15_apps_full.py ฉบับขัดเรียบร้อย เพิ่มสีตาม CONF_FLOOR, debounce เบาๆ (นับเมื่อเจอติดกันสองผล), เวลา "เจอครั้งล่าสุด" และปุ่ม Reset

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

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

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

การสร้างแอปโฟกัสตัวแรกดึงทุกอย่างจากชุดบทเรียนก่อนหน้ามารวมกัน แล้วเพิ่ม "การกระทำ" เข้าไป:

ฝั่ง Edge AI / Apps

  • แอปต่อโมเดล — เล็งโมเดลเดียวด้วย find_model() แทนเมนู (ต่อจาก บทเรียน 1.1–1.3 และ 1.6–1.7)
  • verdict → action — เปลี่ยน label/conf ให้เป็นการกระทำ (การนับ) — เปิด โมดูล 6 (Apps)
  • CONF_FLOOR = ประตูของ action — ตัดสินใจว่าจะเชื่อผลไหม ก่อนลงมือ
  • ขอบขาขึ้น + debounce — นับหนึ่งต่อเหตุการณ์ ไม่ใช่ต่อผลอนุมาน

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

  • โครงแอปโฟกัส — find_model → สร้างครั้งเดียว → select → ลูป → finally: stop
  • ตัวแปรตั้งค่าบนหัวไฟล์ — รีทาร์เก็ตทั้งแอปด้วยการแก้จุดเดียว
  • เก็บกวาดตอนจบ — finally: edge_ai.stop() คืนเครื่องสู่สถานะที่รู้แน่ (เหมือนทุกบทเรียน)

ทั้งหมดนี้ยังยืนบนคำสั่งเดิมแค่ไม่กี่ตัว — สิ่งที่เพิ่มคือ "วิธีคิด" เรื่องการเปลี่ยนผลเป็นการกระทำ ซึ่งจะขยายต่อในสองชุดบทเรียนถัดไป

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

ใช้จริงที่ไหน — แอป Edge AI ต่อโมเดลในโลกจริง

แอปโฟกัสที่เราสร้างวันนี้ ไม่ใช่ของสมมติ ทุกตัวมีสินค้าจริงที่ทำงานด้วยโครงเดียวกัน: โฟกัสโมเดลเดียว + นับ/เตือนเมื่อเจอ

Cough — เครื่องนับ/คัดกรองสุขภาพ นับความถี่การไอในห้องผู้ป่วย · เฝ้าอาการกลางคืน เสียงไม่ออกจากเครื่อง → ความเป็นส่วนตัว คือแอป s15_cough_app วันนี้ + ตัวนับ Alarm — เฝ้าเสียงเตือนในโรงงาน ได้ยินเสียงเตือนเครื่องจักร → log/แจ้งเวร ทำงานในที่เสียงดัง ไม่ต้องพึ่งคน คือแอป s15_alarm_app (รีทาร์เก็ต) Siren — รถฉุกเฉิน/เมืองอัจฉริยะ ได้ยินไซเรน → หรี่เพลง/เตือนคนขับหูตึง รันบนอุปกรณ์ ตอบทันที ไม่พึ่งเน็ต คือแอป s15_siren_app (รีทาร์เก็ต) ร่วมกัน — verdict + เกณฑ์ + action ทุกแอปใช้ conf ตัดสินว่าจะเชื่อไหม แล้วทำ action (นับ · log · เตือน) 6.3–6.4 ต่อ action แรงขึ้น · 6.5–6.6 ต่อ IoT

โมเดลเดียวกัน เปลี่ยนคีย์เวิร์ดกลายเป็นสินค้าคนละตัว — นี่คือพลังของ "แอปต่อโมเดล" ที่ออกแบบมาดี แม่แบบหนึ่งอัน ต่อยอดได้ทั้งตระกูล

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

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

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

  1. เติม s15_apps.py ให้ครบทั้ง 4 ช่อง รันได้จริง — แอป Cough นับได้ (Emulator หรือบอร์ด)
  2. รีทาร์เก็ตเป็น อย่างน้อยหนึ่งโมเดลอื่น (Alarm หรือ Siren) เซฟเป็นไฟล์ใหม่ แล้วยืนยันว่าตัวนับทำงาน
  3. ทดลอง: ตัด and r['conf'] >= CONF_FLOOR ออกชั่วคราว ส่งเสียงมั่วๆ แล้วจดว่าตัวนับเด้งต่างจากเดิมยังไง (แล้วใส่กลับ)

ใบ้ข้อ 3 — เมื่อไม่มีเกณฑ์ conf ทุกครั้งที่คลาสเป้าหมาย "แค่ชนะ" (แม้คะแนนสูสี) ก็จะถูกนับ คุณจะเห็น false positive พุ่งขึ้นทันที นั่นคือเหตุผลที่แอปจริงต้องมีเส้นแบ่ง

วันนี้เราได้: แยกเมนูออกจากแอปโฟกัส · เล็งโมเดลด้วย find_model() · อ่าน scores/latency_ms ให้ครบ · ต่อ verdict เข้ากับ action แรก (การนับ) ด้วยเกณฑ์ CONF_FLOOR และขอบขาขึ้น · รีทาร์เก็ตเป็นตระกูลแอป cough/alarm/siren

ชุดบทเรียนถัดไป (บทเรียน 6.3–6.4) เราจะทำให้ action แรงขึ้น: จาก "นับ" เป็นจุด RGB / เล่นเสียง / เขียน log พร้อม debounce เต็มรูปแบบและการจัดการ false positive อย่างจริงจัง — เจอกันครับ

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