OpenMV Pure Thermal

OpenMV Pure Thermal adalah papan pencitraan termal sistem lengkap yang dibangun di sekitar STMicroelectronics STM32H743 (Cortex‑M7 @ 480 MHz) dengan 64 MB SDRAM eksternal, 32 MB flash QSPI, codec JPEG perangkat keras, layar sentuh kapasitif IPS 4,3" 800×480, output HDMI, soket termal FLIR® Lepton®, dan kamera cahaya tampak OV5640 5MP. Papan ini juga dilengkapi Wi‑Fi, soket microSD, pengukur jarak laser, buzzer, dan iluminator putih daya tinggi.

OpenMV Pure Thermal

Untuk datasheet lengkap, foto, dan dimensi lihat halaman produk OpenMV Pure Thermal.

Sorotan

  • STMicroelectronics STM32H743XI Cortex‑M7 pada 480 MHz.

  • Encoder/decoder JPEG perangkat keras.

  • 64 MB SDRAM eksternal (~400 MB/s) plus 1 MB SRAM internal.

  • 2 MB flash internal + 32 MB flash QSPI eksternal (~50 MB/s baca).

  • Sensor cahaya tampak OV5640 5MP rolling‑shutter.

  • Soket FLIR® Lepton® — menerima modul Lepton 1/2/2.5/3/3.5 apapun, radiometrik atau non‑radiometrik, dengan suhu per‑piksel dalam derajat Celsius.

  • Layar sentuh kapasitif IPS 4,3" 800×480 (warna 24‑bit @ 60 Hz) dengan dukungan gestur hingga 5 titik.

  • Output HDMI melalui serializer DVI TFP410 — hingga 1280×720 @ 60 Hz.

  • Wi‑Fi melalui WINC1500; MJPEG melalui RTSP didukung langsung.

  • USB‑C kecepatan penuh (12 Mb/s, batas arus 900 mA) — terlihat sebagai VCP + USB mass storage di host, juga menangani pengisian daya.

  • Soket microSD — SD hingga 2 GB, SDHC hingga 32 GB, SDXC hingga 2 TB.

  • Pengukur jarak laser VL53L1CX (hingga ~4 m).

  • Buzzer dengan volume/frekuensi yang dikontrol perangkat lunak.

  • Iluminator LED putih daya tinggi selain LED status RGB pengguna.

  • Konektor baterai LiPo dengan pengisian USB pada 500 mA.

  • 10 pin I/O, toleran 5 V dengan output 3,3 V, 25 mA per pin (total 120 mA), mampu interupsi. P6 tidak toleran 5 V saat digunakan dalam mode ADC atau DAC.

  • Konektor ARM 10‑pin SWD untuk debugging ST‑LINK / J‑Link.

  • Konektor Qwiic untuk periferal I²C.

Catatan

Papan ini memiliki slot di tepi kiri bawahnya untuk mur tripod ¼"–20 opsional. Mur ini tidak dipasang dari pabrik — solder satu ke dalam slot jika Anda ingin memasang papan pada tripod kamera standar.

Pinout

OpenMV Pure Thermal pinout

Referensi pin

Nama pin

Fungsi

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 digital

RESET

hubungkan ke GND untuk mereset papan

SYN

pad sinkronisasi bingkai — tidak terhubung

VIN

pad VIN shield — tidak terhubung

BOOT0

hubungkan ke 3,3 V saat power-on untuk DFU / ROM bootloader

BUZZER

buzzer piezo on‑board (digerakkan TIM2/PWM)

LED_RED

kanal merah LED status RGB (aktif rendah)

LED_GREEN

kanal hijau LED status RGB (aktif rendah)

LED_BLUE

kanal biru LED status RGB (aktif rendah)

LED_WHITE

LED iluminator putih daya tinggi

Catatan

