| คำถาม | คำตอบของชุดบทเรียนนี้ | อยู่ช่วงไหน | |
|---|---|---|---|
| Why | ปุ่มกับสวิตช์ก็สั่งงานได้แล้ว ทำไมต้องมาอ่านลูกบิดกับแผ่นสัมผัสอีก | เพราะของที่ IoT ต้องวัดจริง ๆ — อุณหภูมิ ระดับน้ำ แรงดัน ความชื้น ตำแหน่งวาล์ว — ไม่มีตัวไหนตอบมาเป็น 0 กับ 1 มันตอบมาเป็นค่าต่อเนื่องที่สั่นตลอดเวลา และงานของวิศวกรไม่ใช่กำจัดการสั่น แต่คือ เลือกฟิลเตอร์แล้วปกป้องตัวเลือกนั้นได้ | ครึ่งแรก · ADC และ CapSense · สไลด์ "ทำไมค่าดิบถึงสั่น" |
| What | มีอะไรให้ใช้บ้าง | โมดูล sensors สิบห้าชื่อบน Eva Kit — เก้าฟังก์ชัน (บน Eva สี่ตอบ ห้าปฏิเสธด้วย OSError · บน Dev Kit ห้าตัวนั้นทำงานจริง) กับหกเซนเซอร์ย่อย (Dev Kit มีเพิ่ม dps368 sht40 radar) · และโมดูล dsp ทั้งสิบหกชื่อ คือ 8 คลาสกับ 8 ฟังก์ชัน (สองตัวสเปกตรัมเพิ่ม 2026-08-20) ใช้ได้ครบทุกตัวทั้งสองบอร์ด |
สองสไลด์แผนที่โมดูล |
| How | ประกอบยังไงให้ใช้งานได้จริง | อ่านจาก sensors.pot กับ sensors.capsense ป้อนเข้า dsp.EMA และ dsp.Median แล้ววางค่าดิบกับค่ากรองแล้วไว้ข้างกันบนจอเดียว |
สิบไฟล์ตัวอย่าง + ไฟล์ฝึก |
ปลายทางที่จับต้องได้ — เข็มโค้งหมุนตามลูกบิด แถบเลื่อนวิ่งตามนิ้ว และสองบรรทัดล่างที่ฟ้องด้วยตาว่าฟิลเตอร์กำลังทำงานอยู่จริง
บทเรียน 2.4–2.6 คือ "จอสั่งฮาร์ดแวร์" · ชุดบทเรียนนี้กลับด้าน ฮาร์ดแวร์เป็นฝ่ายสั่งจอ
sensors.pot.read() / .percent() / .voltage() แล้วแสดงสามแถวสามสีบนจอsensors.capsense และเข้าใจว่าแผ่นทองแดงรู้ได้อย่างไรว่านิ้วมาแตะdsp.EMA และ dsp.Median ลดการสั่น แล้ว เทียบค่าดิบกับค่ากรองแล้วบนจอพร้อมกันปลายทางของวันนี้: หน้าจอเดียวที่มีเข็มโค้งตามลูกบิด แถบเลื่อนตามนิ้ว และสองบรรทัดล่างที่ฟ้องให้เห็นว่าฟิลเตอร์ทำงานอยู่จริง
วัดกันที่ "อ่านค่าได้และอธิบายค่าที่ได้เป็น" ไม่ใช่แค่ทำให้เข็มขยับ

