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.

OpenMV Pure Thermal

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

Wyprowadzenia OpenMV Pure Thermal

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_GREEN i LED_BLUE

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • Biały oświetlacz — sterowany przez LED_WHITE. LED_WHITE jest 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żywaj low() / high() zamiast on() / 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 zawiera main.py i README.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.py jest wykonywany przy każdym miękkim resecie.

  • main.py jest wykonywany tylko przy zimnym rozruchu, bezpośrednio po boot.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.