OpenMV Pure Thermal¶
L’OpenMV Pure Thermal è una scheda completa per imaging termico costruita attorno allo STMicroelectronics STM32H743 (Cortex‑M7 @ 480 MHz) con 64 MB di SDRAM esterna, 32 MB di flash QSPI, un codec JPEG hardware, un touchscreen capacitivo IPS da 4,3» 800×480, un’uscita HDMI, uno zoccolo termico FLIR® Lepton® e una camera a luce visibile OV5640 da 5MP. Integra inoltre il Wi‑Fi, uno slot microSD, un telemetro laser, un cicalino e un illuminatore bianco ad alta potenza.
Per il datasheet completo, le foto e le dimensioni, consulta la pagina prodotto OpenMV Pure Thermal.
In evidenza¶
STMicroelectronics STM32H743XI Cortex‑M7 a 480 MHz.
Encoder/decoder JPEG hardware.
64 MB di SDRAM esterna (~400 MB/s) più 1 MB di SRAM interna.
2 MB di flash interna + 32 MB di flash QSPI esterna (~50 MB/s in lettura).
Sensore a luce visibile rolling‑shutter OV5640 da 5MP.
Zoccolo FLIR® Lepton® — accetta qualsiasi modulo Lepton 1/2/2.5/3/3.5, radiometrico o non radiometrico, con la temperatura per pixel in gradi Celsius.
Touchscreen capacitivo IPS da 4,3» 800×480 (colore a 24 bit @ 60 Hz) con supporto a gesti fino a 5 punti.
Uscita HDMI tramite serializzatore DVI TFP410 — fino a 1280×720 @ 60 Hz.
Wi‑Fi tramite WINC1500; MJPEG su RTSP supportato di serie.
USB‑C full‑speed (12 Mb/s, con limite di corrente a 900 mA) — appare all’host come VCP + memoria di massa USB e gestisce anche la ricarica.
Slot microSD — SD fino a 2 GB, SDHC fino a 32 GB, SDXC fino a 2 TB.
Telemetro laser VL53L1CX (fino a ~4 m).
Cicalino con volume / frequenza controllati via software.
LED illuminatore bianco ad alta potenza oltre al LED RGB di stato utente.
Connettore per batteria LiPo con ricarica USB a 500 mA.
10 pin di I/O, tolleranti a 5 V con uscita a 3,3 V, 25 mA per pin (120 mA totali), capaci di gestire interrupt. P6 non è tollerante a 5 V quando usato in modalità ADC o DAC.
Connettore ARM SWD a 10 pin per il debug con ST‑LINK / J‑Link.
Connettore Qwiic per periferiche I²C.
Nota
La scheda dispone di una fessura sul bordo inferiore sinistro per un dado per treppiede ¼»–20 opzionale. Non è montato di fabbrica — salda un dado nella fessura se vuoi montare la scheda su un treppiede fotografico standard.
Pinout¶
Riferimento dei pin¶
Nome pin |
Funzione |
|---|---|
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 digitale |
RESET |
collega a GND per resettare la scheda |
SYN |
pad di frame‑sync — non connesso |
VIN |
pad VIN dello shield — non connesso |
BOOT0 |
collega a 3,3 V all’accensione per il bootloader DFU / ROM |
BUZZER |
cicalino piezo a bordo (pilotato da TIM2/PWM) |
LED_RED |
canale rosso del LED RGB di stato (attivo basso) |
LED_GREEN |
canale verde del LED RGB di stato (attivo basso) |
LED_BLUE |
canale blu del LED RGB di stato (attivo basso) |
LED_WHITE |
LED illuminatore bianco ad alta potenza |
Nota
I pad SYN e VIN sullo shield/header non hanno alcun collegamento elettrico sul Pure Thermal — sono presenti solo per compatibilità con l’header. Alimenta invece la scheda tramite USB‑C o tramite il connettore per batteria LiPo a bordo (vedi Pin di alimentazione più sotto). Nota inoltre che il pad VIN è serigrafato VBAT sulla scheda (un errore di etichettatura) — la posizione è quella standard del pin VIN dell’header OpenMV e non è comunque connessa.
Pin di alimentazione¶
3.3V — rail regolato a 3,3 V. Fino a 250 mA disponibili per gli shield.
GND — massa comune.
Il Pure Thermal è alimentato tramite USB‑C o tramite il connettore per batteria LiPo a bordo. La porta USB‑C ha un limite di corrente di 900 mA totali e gestisce anche la ricarica della LiPo a 500 mA, quindi è supportato collegare una batteria insieme all’USB.
Il pulsante di accensione a bordo attiva e disattiva i rail di sistema e funziona sia che la scheda venga alimentata da USB sia da LiPo. Tieni premuto il pulsante per un paio di secondi per cambiare stato — un tocco rapido viene ignorato per evitare spegnimenti accidentali.
La selezione della sorgente segue due semplici regole:
La batteria alimenta la scheda solo quando la sua tensione è superiore a 3 V. Al di sotto di questa soglia, il PMIC a bordo scollega la batteria per proteggerla da una scarica eccessiva.
Quando l’USB è presente, l’USB alimenta la scheda e qualsiasi LiPo collegata si ricarica in background.
Il connettore LiPo dispone anche di protezione da inversione di polarità, quindi collegare la batteria al contrario non danneggia la scheda.
Nota
La scheda instrada anche la tensione della batteria e un segnale di misura della corrente della batteria verso i canali ADC dell’MCU, ma il supporto firmware per entrambi non è ancora stato aggiunto.
Pin di recovery e debug¶
RESET — collega a GND per resettare la scheda. Il Pure Thermal dispone anche di un pulsante RESET dedicato sulla scheda che svolge la stessa funzione.
BOOT0 — collega a 3,3 V mentre alimenti la scheda per entrare nel bootloader ROM dell’STM32 (modalità DFU). OpenMV IDE usa questa modalità per riflashare il bootloader a bordo. Un pulsante BOOT0 dedicato sulla scheda svolge la stessa funzione — tienilo premuto durante l’accensione.
La scheda espone un header di debug SWD (RST / SWCLK / SWDIO / SWO) accanto all’header GPIO, compatibile con gli adattatori ST‑LINK e SEGGER J‑Link. È montato anche un connettore ARM SWD a 10 pin separato — porta gli stessi segnali SWD (niente JTAG completo) ma nel formato standard a 10 pin da 0,05».
Nota
Il pin di trace SWO è condiviso con il clock SPI del FLIR® Lepton® a bordo. SWO non può essere usato contemporaneamente al Lepton — scegline uno dei due.
Sulla scheda è montato un terzo connettore PURE Modules Debug. Espone una manciata di segnali orientati al debug (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 V, GND e due pin GPIO) per collegare moduli complementari. I due pin GPIO su questo connettore sono pilotati da un bus I²C bit‑banged interno anziché da una periferica hardware.
Tutti e tre i connettori di debug (l’header SWD inline, il connettore ARM SWD a 10 pin e il connettore PURE Modules Debug) sono riferiti a 3,3 V — assicurati che il tuo adattatore di debug sia configurato per logica a 3,3 V prima di collegarlo.
Periferiche a bordo¶
LED¶
Il Pure Thermal ha tre LED sulla scheda:
LED RGB utente — controllabile via software, esposto come
LED_RED,LED_GREENeLED_BLUEfrom machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
Illuminatore bianco — pilotato tramite
LED_WHITE.LED_WHITEè cablato attivo alto in hardware mentre il firmware tratta ogni altro LED a bordo come attivo basso, quindi usalow()/high()anzichéon()/off()(che invertirebbero la logica):from machine import LED light = LED("LED_WHITE") light.low() # turn the white LED ON light.high() # turn the white LED OFF
LED di ricarica — pilotato direttamente dall’hardware di gestione dell’alimentazione a bordo, senza controllo software. Funziona indipendentemente dal fatto che i rail di sistema siano accesi o spenti (cioè con il pulsante di accensione in entrambe le posizioni).
Colore
Significato
Blu
in ricarica — vedi errata: potrebbe non spegnersi al completamento della ricarica
Verde
ricarica completata — vedi errata: potrebbe non attivarsi in modo affidabile
Rosso
batteria scarica (≤ 3,2 V, solo quando non è in ricarica attiva)
Cicalino¶
Il cicalino piezo a bordo è cablato a un canale di un timer — pilotalo con machine.PWM per generare toni con frequenza (altezza) e duty cycle (volume) controllati via 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()
Sensore della camera¶
L’OV5640 è la CSI principale sul Pure Thermal — passa cid=csi.OV5640 per indirizzarla esplicitamente:
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()
L’OV5640 dispone di un compressore JPEG a bordo. Imposta csi.CSI.pixformat su csi.JPEG e il sensore consegna frame compressi direttamente alla cam sul bus della camera, il che rende pratiche le acquisizioni ad alta risoluzione: csi.HD (1280×720), csi.FHD (1920×1080) e l’intera modalità 5MP csi.WQXGA2 (2592×1944) vengono tutte trasmesse in JPEG. Regola la compressione con csi.CSI.quality (0-100, più alto = frame più grandi, più dettaglio):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
L’OV5640 ha un obiettivo con autofocus ad attuatore voice-coil. Avvia una singola passata di autofocus tramite csi.CSI.ioctl con csi.IOCTL_TRIGGER_AUTO_FOCUS — il sensore muove il motore di messa a fuoco una volta e si blocca su qualunque cosa si trovi davanti:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
Riemetti l’ioctl ogni volta che la scena cambia — l’autofocus è a scatto singolo, non continuo.
Nota
L’uscita STROBE dell’OV5640 (usata per il flash sincronizzato / l’illuminazione IR) è cablata all’MCU sul Pure Thermal, ma il supporto firmware non è ancora stato aggiunto.
Sensore della camera termica¶
Lo zoccolo FLIR® Lepton® appare come una seconda CSI sulla stessa API csi — sensori camera. Passa cid=csi.LEPTON per indirizzarla e salta il reset 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
L’uscita VSYNC del Lepton (un impulso per ogni frame termico) è cablata all’MCU sul Pure Thermal, ma il supporto firmware non è ancora stato aggiunto.
Entrambe le CSI possono funzionare fianco a fianco. L’esempio seguente preleva un frame a colori dall’OV5640 e un frame termico dal Lepton, poi sovrappone il Lepton al frame a colori usando una palette Ironbow e una maschera alpha che sfuma fino alla trasparenza alle basse intensità:
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,
)
Machine learning¶
ml — Machine Learning esegue modelli TFLite quantizzati sul Cortex‑M7 con kernel CMSIS‑NN — abbastanza veloce per detector compatti a qualche frame al secondo. I modelli sul filesystem di sola lettura /rom vengono caricati direttamente dalla flash senza copiarli nella RAM. Ecco un detector BlazeFace 128×128 che sovrappone il volto rilevato e i suoi sei landmark su ogni frame proveniente dalla camera a luce visibile:
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")
Telemetro laser¶
Il telemetro time‑of‑flight ST VL53L1CX a bordo è cablato al bus I²C 2. Usa il driver congelato vl53l1x — Driver del sensore di distanza ToF VL53L1X per ottenere letture di distanza fino a ~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)
Uscita LCD¶
L’LCD a bordo da 4,3» è 800 × 480 (WVGA) ed è pilotato tramite l’interfaccia di display RGB del modulo display — driver del display — passa framesize=display.FWVGA per corrispondere alla sua risoluzione nativa:
import display
lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True) # turn the LCD backlight on
lcd.write(img)
La retroilluminazione è cablata a un GPIO, quindi backlight() accetta True / False (o qualsiasi valore 0–100, dove 0 è spento e qualsiasi valore diverso da zero è acceso):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
Touchscreen¶
Il controller touch capacitivo è l’FT5X06; le posizioni multi‑touch e gli eventi di gesto sono esposti tramite ft5x06 — Driver del touch screen. Registra una callback per reagire ai tocchi e leggere al suo interno i punti attivi:
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)
Uscita HDMI¶
Il firmware indirizza anche il framebuffer dell’LCD verso il serializzatore HDMI tfp410 — Controller DVI/HDMI a bordo, in modo che un monitor esterno rispecchi ciò che è sull’LCD. Istanzia tfp410.TFP410 per abilitare l’uscita HDMI:
import tfp410
hdmi = tfp410.TFP410()
Se vuoi solo l’uscita HDMI e non ti interessa l’LCD a bordo, spegni la retroilluminazione e aumenta la risoluzione del framebuffer al di sopra del WVGA. Il TFP410 supporta fino a 1280×720 @ 60 Hz, quindi ad esempio:
lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False) # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()
Il pannello a bordo è fisso a 800×480, quindi qualsiasi risoluzione superiore al WVGA è significativa solo sul monitor HDMI esterno.
Per sapere quando un monitor HDMI è stato collegato o scollegato, registra una callback di hot‑plug sul TFP410. La callback scatta con True al collegamento e False allo scollegamento:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
Puoi anche interrogare lo stato della connessione in qualsiasi momento con isconnected() (solo quando non è registrata alcuna callback).
La porta HDMI trasporta anche i canali DDC (display data) e CEC (consumer electronics control), esposti tramite la classe class DisplayData – Dati del Display. Usala per leggere il blocco EDID del monitor collegato (così puoi adattarti alla sua risoluzione / frequenza di aggiornamento native) oppure per inviare/ricevere frame CEC al fine di controllare altri dispositivi HDMI sullo stesso filo:
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¶
Il Wi‑Fi gira su un modulo Microchip WINC1500, esposto tramite l’interfaccia class WINC – driver dello 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
A causa della carenza di componenti, alcune unità Pure Thermal sono state spedite senza il modulo WINC1500 montato. Se network.WINC solleva un errore o non si connette mai, controlla se sulla scheda manca il modulo Wi‑Fi — il resto della camera funziona esattamente allo stesso modo senza di esso.
Scheda microSD¶
Quando viene inserita una scheda, questa viene montata automaticamente su /sdcard ed è utilizzabile attraverso il normale file system:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Riferimento dei bus¶
GPIO¶
Usa machine.Pin per leggere o pilotare qualsiasi pin serigrafato. Le uscite sono CMOS a 3,3 V, tolleranti a 5 V sul lato input e possono assorbire/erogare fino a 25 mA per pin (120 mA totali sull’intero 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())
Qualsiasi pin di input può anche generare un interrupt sulle transizioni di fronte:
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")
Lo stesso hardware può essere usato anche in modalità target (slave) tramite machine.I2CTarget per esporre una regione di memoria a un altro controller I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
Il connettore Qwiic a bordo espone uno di questi bus I²C per moduli plug‑and‑play. La linea Qwiic è level‑shiftata a 5 V tramite transistor open‑drain, quindi il bus è limitato alla sola modalità standard (100 kHz) e modalità fast (400 kHz) — non tentare di far girare fast‑mode‑plus o rate superiori attraverso l’header Qwiic.
Il connettore Qwiic eroga 5 V per alimentare i moduli collegati; non può essere usato per alimentare il Pure Thermal stesso — alimenta invece la scheda tramite USB‑C o il connettore per batteria 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 è l’unico pin analogico utente. Può essere usato come ingresso ADC a 12 bit oppure come uscita DAC.
ADC — fondo scala a 3,3 V sul 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 — tramite
pyb.DAC. Il valore a 8 bit copre 0–3,3 V:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
In modalità ADC o DAC, P6 è tollerante solo a 3,3 V — non fornirgli 5 V.
PWM¶
Pin |
Timer / canale |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Nota
TIM1 è riservato dal firmware per generare il pixel clock del sensore della camera, quindi i canali TIM1 che sono fisicamente su P0/P1/P2 non possono essere usati per il PWM utente senza compromettere la camera.
TIM4 è condiviso con pyb.Servo — istanziare un servo riconfigura l’intero timer per il funzionamento a 50 Hz, quindi non mischiare machine.PWM su P7/P8 con pyb.Servo nello stesso script.
Pilotane uno qualsiasi tramite machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
Bus software bit‑banged¶
machine.SoftI2C e machine.SoftSPI funzionano su qualsiasi GPIO se hai bisogno di un bus aggiuntivo.
Sensore termico (esterno)¶
Oltre al FLIR Lepton a bordo, il firmware include anche il driver fir — driver del sensore termico (fir == far infrared) per imager termici I²C cablati esternamente:
MLX90621 — array IR 16 × 4
MLX90640 — array IR 32 × 24
MLX90641 — array IR 16 × 12
AMG8833 — array IR 8 × 8
Cabla il modulo al bus I²C della scheda e leggi i frame con 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())
Il driver fir comunica con il sensore solo tramite I²C 2 — cabla il modulo a P4 (SCL) e 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 virtuali¶
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"))
I valori di periodo sono in millisecondi. Chiama deinit() per fermare e rilasciare lo slot.
Real‑time clock¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
Se è collegata una batteria LiPo, l’RTC mantiene l’ora anche mentre i rail di sistema sono spenti (spenti tramite il pulsante di accensione a bordo). Con solo l’USB collegato, premere il pulsante di accensione taglia l’alimentazione anche all’RTC — quindi l’ora di sistema non sopravviverà a un ciclo di alimentazione senza una batteria collegata.
Watchdog¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
Informazioni di boot e runtime¶
Finestra del bootloader USB¶
A ogni accensione la camera esegue un breve bootloader (pochi secondi) che permette a OpenMV IDE di aggiornare il firmware senza che l’utente debba entrare in modalità DFU. Una volta scaduta la finestra, il bootloader passa il controllo a boot.py e poi a main.py.
Uno script in esecuzione può rientrare nel bootloader su richiesta chiamando machine.bootloader().
Filesystem e ordine di boot¶
Il firmware del Pure Thermal monta fino a tre filesystem all’avvio:
Flash interna — sempre montata su
/flash. Contienemain.pyeREADME.txtper impostazione predefinita; creata al primissimo avvio.Scheda microSD — se è inserita una scheda, viene montata su
/sdcard.ROMFS — filesystem di sola lettura, mappato in memoria, su
/rom, usato per distribuire grossi asset di dati (ad es. modelli AI) che beneficiano dell’accesso zero‑copy. Montato automaticamente da MicroPython all’avvio, prima che venga eseguito qualsiasi codice Python utente.
Dopo il montaggio, la working directory viene impostata su /sdcard quando la scheda è presente, altrimenti su /flash. L’interprete esegue poi gli script da quella directory:
boot.pyviene eseguito a ogni soft reset.main.pyviene eseguito solo all’avvio a freddo, immediatamente dopoboot.py.
Posizionare un boot.py o main.py sulla scheda SD sovrascrive la copia nella flash senza toccarla.
Quando è connesso tramite USB, il filesystem di boot (/sdcard se è presente una scheda, altrimenti /flash) si enumera anche come unità di memoria di massa USB sull’host. Espelli l’unità prima di resettare la camera in modo che l’host scriva su disco i dati memorizzati in cache.
Nota
I file creati o modificati dal codice in esecuzione sull’OpenMV Cam non compariranno sull’host finché l’unità non viene rimontata. Usa la scheda SD per qualsiasi dato che lo script scrive e rimonta prima di leggere quei file dall’host.
Dimensioni di archiviazione¶
Il Pure Thermal viene fornito con:
/flash— filesystem FAT da 24 MB, lettura/scrittura./rom— ROMFS di sola lettura mappato in memoria da 8 MB, usato per distribuire script e modelli ML che beneficiano dell’accesso mmap zero‑copy./sdcard— dimensione completa di qualunque scheda microSD inserita (quando presente), lettura/scrittura.
Indicatore di hard‑fault¶
Se il LED RGB utente sta ciclando rapidamente attraverso tutti i colori — abbastanza velocemente da sembrare un LED bianco scintillante anziché tinte distinte — il firmware ha incontrato un hard fault non recuperabile. Riflasha il firmware per ripristinare.
Errata hardware¶
Una manciata di stranezze a livello di scheda è documentata negli errata hardware del Pure Thermal. Punti chiave da tenere a mente:
Interferenza del connettore della batteria — alcuni componenti sul PCB si trovano direttamente sotto il connettore della batteria LiPo, e il cuneo sporgente sullo spinotto del cavo della batteria può impigliarsi su di essi quando il cavo viene rimosso, talvolta strappando parti dalla scheda. Taglia via il cuneo dallo spinotto del cavo con delle tronchesi a filo prima del primo utilizzo.
L’RTC si ferma mentre la scheda è spenta — la capacità di carico sul cristallo a 32 kHz (Y2) è troppo elevata. Rimuovere C96 e C97 (la coppia che affianca il cristallo accanto all’STM32) permette all’RTC di continuare a funzionare con l’alimentazione di backup. La maggior parte delle schede viene fornita con questi condensatori già rimossi; se il tuo RTC perde l’ora quando è scollegato, controlla quelle posizioni. Vedi le issue GitHub #1536 e #1600 per la discussione completa.
Il LED indicatore di ricarica resta blu — il caricabatterie può terminare il suo ciclo di carica in un punto qualsiasi tra 4,15 V e 4,19 V senza far passare l’indicatore da blu (in ricarica) a verde (carico). In questo caso la batteria è comunque completamente carica; fidati di una misura di tensione, non del LED.
La serigrafia etichetta erroneamente VIN come VBAT — il pad nella posizione VIN standard dell’header OpenMV è serigrafato
VBATsul Pure Thermal. L’etichetta è sbagliata, ma in pratica non importa perché il pad non ha alcun collegamento elettrico in nessun caso.
Librerie software¶
Consulta l”indice della libreria per l’elenco completo dei moduli — incluso quali sono unici della build del Pure Thermal.