OpenMV Pure Thermal¶
OpenMV Pure Thermal to kompletna płytka do obrazowania termicznego zbudowana wokół układu STMicroelectronics STM32H743 (Cortex‑M7 @ 480 MHz) z 64 MB zewnętrznej pamięci SDRAM, 32 MB pamięci flash QSPI, sprzętowym kodekiem JPEG, 4,3-calowym pojemnościowym ekranem dotykowym IPS 800×480, wyjściem HDMI, gniazdem termicznym FLIR® Lepton® oraz 5-megapikselową kamerą światła widzialnego OV5640. Wyposażono ją również w Wi‑Fi, gniazdo microSD, dalmierz laserowy, brzęczyk oraz wysokomocowy biały oświetlacz.
Pełną kartę katalogową, zdjęcia oraz wymiary znajdziesz na stronie produktu OpenMV Pure Thermal.
Najważniejsze cechy¶
STMicroelectronics STM32H743XI Cortex‑M7 taktowany 480 MHz.
Sprzętowy enkoder/dekoder JPEG.
64 MB zewnętrznej pamięci SDRAM (~400 MB/s) oraz 1 MB wewnętrznej pamięci SRAM.
2 MB wewnętrznej pamięci flash + 32 MB zewnętrznej pamięci flash QSPI (~50 MB/s odczyt).
OV5640 5-megapikselowy sensor światła widzialnego z migawką kroczącą (rolling‑shutter).
Gniazdo FLIR® Lepton® — obsługuje dowolny moduł Lepton 1/2/2.5/3/3.5, radiometryczny lub nieradiometryczny, z temperaturą każdego piksela w stopniach Celsjusza.
4,3-calowy pojemnościowy ekran dotykowy IPS 800×480 (24‑bitowy kolor @ 60 Hz) z obsługą gestów nawet w 5 punktach.
Wyjście HDMI przez serializator DVI TFP410 — nawet 1280×720 @ 60 Hz.
Wi‑Fi przez WINC1500; obsługa MJPEG przez RTSP od razu po wyjęciu z pudełka.
USB‑C full‑speed (12 Mb/s, z ograniczeniem prądu do 900 mA) — widoczne dla hosta jako VCP + pamięć masowa USB, obsługuje również ładowanie.
Gniazdo microSD — SD do 2 GB, SDHC do 32 GB, SDXC do 2 TB.
Dalmierz laserowy VL53L1CX (do ~4 m).
Brzęczyk ze sterowaną programowo głośnością / częstotliwością.
Wysokomocowy biały oświetlacz LED w uzupełnieniu do użytkowej diody statusowej RGB.
Złącze akumulatora LiPo z ładowaniem przez USB prądem 500 mA.
10 pinów I/O, tolerujących 5 V z wyjściem 3,3 V, 25 mA na pin (łącznie 120 mA), obsługujących przerwania. P6 nie toleruje 5 V w trybie ADC ani DAC.
Złącze ARM 10‑pin SWD do debugowania przez ST‑LINK / J‑Link.
Złącze Qwiic dla urządzeń peryferyjnych I²C.
Informacja
Płytka ma na dolnej, lewej krawędzi gniazdo na opcjonalną nakrętkę statywową ¼”–20. Nie jest ona montowana fabrycznie — wlutuj ją w gniazdo, jeśli chcesz zamontować płytkę na standardowym statywie fotograficznym.
Wyprowadzenia¶
Opis pinów¶
Nazwa pinu |
Funkcja |
|---|---|
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 |
cyfrowe I/O |
RESET |
zewrzyj do GND, aby zresetować płytkę |
SYN |
pole synchronizacji ramki (frame‑sync) — niepodłączone |
VIN |
pole VIN nakładki (shield) — niepodłączone |
BOOT0 |
zewrzyj do 3,3 V przy włączaniu zasilania, aby uruchomić DFU / bootloader ROM |
BUZZER |
wbudowany brzęczyk piezo (sterowany przez TIM2/PWM) |
LED_RED |
czerwony kanał statusowej diody RGB (aktywny stanem niskim) |
LED_GREEN |
zielony kanał statusowej diody RGB (aktywny stanem niskim) |
LED_BLUE |
niebieski kanał statusowej diody RGB (aktywny stanem niskim) |
LED_WHITE |
wysokomocowa biała dioda oświetlacza |
Informacja
Pola SYN i VIN na nakładce/listwie nie mają żadnego połączenia elektrycznego w Pure Thermal — są tam wyłącznie ze względu na zgodność z listwą złącz. Zamiast tego zasilaj płytkę przez USB‑C lub wbudowane złącze akumulatora LiPo (patrz Piny zasilania poniżej). Zwróć też uwagę, że pole VIN ma na płytce nadruk VBAT (błąd w opisie) — pozycja odpowiada standardowemu pinowi VIN listwy OpenMV i tak czy inaczej jest niepodłączona.
Piny zasilania¶
3.3V — stabilizowana szyna 3,3 V. Dla nakładek dostępne do 250 mA.
GND — wspólna masa.
Pure Thermal jest zasilana przez USB‑C lub wbudowane złącze akumulatora LiPo. Port USB‑C ma ograniczenie prądu do łącznie 900 mA i obsługuje również ładowanie LiPo prądem 500 mA, więc podłączenie akumulatora jednocześnie z USB jest wspierane.
Wbudowany przycisk zasilania włącza i wyłącza szyny systemowe i działa niezależnie od tego, czy płytka jest zasilana z USB, czy z LiPo. Przytrzymaj przycisk przez kilka sekund, aby zmienić stan — krótkie naciśnięcie jest ignorowane, aby zapobiec przypadkowemu wyłączeniu.
Wybór źródła zasilania kieruje się dwiema prostymi regułami:
Akumulator zasila płytkę tylko wtedy, gdy jego napięcie przekracza 3 V. Poniżej tego progu wbudowany układ PMIC odłącza akumulator, aby chronić go przed nadmiernym rozładowaniem.
Gdy obecne jest USB, płytkę zasila USB, a podłączony akumulator LiPo ładuje się w tle.
Złącze LiPo ma również ochronę przed odwrotną polaryzacją napięcia, więc podłączenie akumulatora odwrotnie nie uszkodzi płytki.
Informacja
Płytka przekazuje również sygnały napięcia akumulatora oraz pomiaru prądu akumulatora z powrotem do kanałów ADC mikrokontrolera, jednak obsługa żadnego z nich nie została jeszcze dodana w oprogramowaniu układowym.
Piny odzyskiwania i debugowania¶
RESET — zewrzyj do GND, aby zresetować płytkę. Pure Thermal ma również na płytce dedykowany przycisk RESET, który robi to samo.
BOOT0 — zewrzyj do 3,3 V podczas zasilania płytki, aby wejść do bootloadera ROM układu STM32 (tryb DFU). OpenMV IDE wykorzystuje ten tryb do ponownego programowania wbudowanego bootloadera. Dedykowany przycisk BOOT0 na płytce robi to samo — przytrzymaj go w momencie podawania zasilania.
Płytka udostępnia listwę debugową SWD (RST / SWCLK / SWDIO / SWO) obok listwy GPIO, zgodną z adapterami ST‑LINK i SEGGER J‑Link. Zamontowane jest również osobne złącze ARM 10‑pin SWD — przenosi te same sygnały SWD (bez pełnego JTAG), ale w standardowym formacie 10‑pinowym o rastrze 0,05”.
Informacja
Pin śledzenia SWO jest współdzielony z zegarem SPI wbudowanego FLIR® Lepton®. SWO nie może być używany jednocześnie z Lepton — wybierz jedno albo drugie.
Na płytce zamontowane jest trzecie złącze PURE Modules Debug. Wyprowadza ono garść sygnałów debugowych (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 V, GND oraz dwa piny GPIO) do podłączania modułów towarzyszących. Dwa piny GPIO na tym złączu są sterowane przez wewnętrzną magistralę I²C realizowaną programowo (bit‑bang), a nie przez sprzętowe urządzenie peryferyjne.
Wszystkie trzy złącza debugowe (wbudowana listwa SWD, złącze ARM 10‑pin SWD oraz złącze PURE Modules Debug) odnoszą się do 3,3 V — upewnij się, że twój adapter debugowy jest skonfigurowany na logikę 3,3 V przed podłączeniem.
Wbudowane urządzenia peryferyjne¶
Diody LED¶
Pure Thermal ma na płytce trzy diody LED:
Użytkowa dioda RGB — sterowana programowo, udostępniona jako
LED_RED,LED_GREENiLED_BLUEfrom machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
Biały oświetlacz — sterowany przez
LED_WHITE.LED_WHITEjest sprzętowo podłączony jako aktywny stanem wysokim, podczas gdy oprogramowanie układowe traktuje każdą inną wbudowaną diodę LED jako aktywną stanem niskim, więc używajlow()/high()zamiaston()/off()(które odwróciłyby logikę):from machine import LED light = LED("LED_WHITE") light.low() # turn the white LED ON light.high() # turn the white LED OFF
Dioda ładowania — sterowana bezpośrednio przez wbudowany układ zarządzania zasilaniem, bez kontroli programowej. Działa niezależnie od tego, czy szyny systemowe są włączone, czy wyłączone (tj. przy przycisku zasilania w dowolnym położeniu).
Kolor
Znaczenie
Niebieski
ładowanie — patrz errata: może nie zgasnąć po zakończeniu ładowania
Zielony
ładowanie zakończone — patrz errata: może nie wyzwalać się niezawodnie
Czerwony
niski poziom akumulatora (≤ 3,2 V, tylko gdy nie trwa aktywne ładowanie)
Brzęczyk¶
Wbudowany brzęczyk piezo jest podłączony do kanału licznika czasu — steruj nim za pomocą machine.PWM, aby uzyskać dźwięki ze sterowaną programowo częstotliwością (wysokość tonu) i współczynnikiem wypełnienia (głośność):
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()
Sensor kamery¶
OV5640 to główny CSI w Pure Thermal — przekaż cid=csi.OV5640, aby zaadresować go jawnie:
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 ma wbudowany kompresor JPEG. Ustaw csi.CSI.pixformat na csi.JPEG, a sensor będzie dostarczał skompresowane ramki bezpośrednio do kamery przez magistralę kamery, co czyni praktycznym przechwytywanie w wysokiej rozdzielczości: csi.HD (1280×720), csi.FHD (1920×1080) oraz pełne 5 MP csi.WQXGA2 (2592×1944) są strumieniowane jako JPEG. Dostrój kompresję za pomocą csi.CSI.quality (0-100, wyższa = większe ramki, więcej szczegółów):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
OV5640 ma autofokusowy obiektyw z aktuatorem cewki głosowej (voice coil). Wyzwól pojedynczy przebieg autofokusa przez csi.CSI.ioctl z csi.IOCTL_TRIGGER_AUTO_FOCUS — sensor jednorazowo przesuwa silnik ostrości i ustawia ostrość na tym, co znajduje się przed nim:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
Ponawiaj wywołanie ioctl za każdym razem, gdy scena się zmieni — autofokus jest jednorazowy, a nie ciągły.
Informacja
Wyjście STROBE układu OV5640 (używane do zsynchronizowanej lampy błyskowej / oświetlenia IR) jest w Pure Thermal podłączone do mikrokontrolera, ale jego obsługa nie została jeszcze dodana w oprogramowaniu układowym.
Sensor kamery termicznej¶
Gniazdo FLIR® Lepton® pojawia się jako drugi CSI w tym samym API csi — sensory kamery. Przekaż cid=csi.LEPTON, aby go zaadresować, i pomiń sprzętowy reset:
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()
Informacja
Wyjście VSYNC układu Lepton (jeden impuls na ramkę termiczną) jest w Pure Thermal podłączone do mikrokontrolera, ale jego obsługa nie została jeszcze dodana w oprogramowaniu układowym.
Oba CSI mogą działać równolegle. Poniższy przykład pobiera kolorową ramkę z OV5640 oraz ramkę termiczną z Lepton, a następnie nakłada obraz z Lepton na kolorową ramkę przy użyciu palety Ironbow oraz maski alfa, która zanika do przezroczystości przy niskiej intensywności:
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,
)
Uczenie maszynowe¶
ml — Uczenie maszynowe uruchamia skwantyzowane modele TFLite na Cortex‑M7 z jądrami CMSIS‑NN — wystarczająco szybko dla kompaktowych detektorów przy kilku klatkach na sekundę. Modele w systemie plików tylko do odczytu /rom ładują się bezpośrednio z pamięci flash bez kopiowania do RAM. Oto detektor BlazeFace 128×128 nakładający wykrytą twarz i jej sześć punktów charakterystycznych na każdą ramkę z kamery światła widzialnego:
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")
Dalmierz laserowy¶
Wbudowany dalmierz typu time‑of‑flight ST VL53L1CX jest podłączony do magistrali I²C 2. Użyj zamrożonego sterownika vl53l1x — sterownik czujnika odległości ToF VL53L1X, aby uzyskać odczyty odległości do ~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)
Wyjście LCD¶
Wbudowany 4,3-calowy LCD ma rozdzielczość 800 × 480 (WVGA) i jest sterowany przez interfejs wyświetlacza RGB modułu display — sterownik wyświetlacza — przekaż framesize=display.FWVGA, aby dopasować się do jego natywnej rozdzielczości:
import display
lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True) # turn the LCD backlight on
lcd.write(img)
Podświetlenie jest podłączone do GPIO, więc backlight() przyjmuje True / False (lub dowolną wartość 0–100, gdzie 0 oznacza wyłączone, a dowolna wartość niezerowa — włączone):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
Ekran dotykowy¶
Pojemnościowym kontrolerem dotyku jest FT5X06; pozycje dotyku wielopunktowego oraz zdarzenia gestów są udostępniane przez ft5x06 — Sterownik ekranu dotykowego. Zarejestruj wywołanie zwrotne, aby reagować na dotyk i odczytywać w nim aktywne punkty:
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)
Wyjście HDMI¶
Oprogramowanie układowe rozprowadza również bufor ramki LCD do wbudowanego serializatora HDMI tfp410 — Kontroler DVI/HDMI, dzięki czemu zewnętrzny monitor odzwierciedla to, co jest na LCD. Utwórz instancję tfp410.TFP410, aby włączyć wyjście HDMI:
import tfp410
hdmi = tfp410.TFP410()
Jeśli chcesz korzystać wyłącznie z wyjścia HDMI i nie zależy ci na wbudowanym LCD, wyłącz podświetlenie i zwiększ rozdzielczość bufora ramki powyżej WVGA. TFP410 obsługuje do 1280×720 @ 60 Hz, więc na przykład:
lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False) # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()
Wbudowany panel ma stałą rozdzielczość 800×480, więc cokolwiek powyżej WVGA ma sens tylko na zewnętrznym monitorze HDMI.
Aby wiedzieć, kiedy monitor HDMI został podłączony lub odłączony, zarejestruj wywołanie zwrotne hot‑plug na TFP410. Wywołanie zwrotne uruchamia się z wartością True przy podłączeniu i False przy odłączeniu:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
Możesz też w dowolnym momencie odpytać stan połączenia za pomocą isconnected() (tylko gdy nie zarejestrowano żadnego wywołania zwrotnego).
Port HDMI przenosi również kanały DDC (dane wyświetlacza) oraz CEC (sterowanie elektroniką użytkową), udostępniane przez klasę klasa DisplayData – dane wyświetlacza. Użyj jej do odczytu bloku EDID podłączonego monitora (abyś mógł dostosować się do jego natywnej rozdzielczości / częstotliwości odświeżania) lub do wysyłania/odbierania ramek CEC w celu sterowania innymi urządzeniami HDMI na tym samym przewodzie:
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 działa przez moduł Microchip WINC1500, udostępniony przez interfejs class WINC – sterownik nakładki 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])
Informacja
Z powodu niedoborów podzespołów niektóre egzemplarze Pure Thermal zostały wysłane bez zamontowanego modułu WINC1500. Jeśli network.WINC zgłasza błąd lub nigdy się nie łączy, sprawdź, czy na płytce nie brakuje modułu Wi‑Fi — reszta kamery działa dokładnie tak samo również bez niego.
Karta microSD¶
Po włożeniu karta jest montowana automatycznie w /sdcard i można z niej korzystać przez zwykły system plików:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Opis magistral¶
GPIO¶
Użyj machine.Pin, aby odczytać lub sterować dowolnym z opisanych nadrukiem pinów. Wyjścia są w standardzie 3,3 V CMOS, tolerujące 5 V po stronie wejścia i mogą pochłaniać/dostarczać do 25 mA na pin (łącznie 120 mA na całej listwie).
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())
Każdy pin wejściowy może również wywołać przerwanie przy zmianach na zboczu:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Magistrala |
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¶
Magistrala |
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")
Ten sam sprzęt może być również używany w trybie urządzenia docelowego (slave) przez machine.I2CTarget, aby udostępnić obszar pamięci innemu kontrolerowi I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
Wbudowane złącze Qwiic wyprowadza jedną z tych magistral I²C dla modułów typu plug‑and‑play. Linia Qwiic jest przekonwertowana napięciowo do 5 V przez tranzystory typu open‑drain, więc magistrala jest ograniczona wyłącznie do trybu standardowego (100 kHz) i trybu szybkiego (400 kHz) — nie próbuj uruchamiać przez listwę Qwiic trybu fast‑mode‑plus ani wyższych szybkości.
Złącze Qwiic wyprowadza 5 V do zasilania podłączonych modułów; nie może być użyte do zasilania samej Pure Thermal — zamiast tego zasilaj płytkę przez USB‑C lub złącze akumulatora LiPo.
SPI¶
Magistrala |
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)¶
Magistrala |
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 i DAC¶
P6 to jedyny użytkowy pin analogowy. Może być używany albo jako 12‑bitowe wejście ADC, albo jako wyjście DAC.
ADC — pełna skala przy 3,3 V na pinie:
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 — przez
pyb.DAC. Wartość 8‑bitowa pokrywa zakres 0–3,3 V:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
W trybie ADC lub DAC P6 toleruje tylko 3,3 V — nie podawaj na niego 5 V.
PWM¶
Pin |
Licznik czasu / kanał |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Informacja
TIM1 jest zarezerwowany przez oprogramowanie układowe do generowania zegara pikseli sensora kamery, więc kanały TIM1 fizycznie obecne na P0/P1/P2 nie mogą być użyte do użytkowego PWM bez zakłócenia działania kamery.
TIM4 jest współdzielony z pyb.Servo — utworzenie instancji serwa rekonfiguruje cały licznik na pracę z częstotliwością 50 Hz, więc nie łącz machine.PWM na P7/P8 z pyb.Servo w tym samym skrypcie.
Steruj dowolnym z nich przez machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
Magistrale programowe (bit‑bang)¶
machine.SoftI2C i machine.SoftSPI działają na dowolnym GPIO, jeśli potrzebujesz dodatkowej magistrali.
Sensor termiczny (zewnętrzny)¶
Oprócz wbudowanego FLIR Lepton oprogramowanie układowe zawiera również sterownik fir — sterownik sensora termicznego (fir == far infrared, daleka podczerwień) dla zewnętrznie podłączonych termowizyjnych sensorów I²C:
MLX90621 — matryca IR 16 × 4
MLX90640 — matryca IR 32 × 24
MLX90641 — matryca IR 16 × 12
AMG8833 — matryca IR 8 × 8
Podłącz moduł do magistrali I²C płytki i odczytuj ramki za pomocą 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())
Sterownik fir komunikuje się z sensorem wyłącznie przez I²C 2 — podłącz moduł do P4 (SCL) i P5 (SDA).
Pomiar czasu¶
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)
Liczniki wirtualne¶
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"))
Wartości okresu są podawane w milisekundach. Wywołaj deinit(), aby zatrzymać i zwolnić slot.
Zegar czasu rzeczywistego¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
Jeśli podłączony jest akumulator LiPo, RTC odmierza czas nawet wtedy, gdy szyny systemowe są wyłączone (wyłączone wbudowanym przyciskiem zasilania). Przy podłączonym tylko USB naciśnięcie przycisku zasilania odcina zasilanie również od RTC — więc czas zegara ściennego nie przetrwa cyklu zasilania bez podłączonego akumulatora.
Watchdog¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
Informacje o rozruchu i działaniu¶
Okno bootloadera USB¶
Przy każdym uruchomieniu kamera wykonuje krótki bootloader (kilka sekund), który pozwala OpenMV IDE zaktualizować oprogramowanie układowe bez konieczności wchodzenia przez użytkownika w tryb DFU. Po wygaśnięciu okna bootloader przekazuje sterowanie do boot.py, a następnie do main.py.
Działający skrypt może na żądanie ponownie wejść w bootloader, wywołując machine.bootloader().
System plików i kolejność rozruchu¶
Oprogramowanie układowe Pure Thermal montuje przy rozruchu do trzech systemów plików:
Wewnętrzna pamięć flash — zawsze montowana w
/flash. Domyślnie zawieramain.pyiREADME.txt; tworzona przy pierwszym uruchomieniu.Karta microSD — jeśli karta jest włożona, montowana jest w
/sdcard.ROMFS — system plików tylko do odczytu, mapowany w pamięci, w
/rom, używany do dostarczania dużych zasobów danych (np. modeli AI), które korzystają z dostępu bez kopiowania (zero‑copy). Montowany automatycznie przez MicroPython przy starcie, przed uruchomieniem jakiegokolwiek kodu Python użytkownika.
Po zamontowaniu katalog roboczy jest ustawiany na /sdcard, gdy karta jest obecna, w przeciwnym razie na /flash. Interpreter uruchamia następnie skrypty z tego katalogu:
boot.pyjest wykonywany przy każdym miękkim resecie.main.pyjest wykonywany tylko przy zimnym rozruchu, bezpośrednio poboot.py.
Umieszczenie pliku boot.py lub main.py na karcie SD nadpisuje kopię w pamięci flash, nie naruszając jej.
Po podłączeniu przez USB system plików rozruchowy (/sdcard, jeśli karta jest obecna, w przeciwnym razie /flash) jest również wyliczany jako dysk pamięci masowej USB na hoście. Wysuń dysk przed zresetowaniem kamery, aby host opróżnił buforowane zapisy.
Informacja
Pliki utworzone lub zmodyfikowane przez kod działający na OpenMV Cam nie pojawią się na hoście, dopóki dysk nie zostanie ponownie zamontowany. Używaj karty SD do wszelkich danych, które skrypt zapisuje, i zamontuj ją ponownie przed odczytem tych plików z hosta.
Rozmiary pamięci¶
Pure Thermal jest dostarczana z:
/flash— system plików FAT o rozmiarze 24 MB, do odczytu/zapisu./rom— system plików ROMFS tylko do odczytu, mapowany w pamięci, o rozmiarze 8 MB, używany do dostarczania skryptów i modeli ML, które korzystają z dostępu mmap bez kopiowania (zero‑copy)./sdcard— pełny rozmiar dowolnej włożonej karty microSD (gdy jest obecna), do odczytu/zapisu.
Wskaźnik twardego błędu (hard fault)¶
Jeśli użytkowa dioda RGB szybko przełącza się przez wszystkie kolory — na tyle szybko, że zwykle wygląda jak migocząca biała dioda LED, a nie odrębne barwy — oprogramowanie układowe napotkało nieodwracalny twardy błąd (hard fault). Aby przywrócić działanie, ponownie wgraj oprogramowanie układowe.
Errata sprzętowa¶
Garść osobliwości na poziomie płytki opisano w erracie sprzętowej Pure Thermal. Kluczowe punkty, o których warto wiedzieć:
Kolizja ze złączem akumulatora — komponenty na PCB znajdują się bezpośrednio pod złączem akumulatora LiPo, a wystający klin na wtyczce kabla akumulatora może zaczepić się o nie przy wyjmowaniu kabla, czasem zrywając części z płytki. Przed pierwszym użyciem odetnij klin z wtyczki kabla obcinakami bocznymi.
RTC zatrzymuje się, gdy płytka jest wyłączona — pojemność obciążenia kwarcu 32 kHz (Y2) jest zbyt wysoka. Usunięcie C96 i C97 (pary po obu stronach kwarcu obok STM32) pozwala RTC działać dalej na zasilaniu podtrzymującym. Większość płytek jest dostarczana z tymi kondensatorami już usuniętymi; jeśli twój RTC traci czas po odłączeniu zasilania, sprawdź te pozycje. Pełny wątek znajdziesz w zgłoszeniach GitHub #1536 oraz #1600.
Dioda wskaźnika ładowania pozostaje niebieska — ładowarka może zakończyć cykl ładowania gdziekolwiek pomiędzy 4,15 V a 4,19 V bez przełączenia wskaźnika z niebieskiego (ładowanie) na zielony (naładowano). Akumulator jest w tym przypadku w pełni naładowany; ufaj pomiarowi napięcia, a nie diodzie LED.
Nadruk błędnie opisuje VIN jako VBAT — pole w standardowej pozycji VIN listwy OpenMV ma na Pure Thermal nadruk
VBAT. Opis jest błędny, ale w praktyce nie ma to znaczenia, ponieważ pole tak czy inaczej nie ma żadnego połączenia elektrycznego.
Biblioteki oprogramowania¶
Pełną listę modułów — w tym te, które są unikalne dla wersji Pure Thermal — znajdziesz w indeksie bibliotek.