ภาพพื้นหลังปกบทเรียน

บทเรียน 5.1 — จากโจทย์จริงสู่แบบ: canvas schema และการออกแบบตอนพัง

AIoT Mini-Product ของทีมเรา: จากโจทย์จริง สู่ของที่ใช้งานได้

โมดูล 5 — Capstone: AIoT Mini-Product

คาถาประจำบทเรียน: ของที่ใช้งานได้ ไม่ใช่ของที่ทำงานได้ตอนสาธิต

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ดูของจริงก่อน — ผลงานของทีมเราเอง

dashboard บทเรียน 3.7–3.9 IMU Compass CapSense Pot telemetry บทเรียน 4.4–4.9 bento/team01/telemetry {"v": 17.4} {"v": 17.6} ข้อความไหลเข้าทุก 5 วินาที ถอด WiFi ออกเงียบ ๆ แล้วจอบอร์ดเป็นยังไง ค้าง · error กลางจอ หรือทำงานต่อแล้วบอกสถานะ ทั้งสองอย่างทำงานได้ทั้งคู่ และทั้งสองอย่างยังไม่ใช่ผลิตภัณฑ์

เปิดสองอย่างขึ้นมาพร้อมกัน: dashboard ที่ทีมสร้างในบทเรียน 3.7–3.9 กับ telemetry ที่ทีมส่งขึ้น broker ในบทเรียน 4.4–4.6 และ 4.7–4.9

ทั้งสองอย่างทำงานได้ทั้งคู่ และทั้งสองอย่างยังไม่ใช่ผลิตภัณฑ์

ลองอย่างนี้: ระหว่างที่มันรันอยู่ ให้เพื่อนถอด WiFi ออกเงียบ ๆ แล้วดูว่าเกิดอะไรขึ้นบนจอ

ชุดบทเรียนนี้เราจะเปลี่ยนงานสองชิ้นนั้นให้เป็นชิ้นเดียวที่ส่งมอบได้

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

demo กับ product ต่างกันตรงไหน

demo — ทางเดินเดียวที่ทุกอย่างต้องดี เซนเซอร์ ส่งขึ้นเน็ต จอแสดงผล เน็ตหลุดตรงกลาง จอค้างทั้งหน้า ทั้งที่เซนเซอร์ยังดี product — เส้นที่สำคัญไม่พึ่งเน็ต เซนเซอร์ ตัดสินบนบอร์ด จอแสดงผล ส่งขึ้นเน็ต เน็ตหลุด จอยังทำงาน
คำถาม demo ตอบว่า product ต้องตอบว่า
ทำไมต้องมีของชิ้นนี้ เพราะมันเท่ เพราะมีคนเสียเงินหรือเสียเวลากับปัญหานี้อยู่
ค่าที่เห็นบนจอคืออะไร ตัวเลขจากเซนเซอร์ ปริมาณที่มีหน่วย และมีคนตัดสินใจจากมันได้
ส่งอะไรขึ้นไป ทุกอย่างที่วัดได้ เฉพาะสิ่งที่ปลายทางใช้จริง
เน็ตหลุดแล้วยังไง ค้าง หรือ error กลางจอ จอทำงานต่อ บอกสถานะ แล้วต่อเองเมื่อเน็ตกลับมา
ใครดูแลมันต่อ ไม่มีใคร มี device id แยกตัว มีสถานะให้ตรวจ

ช่องขวาทั้งห้าข้อ ไม่มีข้อไหนต้องใช้ API ใหม่ที่เรายังไม่เคยเรียนเลยสักตัว

ระยะทางจาก demo ถึง product สั้นกว่าที่คิด แต่ต้องตั้งใจเดิน ไม่ใช่บังเอิญไปถึง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

demo กับ product ต่างกันตรงไหน (ต่อ) — ชิ้นส่วนเดียวกับบทเรียน 2.7–2.9

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

ซ้าย — ภาพ: TT Zop / Wikimedia Commons — CC BY-SA 2.0 · ขวา — ภาพ: Daniel Beardsmore / Wikimedia Commons — สาธารณสมบัติ · ซ้ายคือช่องเก็บลูกบิดของกีตาร์ที่เดินสายเรียบร้อยอยู่ในตัวเครื่อง ขวาคือจอยสติกที่สร้างจาก pot สองตัวแล้วขายเป็นสินค้าจริง — ทั้งสองชิ้นใช้ชิ้นส่วนที่เราเรียนมาแล้วในบทเรียน 2.7–2.9 ความต่างจาก demo อยู่ที่สิ่งที่มองไม่เห็นในภาพ ไม่ใช่ที่ชิ้นส่วน
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ทำไม · คืออะไร · ทำยังไง — แผนที่ของชุดบทเรียนนี้