Pad SYN dan VIN pada shield/header tidak memiliki koneksi listrik pada Pure Thermal — ada hanya untuk kompatibilitas header. Berikan daya ke papan melalui USB‑C atau konektor baterai LiPo on‑board (lihat Pin daya di bawah). Perhatikan juga bahwa pad VIN disilkscreen VBAT pada papan (kesalahan pelabelan) — posisinya adalah pin VIN header OpenMV standar dan tidak terhubung dengan cara apapun.

Pin daya

  • 3,3V — rel 3,3 V yang diregulasi. Hingga 250 mA tersedia untuk shield.

  • GND — ground bersama.

Pure Thermal diberi daya melalui USB‑C atau konektor baterai LiPo on‑board. Port USB‑C dibatasi arus pada 900 mA total dan juga menangani pengisian LiPo pada 500 mA, sehingga mencolokkan baterai bersamaan dengan USB didukung.

Tombol daya on‑board mengaktifkan/menonaktifkan rel sistem dan berfungsi baik saat papan diberi daya dari USB atau dari LiPo. Tahan tombol selama beberapa detik untuk mengubah status — ketukan cepat diabaikan untuk mencegah shutdown yang tidak disengaja.

Pemilihan sumber mengikuti dua aturan sederhana:

  • Baterai hanya memberi daya pada papan ketika tegangannya di atas 3 V. Di bawah ambang batas tersebut PMIC on‑board memutuskan baterai untuk melindunginya dari over-discharge.

  • Saat USB tersambung, USB memberi daya pada papan dan LiPo yang terpasang mengisi daya di latar belakang.

Konektor LiPo juga dilengkapi perlindungan tegangan balik, sehingga mencolokkan baterai secara terbalik tidak akan merusak papan.

Catatan

Papan juga merutekan tegangan baterai dan sinyal sensor arus baterai kembali ke kanal ADC MCU, tetapi dukungan firmware untuk keduanya belum ditambahkan.

Pin pemulihan dan debug

  • RESET — hubungkan ke GND untuk mereset papan. Pure Thermal juga memiliki tombol RESET khusus pada papan yang melakukan hal yang sama.

  • BOOT0 — hubungkan ke 3,3 V saat memberi daya pada papan untuk memasuki ROM bootloader STM32 (mode DFU). OpenMV IDE menggunakan mode ini untuk memflash ulang bootloader on‑board. Tombol BOOT0 khusus pada papan melakukan hal yang sama — tahan saat menerapkan daya.

Papan memperlihatkan header debug SWD (RST / SWCLK / SWDIO / SWO) di samping header GPIO, kompatibel dengan adaptor ST‑LINK dan SEGGER J‑Link. Konektor ARM 10‑pin SWD terpisah juga dipasang — membawa sinyal SWD yang sama (tanpa JTAG penuh) tetapi dalam bentuk standar 0,05" 10‑pin.

Catatan

Pin trace SWO berbagi dengan clock SPI FLIR® Lepton® on‑board. SWO tidak dapat digunakan bersamaan dengan Lepton — pilih salah satu.

Konektor PURE Modules Debug ketiga dipasang pada papan. Konektor ini memperlihatkan beberapa sinyal berorientasi debug (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 V, GND, dan dua pin GPIO) untuk memasang modul pendamping. Dua pin GPIO pada konektor ini digerakkan oleh bus I²C bit-banged internal, bukan periferal perangkat keras.

Ketiga konektor debug (header SWD inline, konektor ARM 10‑pin SWD, dan konektor PURE Modules Debug) direferensikan ke 3,3 V — pastikan adaptor debug Anda dikonfigurasi untuk logika 3,3 V sebelum menghubungkan.

Periferal onboard

LED