หน้าจอของเฉลยปัจจุบันแบ่งเป็นสี่การ์ด และทุกการ์ดตอบคำถามคนละข้อ
ui.Bar วางทับ ui.Scale ที่มีขีดและตัวเลข 0-100 — ตัวเลขเปอร์เซ็นต์จึงไม่ได้ลอยอยู่เฉย ๆ มันมีพิสัยของตัวเองอยู่ข้าง ๆ พร้อมค่าดิบกับโวลต์กำกับ และค่าดิบเทียบค่าที่กรองแล้ว (alpha 0.2, คาบ 200 ms) ซึ่งเป็นบทเรียนหลักของครึ่งหลังของชุดบทเรียนui.Spinbox ที่ผู้ใช้ตั้งเองด้วยปุ่มเพิ่ม/ลดui.Led สองดวงบอกว่าตอนนี้ต่ำกว่าเกณฑ์หรือเกินค่าเดียวกันแสดงได้หลายแบบ — เลือกให้ตรงกับคำถามที่คนดูจออยากรู้ และค่าที่วัดได้ต้องมาพร้อมเกณฑ์ของมันเสมอ
ชุดบทเรียนก่อนหน้าเราสร้างแผงควบคุมของทีมเอง จากบทเรียนนั้นมีสี่อย่างที่วันนี้ใช้ซ้ำทั้งหมด
| ของจากบทเรียน 2.4–2.6 | วันนี้ใช้ตรงไหน |
|---|---|
ui.Label / ui.Bar / ui.Panel และ x, y, w, h, color |
สร้างการ์ด แถบค่า และบรรทัดตัวเลข |
ui.poll() ทุกลูป |
ยังบังคับเหมือนเดิม ไม่เรียกแล้ว widget หายไปได้ถึง 2 วินาที และปุ่มบนจอกดไม่ติด |
time.sleep_ms() คุมจังหวะ |
ชุดบทเรียนนี้ใช้ 200 ms เพราะจอมีของหลายชิ้น |
| งบของคอร์ส 32 widget (เพดานเฟิร์มแวร์ 64) | เฉลยวันนี้ใช้ 33 ชิ้น เกินงบของคอร์สไปหนึ่งชิ้น ต่อยอดเมื่อไรต้องเอาชิ้นเดิมออกก่อน · ข้อเสนอ: ป้ายนิ่ง "อัลฟา 0.2" ในเฉลยบทเรียน 2.9 ตัดได้ก่อน เพราะซ้ำกับ dsp.EMA(alpha=0.2) ในโค้ด ตัดแล้วเหลือ 32 พอดีงบ |
ของใหม่ที่เพิ่มเข้ามา: โมดูล sensors (ลูกบิด + สัมผัส) · โมดูล dsp (ฟิลเตอร์) · widget สามตัวของหน้าจอ HMI คือ ui.Scale (ไม้บรรทัด) ui.Led (ไฟสถานะ) ui.Spinbox (ช่องป้อนเลข) — ตัวอย่างประกอบที่ 09_scale_led_spinbox.py
ลูกบิดบนบอร์ดไม่ได้ส่งตัวเลขออกมา มันส่ง แรงดันไฟ ที่ไล่ต่อเนื่องจาก 0 V ขึ้นไปถึงแรงดันอ้างอิงของวงจร (ตัวเลขจริงของบอร์ดนี้ยังไม่ลงตัว — สองสไลด์ถัดไปว่าด้วยเรื่องนี้โดยเฉพาะ) วงจร SAR ADC ในชิปมีหน้าที่วัดแรงดันนั้นเป็นจังหวะ ๆ แล้วปัดลงขั้นบันไดที่ใกล้ที่สุด
ตัวเลขที่ Python อ่านได้ ไม่ใช่แรงดันจริง แต่เป็น ค่าที่ถูกปัดเข้าขั้นบันไดที่ใกล้ที่สุด ณ วินาทีที่วัด
import sensors
# ไม่ต้องเรียก sensors.init() ทั้งสองบอร์ด - บน Eva Kit เรียกแล้วขึ้น OSError
# ทันที (คอร์จอเป็นเจ้าของบัส) ส่วนบน Dev Kit ผ่าน แต่ก็ไม่จำเป็นอยู่ดี
raw = sensors.pot.read() # 0 - 65535 จำนวนเต็ม ทั้งสองบอร์ด (Dev Kit = VR1)
pct = sensors.pot.percent() # 0.0 - 100.0 เปอร์เซ็นต์ของช่วงเต็มสเกล
volts = sensors.pot.voltage() # ทศนิยม หน่วยโวลต์ (ดูสไลด์ถัดไปก่อนเชื่อตัวเลข)

