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

บทเรียน 3.6 — ลงมือทำ: กราฟความเร่งสามแกน

กราฟ Real-time · ui.Chart หลาย Series: เห็นสัญญาณเป็นเส้นเวลา ไม่ใช่ตัวเลขกระพริบ

โมดูล 3 — แสดงผลเซนเซอร์บน HMI

ต่อจากบทเรียน 3.5 — ui.Chart: กราฟหลาย series และคาบเวลาของลูปจริง

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

MVP checkpoint — ผ่านชุดบทเรียนนี้เมื่อ

กราฟ accel 3 แกนวิ่งสด + ตารางสรุปค่าสุดขีด + ปุ่มเริ่มกับปุ่มหยุดที่แยกกัน

แปลเป็นสิ่งที่ตรวจได้จริง:

  • [ ] จอมีกราฟหนึ่งใบ มีเส้น สามสีแยกกันชัดเจน (X ฟ้า, Y ม่วง, Z เขียวน้ำทะเล)
  • [ ] วางบอร์ดนิ่ง เส้น Z อยู่ราว 9-10 ส่วน X และ Y อยู่ราวศูนย์
  • [ ] เขย่าบอร์ดแล้วทั้งสามเส้นตอบสนองทันที และรอยนั้นเลื่อนไปทางซ้าย
  • [ ] ตารางขวามือขึ้นครบสี่แถว ไม่มีช่องไหนตกบรรทัด และแถว Z ไม่หายไปใต้ขอบ
  • [ ] เขย่าแล้วค่าสูงสุดในตารางขยับขึ้นและ ไม่ลดกลับเอง ส่วนค่าล่าสุดวิ่งตามตัวเลขปัจจุบัน
  • [ ] ตัวเลขในตารางเปลี่ยน วินาทีละครั้ง ส่วนเส้นกราฟยังเดินห้าครั้งต่อวินาที (จ้องดูสิบวินาทีแล้วนับ)
  • [ ] กดหยุดบันทึกแล้วเขย่าแรง ๆ กราฟต้อง ไม่ขยับเลย ไฟหรี่ลง (ไม่ใช่หายไป) และป้ายเปลี่ยนเป็น "หยุดแล้ว"
  • [ ] กดเริ่มบันทึกแล้วกราฟกลับมาวิ่งต่อ ค่าสุดขีดในตารางถูกล้างกลับเป็นขีด สลับไปกลับได้อย่างน้อยสามรอบ
  • [ ] มีป้ายบนจอบอกคาบลูปจริงเป็นมิลลิวินาที และค่าอยู่ในช่วงที่อธิบายได้
  • [ ] รันต่อเนื่อง 3 นาทีโดยไม่ค้างและไม่มี error

ข้อที่เจ็ดคือหัวใจ — ปุ่มที่กดแล้วไฟเปลี่ยนแต่ข้อมูลยังวิ่ง คือปุ่มที่ยังไม่ทำงาน

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

กับดักที่เจอบ่อย (1/2)

อาการ สาเหตุที่แท้จริง วิธีแก้
TypeError ตอนเรียก set_next ส่งทศนิยมเข้าไปตรง ๆ ครอบด้วย int() ทุกครั้ง
NameError: name 's_az' ยังไม่ได้เติมช่อง add_series แต่โค้ดข้างล่างอ้างถึงแล้ว เติมไล่จากบนลงล่าง
มีสี่เส้นแทนที่จะเป็นสาม เผลอ add_series ให้แกน X ด้วย ทั้งที่ series 0 มีมาแล้ว ใช้ set_next(0, ...) กับแกน X
กราฟเดินอืด ๆ ทั้งที่ลูปตั้ง 200 ms ลูปมีแต่ set_next() ซึ่งไม่ปลุกโหมดเร่ง — CM55 ระบายแค่ 80 คำสั่ง/วินาที เพิ่ม lbl.text(...) ในลูปเดียวกัน
กราฟกระตุก จุดหายเป็นช่วง ลูปเร็วเกิน คำสั่งล้นคิว IPC 64 ช่องแล้วถูกทิ้ง เพิ่ม sleep_ms กลับไปที่ 200
เส้นแบนติดขอบบนตลอด ช่วงแกน Y แคบไป แกน Z ชนเพดาน ขยายเป็น min=-20, max=20
กดหยุดบันทึกแล้วกราฟยังวิ่ง if running: ไม่ได้ครอบส่วนที่ป้อนข้อมูล ย้าย set_next เข้าไปใต้ if running:
กดหยุดบันทึกแล้ว widget หายทั้งจอ ไปหยุดลูป ทำให้ ui.poll() ไม่ถูกเรียก การหยุดคือ flag ห้ามหยุดลูป
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