คำถาม คำตอบของชุดบทเรียนนี้ อยู่ช่วงไหน
Why ในเมื่อไม่มี API ใหม่สักตัว ทำไมยังต้องมีชุดบทเรียนนี้ เพราะระยะทางจาก demo ถึง product ไม่ได้วัดด้วยจำนวนบรรทัด มันวัดด้วย การตัดสินใจ — เลือกโจทย์จากความเจ็บปวดจริง ออกแบบข้อมูลให้ฝั่งรับใช้ต่อได้ และตัดสินไว้ล่วงหน้าว่าตอนพังจะให้เกิดอะไร · ของที่ไม่เคยถูกทดสอบตอนเน็ตหลุด ยังไม่ใช่ของที่ส่งมอบได้ ครึ่งแรก · demo กับ product · canvas · ออกแบบตอนพัง
What มีอะไรให้ใช้บ้าง ทุกโมดูลที่คอร์สนี้เปิดไปแล้ว — เก้าโมดูล ตั้งแต่ lcd ถึง tesaiot และวันนี้ ไม่มีชื่อใหม่เพิ่มแม้แต่ชื่อเดียว สไลด์บัญชีรวมเก้าโมดูล
How ประกอบยังไงให้ใช้งานได้จริง กรอก canvas ห้าช่อง Sense → Decide → Show → Send → Act ให้ครบก่อนแตะโค้ด แล้วเติมโครง s12_capstone_starter.py ที่จุด "ทีมเขียนเอง" ห้าจุด เก้าไฟล์ตัวอย่าง (01–05 ในบทเรียน 5.2 · 06–09 ในบทเรียน 5.3) + โครงตั้งต้น + นำเสนอ 10 นาที

ปลายทางที่จับต้องได้ — ของหนึ่งชิ้นที่วางบนโต๊ะแล้วเดินครบวงเอง ตั้งแต่วัด ตัดสิน แสดง ถึงรายงานขึ้น broker และทีมอธิบายได้ว่ามันแก้ปัญหาอะไรให้ใคร รวมทั้งบอกได้ว่ามันยังทำอะไรไม่ได้

บทเรียน 4.7–4.9 เราทำให้ส่งอย่างปลอดภัยได้ · ชุดบทเรียนนี้เราตอบคำถามที่มาก่อนหน้านั้น — จะส่งอะไร ให้ใคร และเขาจะเอาไปทำอะไรต่อ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เป้าหมายของชุดบทเรียนนี้

  1. เลือกโจทย์จาก ความเจ็บปวดจริงในงาน ไม่ใช่จากรายการเซนเซอร์ที่บอร์ดมี
  2. ออกแบบระบบด้วย canvas ห้าช่อง: Sense → Decide → Show → Send → Act
  3. ออกแบบ schema ข้อมูลที่เล็ก คงที่ มีหน่วย และมีตัวตนอุปกรณ์
  4. ออกแบบพฤติกรรมตอนพัง — เน็ตหลุด broker ไม่ตอบ ค่าเซนเซอร์แปลก
  5. ต่อโครง s12_capstone_starter.py จนรัน end-to-end แล้ว นำเสนอ 10 นาที

ปลายทางของวันนี้: บอร์ดวางอยู่บนโต๊ะ จอบอกสถานะ ข้อความไหลขึ้น broker และทีมอธิบายได้ว่ามันแก้ปัญหาอะไรให้ใคร

วันนี้เราไม่ได้เรียน API ใหม่ เราเรียน วิธีตัดสินใจ ว่าจะเอา API ที่มีอยู่ไปทำอะไร

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ปลายทางของชุดบทเรียนนี้ — โครงตั้งต้นที่ทีมจะต่อยอด

หน้าจอจาก BENTO Emulator ของโครงตั้งต้น capstone

หน้าจอจากการรันโค้ดเฉลยบน BENTO Emulator ที่ 800x480 เท่าจอของทั้งสองบอร์ด — ไม่ใช่ภาพวาดและไม่ใช่ mock-up · โค้ดคือ s12_capstone_starter.py ของบทเรียน 5.3

โครงของหน้าจอ แบ่งเป็นสามการ์ด

  • ซ้ายบน ค่าที่วัดได้ตัวใหญ่ พร้อม ui.Bar วางทับ ui.Scale — ค่ากับพิสัยอยู่ด้วยกัน และมีป้ายบอกคุณภาพของค่าเองว่าสดหรือค้าง
  • ซ้ายล่าง ไฟสถานะสามดวง (ปกติ · เฝ้าระวัง · ผิดปกติ) ติดทีละดวง กับปุ่มรับทราบ
  • ขวา ของจริงที่สั่งได้ — ไฟเตือนหน้างาน มีปุ่มเปิดกับปุ่มปิดแยกกันคนละปุ่ม และปุ่มปิดต้องผ่านกล่องยืนยันที่บอกว่าจะเกิดอะไร

นี่คือ starter ไม่ใช่เฉลย — สิ่งที่ให้มาคือ มาตรฐานของหน้าจอ ที่ทีมต้องรักษาไว้ ส่วนเนื้อในเปลี่ยนเป็นโจทย์ของทีมได้ทั้งหมด

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

สิบเอ็ดชุดบทเรียนที่ผ่านมา เราสะสมอะไรไว้บ้าง

แผนภาพสถาปัตยกรรม IIoT: อุปกรณ์ที่ edge หน้าจอ HMI และการส่งข้อมูลขึ้นคลาวด์

