OpenMV Cam M7

Die OpenMV Cam M7 ist ein Cortex‑M7-Board für maschinelles Sehen, das auf dem STMicroelectronics STM32F765 mit 216 MHz, 512 KB internem SRAM und 2 MB internem Flash basiert. Der mitgelieferte OV7725-Sensor erfasst 640×480-Graustufen- oder 320×240-RGB565-Einzelbilder mit bis zu 150 FPS, und die 10‑polige Benutzer-Stiftleiste stellt UART, I²C, SPI, CAN, ADC/DAC und PWM-Peripheriegeräte zur Verfügung.

OpenMV Cam M7

Das vollständige Datenblatt sowie Fotos und Abmessungen finden Sie auf der Produktseite der OpenMV Cam M7.

Highlights

  • STMicroelectronics STM32F765 Cortex‑M7 mit 216 MHz.

  • 512 KB internes SRAM — kein externes SDRAM.

  • 2 MB interner Flash (kein externer QSPI-Flash).

  • OV7725-Sensor — 640×480-Graustufen oder 320×240-RGB565 mit bis zu 150 FPS.

  • Full‑Speed-USB (12 Mb/s) — erscheint auf dem Host als VCP + USB-Massenspeicher.

  • microSD-Steckplatz — SD bis 2 GB, SDHC bis 32 GB, SDXC bis 2 TB.

  • 10 I/O-Pins, 5 V-tolerant mit 3,3-V-Ausgang, 25 mA pro Pin (120 mA insgesamt über die Stiftleiste), interruptfähig. P6 ist im ADC- oder DAC-Modus nicht 5 V-tolerant.

  • Benutzer-RGB-LED und zwei Hochleistungs-850-nm-IR-LEDs für aktive Beleuchtung beim Sehen bei schwachem Licht.

Bemerkung

Die M7 hat keinen Power-Management-Chip an Bord: Es gibt keinen Batterieanschluss, kein Ladegerät, keinen ADC für die Batteriespannung, keine Lade-/Status-LEDs und keinen Hardware-Power-Button. Versorgen Sie das Board über USB oder VIN.

Pinbelegung

OpenMV Cam M7 OV7725 Pinbelegung

Pin-Referenz

Pin-Name

Funktion

P0

UART1 RX / SPI2 MOSI

P1

UART1 TX / SPI2 MISO

P2

SPI2 SCK / CAN2 TX

P3

SPI2 NSS (CS) / CAN2 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

TIM4 CH3

RESET

auf GND ziehen, um das Board zurückzusetzen

SYN

Frame-Sync-Pad — nur mit dem Kamerasensor verdrahtet

BOOT0

beim Einschalten auf 3,3 V ziehen für DFU / ROM-Bootloader

LED_RED

Roter Kanal der RGB-LED (low-aktiv)

LED_GREEN

Grüner Kanal der RGB-LED (low-aktiv)

LED_BLUE

Blauer Kanal der RGB-LED (low-aktiv)

LED_IR

Hochleistungs-IR-LEDs (beide Kanäle werden gemeinsam angesteuert)

Bemerkung

Das SYN-Pad auf der Stiftleiste ist direkt mit der Trigger-/Belichtungsleitung des Kamerasensors verbunden — auf der M7 führt es nicht zum MCU. Steuern oder lesen Sie es extern; aus MicroPython lässt es sich nicht umschalten.

Stromversorgungs-Pins

  • 3.3V — geregelte 3,3-V-Schiene. Bis zu 250 mA für Shields verfügbar (weniger, wenn die microSD-Karte verwendet wird). Anders als bei den neueren Kameras ist dieser Pin bidirektional — siehe die Warnung unten.

  • VIN — 3,6–5 V Eingang. Versorgt das Board über den integrierten Spannungsregler.

  • GND — gemeinsame Masse.

Bemerkung

Wenn sowohl USB als auch VIN anliegen, versorgt diejenige Quelle mit der höheren Spannung das Board — die integrierten Dioden wählen einfach die stärkere Schiene aus.

