OpenMV Cam H7 Plus

OpenMV Cam H7 Plus сочетает STMicroelectronics STM32H743 (Cortex‑M7 @ 480 МГц) с 32 МБ внешней SDRAM, 32 МБ QSPI флеш-памяти, аппаратным кодеком JPEG и 5‑мегапиксельным модулем камеры OV5640 на съёмном носителе. Дополнительная память хорошо подходит для съёмки в высоком разрешении и больших буферов изображений.

OpenMV Cam H7 Plus

Полный паспорт устройства, фотографии и размеры см. на странице продукта OpenMV Cam H7 Plus.

Основные характеристики

  • STMicroelectronics STM32H743 Cortex‑M7 на частоте 480 МГц (1027 DMIPS).

  • Аппаратный кодер/декодер JPEG.

  • 32 МБ внешней SDRAM (32‑бит @ 100 МГц, 400 МБ/с) плюс 1 МБ внутренней SRAM.

  • 2 МБ внутренней флеш-памяти + 32 МБ внешней QSPI флеш-памяти (~100 МБ/с на чтение).

  • OV5640 — 5‑мегапиксельный датчик с роллинг-шаттером.

  • Full‑speed USB (12 Мбит/с) — определяется хостом как VCP + USB-накопитель.

  • Разъём microSD — SD до 2 ГБ, SDHC до 32 ГБ, SDXC до 2 ТБ.

  • Разъём для LiPo-аккумулятора (без встроенного зарядного устройства — подключайте заряженный элемент или питайте от VIN/USB).

  • 10 выводов ввода-вывода, толерантны к 5 В с выходом 3,3 В, 25 мА на вывод (120 мА суммарно по всему разъёму), с поддержкой прерываний. P6 не толерантен к 5 В при использовании в режиме ADC или DAC.

  • Пользовательский RGB-светодиод и два мощных ИК-светодиода 850 нм для активной подсветки при машинном зрении в условиях слабого освещения.

Примечание

У H7 Plus нет встроенной микросхемы управления питанием: нет зарядного устройства, нет ADC для измерения напряжения аккумулятора, нет светодиодов состояния зарядки/питания и нет аппаратной кнопки питания. Подключите заранее заряженный LiPo к JST-разъёму аккумулятора или питайте плату от USB / VIN.

Распиновка

Распиновка OpenMV Cam H7 Plus OV5640

Справочник по выводам

Имя вывода

Функция

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

контактная площадка кадровой синхронизации — подключена только к датчику камеры

BOOT0

подтяните к 3,3 В при включении питания для DFU / ROM-загрузчика

LED_RED

красный канал RGB-светодиода (активный уровень — низкий)

LED_GREEN

зелёный канал RGB-светодиода (активный уровень — низкий)

LED_BLUE

синий канал RGB-светодиода (активный уровень — низкий)

LED_IR

мощные ИК-светодиоды (оба канала управляются совместно)

Примечание

Контактная площадка SYN на разъёме подключена напрямую к линии триггера / экспозиции датчика камеры — на H7 Plus она не идёт к MCU. Управляйте ею или считывайте её извне; из MicroPython переключить её нельзя.

Выводы питания

  • 3.3V — стабилизированная шина 3,3 В. Для шилдов доступно до 250 мА (меньше, если используется карта microSD). В отличие от более новых камер, этот вывод двунаправленный — см. предупреждение ниже.

  • VIN — вход 3,6 – 5 В. Питает плату через встроенный стабилизатор.

  • GND — общая земля.

Также имеется разъём для LiPo 3,7 В, но у H7 Plus нет зарядного устройства — подключайте заранее заряженный элемент или питайте от VIN / USB.

Примечание

Когда одновременно присутствуют USB и VIN/LiPo, приоритет получает вход VIN/LiPo — встроенный переключатель питания выбирает его вместо USB для питания платы.

Предупреждение

На H7 Plus разъём аккумулятора и VIN объединены. Не подключайте LiPo и не подавайте VIN одновременно — два источника будут конфликтовать друг с другом и могут повредить аккумулятор, плату или и то, и другое.

Предупреждение

Вы можете питать H7 Plus, подавая 3,3 В напрямую на вывод 3.3V, если не хотите проходить через встроенный стабилизатор. В этом случае не подавайте одновременно также питание VIN или USB — обратное питание стабилизатора при активном другом источнике может необратимо повредить и вывести камеру из строя.

Совет

Используйте оценщик времени работы от батареи, чтобы смоделировать, как долго H7 Plus проработает от батареи при заданном рабочем цикле активности / глубокого сна.

Выводы восстановления и отладки

  • RESET — подтяните к GND для сброса платы. После отпускания MCU запускается обычным образом.

  • BOOT0 — подтяните к 3,3 В во время подачи питания на плату, чтобы войти в ROM-загрузчик STM32 (режим DFU). OpenMV IDE использует этот режим для перепрошивки встроенного загрузчика.

Плата имеет отладочный разъём SWD (RST / SWCLK / SWDIO / SWO) рядом с разъёмом GPIO, совместимый с адаптерами ST‑LINK и SEGGER J‑Link.

Примечание

Трассировочный вывод SWO разделяется с линией тактирования SPI разъёма камеры. SWO нельзя использовать одновременно с любым модулем камеры, который обменивается данными с MCU по SPI — например с FLIR® Lepton® Adapter Module — выберите что-то одно.

Встроенные периферийные устройства

Светодиоды

У H7 Plus есть один пользовательский RGB-светодиод плюс пара мощных ИК-светодиодов 850 нм:

  • Пользовательский RGB-светодиод — управляется программно, доступен как LED_RED, LED_GREEN и LED_BLUE:

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • ИК-светодиоды — оба светодиода управляются совместно через вывод LED_IR. LED_IR подключён аппаратно как активный высокий, тогда как прошивка трактует все остальные встроенные светодиоды как активные низкие, поэтому используйте low() / high(), а не on() / off() (которые инвертировали бы смысл):

    from machine import LED
    
    ir = LED("LED_IR")
    ir.low()    # turn IR illumination ON
    ir.high()   # turn IR illumination OFF
    

Датчик камеры

OV5640 управляется через модуль csi — датчики камеры:

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
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)

Датчик расположен на съёмном модуле — замените его на любой другой модуль камеры OpenMV (с глобальным затвором, тепловизионный, более высокого разрешения и т. д.) без изменения остальной части платы.

Машинное обучение

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

карта 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")

То же аппаратное обеспечение можно использовать в режиме целевого устройства (ведомого) через machine.I2CTarget, чтобы предоставить область памяти другому контроллеру I²C:

from machine import I2CTarget

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

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, если вам нужна дополнительная шина.

Тепловой датчик (внешний)

Прошивка включает драйвер fir — драйвер теплового датчика (fir == far infrared, дальний инфракрасный) для внешне подключённых тепловизоров:

  • 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

Модуль time охватывает блокирующие задержки, монотонные тики и измерение прошедшего времени:

import time

time.sleep(1)              # seconds
time.sleep_ms(500)
time.sleep_us(10)

start = time.ticks_ms()
# ...do work...
elapsed = time.ticks_diff(time.ticks_ms(), start)

Виртуальные таймеры

machine.Timer планирует периодические или однократные функции обратного вызова, не занимая слот аппаратного таймера. Передайте -1 в качестве id, чтобы использовать виртуальный (программный) таймер:

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(), чтобы остановить и освободить слот.

Часы реального времени

machine.RTC сохраняет астрономическое время при сбросах:

from machine import RTC

rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))   # Y, M, D, weekday, h, m, s, subsec
print(rtc.datetime())

Сторожевой таймер

machine.WDT сбрасывает плату, если приложение зависает. После запуска его нельзя остановить или перенастроить — периодически сбрасывайте его внутри основного цикла:

from machine import WDT

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

Информация о загрузке и времени выполнения

Окно USB-загрузчика

При каждом включении питания камера запускает короткий загрузчик (несколько секунд), который позволяет OpenMV IDE обновить прошивку без необходимости входить в режим DFU вручную. После истечения окна загрузчик передаёт управление boot.py, а затем main.py.