ทั้งสามค่ามาจากการวัดครั้งเดียวกัน ต่างกันแค่หน่วยที่เอามาเสิร์ฟ — read() ดูความละเอียดดิบและความสั่น · percent() เข้ากับ ui.Arc / ui.Bar ที่คิดเป็น 0-100 อยู่แล้ว · voltage() ไว้เทียบกับมัลติมิเตอร์
เปลี่ยนจากที่เคยสอน: สามคำสั่งข้างบน ไม่ได้ตั้งค่า ADC เอง — บน Eva Kit คอร์จอ (CM55) อ่านลูกบิดแล้ว Python หยิบค่าจาก snapshot · บน Dev Kit CM33 อ่าน VR1 บนฐาน QWA309 ตรง (อีกสามตัวอยู่ที่ pots.read(1..3) คืน 0-4095 คนละสเกล) · ทั้งสองทางคืน 0-65535 หน้าตาเดียวกัน — ไม่ต้องมี init() ไม่ต้องหน่วง 500 ms
เลือกหน่วยตาม คนอ่าน ไม่ใช่ตามความสะดวกของโปรแกรม — เกจเป็นเปอร์เซ็นต์ รายงานวิศวกรรมเป็นโวลต์

R34 คือ pot 10 kΩ แบบ linear ต่อคร่อมระหว่างรางไฟกับกราวด์ ขากลาง (wiper) ออกมาเป็น POT_OUT — ตัวแบ่งแรงดันที่ปรับได้ด้วยมือ ตรงตามสัญลักษณ์ในสไลด์ที่แล้ว · กล่องขวา: thermistor TH1 ใช้เส้นทางเดียวกันผ่านตัวต้านทาน 0 Ω ที่ mark ว่า DNI — Eva Kit ใช้ pot กับ thermistor พร้อมกันไม่ได้ ค่าเริ่มต้นคือ pot
บน TESAIoT Dev Kit ลูกบิดที่ sensors.pot อ่านคือ VR1 บนฐาน QWA309 — ผัง QWA309 ระบุแรงดันอ้างอิงของ VR1-4 ไว้ 0-1.8 V (SAR 12 บิต) ขณะที่ voltage() คูณด้วย 3.3 V — ขัดกันแบบเดียวกับ Eva · ส่วนค่าความต้านทาน ทิศหมุน และ taper ของ VR1 ยังไม่ได้วัด ให้ทีมจดจากบอร์ดจริงลงบันทึกการเรียน อย่าเอาตัวเลขของ R34 ไปใช้
หมายเหตุผู้สอน (ต้องเคลียร์ก่อนสอน): ผัง Eva ต่อ R34 กับ VDD_1V8 และผัง QWA309 ก็ระบุ 0-1.8 V แต่
sensors.pot.voltage()คูณด้วย 3.3 V ที่สมมติไว้ ทั้งสองบอร์ด — ยังไม่มีใครเอามิเตอร์ไปยืนยันบนบอร์ดไหนเลย ห้ามพูดตัวเลขใดตัวเลขหนึ่งเป็นความจริงบนกระดาน ให้หมุนสุดแล้วอ่านpot.read()/pot.voltage()เทียบกับมัลติมิเตอร์ที่ขาลูกบิดของบอร์ดจริงก่อน (Eva: ขา P15[1] · Dev Kit: ขากลางของ VR1) แล้วค่อยเขียนตัวเลขลงสไลด์
read() คืนจำนวนเต็ม 0 - 65535 นั่นคือ "สเกลของ API" () ไม่ได้แปลว่าฮาร์ดแวร์ละเอียด 65536 ขั้นจริง
ไทย: ค่าที่อ่านได้ไม่ต่อเนื่อง มันกระโดดทีละขั้น ขั้นหนึ่งใหญ่แค่ไหนขึ้นกับจำนวนบิต และความคลาดเคลื่อนจากการปัดไม่เกินครึ่งขั้น
คิดให้ดูจริง ๆ สมมติ read() คืน 40915
ส่วน ตอบเป็นโวลต์ไม่ได้จนกว่าจะรู้ ของบอร์ดจริง
ตัวส่วนมีสองแบบ อย่าสลับ: แปลงเป็นค่าอ่านใช้ (ratiometric) · ขนาดหนึ่งขั้นใช้

