OpenMV Cam H7 Plus

OpenMV Cam H7 Plus 将 STMicroelectronics STM32H743(Cortex‑M7 @ 480 MHz)与 32 MB 外部 SDRAM、32 MB QSPI 闪存、硬件 JPEG 编解码器以及可拆卸载板上的 OV5640 5MP 摄像头模块结合在一起。额外的内存非常适合高分辨率采集和大型图像缓冲区。

OpenMV Cam H7 Plus

完整的数据手册、照片和尺寸信息请参阅 OpenMV Cam H7 Plus 产品页面

亮点

  • STMicroelectronics STM32H743 Cortex‑M7,480 MHz(1027 DMIPS)。

  • 硬件 JPEG 编码器/解码器

  • 32 MB 外部 SDRAM(32 位 @ 100 MHz,400 MB/s)外加 1 MB 内部 SRAM

  • 2 MB 内部闪存 + 32 MB 外部 QSPI 闪存(读取速度约 100 MB/s)。

  • OV5640 5MP 卷帘快门传感器。

  • 全速 USB(12 Mb/s)——在主机上显示为 VCP + USB 大容量存储设备。

  • microSD 卡座——SD 最高 2 GB,SDHC 最高 32 GB,SDXC 最高 2 TB。

  • LiPo 电池接口(无板载充电器——请连接已充电的电池,或通过 VIN/USB 供电)。

  • 10 个 I/O 引脚5 V 容差,3.3 V 输出,每个引脚 25 mA(整个排针总计 120 mA),支持中断。P6 在 ADC 或 DAC 模式下具备 5 V 容差。

  • 用户 RGB LED 以及两颗大功率 850 nm 红外 LED,用于弱光视觉下的主动照明。

备注

H7 Plus 没有板载电源管理芯片:没有电池充电器、没有电池电压 ADC、没有充电/电源状态 LED,也没有硬件电源按钮。请将已充电的 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

数字 I/O

RESET

拉至 GND 以复位开发板

SYN

帧同步焊盘——仅连接到摄像头传感器

BOOT0

上电时拉至 3.3 V 以进入 DFU / ROM 引导加载程序

LED_RED

RGB LED 红色通道(低电平有效)

LED_GREEN

RGB LED 绿色通道(低电平有效)

LED_BLUE

RGB LED 蓝色通道(低电平有效)

LED_IR

大功率红外 LED(两个通道一同驱动)

备注

排针上的 SYN 焊盘直接连接到摄像头传感器的触发/曝光线——在 H7 Plus 上它连接到 MCU。请在外部驱动或读取它;无法通过 MicroPython 进行切换。

电源引脚

  • 3.3V —— 稳压 3.3 V 电源轨。最多可为扩展板提供 250 mA(使用 microSD 卡时会更少)。与较新的摄像头不同,该引脚是双向的——请参阅下方的警告。

  • VIN —— 3.6 – 5 V 输入。通过板载稳压器为开发板供电。

  • GND —— 公共地。

板上也有一个 3.7 V LiPo 接口,但 H7 Plus 没有电池充电器——请连接已充电的电池,或改用 VIN / USB 供电。

备注

当 USB 和 VIN/LiPo 同时存在时,VIN/LiPo 输入优先——板载电源开关会选择它而非 USB 为开发板供电。

警告

在 H7 Plus 上,电池接口和 VIN 是连接在一起的。请不要同时插入 LiPo 电池并施加 VIN——两路电源会互相冲突,可能损坏电池、开发板或两者。

警告

如果你不想经过板载稳压器,可以将 3.3 V 直接馈入 3.3V 引脚来为 H7 Plus 供电。在这种情况下,请不要同时再施加 VIN 或 USB 电源——在另一路电源处于激活状态时反向驱动稳压器可能会永久损坏并毁坏摄像头。

小技巧

使用 电池续航估算器 来建模 H7 Plus 在给定的激活/深度睡眠占空比下能用电池运行多久。

恢复与调试引脚

  • RESET —— 拉至 GND 以复位开发板。释放后 MCU 即可正常启动。

  • BOOT0 —— 在为开发板供电时拉至 3.3 V,以进入 STM32 ROM 引导加载程序(DFU 模式)。OpenMV IDE 使用此模式来重新刷写板载引导加载程序。

开发板在 GPIO 排针旁提供了 SWD 调试接口(RST / SWCLK / SWDIO / SWO),与 ST‑LINK 和 SEGGER J‑Link 适配器兼容。

备注

SWO 跟踪引脚与摄像头排针的 SPI 时钟线共用。SWO 无法与任何通过 SPI 与 MCU 通信的摄像头模块同时使用——例如 FLIR® Lepton® 适配器模块——只能二选一。

板载外设

LED

H7 Plus 配有单个用户 RGB LED 以及一对大功率 850 nm 红外 LED:

  • 用户 RGB LED —— 软件可控,公开为 LED_REDLED_GREENLED_BLUE::

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • 红外 LED —— 两颗 LED 通过 LED_IR 引脚一同驱动。LED_IR 在硬件上接成高电平有效,而固件将其他所有板载 LED 视为低电平有效,因此请使用 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)以及完整的 5MP csi.WQXGA2(2592×1944)都能以 JPEG 形式流式传输。可用 csi.CSI.quality(0-100,越高 = 帧越大、细节越多)调整压缩::

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

