สุ่มสัญญาณให้ตรงกับโมเดล: อัตราสุ่ม Nyquist หน้าต่าง และ schema ของ CSV
โมดูล 2 — เก็บข้อมูลจากเซนเซอร์ (DAQ) · สไลด์: slides.md · ภาพรวมโมดูล · หน้าหลักสูตร
เริ่มวงจรจากต้นน้ำ เข้าใจว่า DAQ คืออะไร ทำไมอัตราสุ่มต้องคงที่และต้องตรงกับที่โมเดลกิน (50 Hz) ใช้กฎ Nyquist กับสูตรความยาวหน้าต่าง T = N/fs และออกแบบ schema ของไฟล์ CSV ที่เขียนลง flash บนบอร์ด
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ:
- อธิบายได้ว่าทำไม DAQ เป็นขั้นที่ 1 ของวงจรข้อมูล และยกปัจจัยที่ทำให้ dataset เสีย (garbage in, garbage out) ได้อย่างน้อยสามข้อ
- ใช้กฎ Nyquist fs ≥ 2·fmax ตัดสินว่าอัตราสุ่มที่กำหนดพอสำหรับสัญญาณหนึ่งหรือไม่ และคำนวณความยาวของหนึ่ง burst ด้วย T = N/fs
- อธิบายได้ว่าทำไม logger ต้องสุ่มที่ 50 Hz ให้ตรงกับโมเดล Motion บนบอร์ด และจะเกิดอะไรกับรูปคลื่นถ้าเก็บที่อัตราอื่น
- เขียน schema label,ax,ay,az,gx,gy,gz และบรรทัด CSV หนึ่ง sample ได้ถูก และเลือกโหมดเปิดไฟล์ “a” หรือ “w” ได้เหมาะกับสถานการณ์
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ผ่านโมดูล 1 มาแล้ว รู้จักโครงสี่จังหวะและ sensors.bmi270.motion()
เปิด REPL ของ BENTO IDE ไว้ลองเรียก sensors.bmi270.motion() ตอนวางนิ่งเทียบกับตอนเขย่า
- อุปกรณ์: บอร์ด TESAIoT Dev Kit ที่ลงเฟิร์มแวร์ MicroPython ของ BENTO แล้ว หรือ BENTO Emulator ใน BENTO IDE
- เรียนมาก่อน: บทเรียน 1.7 — ลงมือทำ: จาก verdict สู่ action บนบอร์ด
DAQ (Data Acquisition) คือการเก็บข้อมูลดิบจากเซนเซอร์ให้เป็นชุดที่เก็บ ค้น และใช้ต่อได้ เป็นวัตถุดิบตั้งต้นของทุกโมเดล โมเดล Motion ที่เราเล่นในโมดูล 1 ก็เกิดจากคนที่เขย่าเซนเซอร์แล้วเก็บตัวเลขเป็นพัน ๆ sample ก่อน คุณภาพของ dataset ขึ้นกับการติด label ถูก อัตราสุ่มคงที่ ความสมดุลของคลาส และความหลากหลายของสภาพจริง ข้อมูลเข้าเป็นขยะ ผลออกก็เป็นขยะ
อัตราสุ่ม คือจำนวนครั้งที่อ่านเซนเซอร์ต่อวินาที 50 Hz คืออ่านทุก 20 ms ในไฟล์จึงตั้ง RATE_MS = 20 ไม่ใช่เลขสุ่ม
แต่ตรงกับอัตราที่โมเดล Motion บนบอร์ดถูกฝึกมา ถ้าเก็บที่อัตราอื่น รูปคลื่นจะยืดหรือหด ไม่เหมือนที่โมเดลเคยเห็น กฎ Nyquist
บอกว่าต้องสุ่มอย่างน้อยสองเท่าของความถี่สูงสุดที่อยากจับ $f_s \ge 2 f_{max}$ ไม่งั้นสัญญาณเร็วจะแปลงร่างเป็นคลื่นช้าปลอม (aliasing)
ความยาวหนึ่ง burst คือ $T = N / f_s$ เช่น BURST = 200 ที่ 50 Hz ได้ 4 วินาที ยาวพอให้ทำท่าเต็มรอบ เพราะท่าทางเป็นรูปแบบตามเวลา
โมเดลต้องเห็นหลาย sample เรียงกันจึงแยก circle ออกจาก shaking ได้
schema ของ CSV คือบรรทัดแรก label,ax,ay,az,gx,gy,gz เป็นสัญญาระหว่างคนเก็บกับคนเทรน แต่ละบรรทัดถัดไปคือหนึ่ง snapshot
ของ IMU หกแกนพร้อมชื่อท่า ไฟล์เขียนลง flash บนบอร์ด (LittleFS) ด้วย open()/write() แบบเดียวกับ Python บนคอม
โหมด "a" เขียนต่อท้าย ส่วน "w" ทับไฟล์ ใช้ "w" ได้เฉพาะตอนรู้แน่ว่ายังไม่มีไฟล์ ก่อนเขียนโค้ดควรถามเซนเซอร์ใน REPL ก่อน
ว่าค่านิ่งกับค่าเขย่าหน้าตาเป็นอย่างไร จะได้รู้ว่าข้อมูลที่ลงไฟล์ “สมเหตุผล” หรือไม่
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”คำถามชุดเดียวกันอยู่ใน quiz.yaml สำหรับระบบที่ตรวจอัตโนมัติ
-
ข้อใดทำให้ dataset เสียทั้งที่โปรแกรมไม่ขึ้น error (เลือกทุกข้อที่ถูก) (เลือกได้หลายข้อ · เป้าหมายข้อ 1)
- ก) กดปุ่ม shaking แต่วางบอร์ดนิ่ง
- ข) เก็บ idle 1000 sample แต่ shaking แค่ 50 sample
- ค) อัตราสุ่มแกว่งไปมาเดี๋ยวเร็วเดี๋ยวช้า
- ง) เก็บหลายคนหลายท่าทางให้หลากหลาย
เฉลย
ก, ข, ค — label ผิด คลาสไม่สมดุล และอัตราไม่คงที่ ล้วนสอนโมเดลผิดแบบเงียบ ๆ ส่วนความหลากหลายของสภาพจริงทำให้โมเดลทนขึ้น
-
การเขย่ามือเร็วสุดราว 10 Hz อัตราสุ่มต่ำสุดตามกฎ Nyquist คือเท่าไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) 5 Hz
- ข) 10 Hz
- ค) 20 Hz
- ง) 100 Hz
เฉลย
ค — fs ≥ 2·fmax = 2 × 10 = 20 Hz ถ้าต่ำกว่านี้จะเกิด aliasing การเก็บที่ 50 Hz จึงเผื่อไว้พอ
-
เก็บ N = 150 sample ที่ fs = 50 Hz หนึ่ง burst ยาวกี่วินาที (เลือกหนึ่งข้อ · เป้าหมายข้อ 2)
- ก) 0.33 วินาที
- ข) 3 วินาที
- ค) 7.5 วินาที
- ง) 200 วินาที
เฉลย
ข — T = N / fs = 150 / 50 = 3 วินาที
-
ถ้าเก็บ dataset ที่ 25 Hz ไปฝึกหรือเทียบกับโมเดลที่ฝึกมาที่ 50 Hz ปัญหาคืออะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 3)
- ก) ไม่มีปัญหา เพราะค่าแต่ละ sample เหมือนเดิม
- ข) รูปคลื่นตามเวลาจะห่างและยืดต่างจากที่โมเดลเคยเห็น โมเดลจึงอาจทายผิด
- ค) ไฟล์จะใหญ่ขึ้นสองเท่า
- ง) บอร์ดจะเขียนไฟล์ไม่ได้
เฉลย
ข — อัตราสุ่มตอนเก็บข้อมูลต้องเท่ากับตอนใช้งานจริง นี่คือหลักสำคัญของ Edge AI dataset สวยแค่ไหนก็ใช้ไม่ได้ถ้าอัตราไม่ตรง
-
logger กดเก็บสาม burst แต่ไฟล์เหลือแค่ burst สุดท้าย สาเหตุน่าจะเป็นอะไร (เลือกหนึ่งข้อ · เป้าหมายข้อ 4)
- ก) เปิดไฟล์ในลูปบันทึกด้วยโหมด “w” ซึ่งทับไฟล์ทุกครั้ง แทนที่จะใช้ “a”
- ข) ลืมเขียน \n ท้ายบรรทัด
- ค) เรียก motion() แทน acceleration()
- ง) flash เต็ม
เฉลย
ก — โหมด “a” เขียนต่อท้ายโดยไม่ลบของเก่า ใช้ “w” ได้เฉพาะตอนสร้างไฟล์ใหม่พร้อมหัวตาราง
- ใน REPL เรียก
sensors.bmi270.motion()ตอนวางนิ่งและตอนเขย่า จดค่าลงบันทึกการเรียน - คำนวณ T = N/fs ของ BURST = 200 ที่ 50 Hz และที่ 25 Hz
- เขียน schema และบรรทัดตัวอย่างหนึ่งบรรทัดของ sample ที่คุณอ่านได้จริงด้วยมือ
บทเรียน 2.2 เราจะเขียน logger จริงตามสี่จังหวะ schema → sample → record → rate แล้วเก็บ dataset ไฟล์แรกของเรา
บทเรียนถัดไป: บทเรียน 2.2 — ลงมือทำ: DAQ logger เก็บ dataset ลง CSV
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- ถ้าเซนเซอร์ของคุณจับสัญญาณที่แกว่งเร็วสุด 12 Hz คุณจะตั้งอัตราสุ่มเท่าไร และทำไมไม่ตั้งสูงเกินจำเป็น
- label ที่ผิดหนึ่ง burst ใน dataset หลายพันบรรทัด ส่งผลกับโมเดลอย่างไร
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
ข้อใดทำให้ dataset เสียทั้งที่โปรแกรมไม่ขึ้น error (เลือกทุกข้อที่ถูก) (เป้าหมายข้อ 1)
- กดปุ่ม shaking แต่วางบอร์ดนิ่ง
- เก็บ idle 1000 sample แต่ shaking แค่ 50 sample
- อัตราสุ่มแกว่งไปมาเดี๋ยวเร็วเดี๋ยวช้า
- เก็บหลายคนหลายท่าทางให้หลากหลาย
ดูเฉลย
คำตอบ: A. กดปุ่ม shaking แต่วางบอร์ดนิ่ง · B. เก็บ idle 1000 sample แต่ shaking แค่ 50 sample · C. อัตราสุ่มแกว่งไปมาเดี๋ยวเร็วเดี๋ยวช้า
label ผิด คลาสไม่สมดุล และอัตราไม่คงที่ ล้วนสอนโมเดลผิดแบบเงียบ ๆ ส่วนความหลากหลายของสภาพจริงทำให้โมเดลทนขึ้น
-
การเขย่ามือเร็วสุดราว 10 Hz อัตราสุ่มต่ำสุดตามกฎ Nyquist คือเท่าไร (เป้าหมายข้อ 2)
- 5 Hz
- 10 Hz
- 20 Hz
- 100 Hz
ดูเฉลย
คำตอบ: C. 20 Hz
fs ≥ 2·fmax = 2 × 10 = 20 Hz ถ้าต่ำกว่านี้จะเกิด aliasing การเก็บที่ 50 Hz จึงเผื่อไว้พอ
-
เก็บ N = 150 sample ที่ fs = 50 Hz หนึ่ง burst ยาวกี่วินาที (เป้าหมายข้อ 2)
- 0.33 วินาที
- 3 วินาที
- 7.5 วินาที
- 200 วินาที
ดูเฉลย
คำตอบ: B. 3 วินาที
T = N / fs = 150 / 50 = 3 วินาที
-
ถ้าเก็บ dataset ที่ 25 Hz ไปฝึกหรือเทียบกับโมเดลที่ฝึกมาที่ 50 Hz ปัญหาคืออะไร (เป้าหมายข้อ 3)
- ไม่มีปัญหา เพราะค่าแต่ละ sample เหมือนเดิม
- รูปคลื่นตามเวลาจะห่างและยืดต่างจากที่โมเดลเคยเห็น โมเดลจึงอาจทายผิด
- ไฟล์จะใหญ่ขึ้นสองเท่า
- บอร์ดจะเขียนไฟล์ไม่ได้
ดูเฉลย
คำตอบ: B. รูปคลื่นตามเวลาจะห่างและยืดต่างจากที่โมเดลเคยเห็น โมเดลจึงอาจทายผิด
อัตราสุ่มตอนเก็บข้อมูลต้องเท่ากับตอนใช้งานจริง นี่คือหลักสำคัญของ Edge AI dataset สวยแค่ไหนก็ใช้ไม่ได้ถ้าอัตราไม่ตรง
-
logger กดเก็บสาม burst แต่ไฟล์เหลือแค่ burst สุดท้าย สาเหตุน่าจะเป็นอะไร (เป้าหมายข้อ 4)
- เปิดไฟล์ในลูปบันทึกด้วยโหมด "w" ซึ่งทับไฟล์ทุกครั้ง แทนที่จะใช้ "a"
- ลืมเขียน \n ท้ายบรรทัด
- เรียก motion() แทน acceleration()
- flash เต็ม
ดูเฉลย
คำตอบ: A. เปิดไฟล์ในลูปบันทึกด้วยโหมด "w" ซึ่งทับไฟล์ทุกครั้ง แทนที่จะใช้ "a"
โหมด "a" เขียนต่อท้ายโดยไม่ลบของเก่า ใช้ "w" ได้เฉพาะตอนสร้างไฟล์ใหม่พร้อมหัวตาราง
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"สุ่มสัญญาณให้ตรงกับโมเดล: อัตราสุ่ม Nyquist หน้าต่าง และ schema ของ CSV" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "Sampling to match the model: rate, Nyquist, windows and the CSV schema" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/edge-ai-developer/m02-daq/l01-sampling-and-schema/
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA