บทเรียน 2.4 — ลงมือทำ: เก็บ IMU กับเสียงลงไฟล์เดียว

DAQ II: เก็บเสียง + หลายเซนเซอร์บนเส้นเวลาเดียว · มัดสองสัญญาณให้เป็น dataset เดียว

โมดูล 2 — เก็บข้อมูลจากเซนเซอร์ (DAQ)

ต่อจากบทเรียน 2.3 — เสียงและหลายเซนเซอร์บนเส้นเวลาเดียว: PDM 16 kHz ประทับเวลา และ jitter

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

โครงของ multi-sensor capture — 4 ก้าวในลูป

หัวใจทั้งหมดอยู่ใน record() ตรงลูป for _ in range(BURST) แต่ละรอบเดินสี่ก้าวนี้เป๊ะ:

1 · ประทับเวลา t_ms = ticks_diff 2 · อ่าน IMU bmi270.motion() 3 · อ่าน MIC readinto + dbfs 4 · เขียนแถว f.write(... t_ms ...)
  • สี่ก้าวนี้คือสี่ช่องที่คุณต้องเติมในไฟล์ฝึก — เรียงตามนี้เป๊ะ
  • ทั้งสี่ก้าวเกิดใน รอบเดียว จึงถือว่าอ่าน "เวลาเดียวกัน" ก่อน sleep_ms(20) ไปรอบถัดไป

จำโครงสี่ก้าวนี้ไว้ แล้วโค้ดทั้งไฟล์จะอ่านเป็นประโยคเดียว: "ประทับเวลา อ่านสองเซนเซอร์ เขียนหนึ่งแถว วนใหม่"

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

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

ทั้งไฟล์อ่านเป็นประโยคเดียว: "เปิดไมค์ → กดปุ่ม label → วนเก็บ BURST แถว (แต่ละแถวมัด IMU+MIC บน t_ms) → ออกแล้วคืนไมค์"

เปิดไมค์+ไฟล์ PDM_PCM :48 สร้าง widget ปุ่ม label :43 กดปุ่ม label record() :70 ออก? deinit :finally t_ms + IMU เติม 1,2 :78,83 ประทับเวลา + motion() MIC + เขียนแถว เติม 3,4 :88,92 readinto + f.write yes no → วนเก็บ BURST แถว แถวล่าง = สิ่งที่เกิดในลูป record() แต่ละรอบ

ตัวเลขบรรทัด (:78, :83, :88, :92) ชี้ไปที่สี่ # เติม: ในไฟล์ฝึก จำโครงนี้ไว้ เดี๋ยวไล่ดูทีละส่วน

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

ไล่โค้ด (1) — เปิด PDM + เตรียมไฟล์

ส่วนบนของไฟล์ (ให้ไว้แล้ว) เปิดไมโครโฟนหนึ่งครั้ง เตรียม buffer และเขียนหัวตาราง CSV ถ้ายังไม่มีไฟล์:

pdm = PDM_PCM(0, sck="P8_5", data="P8_6", sample_rate=16000)
buf = array.array("h", (0 for _ in range(CHUNK)))

try:
    open(PATH, "r").close()             # มีไฟล์แล้วไหม
except OSError:
    with open(PATH, "w") as f:
        f.write("t_ms,label,ax,ay,az,gx,gy,gz,db\n")   # ยังไม่มี -> เขียนหัวตาราง
  • เปิด PDM นอกลูป ครั้งเดียว เหมือนสร้าง widget ครั้งเดียว — เปิด/ปิดซ้ำๆ ทั้งกินเวลาและเสี่ยงชน
  • หัวตาราง t_ms,label,... คือ schema ของ dataset — เขียนครั้งเดียวตอนไฟล์ยังว่าง

try: open(...,"r") เป็นวิธีเช็ก "ไฟล์มีอยู่ไหม" แบบ MicroPython ถ้าไม่มีจะโยน OSError แล้วเราค่อยเขียนหัวตารางใหม่ — เก็บข้อมูลต่อท้ายได้โดยไม่ทับของเก่า

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

