OpenMV Pure Thermal¶
OpenMV Pure Thermal — это полнофункциональная плата тепловизионной съёмки, построенная на базе STMicroelectronics STM32H743 (Cortex‑M7 @ 480 МГц) с 64 МБ внешней SDRAM, 32 МБ QSPI‑флеш‑памяти, аппаратным кодеком JPEG, 4,3» ёмкостным сенсорным IPS‑экраном 800×480, выходом HDMI, разъёмом для тепловизионного модуля FLIR® Lepton® и 5‑мегапиксельной камерой видимого света OV5640. Кроме того, она включает Wi‑Fi, разъём microSD, лазерный дальномер, зуммер и мощный белый осветитель.
Полный технический паспорт, фотографии и размеры см. на странице продукта OpenMV Pure Thermal.
Основные характеристики¶
STMicroelectronics STM32H743XI Cortex‑M7 на частоте 480 МГц.
Аппаратный кодировщик/декодировщик JPEG.
64 МБ внешней SDRAM (~400 МБ/с) плюс 1 МБ встроенной SRAM.
2 МБ встроенной флеш‑памяти + 32 МБ внешней QSPI‑флеш‑памяти (чтение ~50 МБ/с).
OV5640 — 5‑мегапиксельный датчик видимого света с построчным затвором (rolling shutter).
Разъём FLIR® Lepton® — принимает любой модуль Lepton 1/2/2.5/3/3.5, радиометрический или нерадиометрический, с попиксельной температурой в градусах Цельсия.
4,3» ёмкостный сенсорный IPS‑экран 800×480 (24‑битный цвет @ 60 Гц) с поддержкой жестов до 5 точек касания.
Выход HDMI через DVI‑сериализатор TFP410 — до 1280×720 @ 60 Гц.
Wi‑Fi через WINC1500; MJPEG поверх RTSP поддерживается «из коробки».
Полноскоростной USB‑C (12 Мбит/с, ограничение тока 900 мА) — определяется хостом как VCP + USB‑накопитель, а также обеспечивает зарядку.
Разъём microSD — SD до 2 ГБ, SDHC до 32 ГБ, SDXC до 2 ТБ.
Лазерный дальномер VL53L1CX (до ~4 м).
Зуммер с программно управляемой громкостью / частотой.
Мощный белый светодиодный осветитель в дополнение к пользовательскому RGB‑светодиоду состояния.
Разъём для LiPo‑аккумулятора с зарядкой по USB током 500 мА.
10 выводов ввода/вывода, толерантных к 5 В, с выходом 3,3 В, 25 мА на вывод (всего 120 мА), с поддержкой прерываний. P6 не толерантен к 5 В при использовании в режиме ADC или DAC.
10‑контактный разъём ARM SWD для отладки через ST‑LINK / J‑Link.
Разъём Qwiic для периферии I²C.
Примечание
На нижнем левом краю платы есть гнездо для опциональной гайки штатива ¼»–20. С завода она не устанавливается — впаяйте её в гнездо, если хотите крепить плату на стандартный фотоштатив.
Распиновка¶
Справочник по выводам¶
Имя вывода |
Функция |
|---|---|
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 |
цифровой ввод/вывод |
RESET |
замкните на GND для сброса платы |
SYN |
контактная площадка кадровой синхронизации — не подключена |
VIN |
контактная площадка VIN шилда — не подключена |
BOOT0 |
подайте 3,3 В при включении питания для DFU / ROM‑загрузчика |
BUZZER |
встроенный пьезоэлектрический зуммер (управляется TIM2/PWM) |
LED_RED |
красный канал RGB‑светодиода состояния (активный низкий уровень) |
LED_GREEN |
зелёный канал RGB‑светодиода состояния (активный низкий уровень) |
LED_BLUE |
синий канал RGB‑светодиода состояния (активный низкий уровень) |
LED_WHITE |
мощный белый светодиод осветителя |
Примечание
Контактные площадки SYN и VIN на шилде/разъёме на Pure Thermal не имеют электрического подключения — они присутствуют только для совместимости с разъёмом. Питайте плату через USB‑C или встроенный разъём LiPo‑аккумулятора (см. Выводы питания ниже). Обратите также внимание, что контактная площадка VIN на плате подписана как VBAT (ошибка маркировки) — её положение соответствует стандартному выводу VIN разъёма OpenMV, и она в любом случае не подключена.
Выводы питания¶
3.3V — стабилизированная шина 3,3 В. Для шилдов доступно до 250 мА.
GND — общая земля.
Pure Thermal питается через USB‑C или встроенный разъём LiPo‑аккумулятора. Порт USB‑C ограничен по току до 900 мА суммарно и также обеспечивает зарядку LiPo током 500 мА, поэтому подключение аккумулятора одновременно с USB поддерживается.
Встроенная кнопка питания включает и выключает системные шины и работает независимо от того, питается ли плата от USB или от LiPo. Удерживайте кнопку пару секунд для переключения состояния — короткое нажатие игнорируется, чтобы предотвратить случайное выключение.
Выбор источника подчиняется двум простым правилам:
Аккумулятор питает плату только когда его напряжение выше 3 В. Ниже этого порога встроенный PMIC отключает аккумулятор, чтобы защитить его от чрезмерного разряда.
Когда присутствует USB, плату питает USB, а любой подключённый LiPo заряжается в фоновом режиме.
Разъём LiPo также оснащён защитой от обратного напряжения, поэтому подключение аккумулятора наоборот не повредит плату.
Примечание
Плата также направляет сигналы напряжения аккумулятора и датчика тока аккумулятора обратно на каналы ADC микроконтроллера, но программная поддержка ни того, ни другого пока не добавлена.
Выводы восстановления и отладки¶
RESET — замкните на GND для сброса платы. У Pure Thermal также есть отдельная кнопка RESET на плате, которая делает то же самое.
BOOT0 — подайте 3,3 В во время включения платы для входа в ROM‑загрузчик STM32 (режим DFU). OpenMV IDE использует этот режим для перепрошивки встроенного загрузчика. Отдельная кнопка BOOT0 на плате делает то же самое — удерживайте её при подаче питания.
Плата предоставляет отладочный разъём SWD (RST / SWCLK / SWDIO / SWO) рядом с разъёмом GPIO, совместимый с адаптерами ST‑LINK и SEGGER J‑Link. Также установлен отдельный 10‑контактный разъём ARM SWD — он несёт те же сигналы SWD (без полного JTAG), но в стандартном 10‑контактном форм‑факторе 0,05».
Примечание
Трассировочный вывод SWO разделяется с тактовым сигналом SPI встроенного FLIR® Lepton®. SWO нельзя использовать одновременно с Lepton — выберите что‑то одно.
На плате установлен третий разъём PURE Modules Debug. Он выводит несколько отладочных сигналов (SWCLK, SWDIO, RST, SPI2_MISO, SPI2_MOSI, VBUS, 3,3 В, GND и два вывода GPIO) для подключения сопутствующих модулей. Два вывода GPIO на этом разъёме управляются внутренней программно эмулируемой (bit‑banged) шиной I²C, а не аппаратным периферийным устройством.
Все три отладочных разъёма (встроенный разъём SWD, 10‑контактный разъём ARM SWD и разъём PURE Modules Debug) рассчитаны на 3,3 В — убедитесь, что ваш отладочный адаптер настроен на логику 3,3 В, прежде чем подключать его.
Встроенная периферия¶
Светодиоды¶
У Pure Thermal на плате три светодиода:
Пользовательский RGB‑светодиод — управляемый программно, представлен как
LED_RED,LED_GREENиLED_BLUE:from machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
Белый осветитель — управляется через
LED_WHITE.LED_WHITEаппаратно подключён с активным высоким уровнем, тогда как прошивка рассматривает все остальные встроенные светодиоды как активные низкие, поэтому используйтеlow()/high()вместоon()/off()(которые инвертировали бы логику):from machine import LED light = LED("LED_WHITE") light.low() # turn the white LED ON light.high() # turn the white LED OFF
Светодиод зарядки — управляется напрямую встроенной аппаратурой управления питанием, без программного контроля. Он работает независимо от того, включены системные шины или нет (то есть при любом положении кнопки питания).
Цвет
Значение
Синий
зарядка — см. список ошибок: может не гаснуть по завершении зарядки
Зелёный
зарядка завершена — см. список ошибок: может срабатывать ненадёжно
Красный
низкий заряд аккумулятора (≤ 3,2 В, только когда зарядка не активна)
Зуммер¶
Встроенный пьезоэлектрический зуммер подключён к каналу таймера — управляйте им через machine.PWM для воспроизведения тонов с программно управляемой частотой (высотой) и коэффициентом заполнения (громкостью):
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()
Датчик камеры¶
OV5640 — это основной CSI на Pure Thermal; передайте cid=csi.OV5640, чтобы обратиться к нему явно:
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 имеет встроенный JPEG‑компрессор. Установите csi.CSI.pixformat в csi.JPEG, и датчик будет передавать сжатые кадры прямо в камеру по шине камеры, что делает съёмку с высоким разрешением практичной: csi.HD (1280×720), csi.FHD (1920×1080) и полные 5 Мп csi.WQXGA2 (2592×1944) — все передаются в виде JPEG. Настройте сжатие через csi.CSI.quality (0–100, выше = крупнее кадры, больше деталей):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
OV5640 оснащён автофокусным объективом с актуатором на звуковой катушке. Запустите однократный проход автофокуса через csi.CSI.ioctl с csi.IOCTL_TRIGGER_AUTO_FOCUS — датчик один раз проводит мотором фокуса и фиксируется на том, что находится перед ним:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
Повторно вызывайте ioctl каждый раз при изменении сцены — автофокус однократный, а не непрерывный.
Примечание
Выход STROBE датчика OV5640 (используемый для синхронизированной вспышки / ИК‑подсветки) на Pure Thermal подключён к микроконтроллеру, но программная поддержка для него пока не добавлена.
Датчик тепловизионной камеры¶
Разъём FLIR® Lepton® представлен как второй CSI через тот же API csi — датчики камеры. Передайте cid=csi.LEPTON, чтобы обратиться к нему, и пропустите аппаратный сброс:
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()
Примечание
Выход VSYNC датчика Lepton (один импульс на тепловой кадр) на Pure Thermal подключён к микроконтроллеру, но программная поддержка для него пока не добавлена.
Оба CSI могут работать параллельно. В примере ниже извлекается цветной кадр с OV5640 и тепловой кадр с Lepton, после чего Lepton накладывается поверх цветного кадра с использованием палитры Ironbow и альфа‑маски, которая становится прозрачной при низкой интенсивности:
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,
)
Машинное обучение¶
ml — Машинное обучение запускает квантованные модели TFLite на Cortex‑M7 с ядрами CMSIS‑NN — достаточно быстро для компактных детекторов с несколькими кадрами в секунду. Модели в файловой системе только для чтения /rom загружаются прямо из флеш‑памяти без копирования в RAM. Вот детектор BlazeFace 128×128, накладывающий обнаруженное лицо и его шесть ключевых точек на каждый кадр с камеры видимого света:
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")
Лазерный дальномер¶
Встроенный дальномер ST VL53L1CX, работающий по принципу времени пролёта (time‑of‑flight), подключён к шине I²C 2. Используйте встроенный (frozen) драйвер vl53l1x — Драйвер датчика расстояния ToF VL53L1X для получения показаний расстояния до ~4 м:
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)
Вывод на LCD¶
Встроенный 4,3» LCD имеет разрешение 800 × 480 (WVGA) и управляется через RGB‑интерфейс дисплея модуля display — драйвер дисплея — передайте framesize=display.FWVGA, чтобы соответствовать его собственному разрешению:
import display
lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True) # turn the LCD backlight on
lcd.write(img)
Подсветка подключена к GPIO, поэтому backlight() принимает True / False (или любое значение 0–100, где 0 — выключено, а любое ненулевое — включено):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
Сенсорный экран¶
Контроллер ёмкостного касания — FT5X06; позиции мультитач и события жестов доступны через ft5x06 — драйвер сенсорного экрана. Зарегистрируйте функцию обратного вызова, чтобы реагировать на касания и считывать активные точки внутри неё:
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)
Вывод HDMI¶
Прошивка также дублирует буфер кадра LCD на встроенный HDMI‑сериализатор tfp410 — Контроллер DVI/HDMI, поэтому внешний монитор зеркалирует то, что отображается на LCD. Создайте экземпляр tfp410.TFP410, чтобы включить выход HDMI:
import tfp410
hdmi = tfp410.TFP410()
Если вам нужен только выход HDMI и встроенный LCD не важен, выключите подсветку и увеличьте разрешение буфера кадра выше WVGA. TFP410 поддерживает до 1280×720 @ 60 Гц, например:
lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False) # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()
Встроенная панель фиксирована на 800×480, поэтому всё, что выше WVGA, имеет смысл только на внешнем HDMI‑мониторе.
Чтобы узнать, когда HDMI‑монитор был подключён или отключён, зарегистрируйте функцию обратного вызова горячего подключения на TFP410. Функция вызывается со значением True при подключении и False при отключении:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
Вы также можете в любой момент опросить состояние подключения с помощью isconnected() (только когда не зарегистрирована функция обратного вызова).
Порт HDMI также несёт каналы DDC (данные дисплея) и CEC (управление бытовой электроникой), доступные через класс class DisplayData – данные дисплея. Используйте его для чтения блока EDID подключённого монитора (чтобы адаптироваться к его собственному разрешению / частоте обновления) или для отправки/приёма кадров CEC для управления другими HDMI‑устройствами на той же линии:
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 работает через модуль Microchip WINC1500, доступный через интерфейс class WINC – драйвер 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])
Примечание
Из‑за дефицита компонентов некоторые экземпляры Pure Thermal поставлялись без установленного модуля WINC1500. Если network.WINC вызывает ошибку или никогда не подключается, проверьте плату на отсутствие модуля Wi‑Fi — остальная часть камеры работает точно так же и без него.
Карта microSD¶
При вставке карта автоматически монтируется в /sdcard и доступна через обычную файловую систему:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Справочник по шинам¶
GPIO¶
Используйте machine.Pin для чтения или управления любым из выводов с шелкографией. Выходы — 3,3 В CMOS, толерантны к 5 В на входе, и могут принимать/отдавать до 25 мА на вывод (всего 120 мА на весь разъём).
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())
Любой входной вывод также может вызывать прерывание при переходах фронта:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Шина |
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¶
Шина |
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")
То же оборудование можно также использовать в режиме целевого устройства (slave) через machine.I2CTarget, чтобы предоставить область памяти другому контроллеру I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
Встроенный разъём Qwiic выводит одну из этих шин I²C для модулей plug‑and‑play. Линия Qwiic преобразуется по уровню до 5 В через транзисторы с открытым стоком, поэтому шина ограничена только стандартным режимом (100 кГц) и быстрым режимом (400 кГц) — не пытайтесь использовать fast‑mode‑plus или более высокие скорости через разъём Qwiic.
Разъём Qwiic выводит 5 В для питания подключённых модулей; его нельзя использовать для питания самого Pure Thermal — питайте плату через USB‑C или разъём LiPo‑аккумулятора.
SPI¶
Шина |
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)¶
Шина |
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 и DAC¶
P6 — единственный пользовательский аналоговый вывод. Его можно использовать как 12‑битный вход ADC или выход DAC.
ADC — полная шкала при 3,3 В на выводе:
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 — через
pyb.DAC. 8‑битное значение охватывает 0–3,3 В:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
В режиме ADC или DAC P6 толерантен только к 3,3 В — не подавайте на него 5 В.
PWM¶
Вывод |
Таймер / канал |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Примечание
TIM1 зарезервирован прошивкой для генерации пиксельного тактового сигнала датчика камеры, поэтому каналы TIM1, физически выведенные на P0/P1/P2, нельзя использовать для пользовательского PWM, не нарушив работу камеры.
TIM4 разделяется с pyb.Servo — создание сервопривода переконфигурирует весь таймер на работу с частотой 50 Гц, поэтому не смешивайте machine.PWM на P7/P8 с pyb.Servo в одном скрипте.
Управляйте любым из них через machine.PWM:
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
Программно эмулируемые (bit‑banged) шины¶
machine.SoftI2C и machine.SoftSPI работают на любом GPIO, если вам нужна дополнительная шина.
Тепловизионный датчик (внешний)¶
В дополнение к встроенному FLIR Lepton, прошивка также включает драйвер fir — драйвер теплового датчика (fir == far infrared, дальний инфракрасный) для внешне подключённых тепловизоров с интерфейсом I²C:
MLX90621 — ИК‑матрица 16 × 4
MLX90640 — ИК‑матрица 32 × 24
MLX90641 — ИК‑матрица 16 × 12
AMG8833 — ИК‑матрица 8 × 8
Подключите модуль к шине I²C платы и считывайте кадры с помощью 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())
Драйвер fir общается с датчиком только по I²C 2 — подключите модуль к P4 (SCL) и P5 (SDA).
Тайминг¶
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)
Виртуальные таймеры¶
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"))
Значения периода указаны в миллисекундах. Вызовите deinit(), чтобы остановить таймер и освободить слот.
Часы реального времени¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
Если подключён LiPo‑аккумулятор, RTC продолжают отсчёт времени даже при выключенных системных шинах (выключение через встроенную кнопку питания). При подключённом только USB нажатие кнопки питания отключает питание и от RTC — поэтому без подключённого аккумулятора астрономическое время не сохранится при перезапуске питания.
Сторожевой таймер (watchdog)¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
Информация о загрузке и времени выполнения¶
Окно USB‑загрузчика¶
При каждом включении камера запускает короткий загрузчик (несколько секунд), который позволяет OpenMV IDE обновить прошивку без необходимости входить в режим DFU. По истечении окна загрузчик передаёт управление boot.py, а затем main.py.
Работающий скрипт может повторно войти в загрузчик по запросу, вызвав machine.bootloader().
Файловая система и порядок загрузки¶
Прошивка Pure Thermal при загрузке монтирует до трёх файловых систем:
Встроенная флеш‑память — всегда монтируется в
/flash. По умолчанию содержитmain.pyиREADME.txt; создаётся при самой первой загрузке.Карта microSD — если карта вставлена, она монтируется в
/sdcard.ROMFS — файловая система только для чтения с отображением в память по адресу
/rom, используемая для размещения крупных ресурсов данных (например, моделей ИИ), которым выгоден доступ без копирования. Монтируется автоматически MicroPython при запуске, до выполнения любого пользовательского кода Python.
После монтирования рабочий каталог устанавливается в /sdcard, если карта присутствует, иначе в /flash. Затем интерпретатор запускает скрипты из этого каталога:
boot.pyвыполняется при каждом программном сбросе.main.pyвыполняется только при холодной загрузке, сразу послеboot.py.
Размещение boot.py или main.py на SD‑карте переопределяет копию во флеш‑памяти, не затрагивая её.
При подключении по USB загрузочная файловая система (/sdcard, если карта присутствует, иначе /flash) также определяется на хосте как USB‑накопитель. Извлеките накопитель перед сбросом камеры, чтобы хост сбросил свои кэшированные записи.
Примечание
Файлы, созданные или изменённые кодом, выполняющимся на OpenMV Cam, не появятся на хосте, пока накопитель не будет смонтирован заново. Используйте SD‑карту для любых данных, которые записывает скрипт, и перемонтируйте её перед чтением этих файлов с хоста.
Объёмы хранилища¶
Pure Thermal поставляется со следующим:
/flash— файловая система FAT объёмом 24 МБ, для чтения/записи./rom— отображённая в память ROMFS только для чтения объёмом 8 МБ, используемая для размещения скриптов и ML‑моделей, которым выгоден доступ через mmap без копирования./sdcard— полный объём вставленной карты microSD (если присутствует), для чтения/записи.
Индикатор аппаратного сбоя (hard fault)¶
Если пользовательский RGB‑светодиод быстро перебирает все цвета — настолько быстро, что выглядит как мерцающий белый светодиод, а не отдельные оттенки — прошивка столкнулась с невосстановимым аппаратным сбоем (hard fault). Для восстановления перепрошейте прошивку.
Аппаратные ошибки (errata)¶
Несколько особенностей уровня платы описаны в списке аппаратных ошибок Pure Thermal. Ключевые моменты, о которых следует знать:
Помехи со стороны разъёма аккумулятора — компоненты на печатной плате расположены прямо под разъёмом LiPo‑аккумулятора, и выступающий клин на штекере кабеля аккумулятора может зацепиться за них при отсоединении кабеля, иногда срывая детали с платы. Срежьте клин со штекера кабеля торцевыми кусачками перед первым использованием.
RTC останавливаются при выключенной плате — ёмкость нагрузки на кварцевом резонаторе 32 кГц (Y2) слишком велика. Удаление C96 и C97 (пары по обе стороны от резонатора рядом с STM32) позволяет RTC продолжать работу от резервного питания. На большинстве плат эти конденсаторы уже удалены при поставке; если ваши RTC теряют время при отключении, проверьте эти позиции. Полное обсуждение см. в задачах GitHub #1536 и #1600.
Индикаторный светодиод зарядки остаётся синим — зарядное устройство может завершить цикл зарядки где‑то между 4,15 В и 4,19 В, не переключая индикатор с синего (зарядка) на зелёный (заряжен). Аккумулятор в этом случае всё равно полностью заряжен; доверяйте измерению напряжения, а не светодиоду.
Шелкография ошибочно подписывает VIN как VBAT — контактная площадка в стандартной позиции VIN разъёма OpenMV на Pure Thermal подписана шелкографией как
VBAT. Подпись неверна, но на практике это не имеет значения, поскольку площадка в любом случае не имеет электрического подключения.
Программные библиотеки¶
Полный список модулей — включая те, что уникальны для сборки Pure Thermal — см. в индексе библиотек.