OpenMV Pure Thermal¶
OpenMV Pure Thermal은 STMicroelectronics STM32H743(Cortex‑M7 @ 480 MHz)를 중심으로 구성된 풀시스템 열화상 보드로, 64 MB 외부 SDRAM, 32 MB QSPI 플래시, 하드웨어 JPEG 코덱, 4.3” 800×480 IPS 정전식 터치스크린, HDMI 출력, FLIR® Lepton® 열화상 소켓, 그리고 5MP OV5640 가시광 카메라를 갖추고 있습니다. 또한 Wi‑Fi, microSD 소켓, 레이저 거리계, 부저, 고출력 백색 조명기를 탑재하고 있습니다.
전체 데이터시트, 사진, 치수는 OpenMV Pure Thermal 제품 페이지 를 참조하십시오.
주요 특징¶
STMicroelectronics STM32H743XI Cortex‑M7, 480 MHz.
하드웨어 JPEG 인코더/디코더.
64 MB 외부 SDRAM(~400 MB/s) 및 1 MB 내부 SRAM.
2 MB 내부 플래시 + 32 MB 외부 QSPI 플래시 (~50 MB/s 읽기).
OV5640 5MP 롤링 셔터 가시광 센서.
FLIR® Lepton® 소켓 — 라디오메트릭/비라디오메트릭을 불문하고 Lepton 1/2/2.5/3/3.5 모듈을 모두 수용하며, 픽셀별 온도를 섭씨 단위로 제공합니다.
4.3” 800×480 IPS 정전식 터치스크린 (24비트 색상 @ 60 Hz), 최대 5점 제스처 지원.
TFP410 DVI 시리얼라이저를 통한 HDMI 출력 — 최대 1280×720 @ 60 Hz.
WINC1500을 통한 Wi‑Fi, RTSP 기반 MJPEG를 기본으로 지원합니다.
풀 스피드 USB-C (12 Mb/s, 900 mA 전류 제한) — 호스트에 VCP + USB 대용량 저장장치로 나타나며 충전도 처리합니다.
microSD 소켓 — SD는 최대 2 GB, SDHC는 최대 32 GB, SDXC는 최대 2 TB.
VL53L1CX 레이저 거리 측정기 (최대 ~4 m).
소프트웨어로 볼륨/주파수를 제어하는 부저.
사용자 RGB 상태 LED 외에 추가로 탑재된 고출력 백색 LED 조명기.
500 mA로 USB 충전이 가능한 LiPo 배터리 커넥터.
10개 I/O 핀, 5 V 허용 입력에 3.3 V 출력, 핀당 25 mA(총합 120 mA), 인터럽트 지원. P6은 ADC 또는 DAC 모드로 사용할 때 5 V를 허용하지 않습니다.
ST‑LINK / J‑Link 디버깅을 위한 ARM 10핀 SWD 커넥터.
I²C 주변장치를 위한 Qwiic 커넥터.
참고
보드 좌측 하단 가장자리에는 선택 사양인 ¼”–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 |
디지털 I/O |
RESET |
GND로 당기면 보드가 리셋됩니다 |
SYN |
프레임 동기 패드 — 연결되지 않음 |
VIN |
실드 VIN 패드 — 연결되지 않음 |
BOOT0 |
전원 인가 시 3.3 V로 당기면 DFU / ROM 부트로더로 진입합니다 |
BUZZER |
온보드 피에조 부저(TIM2/PWM 구동) |
LED_RED |
RGB 상태 LED 빨간색 채널(액티브 로우) |
LED_GREEN |
RGB 상태 LED 초록색 채널(액티브 로우) |
LED_BLUE |
RGB 상태 LED 파란색 채널(액티브 로우) |
LED_WHITE |
고출력 백색 조명기 LED |
참고
실드/헤더의 SYN과 VIN 패드는 Pure Thermal에서 전기적으로 연결되어 있지 않습니다 — 헤더 호환성을 위해 존재할 뿐입니다. 대신 USB‑C 또는 온보드 LiPo 배터리 커넥터를 통해 보드에 전원을 공급하십시오(아래 전원 핀 참조). 또한 VIN 패드는 보드 실크스크린에 VBAT로 표기되어 있지만(표기 실수입니다) 이 위치는 표준 OpenMV 헤더의 VIN 핀이며 어느 쪽이든 연결되어 있지 않습니다.
전원 핀¶
3.3V — 레귤레이트된 3.3 V 레일. 실드용으로 최대 250 mA를 사용할 수 있습니다.
GND — 공통 접지.
Pure Thermal은 USB‑C 또는 온보드 LiPo 배터리 커넥터를 통해 전원을 공급받습니다. USB‑C 포트는 총 900 mA로 전류가 제한되며 500 mA로 LiPo 충전도 처리하므로, USB와 함께 배터리를 꽂아 사용하는 것이 지원됩니다.
온보드 전원 버튼은 시스템 레일을 켜고 끄며, 보드가 USB로 전원을 공급받든 LiPo로 공급받든 동작합니다. 상태를 전환하려면 버튼을 몇 초간 누르고 있으십시오 — 우발적인 종료를 방지하기 위해 짧게 누르는 것은 무시됩니다.
전원 소스 선택은 두 가지 간단한 규칙을 따릅니다:
배터리는 전압이 3 V를 초과할 때만 보드에 전원을 공급합니다. 그 임계값 아래로 떨어지면 온보드 PMIC가 과방전으로부터 배터리를 보호하기 위해 배터리를 분리합니다.
USB가 연결되어 있으면 USB가 보드에 전원을 공급하고, 연결된 LiPo는 백그라운드에서 충전됩니다.
LiPo 커넥터에는 역전압 보호 기능도 있어, 배터리를 거꾸로 꽂아도 보드가 손상되지 않습니다.
참고
보드는 배터리 전압과 배터리 전류 감지 신호도 MCU의 ADC 채널로 다시 라우팅하지만, 이에 대한 펌웨어 지원은 아직 추가되지 않았습니다.
복구 및 디버그 핀¶
RESET — GND로 당기면 보드가 리셋됩니다. Pure Thermal에는 동일한 동작을 하는 전용 RESET 버튼도 보드에 있습니다.
BOOT0 — 보드에 전원을 인가하는 동안 3.3 V로 당기면 STM32 ROM 부트로더(DFU 모드)로 진입합니다. OpenMV IDE는 이 모드를 사용하여 온보드 부트로더를 재플래시합니다. 보드의 전용 BOOT0 버튼도 동일한 동작을 합니다 — 전원을 인가하는 동안 버튼을 누르고 있으십시오.
보드는 GPIO 헤더 옆에 SWD 디버그 헤더(RST / SWCLK / SWDIO / SWO)를 노출하며, ST‑LINK 및 SEGGER J‑Link 어댑터와 호환됩니다. 별도의 ARM 10핀 SWD 커넥터도 장착되어 있어 동일한 SWD 신호를 전달하지만(완전한 JTAG은 아님) 표준 0.05” 10핀 폼팩터를 사용합니다.
참고
SWO 트레이스 핀은 온보드 FLIR® Lepton®의 SPI 클록과 공유됩니다. SWO는 Lepton과 동시에 사용할 수 없으므로 둘 중 하나를 선택하십시오.
보드에는 세 번째 PURE Modules Debug 커넥터가 장착되어 있습니다. 이 커넥터는 동반 모듈을 연결하기 위한 몇 가지 디버그 관련 신호(SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3.3 V, GND, 그리고 두 개의 GPIO 핀)를 분기합니다. 이 커넥터의 두 GPIO 핀은 하드웨어 주변장치가 아니라 내부 비트뱅잉 I²C 버스로 구동됩니다.
세 개의 디버그 커넥터(인라인 SWD 헤더, ARM 10핀 SWD 커넥터, PURE Modules Debug 커넥터)는 모두 3.3 V 기준입니다 — 연결하기 전에 디버그 어댑터가 3.3 V 로직으로 설정되어 있는지 확인하십시오.
온보드 주변장치¶
LED¶
Pure Thermal에는 보드에 세 개의 LED가 있습니다:
사용자 RGB LED — 소프트웨어로 제어 가능하며
LED_RED,LED_GREEN,LED_BLUE로 노출됩니다:from machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
백색 조명기 —
LED_WHITE을 통해 구동됩니다.LED_WHITE는 하드웨어에서 액티브 하이로 배선되어 있는 반면 펌웨어는 다른 모든 온보드 LED를 액티브 로우로 취급합니다. 따라서on()/off()(이는 동작이 반전됩니다) 대신low()/high()를 사용하십시오: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, 적극적으로 충전 중이지 않을 때만)
부저¶
온보드 피에조 부저는 타이머 채널에 배선되어 있습니다 — 소프트웨어로 제어되는 주파수(음높이)와 듀티 사이클(볼륨)의 음을 내려면 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은 Pure Thermal의 기본 CSI입니다 — 이를 명시적으로 지정하려면 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에는 보이스 코일 액추에이터 방식의 오토포커스 렌즈가 있습니다. csi.IOCTL_TRIGGER_AUTO_FOCUS와 함께 csi.CSI.ioctl을 통해 단일 오토포커스 패스를 트리거하십시오 — 센서가 포커스 모터를 한 번 스윕하여 앞에 있는 대상에 초점을 맞춥니다:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
장면이 바뀔 때마다 ioctl을 다시 호출하십시오 — 오토포커스는 연속이 아니라 단발성입니다.
참고
OV5640의 STROBE 출력(동기화된 플래시 / IR 조명에 사용)은 Pure Thermal에서 MCU에 배선되어 있지만, 이에 대한 펌웨어 지원은 아직 추가되지 않았습니다.
열화상 카메라 센서¶
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()
참고
Lepton의 VSYNC 출력(열화상 프레임당 한 펄스)은 Pure Thermal에서 MCU에 배선되어 있지만, 이에 대한 펌웨어 지원은 아직 추가되지 않았습니다.
두 CSI는 나란히 실행할 수 있습니다. 아래 예제는 OV5640에서 색상 프레임을, Lepton에서 열화상 프레임을 가져온 다음, Ironbow 팔레트와 저강도에서 투명으로 페이드되는 알파 마스크를 사용하여 Lepton을 색상 프레임 위에 오버레이합니다:
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 — 머신 러닝 은 CMSIS‑NN 커널을 사용하여 Cortex‑M7에서 양자화된 TFLite 모델을 실행합니다 — 초당 몇 프레임의 속도로 소형 검출기를 돌리기에 충분히 빠릅니다. 읽기 전용 /rom 파일 시스템에 있는 모델은 RAM으로 복사하지 않고 플래시에서 직접 로드됩니다. 다음은 가시광 카메라의 모든 프레임에 검출된 얼굴과 여섯 개의 랜드마크를 오버레이하는 128×128 BlazeFace 검출기입니다:
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 ToF(Time‑of‑Flight) 거리계는 I²C 버스 2에 배선되어 있습니다. 프리즈된 vl53l1x — VL53L1X ToF 거리 센서 드라이버 드라이버를 사용하여 최대 ~4 m까지 거리 측정값을 얻으십시오:
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 출력¶
4.3” 온보드 LCD는 800 × 480 (WVGA)이며 display — 디스플레이 드라이버 모듈의 RGB 디스플레이 인터페이스를 통해 구동됩니다 — 네이티브 해상도에 맞추려면 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은 꺼짐이고 0이 아닌 값은 켜짐)를 받습니다:
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
터치스크린¶
정전식 터치 컨트롤러는 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 출력¶
펌웨어는 또한 LCD 프레임버퍼를 온보드 tfp410 — DVI/HDMI 컨트롤러 HDMI 시리얼라이저로 팬아웃하므로, 외부 모니터가 LCD에 표시된 내용을 미러링합니다. HDMI 출력을 활성화하려면 tfp410.TFP410 을 인스턴스화하십시오:
import tfp410
hdmi = tfp410.TFP410()
HDMI 출력만 원하고 온보드 LCD는 신경 쓰지 않는다면, 백라이트를 끄고 프레임버퍼 해상도를 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 모니터가 연결되거나 분리되었을 때를 알려면 TFP410에 핫플러그 콜백을 등록하십시오. 콜백은 연결 시 True로, 분리 시 False로 발동됩니다:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
isconnected() 로 언제든지 연결 상태를 폴링할 수도 있습니다(콜백이 등록되어 있지 않을 때만).
HDMI 포트는 또한 DDC (디스플레이 데이터)와 CEC (가전제품 제어) 채널을 전달하며, 이는 class DisplayData – 디스플레이 데이터 클래스를 통해 노출됩니다. 이를 사용하여 연결된 모니터의 EDID 블록을 읽거나(네이티브 해상도 / 재생률에 맞게 조정할 수 있도록) 동일한 선상의 다른 HDMI 장치를 제어하기 위한 CEC 프레임을 송수신할 수 있습니다:
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 실드 드라이버 인터페이스를 통해 노출됩니다:
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])
참고
부품 부족으로 인해 일부 Pure Thermal 유닛은 WINC1500 모듈이 실장되지 않은 채 출하되었습니다. network.WINC 가 오류를 발생시키거나 연결되지 않는다면 보드에 Wi‑Fi 모듈이 누락되어 있는지 확인하십시오 — 모듈이 없어도 카메라의 나머지 기능은 동일하게 작동합니다.
microSD 카드¶
카드를 삽입하면 /sdcard에 자동으로 마운트되며 일반 파일 시스템을 통해 사용할 수 있습니다:
import os
for entry in os.listdir("/sdcard"):
print(entry)
버스 참조¶
GPIO¶
실크스크린에 표시된 핀을 읽거나 구동하려면 machine.Pin 을 사용하십시오. 출력은 3.3 V CMOS이고 입력 측에서는 5 V를 허용하며, 핀당 최대 25 mA(헤더 전체 합계 120 mA)를 싱크/소스할 수 있습니다.
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")
동일한 하드웨어는 machine.I2CTarget 을 통해 타깃(슬레이브) 모드로도 사용하여 다른 I²C 컨트롤러에 메모리 영역을 노출할 수 있습니다:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
온보드 Qwiic 커넥터는 플러그 앤 플레이 모듈을 위해 이러한 I²C 버스 중 하나를 분기합니다. Qwiic 라인은 오픈 드레인 트랜지스터를 통해 5 V로 레벨 시프트되므로, 버스는 표준 모드(100 kHz)와 패스트 모드(400 kHz)로만 제한됩니다 — Qwiic 헤더로 패스트 모드 플러스 이상의 속도를 실행하려고 하지 마십시오.
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은 유일한 사용자 아날로그 핀입니다. 12비트 ADC 입력 또는 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 |
참고
TIM1은 카메라 센서의 픽셀 클록을 생성하기 위해 펌웨어가 예약하고 있으므로, P0/P1/P2에 물리적으로 존재하는 TIM1 채널은 카메라를 망가뜨리지 않고는 사용자 PWM에 사용할 수 없습니다.
TIM4는 pyb.Servo 와 공유됩니다 — 서보를 인스턴스화하면 타이머 전체가 50 Hz 동작으로 재구성되므로, 같은 스크립트에서 P7/P8의 machine.PWM 과 pyb.Servo 를 함께 사용하지 마십시오.
이들 중 어느 것이든 machine.PWM 을 통해 구동하십시오:
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
소프트웨어 비트뱅잉 버스¶
추가 버스가 필요하다면 machine.SoftI2C 와 machine.SoftSPI 가 모든 GPIO에서 동작합니다.
열화상 센서(오프보드)¶
온보드 FLIR Lepton 외에도, 펌웨어에는 외부에 배선된 I²C 열화상 이미저용 fir — 열 센서 드라이버 (fir == far infrared, 원적외선) 드라이버도 포함되어 있습니다:
MLX90621 — 16 × 4 IR 어레이
MLX90640 — 32 × 24 IR 어레이
MLX90641 — 16 × 12 IR 어레이
AMG8833 — 8 × 8 IR 어레이
모듈을 보드의 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"))
주기 값은 밀리초 단위입니다. 슬롯을 중지하고 해제하려면 deinit() 을 호출하십시오.
실시간 클록¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
LiPo 배터리가 연결되어 있으면 RTC는 시스템 레일이 꺼져 있는 동안에도(온보드 전원 버튼으로 전원이 차단된 상태) 시간을 유지합니다. USB만 연결된 상태에서는 전원 버튼을 누르면 RTC의 전원도 차단됩니다 — 따라서 배터리가 연결되어 있지 않으면 전원을 껐다 켜는 동안 벽시계 시간이 유지되지 않습니다.
워치독¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
부팅 및 런타임 정보¶
USB 부트로더 윈도우¶
전원을 켤 때마다 카메라는 짧은(몇 초간) 부트로더를 실행하여, 사용자가 DFU 모드로 진입하지 않고도 OpenMV IDE가 펌웨어를 업데이트할 수 있도록 합니다. 윈도우가 만료되면 부트로더는 boot.py로, 이어서 main.py로 제어를 넘깁니다.
실행 중인 스크립트는 machine.bootloader() 를 호출하여 필요할 때 부트로더로 다시 진입할 수 있습니다.
파일 시스템 및 부팅 순서¶
Pure Thermal 펌웨어는 부팅 시 최대 세 개의 파일 시스템을 마운트합니다:
내부 플래시 — 항상
/flash에 마운트됩니다. 기본적으로main.py와README.txt를 담고 있으며, 최초 부팅 시 생성됩니다.microSD 카드 — 카드가 삽입되어 있으면
/sdcard에 마운트됩니다.ROMFS —
/rom에 위치한 읽기 전용 메모리 매핑 파일 시스템으로, 제로 카피 액세스의 이점을 누리는 대용량 데이터 자산(예: AI 모델)을 제공하는 데 사용됩니다. 사용자 Python 코드가 실행되기 전에 MicroPython이 시작 시 자동으로 마운트합니다.
마운트 후, 카드가 있을 때는 작업 디렉터리가 /sdcard로 설정되고, 그렇지 않으면 /flash로 설정됩니다. 그런 다음 인터프리터는 해당 디렉터리에서 스크립트를 실행합니다:
boot.py는 모든 소프트 리셋 시 실행됩니다.main.py는boot.py직후 콜드 부팅 시에만 실행됩니다.
SD 카드에 boot.py 또는 main.py를 넣으면 플래시에 있는 사본을 건드리지 않고 이를 오버라이드합니다.
USB로 연결되어 있으면 부팅 파일 시스템(카드가 있으면 /sdcard, 그렇지 않으면 /flash)이 호스트에서 USB 대용량 저장 장치 드라이브로도 열거됩니다. 호스트가 캐시된 쓰기를 플러시하도록 카메라를 리셋하기 전에 드라이브를 꺼내십시오.
참고
OpenMV Cam에서 실행되는 코드로 생성하거나 수정한 파일은 드라이브를 다시 마운트하기 전까지 호스트에 나타나지 않습니다. 스크립트가 기록하는 모든 데이터에는 SD 카드를 사용하고, 호스트에서 해당 파일을 읽기 전에 다시 마운트하십시오.
저장 용량¶
Pure Thermal은 다음과 함께 출하됩니다:
/flash— 24 MB FAT 파일 시스템, 읽기/쓰기./rom— 8 MB 읽기 전용 메모리 매핑 ROMFS로, 제로 카피 mmap 액세스의 이점을 누리는 스크립트와 ML 모델을 제공하는 데 사용됩니다./sdcard— 삽입된 microSD 카드(있을 경우)의 전체 용량, 읽기/쓰기.
하드 폴트 표시기¶
사용자 RGB LED가 모든 색상을 빠르게 순환하여 — 뚜렷한 색조라기보다 반짝이는 백색 LED처럼 보일 만큼 빠르게 — 점멸한다면, 펌웨어가 복구 불가능한 하드 폴트에 도달한 것입니다. 복구하려면 펌웨어를 재플래시하십시오.
하드웨어 정오표¶
보드 수준의 몇 가지 특이 사항은 Pure Thermal 하드웨어 정오표 에 문서화되어 있습니다. 알아두어야 할 주요 항목은 다음과 같습니다:
배터리 커넥터 간섭 — PCB의 부품이 LiPo 배터리 커넥터 바로 아래에 위치하며, 케이블을 분리할 때 배터리 케이블 플러그의 돌출된 쐐기가 부품에 걸려 때때로 부품을 보드에서 떼어낼 수 있습니다. 처음 사용하기 전에 플러시 커터로 케이블 플러그의 쐐기를 잘라내십시오.
보드 전원이 꺼져 있는 동안 RTC가 멈춤 — 32 kHz 크리스털(Y2)의 부하 커패시턴스가 너무 높습니다. C96과 C97(STM32 옆 크리스털 양쪽에 있는 한 쌍)을 제거하면 RTC가 백업 전원으로 계속 동작할 수 있습니다. 대부분의 보드는 이 커패시터가 이미 제거된 상태로 출하됩니다. 연결을 해제했을 때 RTC가 시간을 잃는다면 해당 위치를 확인하십시오. 전체 내용은 GitHub 이슈 #1536 및 #1600 를 참조하십시오.
충전 표시 LED가 파란색으로 유지됨 — 충전기가 표시기를 파란색(충전 중)에서 초록색(충전 완료)으로 전환하지 않고 4.15 V에서 4.19 V 사이의 어느 지점에서든 충전 사이클을 종료할 수 있습니다. 이 경우에도 배터리는 완전히 충전된 상태입니다. LED가 아니라 전압 측정값을 신뢰하십시오.
실크스크린이 VIN을 VBAT로 잘못 표기함 — 표준 OpenMV 헤더의 VIN 위치에 있는 패드가 Pure Thermal에서는 실크스크린에
VBAT로 표기되어 있습니다. 이 표기는 잘못된 것이지만, 패드가 어느 쪽이든 전기적으로 연결되어 있지 않기 때문에 실제로는 문제가 되지 않습니다.
소프트웨어 라이브러리¶
전체 모듈 목록은 라이브러리 색인 을 참조하십시오 — Pure Thermal 빌드에만 고유한 모듈도 포함되어 있습니다.