ภาพ: Paul McLaughlin, Rohan McAdam / Wikimedia Commons — CC BY-SA 4.0 · The Edge คือบอร์ดของเรา · HMI คือจอบทเรียน 3.7–3.9 · เส้นขึ้น cloud คือ MQTT บทเรียน 4.4–4.9
บทเรียน สิ่งที่ได้ วันนี้เอามาใช้ตรงไหน
1 ทัวร์เมนู · lcd.print() · แนวคิด "ส่งเฉพาะสิ่งที่มีความหมาย" ช่อง Show และ Send ของ canvas
2 wifi.connect() · เลข IP ของบอร์ด · กฎว่าลิงก์แบบไหนเรียกว่าใช้ได้ ช่อง Send — ต้องรู้ว่าสายดีจริงก่อนจะเชื่อว่าส่งถึง
3 gpio · ลูป polling · จังหวะเวลา โครงลูปหลักของโปรแกรม
4 ui.Button/Switch/Label · ui.poll() · กฎเหล็ก 5 ข้อ ปุ่มรับทราบและหน้าจอสถานะ
5 sensors.pot · capsense · dsp.EMA การกรองสัญญาณก่อนตัดสิน
6 bmi270.motion() · dsp.tilt() ค่าตัวอย่างในโครงเริ่มต้น
7 ui.Chart หลาย series · cadence 200 ms กราฟย้อนหลังบนหน้าจอผลงาน
8 Panel การ์ด · งบ 32 widget (เพดาน 64) · เกณฑ์สองระดับกันป้ายกระพริบ · รันยาว 10 นาที โครงหน้าจอของผลิตภัณฑ์ และช่อง Decide ที่ป้ายไม่สั่น
9 wifi.connect/is_connected/ip/ping การตรวจสายก่อนส่ง
10 mqtt.connect/publish/subscribe · topic · JSON ช่อง Send
11 tesaiot.* · serverTLS 8884 · ตัวตนอุปกรณ์ ทางยกระดับความปลอดภัยของผลงาน

ไม่มีอะไรในตารางนี้ที่ทีมยังไม่เคยรันเอง วันนี้แค่เอามาต่อกัน

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ทั้งคอร์สเปิดไปเก้าโมดูล — บัญชีรวมก่อนลงมือทำงานจบ

โมดูล มีกี่ชื่อ เปิดที่บทเรียนไหน งานจบใช้ตรงช่องไหนของ canvas
lcd 4 — print console clear theme (เฟิร์มแวร์ 2026-09-06 ขึ้นไปเพิ่ม backlight() เป็นห้า) บทเรียน 1.1–1.3 Show — ทางที่ง่ายที่สุดตอนยังไม่มีหน้า HMI
gpio 18 — ระดับโมดูล 7 · เมธอดของ LED 8 · ของ Button 3 บทเรียน 2.1–2.3 Act — ทางเดียวในคอร์สนี้ที่สั่งของจริงให้ขยับ
ui 132 ชื่อบนโมดูล (นับบน Eva Kit ในบทเรียน 2.4) · บวกเมธอดของ Widget อีก 38 — สิบสี่ตัวที่บทเรียน 3.4–3.6 กางไว้คือส่วนที่กราฟกับการจัดหน้าใช้ บทเรียน 2.4–2.6 · 7 · 8 Show — และเป็นทางที่คนสั่งงานเข้ามาด้วย
sensors 10 ชื่อระดับโมดูล (Eva: ห้าตอบ ห้าปฏิเสธ · Dev Kit: init() scan() ทำงานได้ แต่กติกาของคอร์สคือไม่ต้องเรียก) · บวกกลุ่มเซนเซอร์ที่บอร์ดมี — Eva สี่กลุ่ม (bmi270 bmm350 capsense pot) · Dev Kit เพิ่ม sht40 dps368 เรดาร์ บทเรียน 2.7–2.9 · 6 · 8 Sense
dsp 16 — 8 คลาส 8 ฟังก์ชัน (สเปกตรัมสองตัวเพิ่ม 2026-08-20) บทเรียน 2.7–2.9 · 6 · 7 ระหว่าง Sense กับ Decide — กรองก่อนตัดสิน
mic 8 — โมดูล Python ที่ฝังมากับเฟิร์มแวร์ บทเรียน 3.7–3.9 Sense ทางเลือก สำหรับโจทย์ที่วัดด้วยเสียง
wifi 8 บทเรียน 4.1–4.3 ตรวจสายให้แน่ก่อนจะเชื่อว่าส่งถึง
mqtt 6 บทเรียน 4.4–4.6 Send
tesaiot 28 — ใช้ได้จริง 9 ทั้งสองบอร์ด · สิบหกตัวข้ามคอร์ไปหาชิปที่ไม่ได้เปิด (ได้ OSError · เวลาที่เสียยังไม่ได้วัด) · protected_update() ห้ามเรียก (บน Dev Kit เขียนลงชิปจริง) บทเรียน 4.7–4.9 Send แบบยกระดับ ผ่านพอร์ต 8884

อย่านับซ้ำ — "ตระกูล IMU สิบสี่ชื่อ" ของบทเรียน 3.1–3.3 ไม่ใช่โมดูลที่สิบ มันคือ sensors.bmi270 ห้า + sensors.bmm350 ห้า + dsp อีกสี่ ที่ซ้อนอยู่ในตารางแล้ว

ของที่คอร์สนี้ไม่เคยมีให้ — ไม่มี machine.PWM .ADC .SPI .Timer · dsp มี fft_mag (ตั้งแต่ 2026-08-20) แต่ไม่มี ulab · Eva Kit ไม่มี DPS368 SHT40 เรดาร์ ส่วน Dev Kit มีทั้งสาม (sensors.sht40 อุณหภูมิ/ความชื้น · sensors.dps368 ความกดอากาศ · sensors.radar()) แต่คอร์สไม่ได้เปิดสอน — ทีมบน Dev Kit ใช้ได้ถ้าอ่านซอร์สเอง และต้องมีแผนสำรองบน Eva เสมอ · optiga เป็นการสาธิตท้ายบทเรียน 4.7–4.9 ไม่อยู่ในเกณฑ์ อย่าวางแผนงานจบทับมัน

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

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เริ่มจากปัญหา ไม่ใช่จากรายการเซนเซอร์

