OpenMV Pure Thermal

O OpenMV Pure Thermal é uma placa de imagem térmica de sistema completo construída em torno do STMicroelectronics STM32H743 (Cortex‑M7 @ 480 MHz) com 64 MB de SDRAM externa, 32 MB de flash QSPI, um codec JPEG por hardware, um ecrã tátil IPS capacitivo de 4,3» 800×480, uma saída HDMI, um socket FLIR® Lepton® térmico e uma câmara de luz visível OV5640 de 5MP. Inclui também Wi‑Fi, um socket microSD, um telémetro laser, um buzzer e um iluminador branco de alta potência.

OpenMV Pure Thermal

Para a ficha técnica completa, fotografias e dimensões, consulte a página do produto OpenMV Pure Thermal.

Destaques

  • STMicroelectronics STM32H743XI Cortex‑M7 a 480 MHz.

  • Codificador/descodificador JPEG por hardware.

  • 64 MB de SDRAM externa (~400 MB/s) mais 1 MB de SRAM interna.

  • 2 MB de flash interna + 32 MB de flash QSPI externa (~50 MB/s de leitura).

  • OV5640 sensor de luz visível de 5MP com obturador rolante.

  • Socket FLIR® Lepton® — aceita qualquer módulo Lepton 1/2/2,5/3/3,5, radiométrico ou não radiométrico, com temperatura por pixel em graus Celsius.

  • Ecrã tátil IPS capacitivo de 4,3» 800×480 (cor de 24 bits @ 60 Hz) com suporte de até 5 pontos de gesto.

  • Saída HDMI via serializador DVI TFP410 — até 1280×720 @ 60 Hz.

  • Wi‑Fi via WINC1500; MJPEG sobre RTSP suportado de raiz.

  • USB‑C de velocidade máxima (12 Mb/s, 900 mA com limitação de corrente) — aparece como VCP + armazenamento de massa USB no anfitrião e gere também o carregamento.

  • Socket microSD — SD até 2 GB, SDHC até 32 GB, SDXC até 2 TB.

  • Telémetro laser VL53L1CX (até ~4 m).

  • Buzzer com volume/frequência controlados por software.

  • Iluminador LED branco de alta potência além do LED de estado RGB de utilizador.

  • Conector de bateria LiPo com carregamento USB a 500 mA.

  • 10 pinos de E/S, tolerantes a 5 V com saída de 3,3 V, 25 mA por pino (120 mA no total), com capacidade de interrupção. P6 não é tolerante a 5 V quando utilizado em modo ADC ou DAC.

  • Conector SWD ARM de 10 pinos para depuração com ST‑LINK / J‑Link.

  • Conector Qwiic para periféricos I²C.

Nota

A placa tem uma ranhura na extremidade inferior esquerda para uma porca de tripé ¼»–20 opcional. Não é montada de fábrica — solde-a na ranhura se pretender fixar a placa num tripé de câmara standard.

Pinout

OpenMV Pure Thermal pinout

Referência de pinos

Nome do pino

Função

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

E/S digital

RESET

ligar a GND para reiniciar a placa

SYN

pad de sincronização de fotograma — não ligado

VIN

pad VIN do shield — não ligado

BOOT0

ligar a 3,3 V na ligação para DFU / bootloader ROM

BUZZER

buzzer piezo integrado (controlado por TIM2/PWM)

LED_RED

canal vermelho do LED de estado RGB (activo baixo)

LED_GREEN

canal verde do LED de estado RGB (activo baixo)

LED_BLUE

canal azul do LED de estado RGB (activo baixo)

LED_WHITE

LED iluminador branco de alta potência

Nota

Os pads SYN e VIN no shield/header não têm ligação eléctrica no Pure Thermal — existem apenas para compatibilidade com o header. Alimente a placa através do USB‑C ou do conector de bateria LiPo integrado (ver Pinos de alimentação abaixo). Note também que o pad VIN está serigrafiado como VBAT na placa (um erro de etiquetagem) — a posição é o pino VIN standard do header OpenMV e não está ligado de qualquer forma.

Pinos de alimentação

  • 3,3V — rail regulado de 3,3 V. Até 250 mA disponíveis para shields.

  • GND — massa comum.