ไล่โค้ด (2) — ประทับเวลา t_ms

ช่องเติมที่ 1: ก้าวแรกในลูป จับเวลาของแถวนี้เทียบจุดเริ่ม t0:

t0 = time.ticks_ms()                    # (ให้ไว้แล้ว) จุดศูนย์ของชุดนี้
with open(PATH, "a") as f:
    for _ in range(BURST):
        # เติม 1: t_ms = time.ticks_diff(time.ticks_ms(), t0)
        t_ms = 0
        pass
  • แทน t_ms = 0 / pass ด้วย t_ms = time.ticks_diff(time.ticks_ms(), t0)
  • นี่คือค่าเวลาที่ทั้ง IMU และ MIC ของแถวนี้จะใช้ร่วมกัน — หัวใจของคำว่า "sync"
  • ถ้าลืมเติม: ทุกแถวจะมี t_ms = 0 เหมือนกันหมด เส้นเวลาหาย จับคู่ตามเวลาไม่ได้

t0 ถูกตั้งใหม่ทุกครั้งที่กดปุ่ม label ดังนั้นแต่ละชุด (burst) เริ่มนับเวลาที่ ~0 ของตัวเอง — สะดวกเวลาเอาไปตัดหน้าต่างในโมดูล 4 (Analysis)

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

ไล่โค้ด (3) — อ่าน IMU + MIC พร้อมกัน

ช่องเติมที่ 2 และ 3: อ่านสองเซนเซอร์ติดกันในรอบเดียว นี่คือจุดที่ทำให้ทั้งคู่ "เวลาเดียวกัน":

# เติม 2: อ่านเซนเซอร์ตัวที่หนึ่ง (IMU 6 แกน)
ax = ay = az = gx = gy = gz = 0.0
pass                                    # -> ax, ay, az, gx, gy, gz = sensors.bmi270.motion()

# เติม 3: อ่านเซนเซอร์ตัวที่สอง (เสียงหนึ่งเฟรม)
pass                                    # -> pdm.readinto(buf)
db = dbfs(buf)                          # (ให้ไว้แล้ว) ย่อเฟรมเป็นระดับ dBFS
  • ช่องที่ 2: แทน pass ด้วย ax, ay, az, gx, gy, gz = sensors.bmi270.motion() (ลบบรรทัด = 0.0 ทิ้งได้)
  • ช่องที่ 3: แทน pass ด้วย pdm.readinto(buf) — เติม buffer ด้วยเสียงชุดล่าสุด แล้ว dbfs() ย่อเป็นค่าเดียว
  • อ่านสองอันติดกัน ห่างกันไม่กี่ไมโครวินาที จึงถือว่าเป็น "ช่วงเวลาเดียวกัน" ของแถวนี้ได้

ลำดับสำคัญ: อ่านทั้งคู่ ก่อน เขียนแถว ถ้าเผลออ่าน MIC ในรอบนี้แต่เขียน IMU ของรอบก่อน ข้อมูลจะเหลื่อมเวลากันทันที

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

ไล่โค้ด (4) — เขียนแถวที่มัดสองเซนเซอร์

ช่องเติมที่ 4: รวมทุกอย่างเป็นหนึ่งบรรทัด CSV ที่ทั้ง IMU และ MIC อ้าง t_ms เดียวกัน:

# เติม 4: เขียนหนึ่งแถว
pass
# -> f.write("%d,%s,%.4f,%.4f,%.4f,%.4f,%.4f,%.4f,%.1f\n"
#            % (t_ms, label, ax, ay, az, gx, gy, gz, db))

