OpenMV Cam RT1062

Die OpenMV Cam RT1062 ist eine stromsparende Platine für maschinelles Sehen, die um den NXP i.MX RT1062 (Cortex‑M7 @ 600 MHz) herum aufgebaut ist. Die Platine kombiniert USB‑C‑Highspeed‑Networking, Wi‑Fi/Bluetooth und 10/100‑Ethernet mit einem OV5640‑5MP‑Sensor auf einem austauschbaren Träger. Im Tiefschlaf zieht die Kamera nur ~30 µA aus einem LiPo‑Akku, was sie hervorragend für akkubetriebene Projekte geeignet macht.

OpenMV Cam RT1062

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

Highlights

  • NXP i.MX RT1062 Cortex‑M7 mit 600 MHz.

  • 32 MB externer SDRAM (16‑Bit @ 160 MHz, 320 MB/s) plus 1 MB interner SRAM und 16 MB QSPI‑Flash (133 MHz 4‑Bit SDR, 66 MB/s Lesen); 4 KB EEPROM ab R6+.

  • OV5640, 5MP‑Rolling‑Shutter‑Sensor.

  • Integrierte IMU (12‑Bit‑3‑Achsen‑Beschleunigungssensor, ±2/4/8 g).

  • Highspeed‑USB‑C (480 Mb/s, 1,5 A Strombegrenzung), 10/100 Mb/s Ethernet (PoE‑fähig per Shield), Wi‑Fi a/b/g/n + Bluetooth 5.1 (Chip‑Antenne oder U.FL‑Option).

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

  • LiPo‑Ladegerät (500 mA ab R6+, 100 mA bei R4/R5), RTC mit Pads für Pufferbatterie. Im Tiefschlaf zieht die Platine ~30 µA im Akkubetrieb.

  • 14 I/O‑Pins, alle mit 3,3‑V‑Ausgang / 3,3‑V‑tolerant, 4 mA pro Pin, interrupt‑fähig.

  • Benutzer‑RGB‑LED, Benutzertaste SW, Hardware‑Einschalttaste (Tiefschlaf‑ / Aufweck‑Zustandsautomat) und eine separate Status‑LED für Laden / USB / VIN‑Versorgung.

Warnung

Die I/O‑Pins der RT1062 sind nicht 5‑V‑tolerant. Verbinden Sie das Gerät nicht direkt mit einem 5‑V‑MCU wie dem Arduino Mega. Versorgen Sie die Platine ausschließlich über VIN.

Pinbelegung

OpenMV Cam RT1062 OV5640 Pinbelegung

Pin‑Referenz

Pin‑Name

Funktion

P0

SPI1 MOSI / PWM2 B3

P1

SPI1 MISO / CAN0 TX

P2

SPI1 SCLK / PWM2 B3

P3

SPI1 SS / CAN0 RX

P4

I2C1 SCL / UART1 TX / PWM1 X2

P5

I2C1 SDA / UART1 RX / PWM1 X3

P6

ADC

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3 / Frame‑Sync‑I/O

P11

Aufwecken (active low, zum Aufwecken mit GND verbinden)

P12

RESET — auf GND ziehen, um die Platine zurückzusetzen (kein GPIO)

P13

Digital‑I/O

P14

Digital‑I/O

ON/OFF

Header‑Pad, das die Hardware‑Einschalttaste nachbildet (active low)

SW

Benutzertaste (active low)

ST

low bei VIN‑Versorgung, high bei USB‑Versorgung

CHG

active low; low während ein angeschlossener LiPo‑Akku geladen wird

PG

active low; low, wenn VIN‑ oder USB‑Versorgung anliegt

LED_RED

Roter Kanal der RGB‑LED (active low)

LED_GREEN

Grüner Kanal der RGB‑LED (active low)

LED_BLUE

Blauer Kanal der RGB‑LED (active low)

Bemerkung

Die P10‑Frame‑Sync‑Leitung ist ein gemeinsam genutzter Bus. Sie ist gleichzeitig mit dem MCU, dem Trigger‑ / Belichtungs‑Pin des Kamerasensors und dem Benutzer‑Header verdrahtet. Die Richtung ist anwendungsabhängig — je nach Konfiguration des Sensors kann der MCU, der Sensor oder ein externes Signal die Leitung treiben. Stellen Sie sicher, dass jeweils nur ein Treiber aktiv ist.

Bemerkung

ON/OFF und P11 beziehen sich auf die stets aktive RAW‑Schiene (nicht auf die geschaltete 3,3‑V‑Schiene), sodass sie funktionsfähig bleiben, während sich der Rest der Platine im Tiefschlaf‑ / Energiesparmodus befindet. Beide Eingänge sind active low.