กับดักที่เจอบ่อย (2/2)

อาการ สาเหตุที่แท้จริง วิธีแก้
ตารางขึ้นแค่สองแถวครึ่ง แถว Z หายไป คอลัมน์แคบกว่าข้อความ ข้อความตกบรรทัด ทุกแถวเลยสูงสองเท่า ขยาย .col_width() จนไม่มีช่องไหนตกบรรทัด
ตัวหนังสือไทยในตารางขึ้นเป็นกล่องสี่เหลี่ยม ช่องของตารางวาดจากคนละส่วนกับ Label เฟิร์มแวร์ตั้งฟอนต์ไทยที่ส่วน ITEMS ให้แล้ว ถ้ายังเป็นกล่อง ให้แจ้งผู้สอน
ไฟดับแล้วยังเห็นเป็นวงจาง ๆ ตั้งใจ .value(0) คือหรี่ ไม่ใช่หาย ไฟที่หายไปทำให้แยกไม่ออกว่าดับหรือจอเสีย
เส้นกราฟกระตุกทั้งที่ลูปยังเดิน ทั้งลูปมีแต่ .value() กับ set_next() ซึ่งไม่ปลุกโหมดเร่ง ส่ง .text() อย่างน้อยหนึ่งครั้งต่อรอบ ส่งข้อความเดิมก็ได้
กดปุ่มแล้วไม่มีอะไรเกิดขึ้น เทียบ handle กับ id ผิดตัว หรือลืมเก็บ btn.id() ตรวจว่าเก็บ id ไว้ก่อนเข้าลูป
ค่าเซนเซอร์ค้างตัวเลขเดิม หลังใช้ ui.* auto-task หยุด แต่เราไม่ได้อ่านเองในลูป อ่าน motion() ทุกรอบ
เขย่าเร็วแล้วกราฟโชว์คลื่นช้าแปลก ๆ aliasing — เขย่าเกิน 2.5 Hz ที่ fsf_s 5 Hz รับไหว ไม่ใช่บั๊ก บันทึกไว้

สิบสามในสิบห้าข้อนี้ไม่มี error message (มีแค่ TypeError กับ NameError) — มีแต่ "กราฟดูแปลก ๆ" หรือ "ตารางดูแปลก ๆ" ต้องอ่านอาการเป็น

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

ลงมือทำ — เติมช่องว่างในไฟล์ฝึก

เปิด s07_accel_chart.py มีช่องว่างให้เติม 6 จุด

# เติม: s_az = chart.add_series(COL_AZ)
pass

if running:
    ax, ay, az, gx, gy, gz = sensors.bmi270.motion()
    # เติม: chart.set_next(0, int(ax))
    pass

# เติม: dt = time.ticks_diff(now, last_ms)
pass

for ev in ui.poll():
    h = ev.get('handle')
    if h == start_id:
        # เติม: running = True
        pass
    elif h == stop_id:
        # เติม: running = False
        pass

# เติม: time.sleep_ms(PERIOD_MS)
pass
เติมเป็นสามขั้น แล้วรันทุกขั้น ขั้น 1 · จุดที่ 1-2 ควรเห็นสามเส้นวิ่ง ขั้น 2 · จุดที่ 3 ควรเห็นตัวเลขคาบลูป ขั้น 3 · จุดที่ 4-6 ทดสอบปุ่มสลับไปกลับ

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

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

ตัวอย่างของบทเรียน 3.4–3.6 — สองไฟล์นี้คือชุดที่ทำให้กราฟสดของทีมมีคาบเวลาที่อธิบายได้