Pure Thermal memiliki tiga LED pada papan:

  • LED RGB Pengguna — dapat dikontrol perangkat lunak, diperlihatkan sebagai LED_RED, LED_GREEN dan LED_BLUE

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • Iluminator putih — digerakkan melalui LED_WHITE. LED_WHITE dihubungkan aktif tinggi di perangkat keras sementara firmware memperlakukan setiap LED on‑board lain sebagai aktif rendah, jadi gunakan low() / high() daripada on() / off() (yang akan membalik logika):

    from machine import LED
    
    light = LED("LED_WHITE")
    light.low()    # turn the white LED ON
    light.high()   # turn the white LED OFF
    
  • LED Pengisian — digerakkan langsung oleh perangkat keras manajemen daya on‑board, tanpa kontrol perangkat lunak. Berfungsi baik saat rel sistem hidup atau mati (yaitu dengan tombol daya di posisi manapun).

    Warna

    Arti

    Biru

    mengisi daya — lihat errata: mungkin tidak mati ketika pengisian selesai

    Hijau

    pengisian selesai — lihat errata: mungkin tidak aktif secara andal

    Merah

    baterai lemah (≤ 3,2 V, hanya saat tidak sedang mengisi daya)

Buzzer

Buzzer piezo on‑board dihubungkan ke kanal timer — gerakkan dengan machine.PWM untuk nada dengan frekuensi (nada) dan duty cycle (volume) yang dikontrol perangkat lunak:

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 kamera

OV5640 adalah CSI utama pada Pure Thermal — berikan cid=csi.OV5640 untuk mengalamatkannya secara eksplisit:

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 memiliki kompresor JPEG on-board. Setel csi.CSI.pixformat ke csi.JPEG dan sensor mengirimkan bingkai terkompresi langsung ke kamera melalui bus kamera, yang membuat pengambilan resolusi tinggi menjadi praktis: csi.HD (1280×720), csi.FHD (1920×1080), dan full 5MP csi.WQXGA2 (2592×1944) semuanya streaming sebagai JPEG. Sesuaikan kompresi dengan csi.CSI.quality (0-100, lebih tinggi = bingkai lebih besar, lebih detail):

cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)

OV5640 memiliki lensa autofokus aktuator voice-coil. Picu satu kali autofokus melalui csi.CSI.ioctl dengan csi.IOCTL_TRIGGER_AUTO_FOCUS — sensor menyapu motor fokus sekali dan mengunci pada apapun yang ada di depannya:

cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)

Ulangi ioctl setiap kali scene berubah — autofokus bersifat satu kali, bukan berkelanjutan.

Catatan

Output STROBE OV5640 (digunakan untuk flash/iluminasi IR tersinkronisasi) dihubungkan ke MCU pada Pure Thermal, tetapi dukungan firmware untuk itu belum ditambahkan.

Sensor Kamera Termal

Soket FLIR® Lepton® muncul sebagai CSI kedua pada API csi --- sensor kamera yang sama. Berikan cid=csi.LEPTON untuk mengalamatkannya, dan lewati reset perangkat keras:

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()

Catatan

Output VSYNC Lepton (satu pulsa per bingkai termal) dihubungkan ke MCU pada Pure Thermal, tetapi dukungan firmware untuk itu belum ditambahkan.

Kedua CSI dapat berjalan secara bersamaan. Contoh di bawah ini mengambil bingkai warna dari OV5640 dan bingkai termal dari Lepton, kemudian melapisi Lepton di atas bingkai warna menggunakan palet Ironbow dan masker alpha yang memudar menjadi transparan pada intensitas rendah:

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,
    )

Pembelajaran mesin

ml --- Machine Learning menjalankan model TFLite terkuantisasi pada Cortex‑M7 dengan kernel CMSIS‑NN — cukup cepat untuk detektor kompak pada beberapa bingkai per detik. Model pada filesystem read-only /rom dimuat langsung dari flash tanpa menyalin ke RAM. Berikut adalah detektor BlazeFace 128×128 yang melapisi wajah yang terdeteksi dan enam landmark-nya pada setiap bingkai dari kamera cahaya tampak:

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")

Pengukur jarak laser

Ranger time-of-flight ST VL53L1CX on‑board dihubungkan ke bus I²C 2. Gunakan driver beku vl53l1x --- Driver sensor jarak ToF VL53L1X untuk mendapatkan pembacaan jarak hingga ~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)

Output LCD