เดินย้อนศร — จบไม่สวย "บอร์ดมี IMU กับเข็มทิศ เราจะทำอะไรกับมันดี" ผลที่ได้ ของสวยที่ไม่มีใครอยากได้ เล่าให้คนนอกฟังแล้วเขาถามว่า "แล้วไง" 1 · ใครเสียอะไรอยู่ทุกวัน เวลา เงิน ความปลอดภัย ความมั่นใจ 2 · ตอนนี้เขารู้ได้ยังไงว่ามีปัญหา เดินไปดูเอง รอลูกค้าโทรบ่น หรือรู้ตอนพังแล้ว 3 · ถ้ารู้เร็วขึ้น 30 นาที เปลี่ยนอะไรได้ ตอบไม่ได้ = โจทย์นี้ยังไม่คุ้มที่จะทำ

วิธีที่คนส่วนใหญ่เริ่ม แล้วจบไม่สวย: "บอร์ดมี IMU กับเข็มทิศ เราจะทำอะไรกับมันดี"

วิธีที่ได้ของที่มีคนใช้: เริ่มจากสามคำถามนี้ตามลำดับ

  1. ใครเสียอะไรอยู่ทุกวัน — เวลา เงิน ความปลอดภัย หรือความมั่นใจ
  2. ตอนนี้เขารู้ได้ยังไงว่ามีปัญหา — เดินไปดูเอง รอให้ลูกค้าโทรมาบ่น หรือรู้ตอนของพังไปแล้ว
  3. ถ้ารู้เร็วขึ้นสามสิบนาที จะเปลี่ยนอะไรได้บ้าง — ถ้าตอบไม่ได้ แปลว่าโจทย์นี้ยังไม่คุ้มที่จะทำ

พอตอบครบสามข้อ ค่อยถามว่า "บอร์ดของเราวัดอะไรที่พอจะบอกเรื่องนั้นได้บ้าง"

ทีมที่เดินลำดับนี้จะได้โจทย์ที่เล่าให้คนนอกฟังได้ใน 30 วินาที ทีมที่เดินย้อนกลับมักจบด้วยของสวยที่ไม่มีใครอยากได้

โจทย์ที่ดีเล่าจบก่อนที่คนฟังจะทันถามว่า "แล้วไง"

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เริ่มจากปัญหา ไม่ใช่จากรายการเซนเซอร์ (ต่อ) — โจทย์ของจริงสองแบบ

ถุงลมนิรภัยที่กางออกในรถระหว่างการทดสอบชน เครื่องนับก้าวแบบพกพา

ซ้าย — ภาพ: NHTSA / Wikimedia Commons — สาธารณสมบัติ · ขวา — ภาพ: Arthbkins / Wikimedia Commons — สาธารณสมบัติ · ซ้ายคือถุงลมที่กางจริงในการทดสอบชน โจทย์ที่บังคับเวลาตัดสินใจไว้ที่หลักมิลลิวินาทีและทำผิดแล้วแก้ไม่ได้ · ขวาคือเครื่องนับก้าวที่วางขายจริง โจทย์เดียว จบในกล่องเดียว ไม่มีเมนู ไม่มีการตั้งค่า — ใช้สองภาพนี้ถามทีมว่าโจทย์ของตัวเองเข้มงวดแค่ไหน และเสร็จแล้วหน้าตาควรเป็นอย่างไร
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

AIoT design canvas — ห้าช่องที่ต้องเติมให้ครบก่อนเขียนโค้ด

เติมจากขวาไปซ้ายก็ได้ — เริ่มที่ Act แล้วถอยกลับ มักได้ระบบที่เล็กลงและตรงกว่า Sense วัดอะไร ด้วยอะไร ถี่แค่ไหน กรองยังไง Decide เกณฑ์อะไร ตัดสินบนบอร์ด ยืนยันกี่รอบ ก่อนจึงเชื่อ Show เห็นอะไรบนจอ รู้ใน 2 วินาที สถานะเน็ต ปุ่มรับทราบ Send ส่งอะไร ไปไหน ถี่แค่ไหน schema อะไร ส่ง event Act ใครทำอะไรต่อ ภายในกี่นาที ถ้าไม่มีใครทำ ก็ไม่ต้องส่ง ช่องไหนเติมไม่ได้ แปลว่ายังไม่รู้จักโจทย์ดีพอ ไม่ใช่ยังเขียนโค้ดไม่เป็น

canvas นี้อยู่ในบันทึกการเรียน กรอกให้ครบก่อนแตะคีย์บอร์ด

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

canvas ที่กรอกแล้วหน้าตาเป็นแบบนี้

โจทย์ตัวอย่าง · นั่งร้านชั้นสามเอียงผิดปกติแล้วไม่มีใครรู้จนเช้า ท่าตั้งต้นตอนติดตั้ง เอียงขึ้นเรื่อย ๆ Sense · ทุก 200 ms Decide · 8 / 15 องศา Show · สามระดับ Send · JSON 6 ฟิลด์ Act หัวหน้าไซต์เดินไปดู ภายใน 15 นาที จอที่หน้างานเห็น 17.4 OK WARN ALERT net: online

โจทย์ตัวอย่าง: นั่งร้านชั้นสามของไซต์ก่อสร้าง เอียงผิดปกติแล้วไม่มีใครรู้จนเช้า