สิ่งที่ต้องวัดเอง: เลื่อนลูกบิดช้า ๆ แล้วดูว่า read() เดินทีละเท่าไร ถ้ากระโดดเป็นก้อนละ เท่ากันทุกก้อน ความละเอียดจริงคือ ขั้น — ก้อนละ 16 ก็คือ 4096 ขั้น จดลงบันทึกการเรียน อย่าเดาจากสเปกที่ยังไม่ได้อ่าน
สิ่งที่รู้จากซอร์สเฟิร์มแวร์: ADC ของทั้งสองบอร์ดอ่านได้ 12 บิต (0-4095) แล้วเฟิร์มแวร์คูณขยายเป็น 0-65535 ก่อนส่งให้เรา — 65535 จึงเป็นสเกลของ API ไม่ใช่ความละเอียดของ ADC
"เลขใหญ่" กับ "เลขละเอียด" เป็นคนละเรื่องกัน สเกลขยายได้ แต่ความจริงที่วัดมามีอยู่เท่าเดิม

SAR ย่อมาจาก Successive Approximation Register — แปลตรงตัวคือ "ทะเบียนของการประมาณทีละขั้น"
วิธีทำงานเหมือนเกมทายเลข 1-100 ที่เราเล่นกันตอนเด็ก: เดาครึ่งทางก่อน ถ้าสูงไปก็ตัดครึ่งบนทิ้ง แล้วเดาครึ่งของที่เหลือต่อไป
ทำไมต้องรู้: เพราะการแปลงหนึ่งครั้ง กินเวลา n รอบนาฬิกา ไม่ใช่ทันที นี่คือเหตุผลที่ ADC ทุกตัวมีเพดานอัตราการสุ่ม และเป็นที่มาของกฎ Nyquist ที่เราจะเจอเต็ม ๆ ในบทเรียน 3.4–3.6

เชื่อมกับวันนี้: ตัวเลขที่ sensors.pot.read() คืนมา คือผลของการทายแบบนี้ที่จบไปแล้วเมื่อเสี้ยววินาทีก่อน ไม่ใช่แรงดัน ณ วินาทีที่เราอ่านตัวแปร
สูตรที่ทั้งสองคลิปพาไปถึง — ในลูกบิด กับ คือแทร็กสองท่อนที่ wiper แบ่งเอาไว้ หมุนไปครึ่งทางจึงได้แรงดันครึ่งหนึ่ง · ทั้งสองคลิปเป็นของนอกเวลา (ต้องมีอินเทอร์เน็ต) เนื้อหาในบทเรียนเข้าใจได้ครบโดยไม่ต้องเปิดดู
ลูกบิดคือตัวแบ่งแรงดันที่เราหมุนเปลี่ยนอัตราส่วนได้ด้วยมือ ทุกอย่างที่เหลือในชุดบทเรียนนี้ต่อยอดจากประโยคนี้
ใต้แผ่นพลาสติกของปุ่มสัมผัส (บน Eva Kit คือตรงที่เขียนว่า BTN0 / BTN1 · บน Dev Kit ตำแหน่งและป้ายของแผ่นสัมผัสยังไม่ได้บันทึกในเอกสารชุดนี้ ให้หาบนบอร์ดของทีม — ในโค้ดชื่อ btn0 btn1 slider เหมือนกันทั้งสองบอร์ด) ไม่มีปุ่มกดอยู่เลย มีแค่ แผ่นทองแดงบนแผ่นวงจร ที่เก็บประจุได้จำนวนหนึ่ง เรียกว่า capacitance ชิปจะอัดประจุเข้าไปแล้วจับเวลาว่ามันเต็มเร็วแค่ไหน
นิ้วคนเป็นตัวนำที่ต่อลงกราวด์ผ่านร่างกาย พอนิ้วเข้ามาใกล้ ค่า capacitance ของแผ่นนั้น เพิ่มขึ้น เวลาที่ใช้อัดประจุจึงนานขึ้นเล็กน้อย ชิปวัดความต่างนั้นได้ และสรุปว่า "มีนิ้ว"
แถบเลื่อนใช้หลักการเดียวกัน แต่วางแผ่นทองแดงเรียงกันหลายแผ่น แล้วดูว่านิ้วทำให้แผ่นไหนเปลี่ยนมากที่สุด เอามาถัวเฉลี่ยเป็นตำแหน่ง 0-100

ปุ่มสัมผัสไม่ได้วัด "แรงกด" มันวัด ความใกล้ของตัวนำ — นี่คือเหตุผลที่ใส่ถุงมือยางหนา ๆ แล้วมันไม่ติด