Warnung

Sie können die M7 versorgen, indem Sie 3,3 V direkt in den 3.3V-Pin einspeisen, falls Sie den integrierten Regler umgehen möchten. Legen Sie in diesem Fall nicht gleichzeitig auch VIN oder USB-Strom an — das Rückwärtstreiben des Reglers, während eine andere Quelle aktiv ist, kann die Kamera dauerhaft beschädigen und zerstören.

Tipp

Verwenden Sie den Batterielebensdauer-Schätzer, um zu modellieren, wie lange die M7 für einen bestimmten Aktiv-/Tiefschlaf-Arbeitszyklus mit einer Batterie läuft.

Recovery- und Debug-Pins

  • RESET — auf GND ziehen, um das Board zurückzusetzen. Beim Loslassen startet der MCU normal hoch.

  • BOOT0 — beim Einschalten des Boards auf 3,3 V ziehen, um in den STM32-ROM-Bootloader (DFU-Modus) zu gelangen. OpenMV IDE verwendet diesen Modus, um den integrierten Bootloader neu zu flashen.

Das Board stellt neben der GPIO-Stiftleiste eine SWD-Debug-Stiftleiste (RST / SWCLK / SWDIO) bereit, die mit ST‑LINK- und SEGGER J‑Link-Adaptern kompatibel ist.

Integrierte Peripheriegeräte

LEDs

Die M7 hat eine einzelne Benutzer-RGB-LED sowie ein Paar Hochleistungs-850-nm-IR-LEDs:

  • Benutzer-RGB-LED — softwaregesteuert, bereitgestellt als LED_RED, LED_GREEN und LED_BLUE:

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • IR-LEDs — beide LEDs werden gemeinsam über den LED_IR-Pin angesteuert. LED_IR ist in der Hardware high-aktiv verdrahtet, während die Firmware jede andere integrierte LED als low-aktiv behandelt. Verwenden Sie daher low() / high() anstelle von on() / off() (was die Logik invertieren würde):

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

Kamerasensor

Der OV7725 wird über das csi — Kamerasensoren-Modul angesteuert:

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

Auf der M7 ist der Sensor auf das Board gelötet — er befindet sich nicht auf einem austauschbaren Modul.

microSD-Karte

Wenn eine Karte eingelegt ist, wird sie automatisch unter /sdcard eingebunden und ist über das normale Dateisystem nutzbar:

import os

for entry in os.listdir("/sdcard"):
    print(entry)

Bus-Referenz

GPIO

Verwenden Sie machine.Pin, um beliebige der bedruckten Pins zu lesen oder anzusteuern. Die Ausgänge sind 3,3-V-CMOS, auf der Eingangsseite 5 V-tolerant und können pro Pin bis zu 25 mA aufnehmen/liefern (120 mA insgesamt über die gesamte Stiftleiste).

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

Jeder Eingangs-Pin kann außerdem einen Interrupt bei Flankenwechseln auslösen:

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

Dieselbe Hardware kann über machine.I2CTarget auch im Target- (Slave-)Modus verwendet werden, um einem anderen I²C-Controller einen Speicherbereich bereitzustellen:

from machine import I2CTarget

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

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

Bus

TX

RX

CAN2

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 und DAC

P6 ist der einzige analoge Benutzer-Pin. Er kann entweder als 12‑Bit-ADC-Eingang oder als DAC-Ausgang verwendet werden.

  • ADC — Vollausschlag bei 3,3 V am 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 — über pyb.DAC. Der 8‑Bit-Wert deckt 0–3,3 V ab:

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

Im ADC- oder DAC-Modus ist P6 nur 3,3 V-tolerant — speisen Sie keine 5 V ein.

PWM

Pin

Timer / Kanal

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

P9

TIM4 CH3

Bemerkung

