OpenMV Cam M4

Die OpenMV Cam M4 ist eine kompakte Cortex‑M4-Platine für maschinelles Sehen, die um den STMicroelectronics STM32F427 mit 180 MHz herum aufgebaut ist und über 256 KB internen SRAM sowie 1 MB internen Flash verfügt. Der mitgelieferte OV7725-Sensor nimmt Einzelbilder mit 320×240 in Graustufen oder RGB565 auf, und der 9‑polige Benutzer-Header stellt UART, I²C, SPI, CAN, ADC/DAC und PWM-Peripheriegeräte bereit.

Bemerkung

Der OV7725 war der Standardsensor auf den in Serie gefertigten M4-Platinen. Sehr frühe Varianten der M4 wurden stattdessen mit dem OmniVision OV2640 ausgeliefert — dieselbe QVGA-Vorschau-Pipeline, aber der OV2640 kann zusätzlich bis zu UXGA (1600×1200) JPEG-Einzelbilder aufnehmen. Beide Sensoren werden über dieselbe csi — Kamerasensoren-API angesteuert.

OpenMV Cam M4

Vollständiges Datenblatt, Fotos und Abmessungen finden Sie auf der Produktseite der OpenMV Cam M4.

Höhepunkte

  • STMicroelectronics STM32F427 Cortex‑M4 mit 180 MHz.

  • 256 KB interner SRAM — kein externer SDRAM.

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

  • OV7725-Sensor (oder OV2640 auf sehr frühen M4-Varianten) — 320×240 8‑Bit Graustufen oder RGB565; der OV2640 kann zusätzlich bis zu UXGA (1600×1200) JPEG aufnehmen.

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

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

  • 9 I/O-Pins, 5 V-tolerant mit 3,3 V-Ausgang, 25 mA pro Pin (120 mA gesamt über den Header), 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 unter schwachem Licht.

Bemerkung

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

Pinbelegung

OpenMV Cam M4 OV7725 Pinbelegung

Pin-Referenz

Pin-Name

Funktion

P0

SPI2 MOSI

P1

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

TIM4 CH1

P8

TIM4 CH2

RESET

auf GND ziehen, um die Platine zurückzusetzen

BOOT0

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

SWCLK

ARM-SWD-Takt (Debugger-Zugriff)

SWDIO

ARM-SWD-Daten (Debugger-Zugriff)

LED_RED

Rotkanal der RGB-LED (Low-aktiv)

LED_GREEN

Grünkanal der RGB-LED (Low-aktiv)

LED_BLUE

Blaukanal der RGB-LED (Low-aktiv)

LED_IR

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

Versorgungs-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 die Platine über den integrierten Spannungsregler.

  • GND — gemeinsame Masse.

Bemerkung

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

Warnung

Sie dürfen die M4 versorgen, indem Sie 3,3 V direkt in den 3.3V-Pin einspeisen, falls Sie nicht über den integrierten Spannungsregler gehen möchten. Legen Sie in diesem Fall nicht gleichzeitig auch VIN oder USB-Spannung an — das Rückwärts-Treiben des Reglers, während eine andere Versorgung aktiv ist, kann die Kamera dauerhaft beschädigen und zerstören.

Tipp

Verwenden Sie den Batterielaufzeit-Rechner, um zu modellieren, wie lange die M4 bei einem bestimmten Aktiv-/Tiefschlaf-Tastverhältnis mit einer Batterie läuft.

Recovery- und Debug-Pins

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

  • BOOT0 — beim Einschalten der Platine 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.

SWCLK und SWDIO sind als gewöhnliche Header-Pins herausgeführt (kein dedizierter SWD-Anschluss). Verdrahten Sie RESET, SWCLK, SWDIO, GND und 3,3 V mit einem ST‑LINK- oder SEGGER-J‑Link-Adapter, um die Platine zu debuggen.

Integrierte Peripheriegeräte

LEDs

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

  • Benutzer-RGB-LED — softwaresteuerbar, 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 mitgelieferte Sensor (OV7725 auf Standard-Platinen, OV2640 auf sehr frühen Varianten) 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()

Der Sensor ist auf der M4 auf die Platine gelötet — er befindet sich nicht auf einem austauschbaren Modul.

Bemerkung

Auf OV7725-Platinen ist der FSIN-Pin (Frame-Sync) des Sensors mit dem MCU verdrahtet, aber eine Firmware-Unterstützung dafür wurde nicht hinzugefügt.

