ส่วนบนของไฟล์ สร้าง widget ครั้งเดียว จับความดันอ้างอิง และเช็กไมค์:
dd = ui.Dropdown(text="\n".join(v[0] for v in VIEWS), x=20, y=42, w=280)
seg = ui.Seg7("--", x=44, y=120, color=GREEN)
bar = ui.Bar(x=44, y=250, w=312, h=16, min=0, max=100, value=0, color=AMBER)
chart = ui.Chart(x=420, y=90, w=352, h=210, min=0, max=100)
try: # ไมค์ PDM มีเฉพาะบนบอร์ด
from machine import PDM_PCM
pdm = PDM_PCM(0, sck="P8_5", data="P8_6", sample_rate=16000)
has_mic = True
except Exception:
has_mic = False
p0, _ = sensors.dps368.pressure_temperature() # จุด 0 เมตรของ altitude
p0 จับครั้งเดียวก่อนลูป (นอกลูป) เพราะเป็นจุดอ้างอิงที่ไม่เปลี่ยนโครงนี้คือ "สร้างครั้งเดียว" ของบทเรียน 1.4–1.5 เป๊ะ — widget อยู่นอกลูป ในลูปแค่เปลี่ยนค่า ไม่สร้างใหม่ทุกรอบ
ช่องเติมที่ 1 (บรรทัด :94): แปลง raw ของ IMU เป็นมุมเอียง
if sel == 0: # Tilt
ax, ay, az, gx, gy, gz = sensors.bmi270.motion()
# เติม: มุมเอียงจาก accelerometer -> roll, pitch = dsp.tilt(ax, ay, az)
roll, pitch = 0.0, 0.0
pass
dom = pitch if abs(pitch) >= abs(roll) else roll
pass (และลบ roll, pitch = 0.0, 0.0) ด้วย roll, pitch = dsp.tilt(ax, ay, az)roll, pitch ถูกตั้งเป็น 0 ไว้เป็น placeholderdsp.tilt คืน (roll, pitch) ไม่ใช่ (pitch, roll)เราวาง
roll, pitch = 0.0, 0.0ไว้ก่อน เพื่อให้ไฟล์ รันได้ ตั้งแต่ยังไม่เติม (โชว์ 0) พอเติมจริงค่าถึงจะขยับ — เทคนิคเดียวกับr = Noneในบทเรียน 1.1–1.3
ช่องเติมที่ 2 (บรรทัด :103): เขียนสูตรขนาดเวกเตอร์เอง
elif sel == 1: # Energy
ax, ay, az, gx, gy, gz = sensors.bmi270.motion()
# เติม: energy = ขนาดเวกเตอร์ความเร่ง ลบ 1g
# mag = math.sqrt(ax*ax + ay*ay + az*az) / 9.81 ; energy = abs(mag - 1.0)
energy = 0.0
pass
head = "%.2f" % energy
mag = math.sqrt(ax*ax + ay*ay + az*az) / 9.81 (m/s² เป็น g) แล้ว energy = abs(mag - 1.0)1.0: ตอนวางนิ่ง energy จะค้างที่ ~1.0 แทนที่จะเป็น 0ลองทดลอง: วางนิ่งควรได้ใกล้ 0 เขย่าเบาๆ ได้ ~0.2 เขย่าแรงได้เกิน 1 — ถ้าค่าไม่เป็นแบบนี้ กลับมาเช็กว่าลบ 1g หรือยัง
ช่องเติมที่ 3 (บรรทัด :112): เรียกฟิสิกส์ความดันสำเร็จรูป
elif sel == 2: # Altitude
p, t = sensors.dps368.pressure_temperature()
# เติม: ความสูงจากความดัน เทียบกับ p0 -> alt = dsp.altitude(p, p0)
alt = 0.0
pass
head = "%.1f" % alt
pass ด้วย alt = dsp.altitude(p, p0) — p0 จับไว้ก่อนลูปแล้ว
dsp.altitudeทำสูตร barometric ให้ทั้งดุ้น เราแค่ป้อนความดันปัจจุบันกับจุดอ้างอิง — นี่คือพลังของdsp: ฟิสิกส์ยากๆ ถูกห่อเป็นฟังก์ชันเดียว
ช่องเติมที่ 4 (บรรทัด :125): แปลง RMS เป็น decibel (บนบอร์ด)
else: # Sound dBFS
if has_mic:
pdm.readinto(mbuf)
acc = 0
for s in mbuf:
acc += s * s
rms = math.sqrt(acc / len(mbuf))
# เติม: db = 20 * math.log10(rms / 32768.0)
db = -96.0
if rms > 0:
pass
head = "%d" % int(db)
if rms > 0: แทน pass ด้วย db = 20 * math.log10(rms / 32768.0)rms > 0 ก่อน เพราะ log10(0) คำนวณไม่ได้ (เงียบสนิท = ค่าพื้น -96)สี่ช่องนี้คือสี่สูตรฟิสิกส์ของชุดบทเรียน — เติมครบเมื่อไร ทั้งสี่ปริมาณจะมีชีวิตขึ้นมาพร้อมกัน
เปิด s06_physics_viz.py มี # เติม: วางไว้ 4 จุด ตรงสูตรแปลงของแต่ละปริมาณ:
| # | จุด (บรรทัด) | เติมด้วย | ถ้าลืม |
|---|---|---|---|
| 1 | Tilt :94 |
roll, pitch = dsp.tilt(ax, ay, az) |
เกจมุมค้างที่ 0 |
| 2 | Energy :103 |
mag = math.sqrt(...) / 9.81 ; energy = abs(mag - 1.0) |
พลังงานค้างที่ 0 |
| 3 | Altitude :112 |
alt = dsp.altitude(p, p0) |
ความสูงค้างที่ 0 |
| 4 | dBFS :125 |
db = 20 * math.log10(rms / 32768.0) |
เสียงค้างที่ -96 |
ขั้นตอน:
# เติม: ทีละจุด แทน placeholder ด้วยสูตรตามคำใบ้เติมทีละสูตร ทดสอบทีละปริมาณ — เติม tilt เสร็จลองเอียงก่อน ใช้ได้แล้วค่อยไปสูตรถัดไป จะจับบั๊กง่ายกว่าเติมรวดเดียวสี่อัน
ไม่มีบอร์ดก็เริ่มได้ (สามปริมาณแรกเล่นได้เต็มที่บน Emulator):
s06_physics_viz.py (หรือวางโค้ด)Emulator ใช้เซนเซอร์ จำลอง แต่ API เหมือนบอร์ดจริงทุกบรรทัด — เหมาะกับซ้อมสูตร Tilt/Energy/Altitude ที่บ้าน แล้วมายืนยัน + เล่น dBFS กับของจริงบนบอร์ด