LCD on‑board 4,3" berukuran 800 × 480 (WVGA) dan digerakkan melalui antarmuka tampilan RGB modul display --- driver display — berikan framesize=display.FWVGA untuk mencocokkan resolusi aslinya:

import display

lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True)           # turn the LCD backlight on
lcd.write(img)

Backlight dihubungkan ke GPIO, sehingga backlight() menerima True / False (atau nilai 0–100 apapun, di mana 0 adalah mati dan apapun yang bukan nol adalah hidup):

lcd.backlight(False)           # turn the backlight off
lcd.backlight(True)            # back on

Layar sentuh

Kontroler sentuh kapasitif adalah FT5X06; posisi multi-sentuh dan peristiwa gestur diperlihatkan melalui ft5x06 --- Driver Layar Sentuh. Daftarkan callback untuk bereaksi terhadap sentuhan dan baca titik aktif di dalamnya:

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)

Output HDMI

Firmware juga meneruskan framebuffer LCD ke serializer HDMI tfp410 --- Pengontrol DVI/HDMI on‑board, sehingga monitor eksternal mencerminkan apa yang ada di LCD. Buat instance tfp410.TFP410 untuk mengaktifkan output HDMI:

import tfp410

hdmi = tfp410.TFP410()

Jika Anda hanya menginginkan output HDMI dan tidak peduli dengan LCD on‑board, matikan backlight dan tingkatkan resolusi framebuffer di atas WVGA. TFP410 mendukung hingga 1280×720 @ 60 Hz, misalnya:

lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False)         # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()

Panel on‑board tetap pada 800×480, sehingga apapun di atas WVGA hanya bermakna pada monitor HDMI eksternal.

Untuk mengetahui kapan monitor HDMI telah dicolokkan atau dicabut, daftarkan callback hot-plug pada TFP410. Callback dipanggil dengan True saat disambungkan dan False saat dicabut:

def on_hotplug(connected):
    print("HDMI", "connected" if connected else "disconnected")

hdmi.hotplug_callback(on_hotplug)

Anda juga dapat memeriksa status koneksi kapan saja dengan isconnected() (hanya saat tidak ada callback yang terdaftar).

Port HDMI juga membawa kanal DDC (data tampilan) dan CEC (kontrol elektronik konsumen), diperlihatkan melalui kelas kelas DisplayData -- Data Display. Gunakan untuk membaca blok EDID monitor yang terpasang (agar Anda dapat menyesuaikan dengan resolusi/refresh rate aslinya) atau untuk mengirim/menerima bingkai CEC untuk mengontrol perangkat HDMI lain pada kabel yang sama:

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 berjalan melalui modul Microchip WINC1500, diperlihatkan melalui antarmuka class WINC -- driver shield 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])

Catatan

Karena kekurangan komponen, beberapa unit Pure Thermal dikirim tanpa modul WINC1500 yang terpasang. Jika network.WINC menimbulkan error atau tidak pernah terhubung, periksa papan untuk modul Wi‑Fi yang hilang — sisa kamera bekerja dengan cara yang sama tanpa itu.

Kartu microSD

Saat kartu dimasukkan, kartu tersebut dipasang secara otomatis di /sdcard dan dapat digunakan melalui sistem file biasa:

import os

for entry in os.listdir("/sdcard"):
    print(entry)

Referensi bus

GPIO

Gunakan machine.Pin untuk membaca atau menggerakkan salah satu pin yang disilkscreen. Output adalah 3,3 V CMOS, toleran 5 V pada sisi input, dan dapat menyerap/menghasilkan hingga 25 mA per pin (total 120 mA di seluruh 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())

Pin input manapun juga dapat memicu interupsi pada transisi tepi:

def handler(pin):
    print("triggered:", pin)

Pin("P1", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

Bus

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

Bus

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")

Perangkat keras yang sama juga dapat digunakan dalam mode target (slave) melalui machine.I2CTarget untuk memperlihatkan wilayah memori ke kontroler I²C lain:

from machine import I2CTarget

buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)