ช่อง คำตอบของทีมตัวอย่าง
Sense sensors.bmi270.motion() → dsp.tilt() ทุก 200 ms กรองด้วย dsp.EMA(alpha=0.2) วัดเทียบท่าตั้งต้นตอนติดตั้ง
Decide เกิน 8° = เฝ้าดู, เกิน 15° = ผิดปกติ ต้องเกินติดกัน 3 รอบจึงเชื่อ ตัดสินบนบอร์ดทั้งหมด
Show ตัวเลของศาตัวใหญ่ + แท่งระดับ + คำว่า OK/WARN/ALERT + สถานะเน็ต + ปุ่มรับทราบ
Send JSON 6 ฟิลด์ ไป bento/team01/telemetry — ส่งตอนสถานะเปลี่ยน + heartbeat ทุก 30 วินาที
Act หัวหน้าไซต์ได้แจ้งเตือน เดินไปดูภายใน 15 นาที ถ้าเป็นของจริงต่อเข้าไลน์กลุ่มหรือ SMS

สังเกตว่าช่อง Act เขียนเป็น "คนทำอะไร ภายในกี่นาที" ไม่ใช่ "ส่งขึ้นคลาวด์" — ถ้าปลายทางไม่มีใครทำอะไร ข้อมูลนั้นไม่ต้องส่งตั้งแต่แรก

ตัวอย่างนี้คือโจทย์ที่เฉลย s12_capstone_starter.py ทำจนจบ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

หกโจทย์จากหน้างานจริง — เลือกไปใช้ได้เลย

1 · ความสั่นมอเตอร์ปั๊ม ขนาดความเร่งรวม เกินค่าปกติ 2 เท่า ติดกัน 5 รอบ 2 · ห้องเย็นประตูเปิดค้าง Eva: ใช้ตัวแทน (ประตู) Dev Kit: SHT40 อ่านตรง ขยับแล้วไม่กลับที่เดิมใน 60 วิ 3 · การเคลื่อนย้ายทรัพย์สิน ทิศเปลี่ยนเกิน 30 องศา บอกว่า "ขยับ" ไม่บอกว่าไปไหน 4 · เครื่องจักรเดินเบา สรุปนาที idle ทุก 15 นาที 5 · การใช้งานห้องประชุม capsense = เช็กอิน ไม่ขยับ 10 นาที = ห้องว่าง 6 · การเอียงของนั่งร้าน เกิน 15 องศา ติดกัน 3 รอบ
โจทย์ วัดด้วยอะไรบนบอร์ดนี้ เกณฑ์ที่ใช้ได้จริง ข้อจำกัดที่ต้องพูดตรง ๆ
1 · เฝ้าความสั่นมอเตอร์ปั๊ม bmi270.motion() แล้วคิดขนาดความเร่งรวม ค่าเฉลี่ยเคลื่อนที่สูงกว่าค่าปกติ 2 เท่า ติดกัน 5 รอบ บอร์ดวัดความสั่นระดับหยาบ ไม่ใช่ระดับ FFT ของเครื่องมือวัดจริง
2 · ห้องเย็นอุณหภูมิหลุดเกณฑ์ บน Eva Kit ไม่มีเซนเซอร์อุณหภูมิห้อง → ใช้ตัวแทน: ประตูถูกเปิดค้าง (การเอียงของบานประตู) · บน Dev Kit อ่านตรงได้ จาก sensors.sht40.temperature() ประตูขยับแล้วไม่กลับที่เดิมใน 60 วินาที (Eva) · อุณหภูมิเกินเกณฑ์ติดกัน N รอบ (Dev Kit) ตัวแทนบอกได้แค่ "สาเหตุ" ไม่ได้บอก "อุณหภูมิ" ต้องเขียนไว้ในข้อจำกัด · ทีมที่ใช้ SHT40 ต้องบอกว่างานนี้ย้ายไป Eva ไม่ได้โดยไม่เปลี่ยน Sense
3 · ติดตามการเคลื่อนย้ายทรัพย์สิน bmi270.motion() + bmm350.heading() ทิศเปลี่ยนเกิน 30° หรือมีความเร่งเกินเกณฑ์ = ของถูกยก จับได้ว่า "ขยับ" แต่บอกไม่ได้ว่า "ไปอยู่ที่ไหน" (ไม่มี GPS)
4 · นับเวลาเครื่องจักรเดินเบา ความสั่นต่ำกว่าเกณฑ์ต่อเนื่อง = idle สะสมนาที idle ต่อกะ ส่งสรุปทุก 15 นาที ต้องปรับเกณฑ์กับเครื่องจริงก่อน ค่าจากการทดลองบนโต๊ะใช้ไม่ได้ตรง ๆ
5 · เฝ้าการใช้งานห้องประชุม การเคลื่อนไหวจาก IMU + capsense เป็นปุ่มเช็กอิน มีคนแตะเช็กอิน = ใช้งานอยู่, ไม่มีการขยับ 10 นาที = ห้องว่าง ตัวแทนที่หยาบ ของจริงใช้ PIR หรือกล้องนับคน
6 · เตือนการเอียงของชั้นวาง/นั่งร้าน dsp.tilt() เทียบท่าตั้งต้น เกิน 15° ติดกัน 3 รอบ ต้องยึดบอร์ดให้แน่นจริง ไม่งั้นวัดการเอียงของเทปกาว

เลือกโจทย์ที่ทีมมีคนเคยเจอปัญหานั้นจริง จะเถียงกันเรื่องเกณฑ์ได้สนุกกว่ามาก

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

หกโจทย์ (ต่อ) — ตัวแทนของโจทย์ที่ 2 และโจทย์ที่ต้องฟังเสียง

ภาพถ่ายรีดสวิตช์ในหลอดแก้ว ภาพเคลื่อนไหวรีดสวิตช์ที่หน้าสัมผัสปิดเมื่อแม่เหล็กเข้าใกล้