O Pure Thermal é alimentado através de USB‑C ou do conector de bateria LiPo integrado. A porta USB‑C tem limitação de corrente a 900 mA no total e gere também o carregamento LiPo a 500 mA, pelo que ligar uma bateria juntamente com USB é suportado.

O botão de alimentação integrado comuta os rails do sistema ligado e desligado e funciona quer a placa esteja a ser alimentada por USB ou pela LiPo. Mantenha o botão premido durante alguns segundos para mudar de estado — um toque rápido é ignorado para evitar desligamentos acidentais.

A selecção da fonte segue duas regras simples:

  • A bateria só alimenta a placa quando a sua tensão está acima de 3 V. Abaixo desse limiar, o PMIC integrado desliga a bateria para a proteger de descarga excessiva.

  • Quando o USB está presente, o USB alimenta a placa e qualquer LiPo ligada carrega em segundo plano.

O conector LiPo também dispõe de protecção contra polaridade inversa, pelo que ligar a bateria ao contrário não danifica a placa.

Nota

A placa também encaminha a tensão da bateria e um sinal de detecção de corrente da bateria de volta para canais ADC do MCU, mas o suporte de firmware para ambos ainda não foi adicionado.

Pinos de recuperação e depuração

  • RESET — ligar a GND para reiniciar a placa. O Pure Thermal também tem um botão RESET dedicado na placa que faz o mesmo.

  • BOOT0 — ligar a 3,3 V ao ligar a placa para entrar no bootloader ROM do STM32 (modo DFU). O OpenMV IDE usa este modo para reflashear o bootloader integrado. Um botão BOOT0 dedicado na placa faz o mesmo — mantenha-o premido ao aplicar alimentação.

A placa expõe um header de depuração SWD (RST / SWCLK / SWDIO / SWO) junto ao header GPIO, compatível com adaptadores ST‑LINK e SEGGER J‑Link. Um conector SWD ARM de 10 pinos separado também está montado — transporta os mesmos sinais SWD (sem JTAG completo) mas no form factor standard de 10 pinos 0,05».

Nota

O pino de rastreio SWO é partilhado com o clock SPI do FLIR® Lepton® integrado. O SWO não pode ser usado ao mesmo tempo que o Lepton — escolha um ou outro.

Um terceiro conector PURE Modules Debug está montado na placa. Expõe um conjunto de sinais orientados para depuração (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 V, GND e dois pinos GPIO) para ligar módulos complementares. Os dois pinos GPIO neste conector são controlados por um bus I²C por software (bit-banged) em vez de um periférico de hardware.

Os três conectores de depuração (o header SWD em linha, o conector SWD ARM de 10 pinos e o conector PURE Modules Debug) têm referência a 3,3 V — certifique-se de que o seu adaptador de depuração está configurado para lógica de 3,3 V antes de ligar.

Periféricos integrados

LEDs

O Pure Thermal tem três LEDs na placa:

  • LED RGB de utilizador — controlável por software, exposto como LED_RED, LED_GREEN e LED_BLUE

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • Iluminador branco — controlado através de LED_WHITE. LED_WHITE está ligado activo alto no hardware enquanto o firmware trata todos os outros LEDs integrados como activos baixos, por isso use low() / high() em vez de on() / off() (que inverteriam o sentido):

    from machine import LED
    
    light = LED("LED_WHITE")
    light.low()    # turn the white LED ON
    light.high()   # turn the white LED OFF
    
  • LED de carregamento — controlado directamente pelo hardware de gestão de energia integrado, sem controlo por software. Funciona quer os rails do sistema estejam ligados ou desligados (ou seja, com o botão de alimentação em qualquer posição).

    Cor

    Significado

    Azul

    a carregar — ver errata: pode não se apagar quando o carregamento termina

    Verde

    carregamento completo — ver errata: pode não activar de forma fiável

    Vermelho

    bateria fraca (≤ 3,2 V, apenas quando não está activamente a carregar)

Buzzer

O buzzer piezo integrado está ligado a um canal de temporizador — controle-o com machine.PWM para tons com frequência (altura) e ciclo de trabalho (volume) controlados por software:

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 de câmara

O OV5640 é o CSI principal no Pure Thermal — passe cid=csi.OV5640 para o endereçar explicitamente:

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