Konektor Qwiic on‑board memperlihatkan salah satu bus I²C ini untuk modul plug-and-play. Jalur Qwiic di-level-shift ke 5 V melalui transistor open-drain, sehingga bus dibatasi pada mode standar (100 kHz) dan mode cepat (400 kHz) saja — jangan mencoba menjalankan fast-mode-plus atau laju yang lebih tinggi melalui header Qwiic.

Konektor Qwiic mengeluarkan 5 V untuk memberi daya pada modul yang terpasang; konektor ini tidak dapat digunakan untuk memberi daya pada Pure Thermal itu sendiri — berikan daya pada papan melalui USB‑C atau konektor baterai LiPo.

SPI

Bus

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)

Bus

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 dan DAC

P6 adalah satu-satunya pin analog pengguna. Pin ini dapat digunakan sebagai input ADC 12-bit atau output DAC.

  • ADC — skala penuh pada 3,3 V di pin:

    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 — melalui pyb.DAC. Nilai 8-bit mencakup 0–3,3 V:

    from pyb import DAC
    
    dac = DAC("P6")
    voltage = 1.65
    dac.write(int(voltage / 3.3 * 255))
    

Dalam mode ADC atau DAC P6 hanya toleran 3,3 V — jangan beri tegangan 5 V.

PWM

Pin

Timer / kanal

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

Catatan

TIM1 dicadangkan oleh firmware untuk menghasilkan clock piksel sensor kamera, sehingga kanal TIM1 yang secara fisik ada di P0/P1/P2 tidak dapat digunakan untuk PWM pengguna tanpa merusak kamera.

TIM4 digunakan bersama dengan pyb.Servo — membuat instance servo mengonfigurasi ulang seluruh timer untuk operasi 50 Hz, sehingga jangan mencampur machine.PWM pada P7/P8 dengan pyb.Servo dalam skrip yang sama.

Gerakkan salah satunya melalui machine.PWM

from machine import Pin, PWM

pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)

Bus bit-banged perangkat lunak

machine.SoftI2C dan machine.SoftSPI bekerja pada GPIO manapun jika Anda membutuhkan bus tambahan.

Sensor termal (off‑board)

Selain FLIR Lepton on‑board, firmware juga menyertakan driver fir --- driver sensor termal (fir == far infrared) untuk imager termal I²C yang dihubungkan secara eksternal:

  • MLX90621 — array IR 16 × 4

  • MLX90640 — array IR 32 × 24

  • MLX90641 — array IR 16 × 12

  • AMG8833 — array IR 8 × 8

Hubungkan modul ke bus I²C papan dan baca bingkai dengan 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())

Driver fir hanya berkomunikasi dengan sensor melalui I²C 2 — hubungkan modul ke P4 (SCL) dan P5 (SDA).

Timing

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)

Timer virtual

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"))

Nilai periode dalam milidetik. Panggil deinit() untuk menghentikan dan melepaskan slot.

Real‑time clock

from machine import RTC

rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())

Jika baterai LiPo terhubung, RTC tetap menjaga waktu bahkan saat rel sistem mati (dimatikan melalui tombol daya on‑board). Hanya dengan USB yang terpasang, menekan tombol daya memutus daya ke RTC juga — sehingga waktu dinding tidak akan bertahan setelah siklus daya tanpa baterai yang terpasang.

Watchdog

from machine import WDT

wdt = WDT(timeout=5_000)
while True:
    # ...do work...
    wdt.feed()

Informasi boot dan runtime

Jendela bootloader USB

Pada setiap power-up, kamera menjalankan bootloader singkat (beberapa detik) yang memungkinkan OpenMV IDE memperbarui firmware tanpa pengguna harus memasuki mode DFU. Setelah jendela berakhir, bootloader menyerahkan ke boot.py lalu main.py.

Skrip yang berjalan dapat memasuki kembali bootloader sesuai permintaan dengan memanggil machine.bootloader().

Filesystem dan urutan boot