level.value(max(0, int(db + 60)))       # (ให้ไว้แล้ว) โชว์ระดับเสียงสดๆ
time.sleep_ms(RATE_MS)                  # (ให้ไว้แล้ว) คุมจังหวะ ~50 Hz
  • แทน pass ด้วย f.write(...) ตามรูปแบบในคำใบ้ — ลำดับคอลัมน์ต้องตรง schema หัวตาราง
  • %d สำหรับ t_ms (จำนวนเต็ม ms), %.4f สำหรับค่า IMU, %.1f สำหรับ db
  • ถ้าลืมเติม: ลูปวิ่งครบ แต่ไฟล์ว่างเปล่า (จำนวนแถวขึ้นบนจอ แต่ CSV ไม่มีข้อมูล)

sleep_ms(RATE_MS) คือสิ่งที่ทำให้แถวห่างกัน ~20 ms อย่าเอาออก ไม่งั้นลูปจะรัวจนอัตราสูงเกินและ jitter พุ่ง

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

ไล่โค้ด (5) — เก็บกวาด: คืนไมโครโฟน

ปุ่ม Stop ไม่มีในตัวนี้ (เก็บทีละชุดจบในตัว) แต่ต้อง คืนฮาร์ดแวร์ตอนออก เสมอ:

finally:
    pdm.deinit()                        # คืนไมโครโฟนให้ระบบเสมอ
    lcd.console("<span class=ok> จบ: %d แถวใน %s</span>" % (total, PATH))
  • pdm.deinit() อยู่ใน finally — ไม่ว่าจะออกด้วยปุ่ม back หรือ error ไมโครโฟนจะถูกปิดเสมอ
  • ถ้าไม่ปิด: รันโปรแกรมเสียงตัวถัดไปอาจเปิด PDM ซ้ำไม่ได้ (ฮาร์ดแวร์ยังถูกจอง)

นิสัย embedded เดิมจากบทเรียน 1.1–1.3: ออกจากงานยังไง ทิ้งเครื่องไว้ให้เรียบร้อยแบบนั้น — ชุดบทเรียนนี้ "เครื่อง" คือไมโครโฟน PDM

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

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

เปิด s05_multicapture.py ในไฟล์มี # เติม: วางไว้ 4 จุด ตรงสี่ก้าวของลูปเก็บข้อมูล:

# ก้าว เติมด้วย ถ้าลืม
1 ประทับเวลา t_ms = time.ticks_diff(time.ticks_ms(), t0) ทุกแถว t_ms = 0
2 อ่าน IMU ax, ay, az, gx, gy, gz = sensors.bmi270.motion() คอลัมน์ IMU เป็น 0
3 อ่าน MIC pdm.readinto(buf) คอลัมน์ db นิ่ง ไม่ตามเสียง
4 เขียนแถว f.write("%d,%s,%.4f,...,%.1f\n" % (...)) ไฟล์ว่าง แถวไม่ถูกเขียน

ขั้นตอน:

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

สี่ช่องนี้คือสี่ก้าวของ DAQ หลายเซนเซอร์เป๊ะ — เติมครบเมื่อไร คุณได้ dataset ที่ทุกแถวมัดเสียงกับการเคลื่อนไหวบนเวลาเดียว

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

ลงมือ — เสียงจริงต้องใช้บอร์ดจริง

ต่างจากชุดบทเรียนก่อน ๆ เสียงจริงต้องมาจาก บอร์ด BENTO จริง (Emulator มี PDM_PCM จำลองที่ส่งเสียงสังเคราะห์ ให้ลองโครงโปรแกรมได้ แต่ไม่ใช่เสียงจริง):

  1. เสียบบอร์ด BENTO AI Kit เข้าคอมด้วยสาย USB
  2. เปิด s05_multicapture.py ใน BENTO IDE กด Program to Device
  3. บนจอขึ้นปุ่ม label 3 ปุ่ม + แถบระดับเสียง
  4. กด shaking แล้ว เขย่าบอร์ดพร้อมส่งเสียง ~4 วินาที ดูแถบเสียงขยับ + จำนวนแถวเพิ่ม
  5. ทำครบ idle / circle / shaking แล้วกด < ออก ไฟล์อยู่ที่ /multicapture.csv