Auf OV2640-Platinen sind die Pins STROBE, FREX (Frame-Belichtung) und EXPST (Belichtungs-Reset) des Sensors mit dem MCU verdrahtet, aber eine Firmware-Unterstützung dafür wurde nicht hinzugefügt.

Servo-Header

Die Rückseite der Platine verfügt über zwei Lötpads für Servo-Anschlüsse, die den standardmäßigen 3‑poligen Servo-Header (Signal / VIN / GND) für P7 und P8 herausführen. Die Signal-Pins sind direkt den TIM4-Kanälen 1 und 2 zugeordnet (dieselben Kanäle, die von pyb.Servo verwendet werden), und der V+-Pin an jedem Header ist direkt mit VIN verdrahtet, sodass die Servos ihren Strom von der Eingangsschiene und nicht vom 3,3 V-Regler beziehen.

Löten Sie ein Paar abgewinkelte 3‑polige Header in die Pads und schließen Sie zwei Hobby-Servos an, um eine Schwenk-Neige-Halterung anzusteuern:

from pyb import Servo

pan  = Servo(1)              # P7 — TIM4 CH1
tilt = Servo(2)              # P8 — TIM4 CH2
pan.angle(0)
tilt.angle(0)

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 einen der bedruckten Pins zu lesen oder anzusteuern. Die Ausgänge sind 3,3 V CMOS, eingangsseitig 5 V-tolerant und können bis zu 25 mA pro Pin liefern oder aufnehmen (120 mA gesamt über den gesamten 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())

Jeder Eingangs-Pin kann zudem 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

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

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

Bemerkung

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

TIM4 wird gemeinsam mit pyb.Servo genutzt — das Instanziieren eines Servos konfiguriert den gesamten Timer für den 50 Hz-Betrieb um, mischen Sie daher in demselben Skript nicht machine.PWM auf P7/P8 mit pyb.Servo.

Steuern Sie jeden davon über machine.PWM an:

from machine import Pin, PWM

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

Software-Bit-Banging-Busse

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

Thermosensor (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 der Platine 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 die Platine 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 in den DFU-Modus wechseln 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 betreten, indem es machine.bootloader() aufruft:

import machine

machine.bootloader()

Dateisystem und Boot-Reihenfolge

Die M4-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 — wenn eine Karte eingelegt ist, wird sie unter /sdcard eingebunden.

  • ROMFS — schreibgeschütztes, speichergemapptes Dateisystem unter /rom, das verwendet wird, um große Datenbestände (z. B. KI-Modelle) auszuliefern, die von einem Zero-Copy-Zugriff profitieren. Wird von MicroPython beim Start automatisch eingebunden, bevor irgendein Benutzer-Python-Code ausgeführt wird.

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 wenn das laufende Skript zurückkehrt).

  • main.py wird nur beim Kaltstart ausgeführt, unmittelbar nach boot.py. Bei nachfolgenden Soft-Resets wird boot.py erneut ausgeführt, danach geht es aber direkt in die REPL — um main.py erneut auszuführen, müssen Sie die Platine 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 zu verändern — beide Dateien werden im Boot-Verzeichnis gesucht (/sdcard, wenn die Karte eingebunden ist, andernfalls /flash).

Die standardmäßige main.py, die auf einer frisch geflashten Platine ausgeliefert wird, lässt nur 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 hat.

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 (zum Beispiel um die main.py aus dem Flash auszuführen, selbst wenn eine Karte vorhanden ist), erstellen Sie eine leere Datei namens SKIPSD im Stammverzeichnis von /flash.

Wenn die Kamera über USB verbunden ist, wird das Boot-Dateisystem (/sdcard, wenn eine Karte vorhanden ist, andernfalls /flash) auf dem Host auch als USB-Massenspeicherlaufwerk angemeldet, 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 leert.

Bemerkung

Da das Betriebssystem das Laufwerk als passives Blockgerät behandelt, werden Dateien, die durch auf der OpenMV Cam laufenden Code erstellt oder geändert wurden, erst angezeigt, 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 sie 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 M4 wird ausgeliefert mit:

  • /flash32 KB FAT-Dateisystem, lesen/schreiben.

  • /rom128 KB schreibgeschütztes, speichergemapptes 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 wiederherzustellen; wenn das erneute Flashen nicht hilft, ist die Platine möglicherweise physisch beschädigt.

Software-Bibliotheken

Die vollständige Liste der Module finden Sie im Bibliotheksindex — einschließlich derjenigen, die nur im M4-Build vorhanden sind.