Firmware Pure Thermal memasang hingga tiga filesystem saat boot:

  • Flash internal — selalu dipasang di /flash. Menyimpan main.py dan README.txt secara default; dibuat pada boot pertama kali.

  • Kartu microSD — jika kartu dimasukkan, kartu dipasang di /sdcard.

  • ROMFS — filesystem read-only, memory-mapped di /rom yang digunakan untuk mengirimkan aset data besar (mis. model AI) yang mendapat manfaat dari akses zero-copy. Dipasang secara otomatis oleh MicroPython saat startup, sebelum Python pengguna manapun berjalan.

Setelah dipasang, direktori kerja diatur ke /sdcard ketika kartu ada, jika tidak maka ke /flash. Interpreter kemudian menjalankan skrip dari direktori tersebut:

  • boot.py dieksekusi pada setiap soft reset.

  • main.py dieksekusi hanya pada cold boot, segera setelah boot.py.

Meletakkan boot.py atau main.py ke kartu SD menggantikan salinan di flash tanpa menyentuhnya.

Saat terhubung melalui USB, filesystem boot (/sdcard jika kartu ada, jika tidak maka /flash) juga terdaftar sebagai drive USB mass-storage di host. Keluarkan drive sebelum mereset kamera agar host membuang cache penulisannya.

Catatan

File yang dibuat atau dimodifikasi oleh kode yang berjalan pada OpenMV Cam tidak akan muncul di host sampai drive dipasang ulang. Gunakan kartu SD untuk data apapun yang ditulis kembali oleh skrip, dan pasang ulang sebelum membaca file tersebut dari host.

Ukuran penyimpanan

Pure Thermal dikirim dengan:

  • /flash — filesystem FAT 24 MB, baca/tulis.

  • /rom — ROMFS read-only memory-mapped 8 MB, digunakan untuk mengirimkan skrip dan model ML yang mendapat manfaat dari akses mmap zero-copy.

  • /sdcard — ukuran penuh kartu microSD yang dimasukkan (saat ada), baca/tulis.

Indikator hard‑fault

Jika LED RGB pengguna berputar cepat melalui semua warna — cukup cepat sehingga cenderung terlihat seperti LED putih berkelip daripada warna yang berbeda — firmware telah mengalami hard fault yang tidak dapat dipulihkan. Flash ulang firmware untuk memulihkan.

Errata perangkat keras

Beberapa keanehan tingkat papan didokumentasikan dalam errata perangkat keras Pure Thermal. Item kunci yang perlu diketahui:

  • Interferensi konektor baterai — komponen pada PCB berada langsung di bawah konektor baterai LiPo, dan baji yang menonjol pada kepala kabel baterai dapat tersangkut di dalamnya saat kabel dicabut, terkadang menarik komponen dari papan. Potong baji dari kepala kabel dengan flush cutter sebelum penggunaan pertama.

  • RTC berhenti saat papan dimatikan — kapasitansi beban pada kristal 32 kHz (Y2) terlalu tinggi. Menghapus C96 dan C97 (pasangan yang mengapit kristal di samping STM32) memungkinkan RTC tetap berjalan pada daya cadangan. Sebagian besar papan dikirim dengan kapasitor ini sudah dihapus; jika RTC Anda kehilangan waktu saat dicabut, periksa posisi tersebut. Lihat GitHub issues #1536 dan #1600 untuk thread lengkapnya.

  • LED indikator pengisian tetap biru — pengisi daya mungkin mengakhiri siklus pengisian di mana saja antara 4,15 V dan 4,19 V tanpa mengubah indikator dari biru (mengisi daya) menjadi hijau (terisi). Baterai masih terisi penuh dalam kasus ini; percayakan pengukuran tegangan, bukan LED.

  • Silkscreen melabeli VIN sebagai VBAT — pad pada posisi VIN header OpenMV standar disilkscreen VBAT pada Pure Thermal. Labelnya salah, tetapi tidak masalah dalam praktiknya karena pad tersebut tidak memiliki koneksi listrik dengan cara apapun.

Pustaka perangkat lunak

Lihat indeks pustaka untuk daftar lengkap modul — termasuk mana yang unik untuk build Pure Thermal.