Diese Pins laufen über Pegelwandler, damit sie auf der RAW‑Schiene betrieben werden können. Falls Sie unbedingt direktes 3,3‑V‑GPIO‑Verhalten an ON/OFF oder P11 benötigen (zum Beispiel, um sie von einem 3,3‑V‑MCU ohne Umweg über den Pegelwandler zu treiben), stellt die Platine Pull‑up‑ und 0‑Ohm‑Jumper‑Pads bereit, mit denen Sie den Pegelwandler umgehen können. Dies ist ein fortgeschrittener Hardware‑Umbau — die meisten Benutzer sollten ihn unangetastet lassen.

Bemerkung

P13 und P14 sind standardmäßig einfache GPIOs ohne Sonderfunktion. Die Pads können optional auf andere Signale umgeroutet werden, indem die 0‑Ohm‑Widerstands‑Lötbrücken auf der Rückseite der Platine neu verlötet werden:

  • P13 ↔ CHG‑Status / JTAG TRSTB

  • P14 ↔ ST‑Status / JTAG TDI

Die meisten Benutzer werden diese Jumper nicht anrühren — belassen Sie sie auf der GPIO‑Standardeinstellung, sofern Sie nicht ausdrücklich das Auslesen des Energiemanagements oder JTAG benötigen.

Stromversorgungs‑Pins

  • 3.3V — geregelte 3,3‑V‑Schiene. Auf der RT1062 nur Ausgang — speisen Sie keine externe Spannung in diesen Pin ein. Bis zu 1 A für Shields verfügbar.

  • VIN — 5‑V‑Eingang. Versorgt die Platine und das integrierte LiPo‑Ladegerät.

  • RAW — Ein-/Ausgang, stets aktiv (3,6 V – 5 V). Führt jeweils die aktive Quelle (VIN, USB oder angeschlossener Akku) und kann auch als Eingang verwendet werden. Sie müssen RAW über eine in Reihe geschaltete Diode treiben, wenn Sie Spannung einspeisen — andernfalls fließt Strom zurück in VIN/USB und beschädigt die Versorgung oder den integrierten Schutz.

  • GND — gemeinsame Masse.

Bemerkung

Der integrierte Energiemanagement‑Chip wählt automatisch diejenige von USB oder VIN mit der höheren Spannung zur Versorgung der Platine und des Akku‑Ladegeräts. Ist ein LiPo angeschlossen, wird er mit dem verbleibenden Spielraum geladen, und der Controller greift auf den Akku zurück, um die Platine am Laufen zu halten, falls VIN/USB einbrechen oder abgezogen werden.

Bemerkung

Die Rückseite der Platine verfügt über Lötpads für eine externe 3,3‑V‑RTC‑Pufferbatterie. Verdrahten Sie eine Knopfzelle mit diesen Pads, um die RTC laufen zu lassen, während der Rest der Platine spannungslos ist.

Tipp

Verwenden Sie den Akkulaufzeit‑Schätzer, um zu modellieren, wie lange die RT1062 bei einem gegebenen Aktiv‑ / Tiefschlaf‑Tastverhältnis im Akkubetrieb läuft.

Ethernet‑Pins

Die RT1062 führt die MDI‑Paare des 10/100‑Mb/s‑Ethernet‑PHY auf dedizierten Pads neben dem GPIO‑Header heraus. Die MDI‑Pins dürfen nicht direkt an einen RJ45 verdrahtet werden — Ethernet‑Magnetik (ein Isolationsübertrager, entweder in eine MagJack integriert oder auf dem Shield) ist zwischen PHY und Kabel erforderlich. Das OpenMV‑PoE‑Shield enthält sie; wenn Sie Ihre eigene Buchse bauen, verwenden Sie einen RJ45 mit integrierter Magnetik oder einen externen Übertrager.

  • ETH_LED — Link/Aktivitäts‑LED. Active low, wenn ein Link besteht; blinkt bei Datenverkehr.

  • ETH_TXP / ETH_TXN — Sendepaar.

  • ETH_RXP / ETH_RXN — Empfangspaar.

Bemerkung

Der Header führt außerdem vier mit Reserved bedruckte Pads heraus. Diese sind footprint‑kompatibel mit den Gigabit‑Ethernet‑Paaren der OpenMV N6 (DC P/N und DD P/N), sodass dasselbe Ethernet‑ / PoE‑Shield in beide Platinen gesteckt werden kann. Das PHY der RT1062 beherrscht nur 10/100 Mb/s, daher haben diese vier Pads keine elektrische Verbindung — lassen Sie sie unbeschaltet.