ส่วน IMU กับการเขียน CSV คุณซ้อมแนวคิดได้บน Emulator (จากบทเรียน 2.1–2.2) แต่การอ่านเสียงจริงต้องมาที่บอร์ด — และโปรแกรมเสียงที่รันผ่านบน Emulator ยังไม่ใช่หลักฐานว่าจะรันผ่านบนบอร์ด

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

หน้าจอที่จะเห็นบนบอร์ด (ภาพจำลอง)

ภาพด้านล่างเป็น ภาพวาดจำลองหน้าจอ ให้เห็นล่วงหน้าว่า เมื่อ Program to Device สำเร็จ จอจะมีปุ่ม label สามปุ่ม แถบระดับเสียงสด และตัวนับแถว

s05_multicapture BENTO AI Kit idle circle shaking ระดับเสียง (dBFS) -38 label: shaking rows: 128 console: เก็บ 128 แถว -> /multicapture.csv
  • แตะปุ่ม label (idle / circle / shaking) = ตั้ง t0 ใหม่แล้วเริ่มเก็บ BURST แถวของชุดนั้น
  • แถบ VU ยาว-สั้นตาม db แบบ realtime ตามบรรทัด level.value(max(0, int(db + 60)))
  • บรรทัดล่างคือ console บอกจำนวนแถวสะสมและ path ไฟล์ /multicapture.csv

ภาพนี้วาดมือเพื่อให้นึกหน้าจอออกก่อนถึงบอร์ดจริง ตัวเลข (-38 dBFS, 128 แถว) เป็นตัวอย่าง ของจริงจะวิ่งตามเสียงและท่าที่คุณทำ

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

ทำไมเสียงจริงต้องใช้บอร์ด

Emulator จำลอง IMU / env / dsp / ui ได้ครบ ส่วน ไมโครโฟน PDM จำลองด้วยเสียงสังเคราะห์ ไม่ใช่เสียงจริง และบน TESAIoT Dev Kit (ที่มี audio codec) การเปิด PDM ยังชนกับ clock ของระบบเสียง CM55

Emulator IMU/env/dsp/ui ได้ PDM เสียงสังเคราะห์ BENTO AI Kit PDM ใช้ได้เต็ม ชุดบทเรียนนี้ใช้ตัวนี้ Dev Kit (codec) PDM ชน clock เสียง รอ firmware guard
  • นี่คือความจริงของงานฮาร์ดแวร์: ความสามารถบางอย่างผูกกับตัวชิป ตัวจำลองยังตามไม่ครบ
  • หลักสูตรจึงจัดชุดบทเรียนนี้ให้เก็บเสียงจริงบนบอร์ดเท่านั้น ชัดเจน ไม่กลบเกลื่อน

ความซื่อตรงเรื่องนี้สำคัญ: เราบอกตรงๆ ว่าอะไรรันที่ไหนได้ ไม่หลอกว่า Emulator ทำได้ทุกอย่าง — คุณจะได้วางแผนบทเรียนถูก

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

ตรวจ dataset — เปิด CSV ดูของจริง

เก็บเสร็จแล้วอย่าเพิ่งเชื่อ ตรวจก่อน ดึงไฟล์ออกด้วย BENTO IDE (file transfer) หรือ mpremote แล้วเปิดดู:

# ตรวจเร็วๆ ใน REPL บนบอร์ด: นับแถว + ดูหัว
n = 0
with open("/multicapture.csv") as f:
    head = f.readline()          # t_ms,label,ax,...,db
    for line in f:
        n += 1
print("rows:", n, "| header:", head.strip())
  • เช็กสาม: (1) จำนวนแถว ~ BURST × จำนวนครั้งที่กด, (2) t_ms เพิ่มขึ้นเรื่อยๆ ต่อชุด, (3) db เปลี่ยนตามเสียงจริง
  • ถ้า db นิ่งเป็น -96 ตลอด แปลว่าช่อง 3 (readinto) ยังไม่ได้เติม หรือไมค์ไม่ได้เสียง
  • ถ้า t_ms เป็น 0 หมด แปลว่าช่อง 1 ยังไม่ได้เติม