ต้องทำในบทเรียน · เปิดตามลำดับนี้ ทั้งชุดราว 20 นาที

ลำดับ · เรื่อง · เวลา ไฟล์ ลงมือทำอะไร แล้วจะเข้าใจอะไร
1 · สุ่มช้าไปแล้วได้ความถี่ผี · 8 นาที 03_aliasing_nyquist.py ตั้งค่า PERIOD_MS ของทีมโดยมีเหตุผลรองรับ แทนที่จะเดาแล้วมาแก้ทีหลัง · จะเข้าใจว่าสุ่มช้าเกินไป แล้วได้ความถี่ที่ไม่เคยมีอยู่จริงบนกราฟ
2 · เฝ้าการสั่นด้วยเกณฑ์ที่วัดเอง · 12 นาที 01_imu_vibration_monitor.py ลอกโครงลูปอ่านเซนเซอร์ เส้นเกณฑ์ และปุ่มหยุดกราฟ ไปใส่ไฟล์ของทีมได้ทันที · จะได้รูปร่างของงานเฝ้าการสั่น คือกราฟคู่กับเส้นเกณฑ์ที่วัดมาเอง ไม่ใช่ตัวเลขที่หยิบมาจากที่อื่น

ติดตรงไหน เปิดอันนี้

อาการที่เจอ ไฟล์ที่ตอบอาการนั้น
กดปุ่มเริ่ม/หยุดแล้วจอไม่เปลี่ยนอะไรเลย 02_event_types.py — Button ส่ง clicked ส่วน Switch ส่ง toggled คนละชนิดกัน ดักผิดชนิดคือเงียบ
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

ตัวอย่างของบทเรียน 3.4–3.6 (ต่อ) — อ่านเสริมนอกเวลา: FFT ด้วยมือ แล้วของจริงใน C

อ่านเสริมนอกเวลา — เรื่องนี้อยู่นอกเกณฑ์ผ่านของบทเรียน 3.4–3.6 เพราะ MVP วันนี้วัดที่กราฟสามเส้น ตาราง และปุ่มเริ่ม/หยุดบันทึก ไม่ได้วัดสเปกตรัม: 02_fft64_two_tones.py เขียน FFT 64 จุดด้วยมือทั้งตัว แล้วชี้ว่าข้อมูลชุดเดิมมองคนละมุมได้คำตอบคนละแบบ · พอเข้าใจข้างในแล้ว ของจริงใช้ dsp.fft_mag() ที่คำนวณใน C (firmware 2026-08-20 ขึ้นไป) — ex16_spectrum_analyzer.py คือเครื่องวิเคราะห์สเปกตรัมทั้งเครื่องที่ประกอบจากมัน เก็บไว้เปิดตอนอยากต่อยอดไปงาน predictive maintenance จริง

ภาพถ่ายจอบอร์ด Eva Kit ขณะรัน 02_fft64_two_tones.py สเปกตรัมที่มียอดสองความถี่ หน้าจอจาก Emulator ของ ex16_spectrum_analyzer.py กราฟสเปกตรัมความถี่จาก FFT

ซ้าย — หน้าจอจริงตอนรัน 02_fft64_two_tones.py — บนคือคลื่นที่ป้อนเข้าไป ล่างซ้ายคือสเปกตรัมที่ออกมา วาดบนตารางไฟ 8x8 ด้วย DotMatrix.set_pixels() · ภาพจับที่ขั้นแรก ป้อนโทนเดียว 3 รอบเข้าไป ยอดจึงขึ้นที่ bin 3 เดี่ยว ๆ และเพราะความละเอียดต่อ bin เท่ากับ fs/N = 1.000 Hz เลข bin กับเลขความถี่จึงบังเอิญตรงกันพอดีที่ 3 · บรรทัดล่างคือราคาที่ประหยัดได้จริง FFT เร็วกว่า DFT ตรง ๆ 21 เท่าที่ N = 64 · ภาพหน้าจอจริงจากบอร์ด Eva Kit บันทึกโดยผู้สอน