Wiederherstellungs‑ und Debug‑Pins

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

  • SBL — beim Einschalten der Platine auf 3,3 V ziehen, um in den ROM‑Bootloader‑Modus (Serial Boot Loader) zu gelangen. OpenMV IDE nutzt diesen Modus, um den integrierten Bootloader neu zu flashen.

Ein dedizierter ARM‑10‑Pin‑SWD/JTAG‑Header ist bestückt, kompatibel mit ST‑LINK‑ und SEGGER‑J‑Link‑Adaptern.

Bemerkung

Die RT1062 stellt über diesen Steckverbinder standardmäßig nur SWD‑Debugging bereit. Vollständiges JTAG ist nicht ohne Weiteres verfügbar.

Integrierte Peripherie

LEDs

Die RT1062 hat zwei RGB‑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()
    
  • Power‑LED — direkt von der integrierten Energiemanagement‑Hardware angesteuert, keine Softwaresteuerung. Damit erkennen Sie auf einen Blick, was die Versorgung gerade tut.

    Während des Betriebs:

    Kanal

    Bedeutung

    Blau

    VIN versorgt die Platine (aus bei USB)

    Grün

    USB‑ oder VIN‑Versorgung anliegend

    Rot

    ein angeschlossener LiPo‑Akku wird geladen

    Im Tiefschlaf sind alle Kanäle aus außer Rot, das weiterhin leuchtet, während ein LiPo geladen wird.

Tasten

Die RT1062 hat zwei Tasten:

  • SW — Allzweck‑Benutzertaste. Aus Code als normaler active‑low‑GPIO‑Eingang auslesbar:

    from machine import Pin
    
    sw = Pin("SW", Pin.IN)
    print(sw.value())
    
  • Einschalttaste — von einem dedizierten Zustandsautomaten des Power‑Controllers auf der RT1062‑Platine angesteuert, vollständig in Hardware. Sie ist dem Benutzercode nicht zugänglich; der Controller entscheidet anhand der Haltedauer, was zu tun ist:

    • ~5 s halten, während die Platine läuft → der Zustandsautomat wechselt in den Tiefschlaf.

    • ~1 s halten, während sich die Platine im Tiefschlaf befindet → der Zustandsautomat fährt das System wieder hoch.

    Das Herunterziehen des ON/OFF‑Header‑Pads hat denselben Effekt wie das Drücken der integrierten Einschalttaste — nützlich, um einen externen Schalter zu verdrahten oder die Leitung von einem anderen Mikrocontroller aus zu treiben.

Power‑Status‑Pins

Drei active‑low‑Status‑Eingänge vom integrierten Energiemanagement‑Chip:

  • PG — low, wenn VIN‑ oder USB‑Versorgung anliegt. Stets verbunden.

  • ST — low, wenn die Platine über VIN läuft, high, wenn sie über USB läuft. Standardmäßig nicht verbunden.

  • CHG — low, während ein angeschlossener LiPo‑Akku geladen wird. Standardmäßig nicht verbunden.

from machine import Pin

power_ok = not Pin("PG", Pin.IN).value()

Kamerasensor

Der OV5640 wird über das Modul csi — Kamerasensoren 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 OV5640 verfügt über einen integrierten JPEG‑Kompressor. Setzen Sie csi.CSI.pixformat auf csi.JPEG, und der Sensor liefert komprimierte Einzelbilder direkt über den Kamerabus an die Kamera, was hochauflösende Aufnahmen praktikabel macht: csi.HD (1280×720), csi.FHD (1920×1080) und das volle 5MP‑csi.WQXGA2 (2592×1944) werden allesamt als JPEG gestreamt. Stellen Sie die Kompression mit csi.CSI.quality ein (0–100, höher = größere Einzelbilder, mehr Details):

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

Der Sensor sitzt auf einem austauschbaren Modul — tauschen Sie ihn gegen eines der anderen OpenMV‑Kameramodule (Global Shutter, Wärmebild, höhere Auflösung usw.), ohne den Rest der Platine zu ändern.

Maschinelles Lernen

ml — Maschinelles Lernen führt quantisierte TFLite‑Modelle auf dem Cortex‑M7 mit CMSIS‑NN‑Kerneln aus — schnell genug für kompakte Detektoren mit einigen Einzelbildern pro Sekunde. Modelle auf dem schreibgeschützten /rom‑Dateisystem werden direkt aus dem Flash geladen, ohne in den RAM kopiert zu werden. Hier ist ein 128×128‑BlazeFace‑Detektor, der das erkannte Gesicht und seine sechs Landmarken in jedem Einzelbild überlagert:

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