TIM1 ist von der Firmware reserviert, um den Pixeltakt des Kamerasensors zu erzeugen. Daher können die TIM1-Kanäle, die physisch auf P0/P1/P2 liegen, nicht für Benutzer-PWM verwendet werden, ohne die Kamera zu stören.

TIM4 wird mit pyb.Servo geteilt — das Instanziieren eines Servos konfiguriert den gesamten Timer für den 50-Hz-Betrieb um. Mischen Sie daher in einem Skript nicht machine.PWM auf P7/P8/P9 mit pyb.Servo.

Steuern Sie beliebige davon über machine.PWM an:

from machine import Pin, PWM

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

Softwarebasierte Bit-Banging-Busse

machine.SoftI2C und machine.SoftSPI funktionieren auf jedem GPIO, falls Sie einen zusätzlichen Bus benötigen.

Wärmebildsensor (extern)

Die Firmware enthält den fir — Wärmesensortreiber (fir == far infrared)-Treiber für extern verdrahtete Wärmebildkameras:

  • MLX90621 — 16 × 4 IR-Array

  • MLX90640 — 32 × 24 IR-Array

  • MLX90641 — 16 × 12 IR-Array

  • AMG8833 — 8 × 8 IR-Array

Verdrahten Sie das Modul mit dem I²C-Bus des Boards und lesen Sie Einzelbilder mit 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())

Der fir-Treiber kommuniziert mit dem Sensor nur über I²C 2 — verdrahten Sie das Modul mit P4 (SCL) und P5 (SDA).

Timing

time

Das time-Modul deckt blockierende Verzögerungen, monotone Ticks und die Messung verstrichener Zeit ab:

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)

Virtuelle Timer

machine.Timer plant periodische oder einmalige Callbacks, ohne einen Hardware-Timer-Slot zu belegen. Übergeben Sie -1 als id, um einen virtuellen (Software-)Timer zu verwenden:

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

Periodenwerte sind in Millisekunden angegeben. Rufen Sie deinit() auf, um den Slot zu stoppen und freizugeben.

Echtzeituhr

machine.RTC hält die Echtzeit über Resets hinweg:

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

Watchdog

machine.WDT setzt das Board zurück, wenn die Anwendung hängt. Einmal gestartet kann er nicht mehr gestoppt oder neu konfiguriert werden — füttern Sie ihn regelmäßig innerhalb Ihrer Hauptschleife:

from machine import WDT

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

Boot- und Laufzeitinformationen

USB-Bootloader-Fenster

Bei jedem Einschalten führt die Kamera einen kurzen Bootloader (einige Sekunden) aus, der es OpenMV IDE ermöglicht, die Firmware zu aktualisieren, ohne dass der Benutzer den DFU-Modus aufrufen muss. Nach Ablauf des Fensters übergibt der Bootloader an boot.py und anschließend an main.py.

Ein laufendes Skript kann den Bootloader bei Bedarf erneut aufrufen, indem es machine.bootloader() aufruft:

import machine

machine.bootloader()

Dateisystem und Boot-Reihenfolge

Die M7-Firmware bindet beim Booten bis zu drei Dateisysteme ein:

  • Interner Flash — immer unter /flash eingebunden. Enthält standardmäßig main.py und README.txt; wird beim allerersten Boot erstellt.

  • microSD-Karte — falls eine Karte eingelegt ist, wird sie unter /sdcard eingebunden.

  • ROMFS — schreibgeschütztes, speicherabgebildetes Dateisystem unter /rom, das zum Ausliefern großer Datenbestände (z. B. KI-Modelle) verwendet wird, die von Zero-Copy-Zugriff profitieren. Wird von MicroPython beim Start automatisch eingebunden, bevor irgendein Benutzer-Python-Code läuft.

Nach dem Einbinden wird das Arbeitsverzeichnis auf /sdcard gesetzt, wenn die Karte vorhanden ist, andernfalls auf /flash. Der Interpreter führt dann Skripte aus diesem Verzeichnis aus:

  • boot.py wird bei jedem Soft-Reset ausgeführt (Kaltstart, Ctrl‑D aus der REPL oder immer dann, wenn das laufende Skript zurückkehrt).

  • main.py wird nur beim Kaltstart ausgeführt, unmittelbar nach boot.py. Nachfolgende Soft-Resets führen boot.py erneut aus, fallen aber direkt in die REPL — um main.py erneut auszuführen, müssen Sie das Board vollständig zurücksetzen.

Wenn Sie eine boot.py oder main.py auf die SD-Karte legen, überschreibt dies die Kopie im Flash, ohne sie anzutasten — beide Dateien werden im Boot-Verzeichnis gesucht (/sdcard, wenn die Karte eingebunden ist, andernfalls /flash).

Die standardmäßige main.py, die auf einem frisch geflashten Board ausgeliefert wird, lässt lediglich den blauen Kanal der Benutzer-RGB-LED als Lebenszeichen blinken (zwei kurze Impulse, kurze Pause), sodass Sie ohne angeschlossenen Host erkennen können, dass die Firmware sauber gebootet ist.

sys.path wird erweitert, um alle drei Dateisysteme und ihre lib/-Unterverzeichnisse einzuschließen, sodass importierbare Module in /flash/lib, /sdcard/lib oder /rom/lib liegen können.

Um das System zu zwingen, eine eingelegte SD-Karte zu ignorieren (z. B. um die main.py aus dem Flash auch bei vorhandener Karte auszuführen), erstellen Sie eine leere Datei namens SKIPSD im Stammverzeichnis von /flash.

Wenn die Kamera über USB verbunden ist, wird das Boot-Dateisystem (/sdcard, falls eine Karte vorhanden ist, andernfalls /flash) auf dem Host außerdem als USB-Massenspeicherlaufwerk angezeigt, sodass Sie boot.py, main.py und alle anderen Dateien direkt bearbeiten können. Werfen Sie das Laufwerk aus, bevor Sie die Kamera zurücksetzen, damit der Host seine zwischengespeicherten Schreibvorgänge ausführt.

Bemerkung

Da das Betriebssystem das Laufwerk als passives Blockgerät behandelt, erscheinen Dateien, die von auf der OpenMV Cam laufendem Code erstellt oder geändert werden, erst, wenn der Host das Laufwerk erneut einbindet. Wenn sowohl das Betriebssystem als auch die OpenMV Cam gleichzeitig in dasselbe Dateisystem schreiben, gewinnt das Betriebssystem und überschreibt die von der Kamera vorgenommenen Änderungen. Verwenden Sie die SD-Karte für alle Daten, die das Skript zurückschreibt, und binden Sie das Laufwerk erneut ein, bevor Sie diese Dateien vom Host aus lesen.

Bemerkung

Der rote Kanal der Benutzer-RGB-LED kann kurz aufleuchten, während der Host vom USB-Massenspeicherlaufwerk liest oder darauf schreibt — dies ist eine firmwaregesteuerte Aktivitätsanzeige, kein Fehler.

Speichergrößen

Die M7 wird ausgeliefert mit:

  • /flash96 KB FAT-Dateisystem, Lesen/Schreiben.

  • /rom256 KB schreibgeschütztes, speicherabgebildetes ROMFS.

  • /sdcard — volle Größe der jeweils eingelegten microSD-Karte (sofern vorhanden), Lesen/Schreiben.

Hard-Fault-Anzeige

Wenn die Benutzer-RGB-LED schnell durch alle Farben wechselt — schnell genug, dass sie eher wie eine flackernde weiße LED als wie einzelne Farbtöne aussieht — ist die Firmware auf einen nicht behebbaren Hard Fault gestoßen. Flashen Sie die Firmware neu, um das Problem zu beheben; falls das Neuflashen nicht hilft, ist das Board möglicherweise physisch beschädigt.

Software-Bibliotheken

Im Bibliotheksindex finden Sie die vollständige Liste der Module — einschließlich derer, die nur im M7-Build vorhanden sind.