ภาพนี้คือ
s06_physics_vizที่เติมสูตรครบแล้วรันบน Emulator ค่าที่เห็นคือผลของสูตรdsp.tiltที่คุณเพิ่งเติม ไม่ใช่ภาพนิ่ง ลองเปิด ide.tesaiot.dev แล้วขยับดูเองได้เลย
บนบอร์ดจริงใช้ของจริง เซนเซอร์จริง ครบทั้งสี่ปริมาณรวมทั้งไมค์:
s06_physics_viz.py ใน BENTO IDE กด Program to Deviceจุดที่ควรสังเกต: กราฟ
Chartเก็บประวัติย้อนหลังให้ — เขย่าเป็นจังหวะแล้วดูคลื่นในกราฟ จะเห็น "รูปร่างของการเคลื่อนไหว" ชัดกว่าตัวเลขนิ่งๆ
อยากเจาะลึกคณิต-ฟิสิกส์ของชุดบทเรียนนี้ เลือกดูตามหัวข้อที่อยากต่อยอด:
วิดีโอ
ภาพ / เอกสารอ้างอิง
วิดีโอ/ภาพภายนอกเป็นของเจ้าของต้นฉบับ ใช้เพื่อการศึกษา อ้างอิงลิงก์ต้นทาง
MVP ของบทเรียน 3.1–3.2 (เกณฑ์ผ่านของชุดบทเรียน): สัญญาณดิบ → ปริมาณที่คำนวณได้ → แสดงเห็นบนจอ ครบวงอย่างน้อย หนึ่งปริมาณ (เอียงบอร์ดแล้วมุมเปลี่ยน หรือยกบอร์ดแล้วความสูงเปลี่ยน)
"แสดงเห็นบนจอ" ไม่ใช่แค่ "ตัวเลขขยับ" — คุณต้องบอกได้ว่า energy 0.8 หมายความว่าอะไร ทำไม tilt ใช้ atan2 ได้โดยไม่ต้องรู้หน่วย accel
ถ้าติด ให้ไต่บันไดนี้ทีละขั้น อย่าเพิ่งกระโดดไปดูเฉลย เพราะสูตรจะเข้าหัวตอนที่คุณพยายามเองก่อน:
# เติม: ทั้ง 4 จุดในไฟล์ฝึก + ตารางสองหน้าที่แล้ว บอกว่าแต่ละช่องเติมสูตรอะไรs06_physics_viz.py มีโครงครบทั้งไฟล์แล้ว (รันได้ โชว์ 0/board) เหลือแค่ 4 สูตรให้เติมs06_physics_viz.py เติมครบพร้อมคอมเมนต์อธิบายทุกสูตร (อ่านให้เข้าใจ ปิดไฟล์ แล้วพิมพ์เอง)s06_physics_viz_full.py ฉบับขัดเรียบร้อย เพิ่ม hi/lo hold, ป้าย STEADY/ACTIVE และปุ่ม Resetลองเขียนเองให้สุดก่อนนะ ถ้าติดจริงๆ ค่อยเปิดเฉลยดูทีละสูตร แล้วกลับมาพิมพ์เอง — เดี๋ยวเราค่อย ๆ แกะฟิสิกส์ไปด้วยกัน
การแปลงสัญญาณดิบซ่อนแนวคิด Processing หลายชั้นที่จะใช้ไปตลอดคอร์ส:
ฝั่ง Processing / คณิต-ฟิสิกส์
dsp.tilt/dsp.altitude (สำเร็จ) เทียบ energy/dBFS (เขียนเอง)clamp100)ฝั่ง MicroPython / โครงโปรแกรม
ui.poll เดินตามเป๊ะfinally: pdm.deinit() คืนฮาร์ดแวร์ไมค์เสมอสูตรวันนี้คือ "ก้อนแรก" ของ Analysis: พอเราแปลงดิบเป็นปริมาณได้ ชุดบทเรียนถัด ๆ ไป จะเอาปริมาณพวกนี้ไปกรอง (บทเรียน 4.1–4.2) แปลงเป็นสเปกตรัม (บทเรียน 4.3–4.4) จนเป็น feature ที่โมเดลกินได้จริง (บทเรียน 4.5–4.6)
สี่สูตรที่เราเขียนวันนี้ ไม่ใช่แบบฝึกหัดลอยๆ ทุกสูตรเป็นหัวใจของอุปกรณ์จริงที่ขายอยู่:
เห็นไหมว่าสี่สูตรพื้นฐานนี้อยู่ในของใช้รอบตัวเต็มไปหมด — Processing ที่ดูเรียบง่ายวันนี้ คือชั้นที่ทำให้ "ตัวเลขดิบ" กลายเป็นฟีเจอร์ที่ผลิตภัณฑ์จริงพึ่งพา
งานทำเอง (ท้ายบทเรียน):
s06_physics_viz.py ให้ครบทั้ง 4 สูตร รันได้จริง (Emulator หรือบอร์ด)ใบ้ข้อ 3 — ลองลบ - 1.0 ออกชั่วคราวแล้วดูว่าค่าตอนนิ่งเปลี่ยนไปเป็นเท่าไร นั่นคือ "ฐานแรงโน้มถ่วง" ที่เราตัดทิ้ง
วันนี้เราได้: เข้าใจว่าทำไมต้อง Processing · จับโครง raw → derived → viz · เขียน/เรียก 4 สูตรฟิสิกส์ (tilt/energy/altitude/dBFS) · เลือก widget ให้เข้ากับข้อมูล · แสดงเกจสดๆ
ชุดบทเรียนถัดไป (บทเรียน 3.3–3.4) เราจะต่อยอด Processing ไปอีกขั้น — เอาปริมาณที่แปลงได้มา ตัดสินด้วยกฎ (threshold) เช่น "สบาย/ร้อน" จากอุณหภูมิ+ความชื้น นี่คือ classification แบบคลาสสิกก่อนถึง ML เจอกันครับ