IMU

Die RT1062‑Firmware bindet den integrierten Beschleunigungssensor nicht an das Modul imu — IMU-Sensor an. Kommunizieren Sie stattdessen direkt über den internen I²C‑Bus mit ihm — der Chip befindet sich an Adresse 0x15 und liefert ab Register 0x03 drei vorzeichenbehaftete 12‑Bit‑Beschleunigungskanäle sowie ein 8‑Bit‑Temperaturbyte:

import machine
import time

ADDR     = 0x15
DATA_REG = 0x03
LSB_PER_G = 1024.0    # ±2 g range

def s12(hi, lo):
    v = ((hi << 8) | lo) >> 4
    return v - 0x1000 if v & 0x800 else v

bus = machine.I2C(2)
print("Devices on I²C2:", bus.scan())

while True:
    d = bus.readfrom_mem(ADDR, DATA_REG, 7)
    x = s12(d[0], d[1]) / LSB_PER_G
    y = s12(d[2], d[3]) / LSB_PER_G
    z = s12(d[4], d[5]) / LSB_PER_G
    temp_c = d[6] * 0.586 + 25.0
    print("x=%+.2fg  y=%+.2fg  z=%+.2fg  T=%.1f°C" % (x, y, z, temp_c))
    time.sleep_ms(100)

EEPROM

Platinen ab R6 und später enthalten ein generisches 4‑KB‑I²C‑EEPROM am selben internen Bus wie der Beschleunigungssensor. (Frühere Revisionen haben keines — der Aufruf dieser Snippets auf R4/R5 läuft auf einen Timeout wegen fehlendem I²C‑Ack.) Verwenden Sie die Standard‑machine.I2C‑API readfrom_mem / writeto_mem mit einer 16‑Bit‑Speicheradresse:

import machine
import time

EEPROM_ADDR = 0x50            # default address
PAGE_SIZE   = 32              # bytes per page (both read and write)
EEPROM_SIZE = 4096

bus = machine.I2C(2)

# Dump the entire 4 KB one page at a time
data = bytearray()
for offset in range(0, EEPROM_SIZE, PAGE_SIZE):
    data += bus.readfrom_mem(EEPROM_ADDR, offset, PAGE_SIZE, addrsize=16)
print(len(data), "bytes")

# Write a small payload back at offset 0 (fits in one page)
bus.writeto_mem(EEPROM_ADDR, 0, b"hello, world", addrsize=16)
time.sleep_ms(10)             # ~5 ms write cycle after each page

# Read it back
print(bus.readfrom_mem(EEPROM_ADDR, 0, 12, addrsize=16))

Sowohl Lese‑ als auch Schreibvorgänge müssen innerhalb einer 32‑Byte‑Seite bleiben. Teilen Sie jede größere Übertragung in einen Aufruf pro Seite auf und fügen Sie zwischen aufeinanderfolgenden Schreibvorgängen die ~5‑ms‑Schreibzyklus‑Verzögerung ein.

Wi‑Fi

Das integrierte Modul der CYW43‑Familie wird über network — Netzwerkkonfiguration als Station‑Schnittstelle bereitgestellt. Nach dem Verbinden liefert ipconfig("addr4") das Paar (ip, netmask):

import network, time

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("ssid", "password")
while not wlan.isconnected():
    time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])

Bluetooth

Dasselbe Funkmodul stellt außerdem Bluetooth 5.1 bereit. Verwenden Sie aioble — Async BLE für asyncio‑freundliches BLE — zum Beispiel als Peripheriegerät zu werben und darauf zu warten, dass sich ein Central verbindet:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="OpenMV-RT1062")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

Ethernet

Wenn ein RJ45 (mit Magnetik) an die MDI‑Pads angeschlossen ist, erscheint das 10/100‑PHY als LAN‑Schnittstelle. DHCP läuft automatisch, sobald der Link aufgebaut ist:

import network, time

lan = network.LAN()
lan.active(True)
while not lan.isconnected():
    time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])

microSD‑Karte

Wenn eine Karte eingelegt ist, wird sie automatisch unter /sdcard eingehängt und ist über das reguläre 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 zu treiben. Ausgänge sind 3,3‑V‑CMOS und können bis zu 4 mA pro Pin liefern bzw. aufnehmen.

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 bei Flankenwechseln einen Interrupt 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

P4

P5

from machine import UART

uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)

I²C

Bus

SCL

SDA

I2C1

P4

P5

from machine import I2C