ชุดบทเรียนนี้เหลือตัวอย่างสามไฟล์ หลังตัดเรื่องเลข int16 · บิตมาสก์ · การแพ็กฟิลด์ลงไบต์ ออกจากหลักสูตร ทั้งสามเรื่องไม่มีบทเรียนไหนสอนแล้ว และไม่มีไฟล์ไหนต้องแก้ค่าคงที่ก่อนกด Run

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

เฉลย s07_accel_chart.py — ตั้งต้น กราฟ ตาราง ไฟ และปุ่มสองปุ่ม

import ui
ui.screen()
import time
import sensors

COL_TEXT, COL_DIM = 0xE8EAED, 0x9AA3AF
COL_AX = 0x4A9EFF      # แกน X - เส้นที่ 1 ของจานสีเส้นข้อมูล สีฟ้า
COL_AY = 0x8E7BFF      # แกน Y - เส้นที่ 2 ของจานสีเส้นข้อมูล สีม่วง
COL_AZ = 0x2FB6A8      # แกน Z - เส้นที่ 3 ของจานสีเส้นข้อมูล สีเขียวน้ำทะเล
COL_RUN = 0x4A9EFF     # สีเน้นของจานบทบาท - ใช้กับไฟบอกว่ากำลังบันทึกอยู่
PERIOD_MS = 200        # คาบการสุ่มที่เราเลือก
...
chart = ui.Chart(x=24, y=52, w=292, h=144, min=-20, max=20, color=COL_AX)
s_ay = chart.add_series(COL_AY)
s_az = chart.add_series(COL_AZ)
tbl = ui.Table(x=332, y=52, w=436, h=280, cols=4, value=16)
...                    # col_width + add_row สี่แถว - ท่าที่ 2
led_rec = ui.Led(x=24, y=212, w=48, h=48, color=COL_RUN, value=1)
lbl_rec = ui.Label("กำลังบันทึก", x=88, y=216, color=COL_TEXT, value=20)
lbl_dt = ui.Label("คาบลูป -- ms", x=88, y=252, color=COL_DIM, value=20)
...                    # ปุ่มเริ่ม/หยุด + start_id stop_id - ท่าที่ 3
lo = [None, None, None]
hi = [None, None, None]
นับ widget Chart 1 + Table 1 + ไฟ 1 + ปุ่ม 2 หัวเรื่อง + ป้ายสองป้าย อีก 3 รวม 8 ชิ้น ป้ายใช้สีเดียวกับเส้นในกราฟ ตารางหนึ่งใบแทนป้ายสิบสองช่อง
แถวของตารางถูกสร้างด้วย - ไว้ก่อน ไม่ใช่เว้นว่าง เพราะช่องว่างเปล่าอ่านได้สองแบบ คือ "ยังไม่มีค่า" กับ "จอเสีย" ส่วนขีดอ่านได้แบบเดียว · lo กับ hi เกิดนอกลูปเพราะมันคือความจำของโปรแกรม · เส้นในกราฟใช้สามสีแยกแกน ส่วนตารางใช้ ตัวอักษร X Y Z แยกแทน เพื่อให้อ่านออกแม้พิมพ์เป็นขาวดำ · start_id กับ stop_id เก็บครั้งเดียวตอนสร้าง เพราะบนจอมีสองปุ่ม
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

เฉลย — ลูปหลัก และทำไมเรียงห้าท่าแบบนี้

running = True
last_ms = time.ticks_ms()
last_sec = -1

while True:
    if running:
        try:
            ax, ay, az, gx, gy, gz = sensors.bmi270.motion()
        except OSError:
            pass
        chart.set_next(0, int(ax))
        chart.set_next(s_ay, int(ay))
        chart.set_next(s_az, int(az))
        note(0, ax)          # กราฟลืมจุดที่เก่ากว่า 50 จุด ตารางไม่ลืม

    now = time.ticks_ms()
    dt = time.ticks_diff(now, last_ms)
    last_ms = now

    for ev in ui.poll():     # poll นอก if running เสมอ ไม่งั้นปุ่มตายตอนหยุด
        h = ev.get('handle')
        if h == start_id:
            running = True
            lo = [None, None, None]
            hi = [None, None, None]
            led_rec.value(1)
        elif h == stop_id:
            running = False
            led_rec.value(0)          # หรี่ ไม่ใช่หาย

    sec = time.ticks_ms() // 1000
    if sec != last_sec:               # ตัวเลขขยับวินาทีละครั้ง กราฟขยับ 5 ครั้ง
        last_sec = sec
        for i, v in enumerate((ax, ay, az)):
            tbl.cell(i + 1, 1, cell(lo[i]))
        lbl_dt.text("คาบลูป {} ms".format(dt))

    lbl_rec.text(rec_msg)     # ชีพจร - ส่งข้อความเดิมซ้ำทุกรอบโดยตั้งใจ
    time.sleep_ms(PERIOD_MS)