O OV5640 tem um compressor JPEG integrado. Defina csi.CSI.pixformat como csi.JPEG e o sensor entrega fotogramas comprimidos directamente à câmara através do bus da câmara, o que torna práticas as capturas em alta resolução: csi.HD (1280×720), csi.FHD (1920×1080) e o 5MP completo csi.WQXGA2 (2592×1944) transmitem todos em JPEG. Ajuste a compressão com csi.CSI.quality (0-100, maior = fotogramas maiores, mais detalhe):

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

O OV5640 tem uma lente de autofoco com actuador de bobine de voz. Desencadeie uma passagem de autofoco única via csi.CSI.ioctl com csi.IOCTL_TRIGGER_AUTO_FOCUS — o sensor percorre o motor de foco uma vez e bloqueia no que estiver à sua frente:

cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)

Reemita o ioctl sempre que a cena mudar — o autofoco é de passagem única, não contínuo.

Nota

A saída STROBE do OV5640 (usada para flash sincronizado / iluminação IR) está ligada ao MCU no Pure Thermal, mas o suporte de firmware para tal ainda não foi adicionado.

Sensor de câmara térmica

O socket FLIR® Lepton® aparece como um segundo CSI na mesma API csi — sensores de câmara. Passe cid=csi.LEPTON para o endereçar e ignore o reset de hardware:

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

Nota

A saída VSYNC do Lepton (um pulso por fotograma térmico) está ligada ao MCU no Pure Thermal, mas o suporte de firmware para tal ainda não foi adicionado.

Ambos os CSIs podem funcionar lado a lado. O exemplo abaixo obtém um fotograma de cor do OV5640 e um fotograma térmico do Lepton, e depois sobrepõe o Lepton sobre o fotograma de cor usando uma paleta Ironbow e uma máscara alfa que desvanece para transparente a baixa intensidade:

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

Aprendizagem automática

ml — Machine Learning executa modelos TFLite quantizados no Cortex‑M7 com kernels CMSIS‑NN — rápido o suficiente para detectores compactos a alguns fotogramas por segundo. Os modelos no sistema de ficheiros só de leitura /rom carregam directamente da flash sem copiar para RAM. Aqui está um detector BlazeFace 128×128 que sobrepõe a face detectada e os seus seis pontos de referência em cada fotograma da câmara de luz visível:

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

Telémetro laser

O telêmetro de tempo de voo ST VL53L1CX integrado está ligado ao bus I²C 2. Use o driver frozen vl53l1x — driver do sensor de distância ToF VL53L1X para obter leituras de distância até ~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)

Saída LCD

O LCD integrado de 4,3» é 800 × 480 (WVGA) e é controlado através da interface de visualização RGB do módulo display — controlador de ecrã — passe framesize=display.FWVGA para corresponder à sua resolução nativa:

import display

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

A retroiluminação está ligada a um GPIO, pelo que backlight() aceita True / False (ou qualquer valor de 0–100, onde 0 é desligado e qualquer valor não nulo é ligado):

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

Ecrã tátil

O controlador táctil capacitivo é o FT5X06; posições multi-toque e eventos de gesto são expostos através de ft5x06 — Driver de Ecrã Tátil. Registe um callback para reagir a toques e leia os pontos activos dentro dele:

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)

Saída HDMI

O firmware também encaminha o buffer de fotograma do LCD para o serializador HDMI tfp410 — Controlador DVI/HDMI integrado, de modo a que um monitor externo espelhe o que está no LCD. Instancie tfp410.TFP410 para activar a saída HDMI:

import tfp410

hdmi = tfp410.TFP410()

Se apenas pretende saída HDMI e não se preocupa com o LCD integrado, desligue a retroiluminação e aumente a resolução do buffer de fotograma acima de WVGA. O TFP410 suporta até 1280×720 @ 60 Hz, por exemplo:

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

O painel integrado está fixo a 800×480, por isso qualquer coisa acima de WVGA só é significativa no monitor HDMI externo.

Para saber quando um monitor HDMI foi ligado ou desligado, registe um callback de hot-plug no TFP410. O callback é activado com True ao ligar e False ao desligar:

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

hdmi.hotplug_callback(on_hotplug)

Pode também verificar o estado da ligação a qualquer momento com isconnected() (apenas quando nenhum callback está registado).

