OpenMV Pure Thermal¶
OpenMV Pure Thermal คือบอร์ดถ่ายภาพความร้อนแบบระบบสมบูรณ์ที่สร้างบน STMicroelectronics STM32H743 (Cortex‑M7 @ 480 MHz) พร้อม SDRAM ภายนอก 64 MB, แฟลช QSPI 32 MB, ตัวแปลงสัญญาณ JPEG แบบฮาร์ดแวร์, จอสัมผัสแบบ capacitive IPS 4.3" ขนาด 800×480, ช่องออก HDMI, ซ็อกเก็ต FLIR® Lepton® สำหรับกล้องความร้อน และกล้องแสงปกติ OV5640 ขนาด 5MP นอกจากนี้ยังมี Wi‑Fi, ช่องเสียบ microSD, เครื่องวัดระยะด้วยเลเซอร์, บัซเซอร์ และหลอด LED สีขาวกำลังสูง
สำหรับข้อมูลแผ่นข้อมูล รูปถ่าย และขนาด โปรดดูที่ หน้าผลิตภัณฑ์ OpenMV Pure Thermal
คุณสมบัติเด่น¶
STMicroelectronics STM32H743XI Cortex‑M7 ที่ 480 MHz
ตัวแปลงสัญญาณ JPEG encoder/decoder แบบฮาร์ดแวร์
SDRAM ภายนอก 64 MB (~400 MB/s) บวก SRAM ภายใน 1 MB
แฟลชภายใน 2 MB + แฟลช QSPI ภายนอก 32 MB (~50 MB/s อ่าน)
เซนเซอร์แสงปกติแบบ rolling‑shutter OV5640 ขนาด 5MP
ซ็อกเก็ต FLIR® Lepton® — รองรับ Lepton รุ่น 1/2/2.5/3/3.5 ทั้งแบบ radiometric และ non‑radiometric พร้อมอุณหภูมิต่อพิกเซลเป็นองศาเซลเซียส
จอสัมผัสแบบ capacitive IPS 4.3" ขนาด 800×480 (สี 24 บิต @ 60 Hz) รองรับท่าทางสัมผัสได้สูงสุด 5 จุด
ช่องออก HDMI ผ่าน TFP410 DVI serializer — สูงสุด 1280×720 @ 60 Hz
Wi‑Fi ผ่าน WINC1500; รองรับ MJPEG over RTSP แบบพร้อมใช้งานทันที
USB‑C ความเร็วเต็ม (12 Mb/s, จำกัดกระแส 900 mA) — ปรากฏเป็น VCP + USB mass storage ต่อโฮสต์ รวมถึงรองรับการชาร์จด้วย
ช่องเสียบ microSD — SD สูงสุด 2 GB, SDHC สูงสุด 32 GB, SDXC สูงสุด 2 TB
เครื่องวัดระยะเลเซอร์ VL53L1CX (สูงสุด ~4 ม.)
บัซเซอร์ ที่ควบคุมระดับเสียง/ความถี่ด้วยซอฟต์แวร์
หลอด LED สีขาวกำลังสูง นอกเหนือจาก LED แสดงสถานะ RGB ของผู้ใช้
ขั้วต่อแบตเตอรี่ LiPo พร้อมการชาร์จผ่าน USB ที่ 500 mA
พิน I/O จำนวน 10 พิน, รองรับ 5 V ทนได้ มีแรงดันเอาต์พุต 3.3 V, 25 mA ต่อพิน (รวม 120 mA), รองรับอินเทอร์รัปต์ P6 ไม่ รองรับ 5 V เมื่อใช้ในโหมด ADC หรือ DAC
ARM 10‑pin SWD สำหรับการดีบัก ST‑LINK / J‑Link
ขั้วต่อ Qwiic สำหรับอุปกรณ์ต่อพ่วง I²C
Note
บอร์ดมีช่องที่ขอบล่างซ้ายสำหรับใส่ น็อตขาตั้งกล้อง ¼"–20 แบบเสริม ไม่ได้ติดมาจากโรงงาน — บัดกรีเข้าในช่องถ้าต้องการติดบอร์ดบนขาตั้งกล้องมาตรฐาน
การกำหนดพิน¶
ข้อมูลอ้างอิงพิน¶
ชื่อพิน |
ฟังก์ชัน |
|---|---|
P0 |
UART1 RX / SPI2 MOSI |
P1 |
UART1 TX / SPI2 MISO |
P2 |
SPI2 SCK / FDCAN2 TX |
P3 |
SPI2 NSS (CS) / FDCAN2 RX |
P4 |
I2C2 SCL / UART3 TX / TIM2 CH3 |
P5 |
I2C2 SDA / UART3 RX / TIM2 CH4 |
P6 |
ADC / DAC / TIM2 CH1 |
P7 |
I2C4 SCL / TIM4 CH1 |
P8 |
I2C4 SDA / TIM4 CH2 |
P9 |
digital I/O |
RESET |
ดึงไปที่ GND เพื่อรีเซ็ตบอร์ด |
SYN |
แพด frame‑sync — ไม่ได้ต่อเชื่อม |
VIN |
แพด shield VIN — ไม่ได้ต่อเชื่อม |
BOOT0 |
ดึงไปที่ 3.3 V ขณะเปิดเครื่องเพื่อเข้า DFU / ROM bootloader |
BUZZER |
บัซเซอร์ piezo บนบอร์ด (ขับด้วย TIM2/PWM) |
LED_RED |
ช่องแดงของ LED แสดงสถานะ RGB (active low) |
LED_GREEN |
ช่องเขียวของ LED แสดงสถานะ RGB (active low) |
LED_BLUE |
ช่องน้ำเงินของ LED แสดงสถานะ RGB (active low) |
LED_WHITE |
หลอด LED สีขาวกำลังสูง |
Note
แพด SYN และ VIN บน shield/header ไม่มีการเชื่อมต่อทางไฟฟ้า บน Pure Thermal — มีไว้เพื่อความเข้ากันได้ของ header เท่านั้น จ่ายไฟให้บอร์ดผ่าน USB‑C หรือขั้วต่อแบตเตอรี่ LiPo บนบอร์ดแทน (ดู พินจ่ายไฟ ด้านล่าง) นอกจากนี้ แพด VIN มีการพิมพ์บนบอร์ดว่า VBAT (เป็นข้อผิดพลาดในการระบุชื่อ) — ตำแหน่งเป็นพิน VIN ของ header OpenMV มาตรฐานและไม่ได้ต่อเชื่อมไม่ว่าทิศทางใด
พินจ่ายไฟ¶
3.3V — ราง 3.3 V ที่ผ่านการปรับแรงดัน มีให้สูงสุด 250 mA สำหรับ shield
GND — กราวด์ร่วม
Pure Thermal รับไฟผ่าน USB‑C หรือ ขั้วต่อแบตเตอรี่ LiPo บนบอร์ด พอร์ต USB‑C จำกัดกระแสรวมไว้ที่ 900 mA และรองรับการชาร์จ LiPo ที่ 500 mA ดังนั้นสามารถต่อแบตเตอรี่พร้อมกับ USB ได้
ปุ่มเปิด/ปิด บนบอร์ดสลับเปิด/ปิดรางไฟฟ้าของระบบ และทำงานได้ไม่ว่าจะจ่ายไฟจาก USB หรือ LiPo กดปุ่มค้างไว้สักสองสามวินาที เพื่อสลับสถานะ — การกดเบาจะถูกละเว้นเพื่อป้องกันการปิดเครื่องโดยไม่ตั้งใจ
การเลือกแหล่งจ่ายไฟทำตามกฎง่าย ๆ สองข้อ:
แบตเตอรี่จะจ่ายไฟให้บอร์ดก็ต่อเมื่อแรงดันสูงกว่า 3 V ต่ำกว่าค่าขีดแบ่งนั้น PMIC บนบอร์ดจะตัดแบตเตอรี่ออกเพื่อป้องกันการคายประจุมากเกินไป
เมื่อมี USB ต่ออยู่ USB จะจ่ายไฟให้บอร์ด และ LiPo ที่ต่ออยู่จะชาร์จในเบื้องหลัง
ขั้วต่อ LiPo ยังมี การป้องกันแรงดันย้อนกลับ ดังนั้นการเสียบแบตเตอรี่กลับด้านจะไม่ทำให้บอร์ดเสียหาย
Note
บอร์ดยังส่ง แรงดันแบตเตอรี่ และ สัญญาณวัดกระแสแบตเตอรี่ กลับไปยังช่อง ADC ของ MCU แต่ยังไม่มีการเพิ่มการรองรับเฟิร์มแวร์สำหรับทั้งสองอย่าง
พินสำหรับการกู้คืนและดีบัก¶
RESET — ดึงไปที่ GND เพื่อรีเซ็ตบอร์ด Pure Thermal ยังมี ปุ่ม RESET บนบอร์ดที่ทำงานเหมือนกัน
BOOT0 — ดึงไปที่ 3.3 V ขณะเปิดเครื่องเพื่อเข้าสู่ ROM bootloader ของ STM32 (โหมด DFU) OpenMV IDE ใช้โหมดนี้ในการเขียน bootloader บนบอร์ดใหม่ ปุ่ม BOOT0 บนบอร์ดทำงานเหมือนกัน — กดค้างขณะเปิดเครื่อง
บอร์ดมีหัวต่อดีบัก SWD (RST / SWCLK / SWDIO / SWO) อยู่ถัดจากหัวต่อ GPIO เข้ากันได้กับอะแดปเตอร์ ST‑LINK และ SEGGER J‑Link นอกจากนี้ยังมีขั้วต่อ ARM 10‑pin SWD แบบแยกติดตั้งอยู่ด้วย — มีสัญญาณ SWD เหมือนกัน (ไม่มี JTAG เต็มรูปแบบ) แต่ในรูปแบบ 0.05" 10‑pin มาตรฐาน
Note
พิน trace SWO ใช้ร่วมกับสัญญาณนาฬิกา SPI ของ FLIR® Lepton® บนบอร์ด ไม่สามารถใช้ SWO พร้อมกับ Lepton — ต้องเลือกอย่างใดอย่างหนึ่ง
ขั้วต่อ PURE Modules Debug ตัวที่สามติดตั้งอยู่บนบอร์ด โดยแยกสัญญาณที่เน้นการดีบักออกมาหลายสัญญาณ (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3.3 V, GND และพิน GPIO สองพิน) สำหรับเชื่อมต่อโมดูลเสริม พิน GPIO สองพินบนขั้วต่อนี้ขับเคลื่อนโดย I²C bus แบบ bit‑banged แทนที่จะเป็นอุปกรณ์ต่อพ่วงฮาร์ดแวร์
ขั้วต่อดีบักทั้งสาม (หัวต่อ SWD แบบแนว, ขั้วต่อ ARM 10‑pin SWD และขั้วต่อ PURE Modules Debug) อ้างอิง 3.3 V — ตรวจสอบให้แน่ใจว่าอะแดปเตอร์ดีบักของคุณถูกตั้งค่าสำหรับลอจิก 3.3 V ก่อนเชื่อมต่อ
อุปกรณ์ต่อพ่วงบนบอร์ด¶
LED¶
Pure Thermal มี LED สามดวงบนบอร์ด:
LED RGB สำหรับผู้ใช้ — ควบคุมด้วยซอฟต์แวร์ เข้าถึงได้ผ่าน
LED_RED,LED_GREENและLED_BLUEfrom machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
หลอด LED สีขาว — ขับเคลื่อนผ่าน
LED_WHITELED_WHITEต่อสายแบบ active high ในฮาร์ดแวร์ ในขณะที่เฟิร์มแวร์ถือว่า LED บนบอร์ดอื่น ๆ ทุกดวงเป็น active low ดังนั้นใช้low()/high()แทนon()/off()(ซึ่งจะกลับทิศตรรกะ):from machine import LED light = LED("LED_WHITE") light.low() # turn the white LED ON light.high() # turn the white LED OFF
LED ชาร์จ — ขับเคลื่อนโดยตรงจากฮาร์ดแวร์จัดการพลังงานบนบอร์ด ไม่มีการควบคุมด้วยซอฟต์แวร์ ทำงานได้ไม่ว่ารางระบบจะเปิดหรือปิด (คือไม่ว่าปุ่มเปิด/ปิดจะอยู่ตำแหน่งใด)
สี
ความหมาย
น้ำเงิน
กำลังชาร์จ — ดูข้อผิดพลาด: อาจไม่ดับเมื่อชาร์จเสร็จ
เขียว
ชาร์จเสร็จแล้ว — ดูข้อผิดพลาด: อาจไม่ทำงานได้อย่างน่าเชื่อถือ
แดง
แบตเตอรี่เหลือน้อย (≤ 3.2 V, เฉพาะเมื่อไม่ได้ชาร์จอยู่)
บัซเซอร์¶
บัซเซอร์ piezo บนบอร์ดต่อสายไปยังช่องตัวจับเวลา — ขับด้วย machine.PWM เพื่อสร้างเสียงที่มีการควบคุมความถี่ (ระดับเสียง) และรอบดิวตี้ (ระดับเสียง) ด้วยซอฟต์แวร์:
import time
from machine import Pin, PWM
beep = PWM(Pin("BUZZER"), freq=2_000, duty_u16=32768) # ~50% duty
time.sleep_ms(500) # sound for 0.5 s
beep.deinit()
เซนเซอร์กล้อง¶
OV5640 เป็น CSI หลักบน Pure Thermal — ส่ง cid=csi.OV5640 เพื่อระบุตำแหน่งอย่างชัดเจน:
import csi
cam = csi.CSI(cid=csi.OV5640)
cam.reset(hard=True)
cam.pixformat(csi.RGB565)
cam.framesize(csi.WVGA)
cam.snapshot(time=2000) # let auto‑exposure settle
while True:
img = cam.snapshot()
OV5640 มีตัวบีบอัด JPEG บนบอร์ด ตั้งค่า csi.CSI.pixformat เป็น csi.JPEG แล้วเซนเซอร์จะส่งเฟรมที่บีบอัดแล้วไปยังกล้องโดยตรงผ่านบัสกล้อง ซึ่งทำให้การถ่ายภาพความละเอียดสูงเป็นเรื่องปฏิบัติได้จริง: csi.HD (1280×720), csi.FHD (1920×1080) และ 5MP เต็ม csi.WQXGA2 (2592×1944) สตรีมได้ในรูปแบบ JPEG ปรับการบีบอัดด้วย csi.CSI.quality (0-100 ค่าสูงกว่า = เฟรมใหญ่กว่า รายละเอียดมากกว่า):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
OV5640 มีเลนส์โฟกัสอัตโนมัติแบบ voice‑coil‑actuator เรียกโฟกัสอัตโนมัติแบบครั้งเดียวผ่าน csi.CSI.ioctl พร้อม csi.IOCTL_TRIGGER_AUTO_FOCUS — เซนเซอร์จะกวาดมอเตอร์โฟกัสครั้งเดียวและล็อคที่สิ่งที่อยู่ตรงหน้า:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
เรียก ioctl ซ้ำทุกครั้งที่ฉากเปลี่ยน — โฟกัสอัตโนมัติเป็นแบบครั้งเดียว ไม่ใช่ต่อเนื่อง
Note
เอาต์พุต STROBE ของ OV5640 (ใช้สำหรับแฟลช/ไฟ IR แบบซิงโครไนซ์) ต่อสายไปยัง MCU บน Pure Thermal แต่ยังไม่มีการเพิ่มการรองรับเฟิร์มแวร์สำหรับมัน
เซนเซอร์กล้องความร้อน¶
ซ็อกเก็ต FLIR® Lepton® ปรากฏเป็น CSI ตัวที่สองบน API เดียวกัน csi --- เซ็นเซอร์กล้อง ส่ง cid=csi.LEPTON เพื่อระบุตำแหน่ง และข้ามการรีเซ็ตฮาร์ดแวร์:
import csi
lepton = csi.CSI(cid=csi.LEPTON)
lepton.reset(hard=False)
lepton.pixformat(csi.GRAYSCALE)
lepton.framesize(csi.QVGA)
while True:
img = lepton.snapshot()
Note
เอาต์พุต VSYNC ของ Lepton (หนึ่งพัลส์ต่อเฟรมความร้อน) ต่อสายไปยัง MCU บน Pure Thermal แต่ยังไม่มีการเพิ่มการรองรับเฟิร์มแวร์สำหรับมัน
CSI ทั้งสองสามารถทำงานพร้อมกันได้ ตัวอย่างด้านล่างดึงเฟรมสีจาก OV5640 และเฟรมความร้อนจาก Lepton จากนั้นซ้อนทับ Lepton ไว้บนเฟรมสีโดยใช้พาเลต Ironbow และมาสก์อัลฟ่าที่จางลงเป็นโปร่งใสที่ความเข้มต่ำ:
import csi
import image
import math
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow((i / 255), 2) * 255)
csi0 = csi.CSI()
csi0.reset(hard=True)
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.WVGA)
csi1 = csi.CSI(cid=csi.LEPTON)
csi1.reset(hard=False)
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize(csi.QVGA)
img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())
while True:
img0 = csi0.snapshot()
csi1.snapshot(blocking=False, image=img1)
img0.draw_image(
img1, 0, 0,
color_palette=image.PALETTE_IRONBOW,
alpha_palette=alpha_pal,
hint=image.BILINEAR,
)
การเรียนรู้ของเครื่อง¶
ml --- Machine Learning รันโมเดล TFLite แบบ quantised บน Cortex‑M7 ด้วยเคอร์เนล CMSIS‑NN — เร็วพอสำหรับตัวตรวจจับขนาดกะทัดรัดที่สักสองสามเฟรมต่อวินาที โมเดลในระบบไฟล์แบบอ่านอย่างเดียว /rom โหลดโดยตรงจากแฟลชโดยไม่ต้องคัดลอกไปยัง RAM นี่คือตัวตรวจจับใบหน้า BlazeFace ขนาด 128×128 ที่ซ้อนทับใบหน้าที่ตรวจพบและจุดสำคัญ 6 จุดบนทุกเฟรมจากกล้องแสงปกติ:
import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace
# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))
# Load built-in face detection model
model = ml.Model("/rom/blazeface_front_128.tflite", postprocess=BlazeFace(threshold=0.4))
print(model)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
# faces is a list of ((x, y, w, h), score, keypoints) tuples
for r, score, keypoints in model.predict([img]):
ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)
# keypoints is a ndarray of shape (6, 2)
# 0 - right eye (x, y)
# 1 - left eye (x, y)
# 2 - nose (x, y)
# 3 - mouth (x, y)
# 4 - right ear (x, y)
# 5 - left ear (x, y)
ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))
print(clock.fps(), "fps")
เครื่องวัดระยะเลเซอร์¶
ST VL53L1CX time‑of‑flight ranger บนบอร์ดต่อสายไปยัง I²C bus 2 ใช้ไดรเวอร์แช่แข็ง vl53l1x --- ไดรเวอร์เซนเซอร์วัดระยะ VL53L1X ToF เพื่อรับค่าระยะทางสูงสุด ~4 ม.:
import time
from machine import I2C
import vl53l1x
bus = I2C(2)
tof = vl53l1x.VL53L1X(bus)
while True:
print("Distance:", tof.read(), "mm")
time.sleep_ms(100)
เอาต์พุต LCD¶
LCD บนบอร์ดขนาด 4.3" มีความละเอียด 800 × 480 (WVGA) และขับเคลื่อนผ่านอินเทอร์เฟซจอแสดงผล RGB ของโมดูล display --- ไดรเวอร์ดิสเพลย์ — ส่ง framesize=display.FWVGA เพื่อให้ตรงกับความละเอียดดั้งเดิม:
import display
lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True) # turn the LCD backlight on
lcd.write(img)
แบ็คไลท์ต่อสายไปยัง GPIO ดังนั้น backlight() รับ True / False (หรือค่าใด ๆ ระหว่าง 0–100 โดย 0 คือปิด และค่าที่ไม่ใช่ศูนย์คือเปิด):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
จอสัมผัส¶
ตัวควบคุมการสัมผัสแบบ capacitive คือ FT5X06; ตำแหน่งการสัมผัสหลายจุดและเหตุการณ์ท่าทางมือถูกเปิดเผยผ่าน ft5x06 --- ไดรเวอร์หน้าจอสัมผัส ลงทะเบียนคอลแบ็กเพื่อตอบสนองต่อการสัมผัสและอ่านจุดที่ใช้งานอยู่ภายใน:
import ft5x06
touch = ft5x06.FT5X06()
def on_touch(n):
for i in range(n):
x = touch.get_point_x(i)
y = touch.get_point_y(i)
print("touch", i, "at", x, y)
gesture = touch.get_gesture()
if gesture != ft5x06.GESTURE_NONE:
print("gesture:", gesture)
touch.touch_callback(on_touch)
เอาต์พุต HDMI¶
เฟิร์มแวร์ยังแจกจ่าย framebuffer ของ LCD ไปยัง tfp410 --- ตัวควบคุม DVI/HDMI HDMI serializer บนบอร์ดด้วย ทำให้จอภาพภายนอกสะท้อนสิ่งที่อยู่บน LCD สร้าง tfp410.TFP410 เพื่อเปิดใช้งานเอาต์พุต HDMI:
import tfp410
hdmi = tfp410.TFP410()
หากต้องการเฉพาะเอาต์พุต HDMI และไม่สนใจ LCD บนบอร์ด ให้ปิดแบ็คไลท์และเพิ่มความละเอียด framebuffer ให้เกิน WVGA TFP410 รองรับสูงสุด 1280×720 @ 60 Hz ตัวอย่างเช่น:
lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False) # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()
แผงบนบอร์ดมีความละเอียดคงที่ที่ 800×480 ดังนั้นอะไรก็ตามที่เกิน WVGA จะมีความหมายเฉพาะบนจอภาพ HDMI ภายนอกเท่านั้น
เพื่อทราบเมื่อจอภาพ HDMI ถูกเสียบหรือถอดออก ให้ลงทะเบียนคอลแบ็ก hot‑plug บน TFP410 คอลแบ็กจะทำงานด้วย True เมื่อเชื่อมต่อ และ False เมื่อตัดการเชื่อมต่อ:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
คุณยังสามารถโพลสถานะการเชื่อมต่อได้ทุกเมื่อด้วย isconnected() (เฉพาะเมื่อไม่มีการลงทะเบียนคอลแบ็ก)
พอร์ต HDMI ยังรองรับช่อง DDC (ข้อมูลการแสดงผล) และ CEC (การควบคุมอิเล็กทรอนิกส์สำหรับผู้บริโภค) เปิดเผยผ่านคลาส คลาส DisplayData -- ข้อมูลดิสเพลย์ ใช้มันเพื่ออ่านบล็อก EDID ของจอภาพที่เชื่อมต่ออยู่ (เพื่อให้ปรับตัวตามความละเอียด/อัตราการรีเฟรชดั้งเดิม) หรือเพื่อส่ง/รับเฟรม CEC สำหรับควบคุมอุปกรณ์ HDMI อื่น ๆ บนสายเดียวกัน:
from display import DisplayData
dd = DisplayData(cec=True, ddc=True)
edid = dd.display_id() # EDID bytes from the monitor
print(len(edid), "byte EDID")
# Send a CEC "image view on" command (opcode 0x04) from address 1 to address 0
dd.send_frame(0, 1, b"\x04")
# ...or wait for an incoming CEC frame addressed to us (logical address 1)
src, data = dd.receive_frame(1, timeout=5_000)
print("CEC from", src, ":", data)
Wi‑Fi¶
Wi‑Fi ทำงานผ่านโมดูล Microchip WINC1500 เปิดเผยผ่านอินเทอร์เฟซ class WINC -- ไดรเวอร์ WiFi shield
import network, time
wlan = network.WINC()
wlan.connect("ssid", "password")
while not wlan.isconnected():
time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])
Note
เนื่องจากปัญหาการขาดแคลนชิ้นส่วน บาง Pure Thermal ถูกจัดส่งโดยไม่มีโมดูล WINC1500 ติดตั้ง หาก network.WINC ทำให้เกิดข้อผิดพลาดหรือเชื่อมต่อไม่ได้ ให้ตรวจสอบบอร์ดว่าขาดโมดูล Wi‑Fi — ส่วนที่เหลือของกล้องทำงานได้เหมือนกันทุกอย่างโดยไม่มีมัน
การ์ด microSD¶
เมื่อใส่การ์ดจะถูก mount อัตโนมัติที่ /sdcard และสามารถใช้งานผ่านระบบไฟล์ปกติ:
import os
for entry in os.listdir("/sdcard"):
print(entry)
ข้อมูลอ้างอิงบัส¶
GPIO¶
ใช้ machine.Pin เพื่ออ่านหรือขับพินที่มีชื่อบนบอร์ด เอาต์พุตเป็น 3.3 V CMOS รองรับ 5 V ในด้านอินพุต และสามารถ sink/source ได้สูงสุด 25 mA ต่อพิน (รวม 120 mA ทั่วทั้ง header)
from machine import Pin
out = Pin("P0", Pin.OUT)
out.on()
out.off()
out.value(1)
inp = Pin("P1", Pin.IN, Pin.PULL_UP)
print(inp.value())
พินอินพุตใด ๆ ยังสามารถเรียกอินเทอร์รัปต์บนการเปลี่ยนขอบสัญญาณได้:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
บัส |
TX |
RX |
|---|---|---|
UART1 |
P1 |
P0 |
UART3 |
P4 |
P5 |
from machine import UART
uart = UART(3, baudrate=115200)
uart.write("hello")
uart.read(5)
I²C¶
บัส |
SCL |
SDA |
|---|---|---|
I2C2 |
P4 |
P5 |
I2C4 |
P7 |
P8 |
from machine import I2C
i2c = I2C(2, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")
ฮาร์ดแวร์เดียวกันยังสามารถใช้ในโหมด target (slave) ผ่าน machine.I2CTarget เพื่อเปิดเผยพื้นที่หน่วยความจำให้กับตัวควบคุม I²C อื่น:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
ขั้วต่อ Qwiic บนบอร์ดแยกบัส I²C ตัวหนึ่งเหล่านี้ออกมาสำหรับโมดูลแบบ plug‑and‑play สายอนุกรม Qwiic ถูก level-shifted เป็น 5 V ผ่านทรานซิสเตอร์แบบ open‑drain ดังนั้นบัสจำกัดเฉพาะ โหมดมาตรฐาน (100 kHz) และ โหมดเร็ว (400 kHz) เท่านั้น — อย่าพยายามรันโหมดเร็วพิเศษหรืออัตราสูงกว่าผ่าน Qwiic header
ขั้วต่อ Qwiic จ่าย 5 V เพื่อขับโมดูลที่ต่ออยู่; ไม่สามารถใช้จ่ายไฟให้ Pure Thermal เอง — จ่ายไฟให้บอร์ดผ่าน USB‑C หรือขั้วต่อแบตเตอรี่ LiPo แทน
SPI¶
บัส |
MOSI |
MISO |
SCK |
CS |
|---|---|---|---|---|
SPI2 |
P0 |
P1 |
P2 |
P3 |
from machine import SPI
from machine import Pin
spi = SPI(2, baudrate=10_000_000)
cs = Pin("P3", Pin.OUT, value=1) # CS is not driven by the SPI peripheral
cs.value(0)
spi.write(b"hello")
cs.value(1)
CAN (FDCAN)¶
บัส |
TX |
RX |
|---|---|---|
FDCAN2 |
P2 |
P3 |
from machine import CAN
can = CAN(2, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())
ADC และ DAC¶
P6 เป็นพินอนาล็อกสำหรับผู้ใช้เพียงพินเดียว สามารถใช้เป็นอินพุต ADC 12 บิตหรือเอาต์พุต DAC ได้
ADC — สเกลเต็มที่ 3.3 V ที่พิน:
from machine import ADC import time adc = ADC("P6") while True: voltage = adc.read_u16() * 3.3 / 65535 print(voltage) time.sleep_ms(100)
DAC — ผ่าน
pyb.DACค่า 8 บิตครอบคลุม 0–3.3 V:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
ในโหมด ADC หรือ DAC P6 รองรับเฉพาะ 3.3 V เท่านั้น — ห้ามป้อน 5 V
PWM¶
พิน |
ตัวจับเวลา / ช่อง |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Note
TIM1 ถูกสงวนไว้ โดยเฟิร์มแวร์เพื่อสร้างสัญญาณนาฬิกาพิกเซลของเซนเซอร์กล้อง ดังนั้นช่อง TIM1 ที่อยู่บน P0/P1/P2 ทางกายภาพจึงไม่สามารถใช้สำหรับ PWM ของผู้ใช้โดยไม่ทำให้กล้องเสียหาย
TIM4 ใช้ร่วมกับ pyb.Servo — การสร้าง servo จะตั้งค่าตัวจับเวลาทั้งหมดใหม่เป็นโหมด 50 Hz ดังนั้นอย่าผสม machine.PWM บน P7/P8 กับ pyb.Servo ในสคริปต์เดียวกัน
ขับใด ๆ ของพวกมันผ่าน machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
บัสแบบ Software bit‑banged¶
machine.SoftI2C และ machine.SoftSPI ทำงานบน GPIO ใด ๆ หากต้องการบัสเพิ่มเติม
เซนเซอร์ความร้อน (ภายนอกบอร์ด)¶
นอกเหนือจาก FLIR Lepton บนบอร์ด เฟิร์มแวร์ยังรวมไดรเวอร์ fir --- ไดรเวอร์เซนเซอร์ความร้อน (fir == far infrared) สำหรับเครื่องถ่ายภาพความร้อน I²C แบบต่อสายภายนอก:
MLX90621 — IR array 16 × 4
MLX90640 — IR array 32 × 24
MLX90641 — IR array 16 × 12
AMG8833 — IR array 8 × 8
ต่อสายโมดูลเข้ากับบัส I²C ของบอร์ดและอ่านเฟรมด้วย fir.init() + fir.snapshot()
import time
import image
import fir
fir.init() # auto‑detects the sensor
clock = time.clock()
while True:
clock.tick()
try:
img = fir.snapshot(x_scale=5, y_scale=5,
color_palette=image.PALETTE_IRONBOW,
hint=image.BICUBIC,
copy_to_fb=True)
except OSError:
continue
print(clock.fps())
ไดรเวอร์ fir สื่อสารกับเซนเซอร์ผ่าน I²C 2 เท่านั้น — ต่อสายโมดูลเข้ากับ P4 (SCL) และ P5 (SDA)
เวลา¶
time¶
import time
time.sleep(1)
time.sleep_ms(500)
time.sleep_us(10)
start = time.ticks_ms()
elapsed = time.ticks_diff(time.ticks_ms(), start)
ตัวจับเวลาเสมือน¶
from machine import Timer
one_shot = Timer(-1)
one_shot.init(period=5_000, mode=Timer.ONE_SHOT,
callback=lambda t: print("once"))
periodic = Timer(-1)
periodic.init(period=2_000, mode=Timer.PERIODIC,
callback=lambda t: print("tick"))
ค่า Period เป็นมิลลิวินาที เรียก deinit() เพื่อหยุดและคืนสล็อต
นาฬิกาแบบเรียลไทม์¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
หากต่อแบตเตอรี่ LiPo ไว้ RTC จะเก็บเวลาไว้แม้ขณะที่รางระบบปิดอยู่ (ปิดผ่านปุ่มเปิด/ปิดบนบอร์ด) หากเสียบเฉพาะ USB การกดปุ่มเปิด/ปิดจะตัดไฟไปยัง RTC เช่นกัน — ดังนั้นเวลาจากนาฬิกาจะไม่คงอยู่หลังวงจรไฟฟ้าโดยไม่มีแบตเตอรี่ต่ออยู่
Watchdog¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
ข้อมูลการบูตและรันไทม์¶
หน้าต่าง USB bootloader¶
ในทุกการเปิดเครื่อง กล้องจะรัน bootloader สั้น ๆ (สักสองสามวินาที) ที่ให้ OpenMV IDE อัปเดตเฟิร์มแวร์โดยไม่ต้องให้ผู้ใช้เข้าโหมด DFU หลังจากหน้าต่างหมดเวลา bootloader จะส่งต่อไปยัง boot.py แล้วจึง main.py
สคริปต์ที่กำลังทำงานสามารถกลับเข้าสู่ bootloader ได้ตามต้องการโดยเรียก machine.bootloader()
ระบบไฟล์และลำดับการบูต¶
เฟิร์มแวร์ Pure Thermal mount ระบบไฟล์สูงสุดสามระบบเมื่อบูต:
แฟลชภายใน — mount ที่
/flashเสมอ เก็บmain.pyและREADME.txtตามค่าเริ่มต้น; สร้างในการบูตครั้งแรกการ์ด microSD — หากใส่การ์ดแล้วจะถูก mount ที่
/sdcardROMFS — ระบบไฟล์แบบ memory‑mapped อ่านอย่างเดียวที่
/romใช้สำหรับส่งมอบข้อมูลขนาดใหญ่ (เช่น โมเดล AI) ที่ได้ประโยชน์จากการเข้าถึงแบบ zero‑copy Mount อัตโนมัติโดย MicroPython เมื่อเริ่มต้น ก่อนที่ Python ของผู้ใช้จะทำงาน
หลังจาก mount แล้ว working directory จะถูกตั้งเป็น /sdcard เมื่อมีการ์ดอยู่ มิฉะนั้น /flash จากนั้น interpreter จะรันสคริปต์จากไดเรกทอรีนั้น:
boot.pyถูกรันบน ทุก การ soft resetmain.pyถูกรันเฉพาะ เมื่อบูตเย็น เท่านั้น ทันทีหลังจากboot.py
การวาง boot.py หรือ main.py ลงบนการ์ด SD จะแทนที่ไฟล์ที่อยู่ใน flash โดยไม่แตะต้องมัน
เมื่อเชื่อมต่อผ่าน USB ระบบไฟล์บูต (/sdcard หากมีการ์ดอยู่ มิฉะนั้น /flash) จะแสดงเป็น USB mass‑storage drive บนโฮสต์ด้วย Eject drive ก่อนรีเซ็ตกล้อง เพื่อให้โฮสต์ flush การเขียนที่แคชไว้
Note
ไฟล์ที่สร้างหรือแก้ไขโดยโค้ดที่รันบน OpenMV Cam จะไม่แสดงบนโฮสต์จนกว่า drive จะถูก mount ใหม่ ใช้การ์ด SD สำหรับข้อมูลใด ๆ ที่สคริปต์เขียนกลับ และ mount ใหม่ก่อนอ่านไฟล์เหล่านั้นจากโฮสต์
ขนาดพื้นที่เก็บข้อมูล¶
Pure Thermal จัดส่งพร้อม:
/flash— ระบบไฟล์ FAT 24 MB อ่าน/เขียน/rom— ROMFS แบบ memory‑mapped อ่านอย่างเดียว 8 MB ใช้สำหรับส่งมอบสคริปต์และโมเดล ML ที่ได้ประโยชน์จากการเข้าถึง mmap แบบ zero‑copy/sdcard— ขนาดเต็มของการ์ด microSD ที่ใส่อยู่ (เมื่อมีอยู่) อ่าน/เขียน
ตัวบ่งชี้ hard‑fault¶
หาก LED RGB ของผู้ใช้วนรอบสีต่าง ๆ อย่างรวดเร็ว — เร็วพอที่จะดูเหมือน LED ขาวระยิบระยับ มากกว่าสีที่แตกต่างกัน — เฟิร์มแวร์ได้เกิด hard fault ที่กู้คืนไม่ได้ ให้ reflash เฟิร์มแวร์เพื่อกู้คืน
ข้อผิดพลาดของฮาร์ดแวร์¶
ข้อบกพร่องระดับบอร์ดบางประการมีการบันทึกไว้ใน ข้อผิดพลาดฮาร์ดแวร์ Pure Thermal รายการสำคัญที่ควรทราบ:
การรบกวนจากขั้วต่อแบตเตอรี่ — ชิ้นส่วนบน PCB อยู่ใต้ขั้วต่อแบตเตอรี่ LiPo โดยตรง และลิ่มที่ยื่นออกมาบนปลั๊กสายแบตเตอรี่อาจเกี่ยวชิ้นส่วนเหล่านั้นเมื่อถอดสายออก บางครั้งดึงชิ้นส่วนออกจากบอร์ด ตัดลิ่มออกจากปลั๊กสายด้วยคีมตัดแบน flush cutters ก่อนใช้งานครั้งแรก
RTC หยุดทำงานขณะบอร์ดปิด — ค่า load capacitance บน crystal 32 kHz (Y2) สูงเกินไป การถอด C96 และ C97 (คู่ที่อยู่ข้าง crystal ถัดจาก STM32) ช่วยให้ RTC ทำงานต่อด้วยไฟสำรอง บอร์ดส่วนใหญ่จัดส่งโดยถอด cap เหล่านี้ออกแล้ว หาก RTC ของคุณสูญเสียเวลาเมื่อถอดปลั๊ก ให้ตรวจสอบตำแหน่งเหล่านั้น ดู GitHub issues #1536 และ #1600 สำหรับเธรดเต็ม
LED ตัวบ่งชี้การชาร์จค้างสีน้ำเงิน — ตัวชาร์จอาจสิ้นสุดรอบการชาร์จที่แรงดันระหว่าง 4.15 V ถึง 4.19 V โดยไม่สลับตัวบ่งชี้จากสีน้ำเงิน (กำลังชาร์จ) เป็นสีเขียว (ชาร์จเสร็จ) แบตเตอรี่ยังคงชาร์จเต็มในกรณีนี้ เชื่อการวัดแรงดัน ไม่ใช่ LED
Silkscreen ระบุ VIN ผิดเป็น VBAT — แพดในตำแหน่ง VIN ของ header OpenMV มาตรฐานถูกพิมพ์บนบอร์ดว่า
VBATบน Pure Thermal ป้ายกำกับผิด แต่ไม่มีผลในทางปฏิบัติเพราะแพดนี้ ไม่มีการเชื่อมต่อทางไฟฟ้า ไม่ว่าทิศทางใด
ไลบรารีซอฟต์แวร์¶
ดู ดัชนีไลบรารี สำหรับรายการโมดูลทั้งหมด รวมถึงโมดูลที่มีเฉพาะใน Pure Thermal build