ซ้าย — ภาพ: Bidgee / Wikimedia Commons — CC BY 3.0 · ขวา — ภาพ: Stefan Riepl (Quark48) / Wikimedia Commons — สาธารณสมบัติ · ซ้ายคือรีดสวิตช์ตัวจริงในหลอดแก้ว มีแค่แผ่นโลหะสองแผ่น ขวาคือแอนิเมชันของหน้าสัมผัสคู่นั้นตอนแม่เหล็กเข้าใกล้ (ต้นทางระบุเองว่าเป็นภาพอุดมคติ ไม่ใช่ภาพถ่ายจากของจริง) — ตัวแทน "ประตูถูกเปิดค้าง" ของโจทย์ที่ 2 ทำงานแบบนี้ อุปกรณ์ทั้งชิ้นตอบได้แค่ 1 บิต และจังหวะที่มันปิดคือเหตุผลที่สัญญาณเด้งจนต้องกรอง

หมายเหตุเรื่องเสียง: ไมโครโฟนใช้จาก Python ได้แล้ว โมดูล mic ฝังมากับเฟิร์มแวร์ทั้งสองบอร์ด (boards/KIT_PSE84_EVAL_EPC2/manifest.py และ boards/KIT_PSE84_AI/manifest.py freeze ไฟล์เดียวกัน) และในอีมูเลเตอร์ — mic.start() แล้ว mic.level() คืนความดัง 0-100 ส่วน mic.rms() กับ mic.peak() คืนค่าดิบ 0-32768 · วัดจริงบน Eva Kit 14 ส.ค. 2026 (ตัวเลขบน Dev Kit ยังไม่ได้วัด) ห้องเงียบได้ rms 30 (ระดับ 7) เปิดโทนใส่ไมค์ได้ 19335 (ระดับ 92) ต่างกัน 645 เท่า ซึ่งห่างพอจะตั้งเกณฑ์ตัดสินได้จริง · level() นับเป็นอ็อกเทฟแบบที่หูได้ยิน ไม่ใช่สัดส่วนตรงของสเกลเต็ม จึงขยับตั้งแต่เสียงพูดปกติ

โจทย์ที่ต้องฟังเสียงเริ่มได้เลยวันนี้ — เกณฑ์พลังงานจาก peak() พอสำหรับโจทย์ระดับชุดบทเรียนนี้แล้ว แล้วครอบด้วยกฎ confirm-N เหมือนค่าจากเซนเซอร์ตัวอื่นทุกประการ

ตัวแทนที่ตอบได้ 1 บิต ก็ยังต้องผ่านกฎ confirm-N — สัญญาณเด้งของหน้าสัมผัสคือ "ค่าสั่นวูบเดียว" ในอีกหน้าตาหนึ่ง

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เข้าใจฮาร์ดแวร์ · เมื่อบอร์ดวัดสิ่งที่เราอยากรู้ไม่ได้

กราฟสัญญาณการสั่นตามเวลาของเครื่องปกติเทียบกับเครื่องที่ชำรุด สเปกตรัม envelope ของการสั่นลูกปืน ชี้ความถี่ของความผิดปกติ

ภาพซ้าย: Kolok P. et al., Sensors 25(21):6610 (2025) — CC BY 4.0 · ภาพขวา: Mika D. et al., Sensors 25(23):7371 (2025) — CC BY 4.0 · ซ้าย = สัญญาณดิบของลูกปืนปกติเทียบกับลูกปืนเสีย ซึ่งเป็นระดับที่บอร์ดเราพอจับได้ · ขวา = envelope spectrum ที่ชี้ความถี่ความผิดปกติได้ตรงตัว ซึ่งต้องใช้เครื่องมือวัดจริง ไม่ใช่ `bmi270.motion()` ที่ 5 Hz

Eva Kit มี IMU เข็มทิศ ปุ่มสัมผัส ลูกบิด และจอ — ไม่มีเซนเซอร์อุณหภูมิห้อง ความชื้น ก๊าซ หรือกระแสไฟ · TESAIoT Dev Kit มีชุดเดียวกัน และเพิ่ม SHT40 (อุณหภูมิ/ความชื้น) DPS368 (ความกดอากาศ) กับเรดาร์ — แต่ก็ยังไม่มีก๊าซ ไม่มีกระแสไฟ เรื่อง proxy จึงเป็นเรื่องของทั้งสองบอร์ด ต่างกันแค่ว่าอะไรบ้างที่ต้องใช้ตัวแทน

sensors.bmi270.temperature() มีชื่ออยู่ในโมดูลก็จริง แต่บน Eva Kit มัน โยน OSError ทุกครั้ง เพราะค่านี้ไม่ได้อยู่ใน snapshot ของคอร์จอ และถึงอ่านได้ (บน Dev Kit อ่านได้) มันคืออุณหภูมิของชิป IMU ซึ่งอุ่นตามการทำงานของบอร์ด ไม่ใช่ของห้อง — อุณหภูมิห้องบน Dev Kit ต้องมาจาก sensors.sht40

ทางออกที่วิศวกรใช้จริงคือ proxy — วัดสิ่งที่วัดได้ ซึ่งสัมพันธ์กับสิ่งที่อยากรู้: ห้องเย็นอุ่นขึ้นไหม → ประตูเปิดค้างหรือเปล่า · เครื่องทำงานอยู่ไหม → ความสั่นของโครง · มีคนอยู่ในห้องไหม → การเคลื่อนไหวกับการแตะปุ่ม

กติกาข้อเดียวของการใช้ proxy: บอกให้ชัดว่ามันคือตัวแทน ทั้งบนสไลด์นำเสนอและในชื่อฟิลด์ของ schema — ตั้งชื่อ door_open_s ไม่ใช่ temp_c