A porta HDMI também transporta os canais DDC (dados de visualização) e CEC (controlo de electrónica de consumo), expostos através da classe class DisplayData – Dados do Ecrã. Use-a para ler o bloco EDID do monitor ligado (para se adaptar à sua resolução nativa / taxa de actualização) ou para enviar/receber frames CEC para controlar outros dispositivos HDMI no mesmo cabo:

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

O Wi‑Fi funciona através de um módulo Microchip WINC1500, exposto através da interface class WINC – controlador do 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])

Nota

Devido a escassez de componentes, algumas unidades Pure Thermal foram expedidas sem o módulo WINC1500 montado. Se network.WINC lançar um erro ou nunca conectar, verifique a placa para um módulo Wi‑Fi em falta — o resto da câmara funciona exactamente da mesma forma sem ele.

Cartão microSD

Quando um cartão é inserido, é montado automaticamente em /sdcard e pode ser usado através do sistema de ficheiros regular:

import os

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

Referência de buses

GPIO

Use machine.Pin para ler ou controlar qualquer um dos pinos serigrafiados. As saídas são CMOS de 3,3 V, tolerantes a 5 V no lado da entrada, e podem drenar/fornecer até 25 mA por pino (120 mA no total em todo o 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())

Qualquer pino de entrada também pode disparar uma interrupção em transições de flanco:

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

O mesmo hardware também pode ser usado em modo alvo (escravo) através de machine.I2CTarget para expor uma região de memória a outro controlador I²C:

from machine import I2CTarget

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

O conector Qwiic integrado expõe um destes buses I²C para módulos plug-and-play. A linha Qwiic tem mudança de nível para 5 V através de transistores de drenagem aberta, pelo que o bus está limitado ao modo standard (100 kHz) e modo rápido (400 kHz) apenas — não tente utilizar taxas superiores ao modo rápido através do header Qwiic.

O conector Qwiic fornece 5 V para alimentar os módulos ligados; não pode ser usado para alimentar o próprio Pure Thermal — alimente a placa através de USB‑C ou do conector de bateria 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 e DAC

P6 é o único pino analógico de utilizador. Pode ser usado como entrada ADC de 12 bits ou como saída DAC.

  • ADC — escala completa a 3,3 V no pino:

    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 — através de pyb.DAC. O valor de 8 bits cobre 0–3,3 V:

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

Em modo ADC ou DAC, P6 é tolerante apenas a 3,3 V — não aplique 5 V.

PWM

Pino

Temporizador / canal

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

Nota

TIM1 está reservado pelo firmware para gerar o clock de pixel do sensor da câmara, pelo que os canais TIM1 que estão fisicamente em P0/P1/P2 não podem ser usados para PWM de utilizador sem quebrar a câmara.

TIM4 é partilhado com pyb.Servo — instanciar um servo reconfigura o temporizador inteiro para operação a 50 Hz, por isso não misture machine.PWM em P7/P8 com pyb.Servo no mesmo script.

Controle qualquer um deles via machine.PWM

from machine import Pin, PWM

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

Buses por software (bit-banged)

machine.SoftI2C e machine.SoftSPI funcionam em qualquer GPIO se precisar de um bus extra.

Sensor térmico (externo)

Para além do FLIR Lepton integrado, o firmware também inclui o driver fir — driver de sensor térmico (fir == infravermelho longínquo) para imagiadores térmicos I²C ligados externamente:

  • MLX90621 — array IR de 16 × 4

  • MLX90640 — array IR de 32 × 24

  • MLX90641 — array IR de 16 × 12

  • AMG8833 — array IR de 8 × 8

Ligue o módulo ao bus I²C da placa e leia fotogramas com 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())

O driver fir comunica com o sensor apenas através de I²C 2 — ligue o módulo a P4 (SCL) e P5 (SDA).

Temporização

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)

Temporizadores virtuais

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

Os valores de período estão em milissegundos. Chame deinit() para parar e libertar o slot.

Relógio de tempo real

from machine import RTC

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

Se uma bateria LiPo estiver ligada, o RTC mantém a hora mesmo enquanto os rails do sistema estão desligados (desactivados via o botão de alimentação integrado). Com apenas USB ligado, premir o botão de alimentação corta também a alimentação ao RTC — pelo que a hora do relógio não sobrevive a um ciclo de alimentação sem uma bateria ligada.

Watchdog

from machine import WDT

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

Informação de arranque e tempo de execução