ห้าท่า เรียงเพื่อตัดกองบั๊ก 1 เตรียมเซนเซอร์และจอ ถ้าฐานพัง ที่เหลือไม่มีความหมาย 2 สร้างกราฟ อยากเห็นกรอบเปล่าขึ้นจอก่อน 3 ปุ่มและ flag ปุ่มคือทางออกฉุกเฉิน มาก่อนข้อมูล 4 ป้อนข้อมูลจริง เพี้ยนตอนนี้ = เพี้ยนที่การอ่าน 5 วัดคาบลูป เครื่องมือตรวจของสี่ท่าข้างบน

ui.poll() อยู่ นอก if running: — ปุ่มหยุดที่ฆ่าทางกลับของตัวเองคือบั๊กที่เจอบ่อยที่สุดในหน้าที่มีปุ่มหยุด และมันดูเหมือนจอค้าง ทั้งที่โปรแกรมยังวิ่งครบทุกบรรทัด

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

สรุปบทเรียน · รากฐานที่แตะ · และวันนี้อยู่ตรงไหนของเส้นทาง

ค่าเดี่ยว ไปเป็นเส้นเวลา ไปเป็นแดชบอร์ด ไปเป็น telemetry บทเรียน 2.7–3.3 อ่านค่าเดี่ยว แล้ววาดเป็นแถบกับตัวเลข วันนี้ · บทเรียน 3.4–3.6 เก็บเป็นเส้นเวลา คุมจังหวะการสุ่ม บทเรียน 3.7–3.9 รวมเป็นแดชบอร์ด ภายใต้งบ widget บทเรียน 4.1–5.3 ส่งเส้นเวลานี้ ขึ้นแพลตฟอร์ม

วันนี้เราได้: เข้าใจว่า time series คืออะไรและอัตราสุ่มมีผลอย่างไร · รู้จัก Nyquist และ aliasing พร้อมตัวเลขของลูปเราเอง · ใช้ ui.Chart กับหลาย series ได้ · รู้ว่าทำไมต้อง int() และมันแลกอะไรไป · เลือกช่วงแกน Y ด้วยเหตุผลของตัวเอง · ทำปุ่มเริ่ม/หยุดบันทึกด้วย flag ที่ไม่ฆ่าลูป · วัดคาบลูปจริงและเอาขึ้นจอ · และรู้ว่าทำไมลูปที่มีแต่กราฟถึงช้ากว่าลูปที่มีป้ายด้วย 40 เท่า

รากฐานที่แตะไป: การสุ่มตัวอย่างและคาบการสุ่ม · ทฤษฎีบทไนควิสต์และ aliasing · การสูญเสียความละเอียดจากการแปลงเป็นจำนวนเต็ม · ring buffer และคิวที่มีขนาดจำกัด · การวัดเวลาด้วยตัวนับที่วนกลับ · สถานะที่ต้องอยู่นอกลูป · การใช้สีเป็นภาษาสื่อความหมาย · การทำให้โปรแกรมรายงานสมรรถนะของตัวเอง

คำถามคิดต่อ: ถ้าต้องส่งข้อมูลนี้ขึ้นคลาวด์ในบทเรียน 4.4–4.6 จะส่งทุกจุดที่ 5 Hz หรือส่งเฉพาะตอนที่มีอะไรน่าสนใจ · ค่าอะไรควรสรุปก่อนส่ง · ถ้าเน็ตหลุดสามนาที ข้อมูลช่วงนั้นควรหายไปเลยหรือควรเก็บไว้