i2c = I2C(1, 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(1, addr=0x42, mem=buf)

SPI

Bus

MOSI

MISO

SCK

CS

SPI1

P0

P1

P2

P3

from machine import SPI
from machine import Pin

spi = SPI(1, 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

CAN1

P1

P3

Bemerkung

CAN wird auf dieser Platine in Firmware v5.0.0 noch nicht unterstützt.

from machine import CAN

can = CAN(1, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())

ADC

Der einzige Benutzer‑ADC‑Pin ist P6, der bei ~3,3 V Vollausschlag erreicht:

from machine import ADC
import time

adc = ADC("P6")
while True:
    voltage = adc.read_u16() * 3.3 / 65535
    print(voltage)
    time.sleep_ms(100)

PWM

Pin

FlexPWM‑Kanal

P0

PWM2 B3

P2

PWM2 B3

P4

PWM1 X2

P5

PWM1 X3

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3

Treiben Sie einen davon über machine.PWM:

from machine import Pin, PWM

pwm = PWM(Pin("P9"), 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.

Wärmebildsensor (extern)

Die Firmware enthält den Treiber fir — Wärmesensortreiber (fir == far infrared) 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 4 — verdrahten Sie das Modul mit P4 (SCL) und P5 (SDA).

Timing

time

Das Modul time 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 behält die Wanduhrzeit über Resets hinweg bei und (mit der optionalen, an die rückseitigen Pads verdrahteten 3,3‑V‑Pufferbatterie, siehe Stromversorgungs‑Pins) auch über einen vollständigen Spannungsverlust 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())

Die RTC läuft auch im Tiefschlaf weiter, sodass Sie sie als Aufweckquelle für machine.deepsleep() verwenden können.

Watchdog

machine.WDT setzt die Platine zurück, falls 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 aus (wenige Sekunden), 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 RT1062‑Firmware hängt beim Booten bis zu drei Dateisysteme ein:

  • Interner Flash — stets unter /flash eingehängt. 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 eingehängt.

  • ROMFS — schreibgeschütztes, speicherabgebildetes 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 eingehängt, bevor irgendein Benutzer‑Python‑Code läuft.

Nach dem Einhängen 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 dem REPL oder immer 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, springen aber direkt zum REPL — um main.py erneut auszuführen, müssen Sie die Platine vollständig zurücksetzen.

Wird eine boot.py oder main.py auf die SD‑Karte gelegt, überschreibt dies die Kopie im Flash, ohne diese zu verändern — beide Dateien werden im Boot‑Verzeichnis gesucht (/sdcard, wenn die Karte eingehängt ist, andernfalls /flash).

Die standardmäßige main.py, die auf einer frisch geflashten Platine ausgeliefert wird, lässt lediglich den blauen Kanal der Benutzer‑RGB‑LED als Heartbeat blinken (zwei kurze Impulse, kurze Pause), sodass Sie erkennen können, dass die Firmware sauber gebootet ist, ohne dass ein Host angeschlossen 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 (zum Beispiel um die main.py im Flash auch bei eingelegter Karte auszuführen), erstellen Sie eine leere Datei namens SKIPSD im Wurzelverzeichnis von /flash.

Wenn die Platine über USB verbunden ist, meldet sich das Boot‑Dateisystem (/sdcard, falls eine Karte vorhanden ist, andernfalls /flash) auf dem Host zusätzlich als USB‑Massenspeicherlaufwerk an, 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 schreibt.

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 neu einhängt. Wenn sowohl das Betriebssystem als auch die OpenMV Cam gleichzeitig dasselbe Dateisystem beschreiben, gewinnt das Betriebssystem und überschreibt von der Kamera vorgenommene Änderungen. Verwenden Sie die SD‑Karte für alle Daten, die das Skript zurückschreibt, und hängen Sie das Laufwerk neu 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 RT1062 wird ausgeliefert mit:

  • /flash4 MB FAT‑Dateisystem, lesen/schreiben.

  • /rom8 MB schreibgeschütztes, speicherabgebildetes ROMFS, das verwendet wird, um Skripte und ML‑Modelle auszuliefern, die von einem Zero‑Copy‑mmap‑Zugriff profitieren.

  • /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 — so schnell, dass sie eher wie eine funkelnde weiße LED als wie einzelne Farbtöne aussieht — hat die Firmware einen nicht behebbaren Hard Fault erlitten. Flashen Sie die Firmware neu, um die Platine wiederherzustellen; hilft das Neuflashen nicht, ist die Platine möglicherweise physisch beschädigt.

Softwarebibliotheken

Im Bibliotheksverzeichnis finden Sie die vollständige Liste der Module — einschließlich derjenigen, die nur im RT1062‑Build vorhanden sind.