Janela do bootloader USB

Em cada arranque, a câmara executa um bootloader curto (alguns segundos) que permite ao OpenMV IDE actualizar o firmware sem que o utilizador precise de entrar no modo DFU. Após o fim da janela, o bootloader passa o controlo para boot.py e depois para main.py.

Um script em execução pode re-entrar no bootloader a pedido chamando machine.bootloader().

Sistema de ficheiros e ordem de arranque

O firmware do Pure Thermal monta até três sistemas de ficheiros no arranque:

  • Flash interna — sempre montada em /flash. Contém main.py e README.txt por omissão; criada no primeiro arranque.

  • Cartão microSD — se um cartão estiver inserido, é montado em /sdcard.

  • ROMFS — sistema de ficheiros só de leitura mapeado em memória em /rom, usado para distribuir grandes recursos de dados (p. ex. modelos de IA) que beneficiam de acesso sem cópia. Montado automaticamente pelo MicroPython no arranque, antes de qualquer Python de utilizador ser executado.

Após a montagem, o directório de trabalho é definido como /sdcard quando o cartão está presente, caso contrário /flash. O interpretador executa então scripts a partir desse directório:

  • boot.py é executado em cada reset por software.

  • main.py é executado apenas no arranque a frio, imediatamente após boot.py.

Colocar um boot.py ou main.py no cartão SD substitui a cópia em flash sem a modificar.

Quando ligado via USB, o sistema de ficheiros de arranque (/sdcard se um cartão estiver presente, caso contrário /flash) também aparece como unidade de armazenamento de massa USB no anfitrião. Ejicte a unidade antes de reiniciar a câmara para que o anfitrião liberte as suas escritas em cache.

Nota

Os ficheiros criados ou modificados por código a correr na OpenMV Cam não aparecem no anfitrião até que a unidade seja remontada. Use o cartão SD para quaisquer dados que o script escreva, e remonte antes de ler esses ficheiros a partir do anfitrião.

Tamanhos de armazenamento

O Pure Thermal é fornecido com:

  • /flash — sistema de ficheiros FAT de 24 MB, leitura/escrita.

  • /rom — ROMFS de 8 MB só de leitura mapeado em memória, usado para distribuir scripts e modelos ML que beneficiam de acesso mmap sem cópia.

  • /sdcard — tamanho total do cartão microSD inserido (quando presente), leitura/escrita.

Indicador de falha grave

Se o LED RGB de utilizador estiver a ciclar rapidamente por todas as cores — rápido o suficiente para parecer um LED branco cintilante em vez de matizes distintos — o firmware atingiu uma falha grave irrecuperável. Reflasheie o firmware para recuperar.

Errata de hardware

Alguns peculiaridades ao nível da placa estão documentadas na errata de hardware do Pure Thermal. Pontos-chave a ter em atenção:

  • Interferência do conector da bateria — os componentes no PCB ficam directamente sob o conector da bateria LiPo, e a cunha saliente no conector do cabo da bateria pode enganchar neles ao remover o cabo, por vezes arrancando componentes da placa. Corte a cunha do conector do cabo com cortadores de ras antes da primeira utilização.

  • O RTC para enquanto a placa está desligada — a capacitância de carga no cristal de 32 kHz (Y2) é demasiado elevada. Remover C96 e C97 (o par flanqueando o cristal junto ao STM32) permite ao RTC continuar a funcionar com alimentação de reserva. A maioria das placas é expedida com estes condensadores já removidos; se o seu RTC perder a hora quando desligado, verifique essas posições. Ver issues GitHub #1536 e #1600 para o fio completo.

  • O LED indicador de carregamento fica azul — o carregador pode terminar o seu ciclo de carga entre 4,15 V e 4,19 V sem mudar o indicador de azul (a carregar) para verde (carregado). A bateria está ainda totalmente carregada neste caso; confie numa medição de tensão, não no LED.

  • A serigrafia etiqueta VIN como VBAT — o pad na posição VIN standard do header OpenMV está serigrafiado como VBAT no Pure Thermal. A etiqueta está errada, mas na prática não tem importância porque o pad não tem ligação eléctrica de qualquer forma.

Bibliotecas de software

Consulte o índice de biblioteca para a lista completa de módulos — incluindo quais são exclusivos da compilação Pure Thermal.