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.
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¶
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_GREENundLED_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_IRist in der Hardware High-aktiv verdrahtet, während die Firmware jede andere integrierte LED als Low-aktiv behandelt; verwenden Sie daherlow()/high()anstelle vonon()/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
/flasheingebunden. Enthält standardmäßigmain.pyundREADME.txt; wird beim allerersten Boot erstellt.microSD-Karte — wenn eine Karte eingelegt ist, wird sie unter
/sdcardeingebunden.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.pywird bei jedem Soft-Reset ausgeführt (Kaltstart,Ctrl‑Daus der REPL oder immer wenn das laufende Skript zurückkehrt).main.pywird nur beim Kaltstart ausgeführt, unmittelbar nachboot.py. Bei nachfolgenden Soft-Resets wirdboot.pyerneut ausgeführt, danach geht es aber direkt in die REPL — ummain.pyerneut 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:
/flash— 32 KB FAT-Dateisystem, lesen/schreiben./rom— 128 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.