传感器位于一个可拆卸模块上——可将其更换为任何其他 OpenMV 摄像头模块(全局快门、热成像、更高分辨率等),而无需更改开发板的其余部分。

机器学习

ml --- 机器学习 使用 CMSIS‑NN 内核在 Cortex‑M7 上运行量化的 TFLite 模型——速度足以让紧凑型检测器以每秒几帧的速度运行。位于只读 /rom 文件系统上的模型可直接从闪存加载,无需复制到 RAM。下面是一个 128×128 的 BlazeFace 检测器,将检测到的人脸及其六个关键点叠加到每一帧上::

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 V CMOS,输入侧具备 5 V 容差,每个引脚可灌入/拉出最高 25 mA(整个排针总计 120 mA)。

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 V::

    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 V::

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

在 ADC 或 DAC 模式下,P6 仅具备 3.3 V 容差——请勿向其馈入 5 V

PWM

引脚

定时器 / 通道

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

备注

TIM1 被固件保留用于生成摄像头传感器的像素时钟,因此物理上位于 P0/P1/P2 上的 TIM1 通道无法用于用户 PWM,否则会破坏摄像头功能。

TIM4 与 pyb.Servo 共用——实例化一个舵机会将整个定时器重新配置为 50 Hz 运行,所以不要在同一个脚本中将 P7/P8 上的 machine.PWMpyb.Servo 混用。

可通过 machine.PWM 驱动其中任意一个::

from machine import Pin, PWM

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

软件位操作总线

如果你需要额外的总线,machine.SoftI2Cmachine.SoftSPI 可在任意 GPIO 上工作。

热成像传感器(板外)

固件包含用于外部连接的热成像仪的 fir --- 热成像传感器驱动(fir == 远红外) 驱动:

  • 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.pyREADME.txt;在首次启动时创建。

  • microSD 卡 —— 若插入了卡,则挂载在 /sdcard

  • ROMFS —— 位于 /rom 的只读、内存映射文件系统,用于装载受益于零拷贝访问的大型数据资源(例如 AI 模型)。由 MicroPython 在启动时、任何用户 Python 运行之前自动挂载。

挂载完成后,工作目录会在卡存在时设为 /sdcard,否则为 /flash。解释器随后从该目录运行脚本:

  • boot.py 会在每一次软复位时执行(冷启动、从 REPL 按 Ctrl‑D,或正在运行的脚本返回时)。

  • main.py 仅在冷启动时执行,紧接在 boot.py 之后。后续的软复位会重新运行 boot.py 但直接进入 REPL——要重新运行 main.py,你必须完全复位开发板。

boot.pymain.py 放到 SD 卡上会覆盖闪存中的副本而不改动它——这两个文件都在启动目录中查找(卡挂载时为 /sdcard,否则为 /flash)。

刚刷写完的开发板上随附的默认 main.py 只是闪烁用户 RGB LED 的蓝色通道作为心跳(两次短脉冲,短暂间隔),这样你无需连接任何主机即可判断固件是否干净启动。

sys.path 会被扩展以包含全部三个文件系统及其 lib/ 子目录,因此可导入的模块可以放在 /flash/lib/sdcard/lib/rom/lib 中。

要强制系统忽略已插入的 SD 卡(例如即使有卡也运行闪存中的 main.py),请在 /flash 的根目录创建一个名为 SKIPSD 的空文件。

通过 USB 连接时,启动文件系统(卡存在时为 /sdcard,否则为 /flash)也会在主机上枚举为 USB 大容量存储驱动器,让你能直接编辑 boot.pymain.py 以及任何其他文件。在复位摄像头之前请弹出该驱动器,以便主机刷新其缓存的写入。

备注

由于操作系统将该驱动器视为被动块设备,OpenMV Cam 上运行的代码所创建或修改的文件在主机重新挂载该驱动器之前不会显示出来。如果操作系统和 OpenMV Cam 同时写入同一文件系统,操作系统会胜出并覆盖摄像头所做的更改。对于脚本回写的任何数据请使用 SD 卡,并在从主机读取这些文件之前重新挂载。

备注

在主机从 USB 大容量存储驱动器读取或写入时,用户 RGB LED 的红色通道可能会短暂点亮——这是固件驱动的活动指示,并非故障。

存储容量

H7 Plus 出厂时配有:

  • /flash —— 24 MB FAT 文件系统,可读写。

  • /rom —— 8 MB 只读内存映射 ROMFS,用于装载受益于零拷贝 mmap 访问的脚本和机器学习模型。

  • /sdcard —— 所插入 microSD 卡的全部容量(存在时),可读写。

硬故障指示

如果用户 RGB LED 在快速循环显示所有颜色——快到看起来更像是一颗闪烁的白色 LED 而非各种独立色调——则说明固件遇到了无法恢复的硬故障。请重新刷写固件以恢复;如果重新刷写无济于事,开发板可能已遭到物理损坏。

软件库

完整的模块列表请参阅 库索引——包括哪些模块是 H7 Plus 版本独有的。