เก็บไฟล์ของวันนี้ไว้ให้ดี บทเรียน 3.7–3.9 เราจะเปิดมันขึ้นมาต่อยอด ไม่ได้เริ่มใหม่

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

ใช้จริงที่ไหน — สี่มุมของกราฟ real-time ในสนามจริง

โรงงาน · Vibration Monitoring กราฟความสั่นของมอเตอร์แบบสด ช่างเห็นทันที ว่าลูกปืนเริ่มเปลี่ยนรูปแบบการสั่นหรือยัง อัตราสุ่มจริง: หลักกิโลเฮิรตซ์ ไม่ใช่ 5 Hz การแพทย์ · Patient Monitor คลื่นหัวใจและออกซิเจนวิ่งบนจอข้างเตียง ปุ่ม freeze ให้หมอหยุดดูจังหวะที่ผิดปกติ ปุ่ม freeze คือ flag ตัวเดียวกับที่เราเพิ่งเขียน ขนส่ง · Fleet Telematics กราฟความเร่งของรถบรรทุก จับการเบรกกะทันหัน และการเข้าโค้งแรง เพื่อประเมินพฤติกรรมคนขับ เซนเซอร์ตัวเดียวกับบนบอร์ดเรา ต่างที่โจทย์ โครงสร้าง · Structural Health เซนเซอร์บนสะพานและอาคารสูง เฝ้าการสั่น ก่อนและหลังแผ่นดินไหว เทียบรูปคลื่นย้อนหลัง ที่นี่ "หน้าต่างเวลา" ยาวเป็นวัน ไม่ใช่ 10 วินาที

ทั้งสี่มุมใช้แนวคิดเดียวกับวันนี้ทั้งหมด ต่างกันที่ อัตราสุ่ม ความยาวหน้าต่างเวลา และสิ่งที่ทำต่อกับข้อมูล

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

ต่อยอด — คิดต่อเอง (เลือกทำ 1 ข้อ)

ข้อ 1 · เครื่องกำเนิดสัญญาณของทีม
ต่อยอดจากโค้ดอุ่นเครื่อง ทำหน้าที่ป้อนคลื่นสี่แบบ (สี่เหลี่ยม ไซน์ สามเหลี่ยม ฟันเลื่อย) ลงกราฟโดยไม่ใช้เซนเซอร์เลย แล้วใส่ปุ่มสลับรูปคลื่น บันทึกว่าคลื่นแบบไหนดูผิดเพี้ยนเร็วที่สุดเมื่อเพิ่มความถี่ และเทียบกับที่ Nyquist ทำนายไว้

ข้อ 2 · กราฟความละเอียดสูง
เปลี่ยนไปใช้ int(ax * 100) พร้อมขยายช่วงเป็น min=-2000, max=2000 แล้ววางเทียบกับกราฟเดิม บันทึกว่าเห็นรายละเอียดอะไรเพิ่มขึ้น และเสียอะไรไปหรือไม่

ข้อ 3 · ตารางทดลอง cadence
ทดลอง PERIOD_MS ที่ 500, 200, 100, 50 และ 20 บันทึกคาบลูปจริงที่วัดได้ในแต่ละค่า แล้วหาว่าจุดไหนที่เริ่มเห็นอาการเฟรมหาย · โจทย์เพิ่ม: ทำการทดลองซ้ำสองรอบ รอบหนึ่งมีบรรทัด lbl.text() รอบหนึ่งไม่มี แล้วเทียบตัวเลข

ข้อ 4 · เส้นดิบเทียบเส้นกรอง
เพิ่ม series ที่สี่เป็นค่าที่ผ่าน dsp.EMA(alpha=0.2) ของแกนใดแกนหนึ่ง วางทับเส้นดิบของแกนเดียวกัน แล้วอธิบายว่าฟิลเตอร์แลกอะไรกับอะไร (ลองปรับ alpha เป็น 0.05 กับ 0.5 ประกอบ)

กราฟสัญญาณไซน์ที่มีสัญญาณรบกวน เทียบกับเส้นค่าเฉลี่ยเคลื่อนที่ที่เรียบกว่า