บน Eva Kit ปุ่มสองปุ่ม CSB1 / CSB2 เป็นแบบ CSX (mutual-capacitance) — สังเกตว่าแต่ละปุ่มมีขา Tx กับ Rx แยกกัน ไม่ใช่ขาเดียว ประจุถูกส่งจาก Tx ไป Rx และนิ้วเข้ามา "ขโมย" ส่วนหนึ่งไป · แถบเลื่อนคือ 5 อิเล็กโทรด (RX0-RX4) ที่ชิปถัวเฉลี่ยออกมาเป็นตำแหน่งเดียว 0-100 · ผังอิเล็กโทรดของ Dev Kit ยังไม่มีในเอกสารชุดนี้ — แต่ค่าที่โค้ดได้รับคือชุดเดียวกัน
ในโค้ดเราเห็นแค่
btn0 / btn1 / sliderสามค่า เหมือนกันทั้งสองบอร์ด — ข้างใต้มันคืออิเล็กโทรดหลายแผ่นกับชิปอีกตัวหนึ่งที่ทำงานให้ตลอดเวลา
งานสัมผัสไม่ได้ทำโดยชิปหลัก แต่ทำโดย PSoC 4000T อีกตัวหนึ่งบนบอร์ด ทำหน้าที่นี้อย่างเดียวตลอดเวลา — ทั้ง Eva Kit และ Dev Kit ใช้ทางเดียวกัน คือชิปตัวนี้ส่งค่าให้คอร์จอ (CM55) แล้ว Python ขอต่อจากคอร์จอ
หมายเหตุผู้สอน: ถ้าชิป 4000T ยังไม่ถูก flash ทุกค่าที่อ่านได้จะเป็น 255 หรือโยน
OSError— ต้องตรวจให้ครบทุกบอร์ดก่อนเข้าชุดบทเรียนนี้
ค่าความจุของแผ่นทองแดงไม่ได้คงที่ตายตัว มันเปลี่ยนตามความชื้น อุณหภูมิ และแม้แต่ฝุ่นบนหน้าจอ ชิปจึงไม่ตัดสินจากค่าดิบ แต่ตัดสินจาก ส่วนต่างเทียบกับค่าตอนไม่มีนิ้ว ค่านั้นเรียกว่า baseline
บนบอร์ดของเรา baseline ถูกเก็บ ครั้งแรกที่ไดรเวอร์อ่านชิปตัวนี้ และไดรเวอร์นั้นอยู่บนคอร์จอ ไม่ใช่ในสคริปต์ของเรา — แปลว่า baseline ถูกเก็บ ตอนบอร์ดบูต ไม่ใช่ตอนเรากด Program to Device · เผลอวางนิ้วค้างบนปุ่มตอนบูต ชิปจะจำ "สภาพมีนิ้ว" ว่าเป็นสภาพปกติ แล้วรายงานกลับด้านทั้งบทเรียน
b0, b1 = sensors.capsense.buttons() # (True/False, True/False) เทียบกับ baseline แล้ว
pos = sensors.capsense.slider() # 0 - 100
d = sensors.capsense.read() # {'btn0': bool, 'btn1': bool, 'slider': int}
เจอปุ่มรายงานกลับด้านเมื่อไร อย่าไปแก้โค้ด ให้ยกนิ้วออกให้หมดแล้ว ถอดสาย USB แล้วเสียบกลับ — บน Dev Kit ห้ามโยกสวิตช์บนฐาน สวิตช์พวกนั้นคือสวิตช์ไฟ ไม่ใช่ปุ่มรีเซ็ต · รันสคริปต์ใหม่เฉย ๆ ไม่ได้เก็บ baseline ใหม่
sensors (1/2) — สิบห้าชื่อบน Eva Kit และสองบอร์ดตอบไม่เหมือนกันสิบห้าชื่อแบ่งเป็นสองพวก — เก้าตัวเป็นฟังก์ชันที่เรียกตรงได้ และอีกหกตัวเป็นเซนเซอร์ย่อยกับตัววินิจฉัย ซึ่งมีเมธอดของตัวเองอีกชั้น · หน้านี้คือหกแถวที่ สองบอร์ดตอบเหมือนกัน ห้าตัวที่ตอบต่างกันอยู่หน้าถัดไป
| ชื่อ | ทำอะไร | บน Eva Kit | บน Dev Kit |
|---|---|---|---|
snapshot() |
ขอค่าทั้งชุดครั้งเดียว คืน dict สามกลุ่ม bmi270 capsense pot |
ทางหลัก — ค่าทั้งชุดมาจากคอร์จอ | ทางหลักเหมือนกัน dict หน้าตาเดียวกัน — IMU อ่านสดจาก CM33 · pot กับ capsense ใน snapshot มาจากคอร์จอที่อ่านทุก 200 ms (sensors.pot.read() ต่างหากที่อ่านตรง) |
read_all() |
อ่านทุกเซนเซอร์ที่มี | เรียก snapshot() ต่อให้ตรง ๆ คืนของเหมือนกันเป๊ะ |
คืน pot เป็น float ไม่ใช่ dict — คนละหน้าตากับ snapshot() |
auto_status() |
สถานะงานเบื้องหลัง คืน running rate_ms push_count mask |
เรียกได้ ใช้ดูว่ามีใครถูกเปิดไว้ | เรียกได้ |
auto_rate(ms) |
ตั้งจังหวะงานเบื้องหลัง หนีบไว้ 20-5000 ms เงียบ ๆ | เรียกได้ แต่ไม่มีผล เพราะ auto() เปิดไม่ได้ |
เรียกได้ และมีผลเมื่อ auto() เปิดอยู่ |
bmi270 bmm350 capsense pot |
สี่กลุ่มเซนเซอร์ที่มีทั้งสองบอร์ด — แต่ละตัวมีเมธอดของตัวเอง | ใช้ได้ทุกตัว | ใช้ได้ทุกตัว + มี dps368 sht40 radar เพิ่ม |
bmm350_diag bmm350_debug |
ตัววินิจฉัยเข็มทิศ ใช้ตอนหาสาเหตุว่าทำไมค่าเพี้ยน | เรียกได้ | เรียกได้ |
dps368 sht40 และ radar ไม่มีอยู่ในโมดูลเลยบน Eva Kit — พิมพ์ sensors.sht40 จะได้ AttributeError เพราะธง BSP ตั้งไว้ 0 ตั้งแต่คอมไพล์ (Eva ไม่มีชิปพวกนั้น) · บน Dev Kit สามชื่อนี้มีจริง จึงเป็นสามชื่อที่ print(dir(sensors)) บนสองบอร์ดให้ผลต่างกัน — รายชื่อบนบอร์ดคือความจริง ตารางนี้คือแผนที่
sensors (2/2) — ห้าตัวที่ Eva ปฏิเสธ และทำไมห้าในเก้าฟังก์ชันตอบต่างกันตามบอร์ด — บน Eva Kit ปฏิเสธด้วย OSError บน Dev Kit ทำงานจริง
| ชื่อ | ทำอะไร | บน Eva Kit | บน Dev Kit |
|---|---|---|---|
init() |
ปลุกเซนเซอร์และตั้งค่าบัส | OSError | ผ่าน (ไฟล์ทัวร์พิมพ์ค่าที่คืนให้ดู) — แต่ไม่ต้องเรียก เฟิร์มแวร์ปลุกให้ตั้งแต่บูต |
scan() |
ไล่หาอุปกรณ์บนบัส I2C ทีละแอดเดรส | OSError | ผ่าน คืนรายการที่อยู่ที่พบ |
push() |
ยัดค่าที่อ่านได้ข้ามไปให้คอร์จอ | OSError | ส่งค่าจริงหนึ่งครั้ง |
live_push() |
ทำแบบ push() วนไปเรื่อย ๆ |
OSError | วนไม่รู้จบจนกด Ctrl+C — อย่าเรียกเล่น |
auto() |
เปิดงานเบื้องหลังให้อ่านเซนเซอร์เอง | OSError | เปิด background task ค้างไว้ |
ห้าตัวที่ Eva ปฏิเสธ ปฏิเสธด้วยเหตุผลเดียวกันหมด ทั้งห้าจบลงที่การขับบัส SCB0 ซึ่งบน Eva คอร์จอถือไว้ ตัวที่อันตรายที่สุดคือ auto() เพราะมันไม่ได้ขับบัสเอง มันไปเปิดงานเบื้องหลังที่ขับบัสแทน อาการค้างจึงอยู่ต่อหลังบรรทัดนั้นจบไปแล้ว และไม่มี try/except ไหนช่วยได้ เพราะการค้างไม่ใช่ exception · บน Dev Kit บัส I2C ของ IMU เป็นของ CM33 เอง ห้าตัวนี้จึง "ทำงาน" — ซึ่งไม่ได้แปลว่าควรเรียก: live_push() วนจนกด Ctrl+C และ auto() เปิดงานค้างไว้หลังสคริปต์จบ
ลองเรียกเก้าตัวที่เรียกตรงได้ด้วยตัวเองที่
09_sensors_api_tour.py— มันเรียกจริงแล้ว ให้บอร์ดเป็นคนบอก ว่าใครตอบ ใครปฏิเสธ ไม่ใช่ตารางที่พิมพ์ค้างไว้ (บน Dev Kit ไฟล์นี้ตั้งใจข้ามpush()live_push()auto()ด้วยเหตุผลข้างบน)
snapshot() คืนอะไรมาบ้าง — และคำว่า sequence มีไว้ทำไมd = sensors.snapshot() # dict หน้าตาเดียวกันทั้งสองบอร์ด
d['pot'] # {'raw': 0-65535, 'percent': 0.0-100.0, 'voltage': float, 'sequence': int}
d['capsense'] # {'btn0': bool, 'btn1': bool, 'slider': 0-100, 'sequence': int}
d['bmi270'] # {'ax','ay','az' m/s2, 'gx','gy','gz' deg/s, 'sequence': int}
การเรียกครั้งเดียวได้ครบทั้งสามกลุ่ม จากการอ่านจังหวะเดียวกัน ต่างจากเรียก pot.percent() แล้ว capsense.slider() ซึ่งเป็นการถามแยกสองรอบ ได้ค่าคนละจังหวะ และช้ากว่าเท่าตัว · read_all() บน Eva Kit คืนของเดียวกับ snapshot() เป๊ะ แต่บน Dev Kit มันคืน pot เป็น float — ในคอร์สนี้ใช้ snapshot() ให้ตรงกันทั้งสองบอร์ด
ช่อง sequence คือเลขนับตัวอย่างของเซนเซอร์กลุ่มนั้น ถ้าเลขนี้ไม่ขยับระหว่างสองรอบ แปลว่าเราอ่านค่าเดิมซ้ำ ไม่ใช่ว่าโลกหยุดนิ่ง — บน Eva Kit คอร์จออ่านทุก 200 ms ถ้าลูปของเราเร็วกว่านั้น เราจะเจอค่าเดิมแน่นอน (บน Dev Kit ค่า IMU ใน snapshot อ่านสดจาก CM33 ส่วน pot กับ capsense ยังมาจากคอร์จอทุก 200 ms ตัวเลขจึงเดินคนละจังหวะกัน) นี่คือเครื่องมือที่บอกได้ว่าจังหวะลูปเราเร็วเกินความจริงของข้อมูลหรือยัง
ยังมีอีกสองชื่อสำหรับงานซ่อม sensors.bmm350_diag() คืน dict สิบสองช่องสำหรับไล่ปัญหาเข็มทิศ และ sensors.bmm350_debug() พิมพ์ค่ารีจิสเตอร์ออกคอนโซล ทั้งคู่เป็นเครื่องมือของผู้สอนตอนบอร์ดมีปัญหา ไม่ใช่ของที่ใช้ในงานปกติ — และทั้งคู่ หยุดงานเบื้องหลังแล้ว re-init ชิป จึงกินเวลาและกวนค่าที่กำลังอ่านอยู่
read_all()บน Eva Kit เป็นบทเรียนเงียบ ๆ อีกข้อ: ชื่อที่ฟังดูทรงพลังกว่า ไม่ได้แปลว่าทำมากกว่า — เปิดซอร์สดูจึงรู้ว่ามันคือบรรทัดเดียวที่เรียกsnapshot()ต่อ (บน Dev Kit มันเป็นคนละฟังก์ชันและคืนpotเป็น float)
บทเรียน 2.4–2.6 คือ "จอสั่งฮาร์ดแวร์" บทเรียน 2.7–2.9 คือ "ฮาร์ดแวร์สั่งจอ" — ทิศทางข้อมูลกลับด้านกัน