การ "เปิดไฟล์ดูจริง" คือทักษะ DAQ ที่ประเมินค่าไม่ได้ — dataset ที่ดูดีบนจอแต่ไฟล์เพี้ยน จะทำให้โมเดลที่ train ออกมาพังเงียบๆ ตรวจตั้งแต่ต้นทางเสมอ

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

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

อยากเข้าใจ PDM / PCM และการเก็บ dataset ให้ลึกขึ้น ลองตามลิงก์เหล่านี้ได้ตามสะดวก (เปิดในเบราว์เซอร์):

วิดีโอ (ภาษาอังกฤษ อธิบายเห็นภาพ)

  • Digital audio — การสุ่มเสียงเป็นตัวเลขทำงานยังไง — ช่อง Computerphile: https://www.youtube.com/@Computerphile
  • A/D และ D/A sampling อธิบายด้วยของจริงบน oscilloscope — Xiph.org Digital Show & Tell: https://xiph.org/video/vid2.shtml
  • The Fourier Transform เข้าใจแบบเห็นภาพ (ปูทางสู่ spectrogram ในบทเรียน 4.5–4.6) — ช่อง 3Blue1Brown: https://www.youtube.com/@3blue1brown

ภาพ / บทความอ้างอิง (เปิดเสรี)

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

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

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

ชัยชนะที่เห็นได้ของชุดบทเรียนนี้ · ไฟล์ dataset ที่ทุกแถวมัดทั้งเสียงและการเคลื่อนไหวไว้บนเวลาเดียวกัน

MVP ของบทเรียน 2.3–2.4 (เกณฑ์ผ่านของชุดบทเรียน): คุณเก็บ dataset ที่ log ≥2 เซนเซอร์บนเส้นเวลาเดียว ได้จริง — ไฟล์ /multicapture.csv มีคอลัมน์ t_ms + IMU + db และค่าจริงเปลี่ยนตามท่า/เสียง

  • ทำบน บอร์ดจริง (เสียงจริงต้องมาจากไมโครโฟนบนบอร์ด)
  • อธิบายได้ว่าโค้ดประทับ t_ms ตรงไหน อ่านสองเซนเซอร์ตรงไหน และทำไมต้องอยู่ในรอบเดียว

"เก็บได้" ไม่พอ ต้อง "เก็บตรงเวลา" — คุณต้องชี้ได้ว่าแถวไหนคือช่วงที่คุณเขย่า+ส่งเสียง และ db กับ IMU ในแถวนั้นสอดคล้องกัน

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

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

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

  • ใบ้ — คำใบ้อยู่ในคอมเมนต์ # เติม: ทั้ง 4 จุดในไฟล์ฝึก + ตารางสี่ก้าวหน้าที่แล้ว บอกว่าแต่ละช่องเติมอะไร
  • เริ่มจากโครง — s05_multicapture.py มีโครงครบทั้งไฟล์แล้ว (UI + เปิด PDM + finally) เหลือแค่ 4 บรรทัดในลูปให้เติม
  • เฉลย — s05_multicapture.py เติมครบพร้อมคอมเมนต์อธิบายทุกก้าว (อ่านให้เข้าใจ ปิดไฟล์ แล้วพิมพ์เอง)
  • ฉบับเต็ม — s05_multicapture_full.py เพิ่มเก็บ WAV เสียงดิบคู่ CSV + วัด dt/jitter จริง + สรุป peak dBFS ต่อ label ลง manifest

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

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

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

การเก็บ dataset หลายเซนเซอร์ซ่อนแนวคิด DAQ หลายชั้นที่จะใช้ไปตลอดคอร์ส:

ฝั่ง DAQ / dataset

  • Shared timeline — สองเซนเซอร์อ้าง t_ms เดียว จึงจับคู่/ตัดหน้าต่างตามเวลาได้
  • Audio front-end — PDM → PCM → RMS → dBFS คือก้าวแรกก่อนทำ spectrogram (บทเรียน 4.5–4.6)
  • Sampling rate + jitter — ตั้งอัตราด้วย sleep_ms แล้วตรวจด้วย t_ms จริง
  • Label ในไฟล์ — เก็บ label พร้อมข้อมูล = dataset พร้อม train

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

  • เปิดฮาร์ดแวร์ครั้งเดียว — PDM_PCM(...) นอกลูป เหมือนสร้าง widget ครั้งเดียว
  • ticks_ms / ticks_diff — คู่มาตรฐานวัดเวลาสั้นๆ กัน wrap-around
  • เก็บกวาดตอนจบ — finally: pdm.deinit() คืนไมโครโฟนสู่สถานะที่รู้แน่

ทั้งหมดต่อยอดจากบทเรียน 2.1–2.2 ตรงๆ — DAQ ไม่ใช่เรื่องเขียนใหม่ทุกครั้ง แต่คือ pattern ที่ขยายทีละเซนเซอร์

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

ใช้จริงที่ไหน — multi-sensor dataset ในโลกจริง

การมัดหลายเซนเซอร์บนเวลาเดียว ไม่ใช่แบบฝึกหัด มันคือวิธีที่ dataset ระดับสินค้าถูกเก็บจริง:

สุขภาพ — นาฬิกา/แพตช์ IMU + เสียง + ชีพจร บนเวลาเดียว แยก "ไอ" จาก "ขยับตัว" ต้องดูหลายสัญญาณ โรงงาน — ตรวจเครื่องจักร สั่นสะเทือน (IMU) + เสียง (MIC) พร้อมกัน จับความผิดปกติที่สัญญาณเดียวมองไม่เห็น บ้าน — ตรวจเหตุการณ์ เรดาร์ (มีคน) + เสียง (เหตุการณ์) ยืนยันกัน ลด false alarm เพราะสองสัญญาณต้องตรงกัน ร่วมกัน — เส้นเวลาคือกาว ทุกงานเริ่มจาก dataset ที่ทุกสัญญาณตรงเวลา คือทักษะที่คุณเพิ่งทำวันนี้

ไฟล์ /multicapture.csv ที่คุณเพิ่งเก็บ ใช้หลักการเดียวกับ dataset ของสินค้าจริงเหล่านี้เป๊ะ — เราแค่ทำในสเกลเล็ก เพื่อจะย้อนไป train โมเดลเองในโมดูล 5 (Training)

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

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

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

  1. เติม s05_multicapture.py ให้ครบทั้ง 4 ช่อง รันบนบอร์ดจนได้ /multicapture.csv
  2. เก็บครบ 3 label (idle / circle / shaking) แต่ละ label ทำท่า + ส่งเสียงต่างกัน แล้วเปิด CSV ยืนยันว่า db และ IMU เปลี่ยนตามจริง
  3. ตรวจเส้นเวลา: t_ms ในแต่ละชุดเพิ่มขึ้นเรื่อยๆ และห่างกันใกล้ 20 ms ไหม — จดว่าเจอ jitter ตรงไหน

ใบ้ข้อ 3 — ถ้าช่วงเวลาเพี้ยนมาก ลองลด CHUNK เสียง หรือลดงานในลูป แล้วเทียบ t_ms ใหม่

วันนี้เราได้: อ่านไมโครโฟน PDM เป็น dBFS · เข้าใจเส้นเวลาร่วม · อ่าน IMU+MIC ในลูปเดียว · เก็บ dataset หลายเซนเซอร์ที่ทุกแถวตรงเวลา (t_ms + IMU + db)

ชุดบทเรียนถัดไป (บทเรียน 3.1–3.2) เราเข้าสู่ Pillar 2 (Processing) — เอาสัญญาณดิบที่เก็บมา แปลงเป็นปริมาณเชิงฟิสิกส์ (tilt / altitude / พลังงาน) แล้วโชว์เป็นเกจสดบนจอ เจอกันครับ

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