OpenMV Pure Thermal¶
A OpenMV Pure Thermal é uma placa completa de imageamento térmico 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, uma tela sensível ao toque capacitiva IPS de 4,3” e 800×480, uma saída HDMI, um soquete térmico FLIR® Lepton® e uma câmera de luz visível OV5640 de 5MP. Ela também inclui Wi‑Fi, um soquete microSD, um telêmetro a laser, um buzzer e um iluminador branco de alta potência.
Para o datasheet completo, fotos e dimensões, consulte a página do produto OpenMV Pure Thermal.
Destaques¶
STMicroelectronics STM32H743XI Cortex‑M7 a 480 MHz.
Codificador/decodificador 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).
Sensor de luz visível OV5640 de 5MP com rolling shutter.
Soquete 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.
Tela sensível ao toque capacitiva IPS de 4,3” e 800×480 (cor de 24 bits @ 60 Hz) com suporte a gestos de até 5 pontos.
Saída HDMI via serializador DVI TFP410 — até 1280×720 @ 60 Hz.
Wi‑Fi via WINC1500; MJPEG sobre RTSP suportado de imediato.
USB‑C full‑speed (12 Mb/s, com limite de corrente de 900 mA) — aparece como VCP + armazenamento em massa USB para o host, e também gerencia o carregamento.
Soquete microSD — SD até 2 GB, SDHC até 32 GB, SDXC até 2 TB.
Telêmetro a 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 status RGB do usuário.
Conector de bateria LiPo com carregamento via USB a 500 mA.
10 pinos de I/O, tolerantes a 5 V com saída de 3,3 V, 25 mA por pino (120 mA no total), com capacidade de interrupção. O P6 não é tolerante a 5 V quando usado em modo ADC ou DAC.
Conector ARM SWD de 10 pinos para depuração com ST‑LINK / J‑Link.
Conector Qwiic para periféricos I²C.
Nota
A placa possui um encaixe na borda inferior esquerda para uma porca de tripé de ¼”–20 opcional. Ela não vem instalada de fábrica — solde uma no encaixe se quiser montar a placa em um tripé de câmera padrão.
Pinagem¶
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 |
I/O digital |
RESET |
puxe para GND para resetar a placa |
SYN |
pad de sincronização de quadros — não conectado |
VIN |
pad VIN do shield — não conectado |
BOOT0 |
puxe para 3,3 V ao ligar para o bootloader DFU / ROM |
BUZZER |
buzzer piezo embarcado (acionado por TIM2/PWM) |
LED_RED |
canal vermelho do LED de status RGB (ativo em nível baixo) |
LED_GREEN |
canal verde do LED de status RGB (ativo em nível baixo) |
LED_BLUE |
canal azul do LED de status RGB (ativo em nível baixo) |
LED_WHITE |
LED iluminador branco de alta potência |
Nota
Os pads SYN e VIN no shield/header não têm conexão elétrica na Pure Thermal — eles existem apenas para compatibilidade de header. Em vez disso, alimente a placa através do USB‑C ou do conector de bateria LiPo embarcado (veja Pinos de alimentação abaixo). Observe também que o pad VIN está serigrafado como VBAT na placa (um erro de rotulagem) — a posição é a do pino VIN padrão do header OpenMV e não está conectada de qualquer forma.
Pinos de alimentação¶
3.3V — trilho regulado de 3,3 V. Até 250 mA disponíveis para shields.
GND — terra comum.
A Pure Thermal é alimentada através do USB‑C ou do conector de bateria LiPo embarcado. A porta USB‑C é limitada a 900 mA no total e também gerencia o carregamento do LiPo a 500 mA, então conectar uma bateria junto com o USB é suportado.
O botão de energia embarcado liga e desliga os trilhos do sistema e funciona quer a placa esteja sendo alimentada por USB ou pelo LiPo. Mantenha o botão pressionado por alguns segundos para alternar o estado — um toque rápido é ignorado para evitar desligamento acidental.
A seleção de fonte segue duas regras simples:
A bateria só alimenta a placa quando sua tensão está acima de 3 V. Abaixo desse limiar, o PMIC embarcado desconecta a bateria para protegê‑la contra descarga excessiva.
Quando o USB está presente, o USB alimenta a placa e qualquer LiPo conectado carrega em segundo plano.
O conector LiPo também possui proteção contra tensão reversa, então conectar a bateria ao contrário não danificará a placa.
Nota
A placa também encaminha a tensão da bateria e um sinal de leitura da corrente da bateria de volta para canais ADC do MCU, mas o suporte de firmware para qualquer um deles ainda não foi adicionado.
Pinos de recuperação e depuração¶
RESET — puxe para GND para resetar a placa. A Pure Thermal também possui um botão RESET dedicado na placa que faz a mesma coisa.
BOOT0 — puxe para 3,3 V enquanto alimenta a placa para entrar no bootloader ROM do STM32 (modo DFU). O OpenMV IDE usa esse modo para regravar o bootloader embarcado. Um botão BOOT0 dedicado na placa faz a mesma coisa — mantenha‑o pressionado enquanto liga a alimentação.
A placa expõe um header de depuração SWD (RST / SWCLK / SWDIO / SWO) ao lado do header GPIO, compatível com adaptadores ST‑LINK e SEGGER J‑Link. Um conector ARM SWD de 10 pinos separado também está instalado — ele carrega os mesmos sinais SWD (sem JTAG completo), mas no formato padrão de 10 pinos de 0,05”.
Nota
O pino de trace SWO é compartilhado com o clock SPI do FLIR® Lepton® embarcado. O SWO não pode ser usado ao mesmo tempo que o Lepton — escolha um ou outro.
Um terceiro conector PURE Modules Debug está instalado na placa. Ele expõe um punhado de sinais voltados para depuração (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 V, GND e dois pinos GPIO) para conectar módulos complementares. Os dois pinos GPIO neste conector são acionados por um barramento I²C por bit‑banging interno, em vez de um periférico de hardware.
Todos os três conectores de depuração (o header SWD em linha, o conector ARM SWD de 10 pinos e o conector PURE Modules Debug) são referenciados a 3,3 V — certifique‑se de que seu adaptador de depuração esteja configurado para lógica de 3,3 V antes de conectar.
Periféricos embarcados¶
LEDs¶
A Pure Thermal possui três LEDs na placa:
LED RGB do usuário — controlável por software, exposto como
LED_RED,LED_GREENeLED_BLUEfrom machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
Iluminador branco — acionado através de
LED_WHITE. OLED_WHITEé ligado ativo em nível alto no hardware, enquanto o firmware trata todos os outros LEDs embarcados como ativos em nível baixo, então uselow()/high()em vez deon()/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 — acionado diretamente pelo hardware de gerenciamento de energia embarcado, sem controle por software. Ele funciona quer os trilhos do sistema estejam ligados ou desligados (ou seja, com o botão de energia em qualquer posição).
Cor
Significado
Azul
carregando — veja a errata: pode não desligar quando o carregamento for concluído
Verde
carregamento concluído — veja a errata: pode não disparar de forma confiável
Vermelho
bateria fraca (≤ 3,2 V, somente quando não está carregando ativamente)
Buzzer¶
O buzzer piezo embarcado está ligado a um canal de timer — acione‑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âmera¶
O OV5640 é o CSI principal na Pure Thermal — passe cid=csi.OV5640 para endereçá‑lo 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 possui um compressor JPEG embarcado. Defina csi.CSI.pixformat como csi.JPEG e o sensor entrega quadros comprimidos diretamente à câmera pelo barramento de câmera, 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) são todos transmitidos como JPEG. Ajuste a compressão com csi.CSI.quality (0-100, maior = quadros maiores, mais detalhes):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
O OV5640 possui uma lente com autofoco acionada por voice coil. Dispare uma única passagem de autofoco via csi.CSI.ioctl com csi.IOCTL_TRIGGER_AUTO_FOCUS — o sensor varre o motor de foco uma vez e trava no que estiver à sua frente:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
Reemita o ioctl sempre que a cena mudar — o autofoco é de disparo único, não contínuo.
Nota
A saída STROBE do OV5640 (usada para flash sincronizado / iluminação IR) está ligada ao MCU na Pure Thermal, mas o suporte de firmware para ela ainda não foi adicionado.
Sensor de câmera térmica¶
O soquete FLIR® Lepton® aparece como um segundo CSI na mesma API csi — sensores de câmera. Passe cid=csi.LEPTON para endereçá‑lo e pule 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 quadro térmico) está ligada ao MCU na Pure Thermal, mas o suporte de firmware para ela ainda não foi adicionado.
Ambos os CSIs podem funcionar lado a lado. O exemplo abaixo extrai um quadro colorido do OV5640 e um quadro térmico do Lepton, depois sobrepõe o Lepton sobre o quadro colorido usando uma paleta Ironbow e uma máscara alfa que desvanece para transparente em 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,
)
Aprendizado de máquina¶
ml — Aprendizado de Máquina executa modelos TFLite quantizados no Cortex‑M7 com kernels CMSIS‑NN — rápido o suficiente para detectores compactos a alguns quadros por segundo. Modelos no sistema de arquivos somente leitura /rom carregam diretamente da flash sem copiar para a RAM. Aqui está um detector BlazeFace de 128×128 sobrepondo o rosto detectado e seus seis pontos de referência em cada quadro da câmera 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 a laser¶
O telêmetro time‑of‑flight ST VL53L1CX embarcado está ligado ao barramento I²C 2. Use o driver congelado vl53l1x — Driver do sensor de distância ToF VL53L1X para obter leituras de distância de 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 embarcado de 4,3” é 800 × 480 (WVGA) e é acionado através da interface de display RGB do módulo display — driver de display — 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 luz de fundo está ligada a um GPIO, então backlight() aceita True / False (ou qualquer valor de 0–100, onde 0 é desligado e qualquer valor diferente de zero é ligado):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
Tela sensível ao toque¶
O controlador de toque capacitivo é o FT5X06; posições de multi‑toque e eventos de gesto são expostos através de ft5x06 — Driver de Tela de Toque. Registre um callback para reagir aos toques e ler os pontos ativos 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 distribui o framebuffer do LCD para o serializador HDMI tfp410 — Controlador DVI/HDMI embarcado, de modo que um monitor externo espelha o que está no LCD. Instancie tfp410.TFP410 para habilitar a saída HDMI:
import tfp410
hdmi = tfp410.TFP410()
Se você quiser apenas a saída HDMI e não se importar com o LCD embarcado, desligue a luz de fundo e aumente a resolução do framebuffer acima de WVGA. O TFP410 suporta até 1280×720 @ 60 Hz, então, 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 embarcado é fixo em 800×480, então qualquer resolução acima de WVGA só faz sentido no monitor HDMI externo.
Para saber quando um monitor HDMI foi conectado ou desconectado, registre um callback de hot‑plug no TFP410. O callback dispara com True na conexão e False na desconexão:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
Você também pode consultar o estado da conexão a qualquer momento com isconnected() (somente quando nenhum callback estiver registrado).
A porta HDMI também carrega os canais DDC (dados de display) e CEC (controle de eletrônicos de consumo), expostos através da classe classe DisplayData – Dados do Display. Use‑a para ler o bloco EDID do monitor conectado (de modo a se adaptar à sua resolução / taxa de atualização nativa) ou para enviar/receber quadros CEC para controlar outros dispositivos HDMI no mesmo fio:
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 sobre um módulo Microchip WINC1500, exposto através da interface class WINC – driver 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 à escassez de componentes, algumas unidades da Pure Thermal foram enviadas sem o módulo WINC1500 instalado. Se network.WINC gerar um erro ou nunca conectar, verifique se a placa está sem o módulo Wi‑Fi — o restante da câmera funciona exatamente da mesma forma sem ele.
Cartão microSD¶
Quando um cartão é inserido, ele é montado automaticamente em /sdcard e pode ser usado através do sistema de arquivos comum:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Referência de barramentos¶
GPIO¶
Use machine.Pin para ler ou acionar qualquer um dos pinos serigrafados. As saídas são CMOS de 3,3 V, tolerantes a 5 V no lado de 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 borda:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Barramento |
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¶
Barramento |
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 embarcado expõe um desses barramentos I²C para módulos plug‑and‑play. A linha Qwiic tem nível deslocado para 5 V através de transistores dreno‑aberto, então o barramento é limitado apenas ao modo padrão (100 kHz) e ao modo rápido (400 kHz) — não tente rodar fast‑mode‑plus ou taxas mais altas através do header Qwiic.
O conector Qwiic fornece 5 V para alimentar módulos conectados; ele não pode ser usado para alimentar a própria Pure Thermal — em vez disso, alimente a placa através do USB‑C ou do conector de bateria LiPo.
SPI¶
Barramento |
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)¶
Barramento |
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¶
O P6 é o único pino analógico do usuário. Ele pode ser usado como uma entrada ADC de 12 bits ou como uma 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, o P6 é tolerante somente a 3,3 V — não aplique 5 V nele.
PWM¶
Pino |
Timer / canal |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Nota
O TIM1 é reservado pelo firmware para gerar o clock de pixel do sensor de câmera, então os canais do TIM1 que estão fisicamente em P0/P1/P2 não podem ser usados para PWM do usuário sem quebrar a câmera.
O TIM4 é compartilhado com pyb.Servo — instanciar um servo reconfigura todo o timer para operação a 50 Hz, então não misture machine.PWM em P7/P8 com pyb.Servo no mesmo script.
Acione qualquer um deles via machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
Barramentos por bit‑banging em software¶
machine.SoftI2C e machine.SoftSPI funcionam em qualquer GPIO caso você precise de um barramento extra.
Sensor térmico (externo)¶
Além do FLIR Lepton embarcado, o firmware também inclui o driver fir — driver de sensor térmico (fir == far infrared) para imageadores térmicos I²C conectados 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
Conecte o módulo ao barramento I²C da placa e leia quadros 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 só se comunica com o sensor através do I²C 2 — conecte 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)
Timers 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 são em milissegundos. Chame deinit() para parar e liberar 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 conectada, o RTC mantém a hora mesmo enquanto os trilhos do sistema estão desligados (desligados pelo botão de energia embarcado). Apenas com o USB conectado, pressionar o botão de energia corta a alimentação do RTC também — então o horário de relógio não sobreviverá a um ciclo de energia sem uma bateria conectada.
Watchdog¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
Informações de boot e tempo de execução¶
Janela do bootloader USB¶
A cada inicialização, a câmera executa um bootloader curto (alguns segundos) que permite que o OpenMV IDE atualize o firmware sem que o usuário precise entrar no modo DFU. Após a janela expirar, o bootloader passa o controle para boot.py e em seguida main.py.
Um script em execução pode reentrar no bootloader sob demanda chamando machine.bootloader().
Sistema de arquivos e ordem de boot¶
O firmware da Pure Thermal monta até três sistemas de arquivos no boot:
Flash interna — sempre montada em
/flash. Contémmain.pyeREADME.txtpor padrão; criada no primeiro boot.Cartão microSD — se um cartão estiver inserido, ele é montado em
/sdcard.ROMFS — sistema de arquivos somente leitura, mapeado em memória, em
/rom, usado para enviar grandes ativos de dados (por exemplo, modelos de IA) que se beneficiam de acesso zero‑copy. Montado automaticamente pelo MicroPython na inicialização, antes de qualquer Python do usuário ser executado.
Após a montagem, o diretório de trabalho é definido como /sdcard quando o cartão está presente, caso contrário /flash. O interpretador então executa scripts a partir desse diretório:
boot.pyé executado em cada soft reset.main.pyé executado somente no cold boot, imediatamente apósboot.py.
Colocar um boot.py ou main.py no cartão SD substitui a cópia na flash sem alterá‑la.
Quando conectado por USB, o sistema de arquivos de boot (/sdcard se um cartão estiver presente, caso contrário /flash) também é enumerado como uma unidade de armazenamento em massa USB no host. Ejete a unidade antes de resetar a câmera para que o host descarregue suas gravações em cache.
Nota
Arquivos criados ou modificados por código em execução na OpenMV Cam não aparecerão no host até que a unidade seja remontada. Use o cartão SD para quaisquer dados que o script grave de volta, e remonte antes de ler esses arquivos a partir do host.
Tamanhos de armazenamento¶
A Pure Thermal vem com:
/flash— sistema de arquivos FAT de 24 MB, leitura/escrita./rom— ROMFS somente leitura mapeado em memória de 8 MB, usado para enviar scripts e modelos de ML que se beneficiam de acesso por mmap zero‑copy./sdcard— tamanho total de qualquer cartão microSD inserido (quando presente), leitura/escrita.
Indicador de hard fault¶
Se o LED RGB do usuário estiver ciclando rapidamente por todas as cores — rápido o suficiente para parecer um LED branco cintilante em vez de matizes distintos — o firmware atingiu um hard fault irrecuperável. Regrave o firmware para recuperar.
Errata de hardware¶
Um punhado de peculiaridades em nível de placa estão documentadas na errata de hardware da Pure Thermal. Itens importantes a observar:
Interferência do conector da bateria — componentes na PCB ficam diretamente sob o conector da bateria LiPo, e a cunha saliente no plugue do cabo da bateria pode prender neles quando o cabo é removido, às vezes arrancando peças da placa. Apare a cunha do plugue do cabo com um alicate de corte rente antes do primeiro uso.
O RTC para enquanto a placa está desligada — a capacitância de carga no cristal de 32 kHz (Y2) é alta demais. Remover C96 e C97 (o par que flanqueia o cristal ao lado do STM32) permite que o RTC continue funcionando com a alimentação de backup. A maioria das placas é enviada com esses capacitores já removidos; se o seu RTC perde a hora quando desconectado, verifique essas posições. Veja as issues do GitHub #1536 e #1600 para o tópico completo.
O LED indicador de carregamento permanece azul — o carregador pode encerrar seu ciclo de carga em qualquer ponto entre 4,15 V e 4,19 V sem mudar o indicador de azul (carregando) para verde (carregado). A bateria ainda está totalmente carregada nesse caso; confie em uma medição de tensão, não no LED.
A serigrafia rotula incorretamente VIN como VBAT — o pad na posição VIN padrão do header OpenMV está serigrafado como
VBATna Pure Thermal. O rótulo está errado, mas isso não importa na prática porque o pad não tem conexão elétrica de qualquer forma.
Bibliotecas de software¶
Consulte o índice da biblioteca para a lista completa de módulos — incluindo quais são exclusivos do build da Pure Thermal.