Работающий скрипт может повторно войти в загрузчик по запросу, вызвав machine.bootloader():

import machine

machine.bootloader()

Файловая система и порядок загрузки

Прошивка H7 Plus монтирует при загрузке до трёх файловых систем:

  • Внутренняя флеш-память — всегда монтируется в /flash. По умолчанию содержит main.py и README.txt; создаётся при самой первой загрузке.

  • Карта microSD — если карта вставлена, она монтируется в /sdcard.

  • ROMFS — файловая система только для чтения с отображением в память по адресу /rom, используется для поставки крупных ресурсов данных (например, моделей ИИ), которым выгоден доступ без копирования. Монтируется автоматически MicroPython при запуске, до выполнения любого пользовательского кода Python.

После монтирования рабочий каталог устанавливается в /sdcard, когда карта присутствует, иначе в /flash. Затем интерпретатор выполняет скрипты из этого каталога:

  • boot.py выполняется при каждом программном сбросе (холодная загрузка, Ctrl‑D из REPL или всякий раз, когда работающий скрипт завершается).

  • main.py выполняется только при холодной загрузке, сразу после boot.py. Последующие программные сбросы повторно выполняют boot.py, но сразу переходят в REPL — чтобы повторно выполнить main.py, нужно полностью сбросить плату.

Размещение boot.py или main.py на SD-карте переопределяет копию во флеш-памяти, не затрагивая её — оба файла ищутся в каталоге загрузки (/sdcard, когда карта смонтирована, иначе /flash).

Стандартный main.py, поставляемый на свежепрошитой плате, просто мигает синим каналом пользовательского RGB-светодиода как сигнал работоспособности (два коротких импульса, короткая пауза), чтобы вы могли понять, что прошивка загрузилась корректно, без подключённого хоста.

sys.path расширяется для включения всех трёх файловых систем и их подкаталогов lib/, поэтому импортируемые модули могут располагаться в /flash/lib, /sdcard/lib или /rom/lib.

Чтобы заставить систему игнорировать вставленную SD-карту (например, чтобы выполнить main.py из флеш-памяти даже при наличии карты), создайте пустой файл с именем SKIPSD в корне /flash.

При подключении по USB загрузочная файловая система (/sdcard, если карта присутствует, иначе /flash) также определяется на хосте как USB-накопитель, позволяя редактировать boot.py, main.py и любые другие файлы напрямую. Извлекайте накопитель перед сбросом камеры, чтобы хост сбросил свои кэшированные записи.

Примечание

Поскольку ОС трактует накопитель как пассивное блочное устройство, файлы, созданные или изменённые кодом, работающим на OpenMV Cam, не появятся, пока хост повторно не смонтирует накопитель. Если и ОС, и OpenMV Cam записывают в одну и ту же файловую систему одновременно, верх возьмёт ОС и перезапишет изменения, сделанные камерой. Используйте SD-карту для любых данных, которые скрипт записывает обратно, и перемонтируйте перед чтением этих файлов с хоста.

Примечание

Красный канал пользовательского RGB-светодиода может кратковременно загораться, пока хост читает с USB-накопителя или записывает на него — это индикатор активности, управляемый прошивкой, а не неисправность.

Размеры хранилища

H7 Plus поставляется со следующим:

  • /flash — файловая система FAT 24 МБ, чтение/запись.

  • /rom8 МБ ROMFS с отображением в память только для чтения, используется для поставки скриптов и ML-моделей, которым выгоден доступ через mmap без копирования.

  • /sdcard — полный размер вставленной карты microSD (при наличии), чтение/запись.

Индикатор аппаратного сбоя

Если пользовательский RGB-светодиод быстро перебирает все цвета — настолько быстро, что это скорее выглядит как мерцающий белый светодиод, а не отдельные оттенки — прошивка столкнулась с неустранимым аппаратным сбоем. Перепрошейте прошивку для восстановления; если перепрошивка не помогает, плата может быть физически повреждена.

Программные библиотеки

Полный список модулей — включая те, что уникальны для сборки H7 Plus — см. в индексе библиотек.