proxy ที่ประกาศตัวว่าเป็น proxy คืองานวิศวกรรม · proxy ที่แอบอ้างเป็นของจริงคือการหลอกลูกค้า

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ส่งอะไรขึ้นไป — schema ที่อยู่ได้นาน

{"id": "team01", "v": 17.4, "unit": "deg", "state": "ALERT", "kind": "event", "t": 812340} id มาจากบอร์ดไหน บน broker สาธารณะ ยิ่งจำเป็น v + unit ค่าที่ตัดสินแล้ว ไม่ใช่ค่าดิบ หน่วยกันตีความผิด state คำตัดสินของบอร์ด ปลายทางไม่คิดซ้ำ จะได้ไม่ขัดกัน kind event · heartbeat ack · back คนละการกระทำ t เวลาบนบอร์ด ใช้เรียงลำดับ ดูว่ามาช้าไหม

payload ของเราในโครงเริ่มต้นหน้าตาแบบนี้

{"id": "team01", "v": 17.4, "unit": "deg", "state": "ALERT", "kind": "event", "t": 812340}

หกฟิลด์ และทุกฟิลด์มีเหตุผล

ฟิลด์ ทำไมต้องมี
id ปลายทางต้องแยกออกว่าข้อความนี้มาจากบอร์ดตัวไหน — บน broker สาธารณะยิ่งจำเป็น
v ค่าที่ตัดสินใจแล้ว ไม่ใช่ค่าดิบสามแกน ปัดทศนิยมให้พอใช้ ไม่ต้องส่ง 6 ตำแหน่ง
unit ตัวเลขที่ไม่มีหน่วยคือตัวเลขที่ตีความผิดได้ ยานอวกาศเคยตกเพราะเรื่องนี้
state คำตัดสินของบอร์ด ปลายทางไม่ต้องมาคำนวณซ้ำและได้คำตอบไม่ตรงกัน
kind บอกว่านี่คือ event, heartbeat หรือการรับทราบ — คนละความหมาย คนละการกระทำ
t เวลาบนบอร์ด ใช้เรียงลำดับและดูว่าข้อความมาช้าไปแค่ไหน

กติกาที่ทำให้ schema อยู่ได้นาน: ชื่อฟิลด์คงที่ตลอดโครงการ · เพิ่มฟิลด์ใหม่ได้ แต่ห้ามเปลี่ยนความหมายของฟิลด์เดิม · payload ขาออกกระชับ ต่ำกว่า 1000 ไบต์เสมอ

ฝั่งรับเขียนโค้ดแกะข้อมูลครั้งเดียว ถ้าเราเปลี่ยนชื่อฟิลด์ทีหลัง เขาต้องแก้ทั้งระบบ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ส่งเหตุการณ์ ไม่ใช่สตรีมดิบ

ส่งทุกค่า ทุก 200 ms 432,000 ข้อความต่อวัน 39 MB ต่อบอร์ด · 100 บอร์ด = 3.9 GB ต่อวัน ส่งตอนสถานะเปลี่ยน + heartbeat ทุก 30 วินาที event จริง 2,883 ข้อความต่อวัน ลดลงร้อยกว่าเท่า ปลายทางอ่านง่ายกว่าเดิม

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

ลองคิดเลขให้เห็นภาพ อ่านค่าทุก 200 ms แล้วส่งทุกค่า

  • 5 ครั้งต่อวินาที × 86,400 วินาที = 432,000 ข้อความต่อวัน ต่อหนึ่งบอร์ด
  • ข้อความละ ~90 ไบต์ = ราว 39 MB ต่อวัน ต่อบอร์ด · มี 100 บอร์ดคือ 3.9 GB ต่อวัน
  • ในจำนวนนั้น เหตุการณ์ที่มีคนต้องทำอะไรจริง ๆ อาจมีวันละ 3 ครั้ง

แบบส่งเหตุการณ์: ส่งตอนสถานะเปลี่ยน + heartbeat ทุก 30 วินาที = 2,883 ข้อความต่อวัน ลดลงร้อยกว่าเท่า และปลายทางอ่านง่ายกว่าเดิม

ทำไมยังต้องมี heartbeat: ถ้าเงียบอย่างเดียว ปลายทางแยกไม่ออกระหว่าง "ทุกอย่างปกติ" กับ "บอร์ดตายไปแล้วเมื่อวาน"

ดูเพิ่ม (6 นาที): MQTT Essentials Part 6 — MQTT Topic Best Practices — HiveMQ — 5:50 — การออกแบบลำดับชั้น topic และ wildcard + # ที่ฝั่งรับใช้ query

ความเงียบไม่ใช่ข่าวดี จนกว่าเราจะออกแบบให้ความเงียบมีความหมาย

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เกร็ด: MQTT เกิดมาเพื่อสัญญาณที่แย่

แผนภาพระบบ MQTT: ผู้ส่งและผู้รับหลายรายเชื่อมผ่าน broker ตรงกลาง

ภาพ: Chine3me / Wikimedia Commons — CC0 1.0 · ผู้ส่งกับผู้รับไม่เคยรู้จักกัน broker เป็นคนกลาง — โครงสร้างนี้เองที่ทำให้อุปกรณ์หลุดแล้วระบบไม่ล้มทั้งเส้น

ดูเพิ่ม (5 นาที): MQTT Essentials Part 10 — Last Will and Testament — HiveMQ — 5:27 — broker ประกาศแทนเราเมื่อเราหายไปแบบไม่บอกกล่าว ซึ่งคือกลไกที่ตอบคำถาม "บอร์ดเงียบไป แปลว่าปกติหรือตาย"