ภาพ: Christophe Dang Ngoc Chan, Wikimedia Commons, CC BY-SA 4.0 — ค่าเฉลี่ยเคลื่อนที่บนสัญญาณรบกวน · ใช้ประกอบข้อ 4

กราฟสัญญาณสะอาดเทียบกับสัญญาณเดียวกันที่มีสัญญาณรบกวนปน

ภาพ: Yves-Laurent Allaert, Wikimedia Commons, CC BY-SA 3.0 — สัญญาณสะอาด เทียบ สัญญาณที่มีสัญญาณรบกวน

เขียนคำตอบลงบันทึกการเรียน แล้วเอามาเล่าให้เพื่อนฟังต้นชุดบทเรียนถัดไป

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

หน้าจอของทุกไฟล์ในชุดบทเรียนนี้

หน้าจอของ 01_imu_vibration_monitor.py: เฝ้าการสั่นของเครื่องจักร หน้าจอของ 02_fft64_two_tones.py: FFT radix-2 เขียนเองทั้งตัว 64 จุด หน้าจอของ 03_aliasing_nyquist.py: สุ่มช้าเกินไป แล้วได้ความถี่ที่ไม่เคยมีอยู่จริง

01 เฝ้าการสั่นของเครื่องจักร · 02 FFT radix-2 เขียนเองทั้งตัว 64 จุด · 03 สุ่มช้าเกินไป แล้วได้ความถี่ที่ไม่เคยมีอยู่จริง
ภาพจากตัวจำลอง bento_sim ซึ่งเรนเดอร์ด้วยโค้ด CM55 ชุดเดียวกับที่รันบนบอร์ด ที่ 800x480 เท่าจอของ Eva Kit และ Dev Kit — แสดงหน้าจอที่ตัวอย่างสร้าง ค่าจากเซนเซอร์ WiFi และไมค์เป็นค่าแทนบนเครื่องโฮสต์ ไม่ใช่ผลการวัดของบอร์ด
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · ดัดแปลงจาก AIoT in Action (AIC มหาวิทยาลัยบูรพา) · CC BY-NC 4.0

อ้างอิงและเครดิต

แหล่งปฐมภูมิ

  • Chapter 20: Analog to Digital Conversion — ADI University Wiki — https://wiki.analog.com/university/courses/electronics/text/chapter-20 (มีเงื่อนไข Nyquist อยู่ในบทเดียวกัน)
  • Practical Electronics for Inventors, 4th ed. — §6.1.1 Precision/Accuracy/Resolution (หน้า 817) · §12.9.5-6 ADC
  • An Intuitive Look at Moving Average and CIC Filters — Tom Verbeure — https://tomverbeure.github.io/2020/09/30/Moving-Average-and-CIC-Filters.html
  • BMI270 datasheet BST-BMI270-DS000-08 rev 1.6 — Bosch Sensortec
  • ตัวเลขโหมดเร่งของ IPC อ่านจากซอร์สเฟิร์มแวร์เอง: .../ipc_ui/ipc_ui.c — IPC_UI_TIMER_MS, IPC_UI_FAST_TIMER_MS, IPC_UI_MAX_PER_TICK, IPC_UI_FAST_TIMEOUT_MS, ui_arm_fast_mode() (สไลด์ผู้สอน)

วิดีโอที่ฝังไว้ในชุดบทเรียนนี้ (ตรวจแล้วว่าเปิดได้)

nac9qyJT-sY An intuitive introduction to oversampling and noise shaping — Analog Snippets · 12:08 · plq_Nmud5CM ADC Quantization and Resolution — Microchip Developer Help · ยาวยังไม่ยืนยัน · yYHHuhDwhec Sigma-Delta ADC: Oversampling, Noise Shaping & Decimation — Byte-Sized Learning · 5:01 · RLQGZl0lpjQ Working principle of an accelerometer — Bosch Sensortec · 1:01 — คำอธิบายว่าดูเพื่ออะไร อยู่ใต้คลิปในสไลด์ที่ฝังไว้แล้ว

เครดิตภาพ — Wikimedia Commons และ PMC open-access (CC0 / CC BY / CC BY-SA / PD) · รายละเอียดที่ CREDITS.md

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