MQTT ถูกออกแบบตั้งแต่ปี 1999 โดยวิศวกรสองคน (Andy Stanford-Clark จาก IBM และ Arlen Nipper) สำหรับงานที่ฟังดูไม่น่าเกี่ยวกับเราเลย: ตรวจวัดท่อส่งน้ำมันกลางทะเลทราย ที่เชื่อมโลกด้วยสัญญาณดาวเทียมซึ่งทั้งช้า ทั้งแพง ทั้งหลุดบ่อย

ข้อจำกัดนั้นเองที่ทำให้โพรโทคอลนี้หน้าตาแบบที่เป็น — ส่วนหัวเล็กมาก มีระดับการรับประกันการส่งให้เลือก และมีแนวคิด "last will" คือข้อความที่ broker จะประกาศแทนเราเมื่อเราหายไปแบบไม่บอกกล่าว

เชื่อมกับวันนี้: ทีมที่ออกแบบ payload ให้เล็กและส่งเป็นเหตุการณ์ กำลังใช้โพรโทคอลตรงตามเจตนาของคนออกแบบเมื่อยี่สิบกว่าปีก่อน ส่วนทีมที่ยิงค่าดิบทุก 200 ms กำลังใช้มันผิดวิธี และจะเจอปัญหาเดียวกับที่ท่อน้ำมันเจอ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ออกแบบตอนพัง — สิ่งที่แยก product ออกจาก demo

connected ส่ง event + heartbeat จอขึ้น net: online retrying นัดต่อใหม่ทุก 10 วินาที ไม่ต่อรัว ๆ ในลูป offline นับที่ส่งไม่สำเร็จไว้ ทิ้ง หรือ เก็บไว้ส่งทีหลัง เน็ตหลุด ต่อไม่ติด เน็ตกลับมา ต่อเอง แล้วส่ง kind: back บอกฝั่งรับทันที ไม่ว่าอยู่สถานะไหน ลูปยังเดินครบทุกรอบ จอจึงไม่มีวันค้าง ทั้งสองคำตอบเรื่อง "ทิ้ง หรือ เก็บ" ถูกได้ ที่ผิดคือไม่เคยตัดสินใจ

เน็ตหลุดกลางงานไม่ใช่กรณีพิเศษ มันคือสภาพปกติของอุปกรณ์ที่ติดตั้งจริง

สถานการณ์ demo ทำ product ต้องทำ
WiFi หลุด โปรแกรมตาย หรือค้างรอ จอวาดต่อ ขึ้นคำว่า offline แล้วนัดลองใหม่ทุก 10 วินาที
broker ไม่ตอบ publish เงียบ ไม่มีใครรู้ นับจำนวนครั้งที่ส่งไม่สำเร็จ แล้วโชว์บนจอ
เน็ตกลับมา ต้องรีเซ็ตบอร์ดเอง ต่อเอง แล้วส่งข้อความบอกว่ากลับมาแล้ว
ค่าเซนเซอร์กระโดดวูบเดียว เตือนทันที คนวิ่งมาดูแล้วไม่เจออะไร ต้องเกินเกณฑ์ติดกันหลายรอบจึงเปลี่ยนสถานะ
เตือนแล้วไม่มีใครอยู่หน้าจอ ข้อความแวบเดียวแล้วหาย ค้างสถานะไว้จนมีคนกดรับทราบ

การตัดสินใจที่ต้องเลือกให้ชัดตั้งแต่วันนี้: ตอนออฟไลน์ ทีมจะ ทิ้ง ข้อมูลหรือ เก็บไว้ส่งทีหลัง

โครงเริ่มต้นเลือกทิ้งแล้วนับไว้ เพราะค่าความเอียงเมื่อสิบนาทีที่แล้วไม่มีประโยชน์กับคนที่กำลังยืนอยู่ใต้ที่นั่งร้าน ถ้าทีมทำเครื่องนับจำนวนชิ้นงาน คำตอบอาจกลับกัน — เก็บไว้ให้ครบสำคัญกว่าความสด

ทั้งสองคำตอบถูกได้ ที่ผิดคือไม่เคยตัดสินใจ แล้วปล่อยให้พฤติกรรมเป็นไปตามบังเอิญ

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ออกแบบตอนพัง (ต่อ) — เครื่องยังมีชีวิตไหม คนเดินผ่านรู้ได้จากอะไร

ภาพเคลื่อนไหวแผง LED ของซูเปอร์คอมพิวเตอร์ CM-5 ที่กะพริบตามภาระงานจริง

ภาพ: Morn / Wikimedia Commons — CC0 1.0 — แผง LED ของซูเปอร์คอมพิวเตอร์ Thinking Machines CM-5 ที่วิ่งตามภาระงานจริง ไม่ใช่ลูปตกแต่ง: จังหวะไฟคือหลักฐานว่าเครื่องยังมีชีวิตและยังทำงานอยู่ ของที่ product มีแล้วแต่ demo มักไม่มี · ถามทีมตรง ๆ ว่า ถ้าเครื่องของเราค้าง คนที่เดินผ่านจะรู้ได้จากอะไร
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ตารางที่แล้วเรียงตาม "บทเรียน" ตารางนี้เรียงตาม "โมดูล" — เพราะตอนออกแบบงานจบ คำถามไม่ใช่ "บทเรียนไหนสอนอะไร" แต่คือ "ของที่มีอยู่ในมือทั้งหมดมีอะไรบ้าง"