OpenMV AE3

OpenMV AE3 perustuu Alif Ensemble E3 ‑piiriin — kaksiytimiseen ARM Cortex‑M55 SoC:hen (400 MHz HP‑ydin + 160 MHz HE‑ydin), jossa on kaksi sisäänrakennettua NPU:ta (400 MHz / 204 GOPS HP NPU + 160 MHz / 46 GOPS HE NPU). Kortissa NPU:t yhdistyvät PAG7936 1 MP global‑shutter‑sensoriin, USB‑C high‑speediin, Wi‑Fiin, Bluetooth 5.1:een, LSM6DSM IMU:hun, mikrofoniin ja 8×8 VL53L8CX time‑of‑flight ‑etäisyysmittariin — kaikki 30 × 30 mm:n kortilla.

OpenMV AE3

Täydellinen datalehti, valokuvat ja mitat löytyvät OpenMV AE3 ‑tuotesivulta.

Kohokohdat

  • Alif Ensemble E3 — kaksiytiminen ARM Cortex‑M55, jossa Helium 128‑bittinen SIMD, 400 MHz HP‑ydin + 160 MHz HE‑ydin (~640 / ~256 DMIPS, CoreMark 1748 / 752).

  • Kaksi NPU:ta: 400 MHz / 204 GOPS HP NPU + 160 MHz / 46 GOPS HE NPU tekoälyä/koneoppimista varten — ajaa YOLO‑objektintunnistusta muiden työkuormien rinnalla.

  • Laitteistopohjainen 2D GPU skaalausta varten.

  • 13,5 MB sisäistä SRAM‑muistia sekä 5,5 MB sisäänrakennettua MRAM‑muistia ja 32 MB ulkoista oktaalia flash‑muistia (100 MHz 8‑bittinen DDR, 200 MB/s luku).

  • 4 KB varmistus‑RAM sisäänrakennetulla RTC:llä.

  • PAG7936 1 MP värillinen global‑shutter‑sensori.

  • Sisäänrakennettu IMU (LSM6DSM‑kiihtyvyysanturi + gyroskooppi), mikrofoni ja VL53L8CX 8×8 time‑of‑flight ‑sensori (jopa 4 m).

  • High‑speed USB‑C (480 Mb/s) EMI‑suodatuksella ja TVS‑suojauksella, Wi‑Fi a/b/g/n + Bluetooth 5.1 (piiriantenni tai U.FL‑vaihtoehto).

  • 10 käyttäjän I/O‑nastaa — P0–P3 sivuriveissä, P4–P5 Qwiic‑liittimessä ja P6–P9 takana olevassa B2B‑rivissä. Myös lisädebug‑ ja palautuslinjat on reititetty B2B‑riviin.

  • Kaikki nastat 3,3 V lähtö / 3,3 V sietävät, 25 mA per nasta, keskeytyskykyiset. ADC‑tulot ovat 1,8 V ‑referenssillä.

  • Käyttäjän RGB LED, käyttäjäpainike, palautuskytkin, Qwiic‑liitin.

  • 80 µA syväuni 3,3 V:ssa (24 mA jouten, 50–60 mA aktiivisena).

Varoitus

AE3:n I/O‑nastat eivät siedä 5 V:tä. Älä kytke laitetta suoraan 5 V:n MCU:hun kuten Arduino Mega — käytä tasonmuunninta kaikille 5 V:n signaaleille.

Nastojen sijoittelu

OpenMV AE3 PAG7936 ‑nastojen sijoittelu

Nastojen viite

AE3 tuo esiin 10 käyttäjänastaa sivuriveissä (P0–P9). Lisäsignaalit — mukaan lukien JTAG ja palautuslinja — on reititetty kortin takana olevaan B2B‑riviin (board‑to‑board) suojuksia ja kantokortteja varten.

Nastan nimi

Referenssi

Toiminto

P0

3,3 V

SPI0 MOSI / I2C2 SCL / UART4 TX / TIM0 T1 / PDM D3

P1

3,3 V

SPI0 MISO / I2C2 SDA / UART4 RX / TIM0 T0

P2

3,3 V

SPI0 SCLK / LPI2C SDA / UART5 TX / TIM1 T1

P3

3,3 V

SPI0 SS / LPI2C SCL / UART5 RX / TIM1 T0 / PDM C3

P4

3,3 V

I2C1 SCL / UART1 TX / TIM2 T1 / PDM C0 / CAN TX

P5

3,3 V

I2C1 SDA / UART1 RX / TIM2 T0 / PDM D0 / CAN RX

P6

1,8 V

I2C1 SDA / UART3 CTS / TIM9 T0 (vain B2B)

P7

1,8 V

I2C1 SCL / UART3 RTS / TIM9 T1 (vain B2B)

P8

1,8 V

I3C SDA / UART3 RX / TIM5 T0 / ADC ch S10 (vain B2B)

P9

1,8 V

I3C SCL / UART3 TX / TIM5 T1 / ADC ch S11 (vain B2B)

P10

1,8 V

GPIO / JTAG TCK (vain B2B)

P11

1,8 V

GPIO / JTAG TDO (vain B2B)

P13

1,8 V

GPIO / JTAG TMS (vain B2B)

P14

1,8 V

GPIO / JTAG TDI (vain B2B)

RESET

3,3 V

kytke GND:hen nollataksesi kortin

SW

3,3 V

käyttäjäpainike (aktiivinen matalalla)

LED_RED

3,3 V

RGB LED:n punainen kanava (aktiivinen matalalla)

LED_GREEN

3,3 V

RGB LED:n vihreä kanava (aktiivinen matalalla)

LED_BLUE

3,3 V

RGB LED:n sininen kanava (aktiivinen matalalla)

Muista

P0–P5 ovat sivuriveissä (3,3 V referenssi); P6–P9 tuodaan esiin vain kortin takana olevassa B2B‑rivissä ja ovat 1,8 V referenssillä. 3,3 V:n syöttäminen 1,8 V referenssillä toimivaan nastaan vaurioittaa SoC:tä — varmista, että kaikki B2B‑riviin kytketyt signaalit ovat 1,8 V:ssa.

Virtanastat

  • 3.3V — AE3:n päävirtakisko. Sama 3,3 V kisko tuodaan esiin GPIO‑rivin juotostyynyissä, Qwiic‑liittimessä ja kortin takana olevassa B2B‑rivissä.

  • 1.8V — tuodaan esiin B2B‑rivissä vain lähtönä. Käytä sitä 1,8 V ‑logiikan oheislaitteiden virransyöttöön B2B‑kantokortilla; älä syötä siihen jännitettä kortin ulkopuolelta.

  • GND — yhteinen maa.

AE3:ssa ei ole VIN‑nastaa eikä LiPo‑laturia. Sitä voidaan syöttää virralla kolmen reitin kautta:

  • USB‑C — kortilla oleva regulaattori pudottaa USB:n 5 V:n 3,3 V:iin ja syöttää sen 3,3 V kiskolle.

  • Qwiic‑liitin — syötä säädelty 3,3 V virtalähde Qwiic‑riviin syöttääksesi kortille virtaa Qwiic‑moduulista.

  • GPIO‑rivi / B2B 3,3 V tyynyt — syötä säädelty 3,3 V virtalähde mihin tahansa I/O‑rivin tai B2B‑liittimen 3,3 V tyynyyn.

USB‑regulaattori syöttää kiskoa ideaalidiodin kautta, joten ulkoiset 3,3 V virtalähteet Qwiic‑ / GPIO‑ / B2B‑puolella voivat syöttää kortille virtaa silloinkin kun USB on edelleen kytkettynä, syöttämättä virtaa takaisin USB‑regulaattoriin.

Vihje

Käytä akun keston arviointityökalua mallintaaksesi, kuinka kauan AE3 toimii akulla annetulla aktiivisen ja syväunen käyttösuhteella.

Palautus‑ ja debug‑nastat

  • RESET — kytke GND:hen nollataksesi kortin. Vapauttaminen antaa SoC:n käynnistyä normaalisti.

Kortin etupuolella (kamerapuolella) vasemmassa alakulmassa on palautuskytkin. Käytössä ollessaan se pakottaa AE3:n SE UART:n ulos USB:n kautta, jotta OpenMV IDE voi uudelleenflashata kortilla olevan käynnistyslataimen. Sama palautustila voidaan laukaista etänä vetämällä B2B‑liittimen RECOVERY‑nasta matalaksi.

AE3 tukee sekä SWD‑ että täyttä JTAG‑debugausta:

  • Kortin sivulla oleva 1,8 V SWD‑rivi on tarkoitettu Tag-Connect ECV3-06-CTX ‑kaapelille ja erottelee neljä SWD‑signaalia (TCK / TMS / TDO / RSTN) sekä GND:n.

  • Kortin takana oleva B2B‑rivi tuo esiin samat debug‑nastat (P10 = TCK, P11 = TDO, P13 = TMS, P14 = TDI) sekä järjestelmän RSTN:n ja erillisen JTAG RSTN:n. Näitä nastoja voidaan käyttää joko SWD:hen (TCK + TMS) tai täyteen JTAG:iin; JTAG RSTN ‑linjaa tarvitaan vain täydessä JTAG‑tilassa.

Kaikki debug‑signaalit ovat 1,8 V referenssillä — varmista, että debug‑sovitin on konfiguroitu 1,8 V logiikalle ennen kytkemistä.

Sisäänrakennetut oheislaitteet

LEDit

AE3:ssa on yksi käyttäjän RGB LED, joka on ohjelmallisesti ohjattavissa machine.LED ‑kautta:

from machine import LED

LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()

Käyttäjäpainike

AE3:ssa on yksi käyttäjäpainike (SW):

from machine import Pin

sw = Pin("SW", Pin.IN)
print(sw.value())

Asettaaksesi kortin syväuneen ja antaaksesi SW:n herättää sen takaisin, kutsu vain machine.deepsleep() — herätyskonfiguraatiota ei tarvita, painike on kytketty suoraan herätystuloon:

import machine

machine.deepsleep()   # press SW to wake the board

Voit myös kytkeä SW:n ohjelmalliseksi virtakytkimeksi. Laukaise nousevalla reunalla — linja asettuu korkealle sen jälkeen kun käyttäjä vapauttaa painikkeen, joten seuraava painallus on yksiselitteisesti herätystapahtuma:

import machine
from machine import Pin

def power_off(_):
    machine.deepsleep()

Pin("SW", Pin.IN).irq(power_off, Pin.IRQ_RISING)

# ...rest of the application runs here. Press SW once to sleep,
# press it again to wake.

Kamerasensori

PAG7936:ta ohjataan csi — kennot ‑moduulin kautta:

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.HD)         # 1280×800
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

PAG7936 tukee liipaistua tilaa — pikseli‑integrointi tahdistuu täsmälleen jokaisen csi.CSI.snapshot ‑kutsun kanssa vapaasti juoksevan kehyskellon sijaan, mikä on hyödyllistä kuvauksen synkronoinnissa ulkoiseen tapahtumaan tai toiseen sensoriin. Ota se käyttöön csi.CSI.ioctl:n kautta argumentilla csi.IOCTL_SET_TRIGGERED_MODE. Kehysnopeus putoaa noin puoleen vapaasti juoksevasta tilasta, koska luenta ei enää liukuhihnoitu seuraavan kehyksen integroinnin kanssa:

cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)

NPU

AE3:n kaksi sisäänrakennettua NPU:ta (400 MHz / 204 GOPS HP NPU + 160 MHz / 46 GOPS HE NPU) tuodaan esiin ml — Koneoppiminen ‑moduulin kautta. Vain luku ‑tyyppisessä /rom ‑tiedostojärjestelmässä tallennetut mallit latautuvat suoraan flash‑muistista kopioimatta RAM‑muistiin, joten suuretkin tunnistimet mahtuvat mukavasti elävän kehyspuskurin rinnalle. Aja YOLOv8‑tunnistinta jokaiselle kehykselle ja piirrä ennusteet elävän kuvan päälle:

import csi
import time
import ml
from ml.postprocessing.ultralytics import YoloV8

# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)

# Load YOLO V8 model from ROM FS.
model = ml.Model("/rom/yolov8n_192.tflite", postprocess=YoloV8(threshold=0.4))
print(model)

# Visualization parameters.
n = len(model.labels)
model_class_colors = [
    (int(255 * i // n), int(255 * (n - i - 1) // n), 255)
    for i in range(n)
]

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()

    # boxes is a list of list per class of ((x, y, w, h), score) tuples
    boxes = model.predict([img])

    # Draw bounding boxes around the detected objects
    for i, class_detections in enumerate(boxes):
        rects = [r for r, score in class_detections]
        labels = [model.labels[i] for j in range(len(rects))]
        colors = [model_class_colors[i] for j in range(len(rects))]
        ml.utils.draw_predictions(img, rects, labels, colors, format=None)

    print(clock.fps(), "fps")

HE‑ydin

AE3 pakkaa kaksi Cortex‑M55‑ydintä yhteen MCU:hun: high-performance (HP) ‑ytimen, joka ajaa MicroPython‑pääinstanssia, kameraa, HP NPU:ta, USB:tä ja niin edelleen; sekä high-efficiency (HE) ‑ytimen, joka toimii paljon pienemmällä virrankulutuksella ja käynnistää oman pienen MicroPython‑instanssinsa. Molemmat ytimet jakavat Open-AMP / RPMsg ‑viestiväylän, joten HP‑ydin voi lähettää Python‑funktioita HE‑ytimelle, saada tuloksia takaisin ja pitää nämä kaksi puolikasta toisistaan riippumattomina.

Yksinkertaisin lähtökohta on @openamp.async_remote ‑dekoraattori. Se sarjallistaa Python‑funktion, lähettää sen HE‑ytimelle, ja HE‑ydin ajaa sen asyncio‑tehtävänä. Tehtävien rekisteröinnin jälkeen instansoi openamp.RemoteProc HE‑laiteohjelmiston flash‑osoitteella ja kutsu rproc.start() käynnistääksesi toisen ytimen. Ilman takaisinkutsua dekoroidun funktion print()‑tuloste välitetään oletuspäätepisteen kautta HP‑ytimen stdout:iin — kätevää ”hello world” ‑esimerkkiin:

import time
import openamp

@openamp.async_remote
async def task1(ept):
    import asyncio
    while True:
        print("Hello from the HE core!")
        await asyncio.sleep(1)

# Boot the HE core. This runs the registered tasks.
rproc = openamp.RemoteProc(0x80320000)
rproc.start()

while True:
    print("Hello from the HP core!")
    time.sleep(1)

Kaksisuuntaista viestintää varten välitä takaisinkutsu dekoraattorille. Takaisinkutsu ajetaan HP‑ytimellä aina kun HE‑tehtävä kutsuu ept.send()

import time
import openamp

def task_callback(src_addr, data):
    print("HP received:", data.decode())

@openamp.async_remote(task_callback)
async def task1(ept):
    import asyncio
    count = 0
    while True:
        ept.send(f"count = {count}")
        count += 1
        await asyncio.sleep(1)

rproc = openamp.RemoteProc(0x80320000)
rproc.start()

while True:
    time.sleep(1)

HE‑ytimellä on oma HE NPU (160 MHz, 46 GOPS), joten se voi ajaa toista ML‑mallia rinnakkain sen kanssa mitä HP‑ytimen HP NPU on tekemässä. Hyödyllinen jako on sijoittaa pieni aina päällä oleva liipaisu‑/luokittelumalli HE‑puolelle ja antaa HP‑ytimen reagoida vain kun jotain mielenkiintoista on havaittu — avainsanojen tunnistus kortilla olevasta mikrofonista sopii hyvin, koska se on jatkuvaa, vähäkaistaista ja HE‑ydin pysyy paljon pienemmässä virrankulutuksessa kuin HP. Jäädytetty ml.apps.MicroSpeech ‑apuväline tunnistaa ”Yes” ja ”No” suoraan laatikosta — sano sanat kovaa ja selkeästi kortilla olevaan mikrofoniin laukaistaksesi tunnistuksen:

import time
import openamp

def task_callback(src_addr, data):
    print("Heard:", data.decode())

@openamp.async_remote(task_callback)
async def task1(ept):
    from ml.apps import MicroSpeech
    speech = MicroSpeech(gain_db=24)
    while True:
        label, scores = speech.listen(timeout=0, threshold=0.70)
        if label:
            ept.send(label)

rproc = openamp.RemoteProc(0x80320000)
rproc.start()

while True:
    time.sleep(1)

Rikkaampaa jakoa varten aja BlazeFacea HP NPU:lla samalla kun HE‑ydin hoitaa avainsanojen tunnistusta taustalla — HP‑silmukka piirtää viimeisimmän kuullun avainsanan kamerakehyksen päälle:

import csi
import time
import openamp
import ml
from ml.postprocessing.mediapipe import BlazeFace

label = None
label_ticks = 0
LABEL_HOLD_MS = 2000

def task_callback(src_addr, data):
    global label, label_ticks
    label = data.decode()
    label_ticks = time.ticks_ms()

@openamp.async_remote(task_callback)
async def task1(ept):
    from ml.apps import MicroSpeech
    speech = MicroSpeech(gain_db=24)
    while True:
        l, scores = speech.listen(timeout=0, threshold=0.70)
        if l:
            ept.send(l)

# Start the HE core before initializing the camera on the HP core.
rproc = openamp.RemoteProc(0x80320000)
rproc.start()

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace(threshold=0.4))

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()
    for r, score, keypoints in model.predict([img]):
        ml.utils.draw_predictions(img, [r], ("face",),
                                  ((0, 0, 255),), format=None)
        ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))
    if label is not None:
        if time.ticks_diff(time.ticks_ms(), label_ticks) < LABEL_HOLD_MS:
            img.draw_string((4, 4), f"Heard: {label}",
                            color=(255, 0, 0), scale=2)
        else:
            label = None
    print(clock.fps(), "fps")

HE‑ydin soveltuu hyvin aina päällä oleviin tai matalanopeuksisiin työkuormiin, joiden et halua kilpailevan HP‑puolen kamera‑/NPU‑liukuhihnan kanssa — pieni ML‑päättely, kevyt DSP mikrofoni‑ tai IMU‑datalle ja vastaavat taustatehtävät.

Muutama rajoite, jotka kannattaa pitää mielessä:

  • Pysy mikrofonissa ja IMU:ssa kun ohjaat oheislaitteita HE‑ytimestä — ne ovat se, mitä varten HE‑puoli on suunniteltu. Kunkin oheislaitteen voi omistaa vain yksi ydin kerrallaan, joten valitse sille HP tai HE ja pysy siinä koko skriptin elinkaaren ajan.

  • Kunkin @openamp.async_remote ‑tehtävän rungon on sarjallistuttava alle 500 tavuun mpy‑tavukoodia — pidä funktio pienenä ja eriytä raskaampi logiikka erillisiin kirjastomoduuleihin, jotka jäädytetään laiteohjelmistoon.

  • Lähetetyn funktion sisällä olevat importit näkevät vain ne moduulit, jotka ovat olemassa HE‑ytimen tiedostojärjestelmässä. HE‑ytimellä on oma /rom ROMFS — erillään HP‑ytimen /rom:sta — joten moduulit ja ML‑mallit, jotka haluat HE:n käyttöön, on leivottava HE‑puolen ROMFS‑imageen, ei HP‑puolen.

Mikrofoni

Kortilla oleva mikrofoni kaapataan audio — Audio-moduuli:n kautta. Kukin puskuri saapuu etumerkillisenä 16‑bittisenä PCM bytearray:nä, mikä tekee sen syöttämisestä ulab/numpy:hin triviaalia nopeaa DSP:tä varten. Yksinkertainen äänekkyyden tunnistin — tulosta aina kun RMS‑äänenvoimakkuus ylittää kynnysarvon:

import audio
from ulab import numpy as np

def loudness(pcmbuf):
    samples = np.array(np.frombuffer(pcmbuf, dtype=np.int16), dtype=np.float)
    rms = np.sqrt(np.mean(samples ** 2))
    if rms > 10000:
        print("Loud!", int(rms))

audio.init(channels=1, frequency=16000, gain_db=24)
audio.start_streaming(loudness)

while True:
    pass

IMU

Kortilla oleva LSM6DSM‑kiihtyvyysanturi + gyroskooppi tuodaan esiin imu — imu-sensori:n kautta:

import imu
import time

while True:
    print(imu.acceleration_mg())   # (x, y, z) in milli‑g
    print(imu.angular_rate_mdps()) # (x, y, z) in milli‑deg/s
    time.sleep_ms(100)

Time‑of‑flight ‑sensori

AE3:ssa on VL53L8CX 8×8 monivyöhykkeinen time‑of‑flight ‑sensori, joka palauttaa jopa 64 etäisyyslukemaa kehystä kohden, maksimietäisyyden ollessa ~4 m. Se tuodaan esiin tof — time-of-flight-sensorin ohjain ‑moduulin kautta — kutsu tof.init() käynnistääksesi sensorin ja tof.read_depth() napataksesi syvyyskehyksen litteänä listana millimetrilukemia (yksi per vyöhyke):

import tof

tof.init()
while True:
    depth, depth_min, depth_max = tof.read_depth()
    print("min:", depth_min, "mm  max:", depth_max, "mm")

Syvyystaulukko voidaan myös piirtää pääsensorin värikehyksen päälle — tof.draw_depth() maalaa sen olemassa olevan image.Image:n päälle, kun taas tof.snapshot() palauttaa juuri renderöidyn syvyyskuvan:

import image
import tof
import csi

# Bring up the VL53L8CX time-of-flight sensor.
tof.init()

# Configure the main camera at VGA RGB565.
cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.VGA)

# Off-screen framebuffer used to compose the camera frame and the
# up-scaled depth heat-map side by side before pushing the result
# back to the live preview.
b = image.Image(640, 480, image.RGB565)

while True:
    # Grab a colour frame from the main camera.
    img = cam.snapshot()

    try:
        # Capture TOF data [depth map, min distance, max distance].
        # vflip / hmirror align the ToF orientation with the camera.
        depth, dmin, dmax = tof.read_depth(vflip=True, hmirror=True)

        # Zones with no return read back as 0.0 — clamp them to the
        # frame's max distance so the colour palette doesn't show
        # them as "closest".
        for i in range(0, len(depth)):
            if depth[i] == 0.0:
                depth[i] = dmax

    except RuntimeError:
        # The sensor occasionally faults on a frame; reset and skip.
        tof.reset()
        continue

    # Draw the camera frame into the left half of the framebuffer,
    # scaled to 60% so it leaves room for the depth heat-map on
    # the right.
    b.draw_image(img, x=0, y=64+8, x_scale=0.6, hint=image.BILINEAR)

    # Up-sample the 8x8 depth array 30x with bicubic smoothing and
    # blend it into the right half using the depth palette.
    # scale=(0, 400) maps 0-400 mm to the full palette range.
    tof.draw_depth(b, depth, x=320+64+16, y=64+8, alpha=255,
                   hint=image.BICUBIC, x_scale=30, y_scale=30,
                   scale=(0, 400), color_palette=image.PALETTE_DEPTH)

    # Copy the composed framebuffer back into the live preview so
    # OpenMV IDE shows both panels.
    img.set(b)

Wi‑Fi

Kortilla oleva CYW43439 tuodaan esiin network — verkkomääritykset:n kautta asema‑rajapintana. Yhdistämisen jälkeen ipconfig("addr4") palauttaa (ip, netmask) ‑parin:

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

Sama CYW43439 tuo esiin myös Bluetooth 5.1:n. Käytä aioble — Asynkroninen BLE:a asyncio‑ystävälliseen BLE:hen — esimerkiksi mainosta oheislaitteena ja odota keskusyksikön yhdistävän:

import asyncio
import aioble

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

asyncio.run(run())

Väylien viite

GPIO

Käytä machine.Pin:tä lukeaksesi tai ohjataksesi mitä tahansa silkkipainettua nastaa. Lähdöt ovat 3,3 V CMOS ja voivat nieluttaa/syöttää jopa 25 mA per nasta.

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

Mikä tahansa tulonasta voi myös laukaista keskeytyksen reunasiirtymillä:

def handler(pin):
    print("triggered:", pin)

Pin("P1", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

Väylä

TX

RX

RTS

CTS

UART1

P4

P5

UART3

P9

P8

P7

P6

UART4

P0

P1

UART5

P2

P3

from machine import UART

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

UART3 on ainoa väylä, jossa on laitteistopohjainen vuonohjaus. Koska P6–P9 sijaitsevat B2B‑rivissä ja ovat 1,8 V referenssillä, UART3 toimii vain tasonmuuntimen tai B2B‑kantokortin kautta — älä kytke 3,3 V logiikkaa siihen suoraan.

I²C

Väylä

SCL

SDA

I2C1

P4

P5

I2C2

P0

P1

LPI2C

P3

P2

from machine import I2C

i2c = I2C(1, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")

Kortilla oleva Qwiic‑liitin erottelee I2C2:n 3,3 V:ssa.

I2C1:tä ja I2C2:ta voidaan käyttää myös kohde‑ (slave) tilassa machine.I2CTarget:n kautta tuomaan muistialueen esiin toiselle I²C‑ohjaimelle:

from machine import I2CTarget

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

Muista

LPI2C‑oheislaitetta ei ole tuotu esiin laiteohjelmistossa. Esiin tuotuna se tukisi vain kohde‑ (slave) tilaa, ja I2C1 ja I2C2 kattavat jo sekä ohjain‑ että kohdekäytön.

SPI

Väylä

MOSI

MISO

SCK

CS

SPI0

P0

P1

P2

P3

from machine import SPI
from machine import Pin

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

ADC

Alif Ensemble E3 tuo esiin kaksi 12‑bittistä ADC‑kanavaa nastoissa P8 ja P9 (vain B2B‑rivi). Molemmat tulot ovat 1,8 V referenssillä — read_u16 palauttaa 0–65535 alueella 0–1,8 V nastassa:

from machine import ADC
import time

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

Varoitus

AE3:n ADC‑tulot ovat 1,8 V referenssillä, eivät 3,3 V. Raa’an 3,3 V signaalin syöttäminen kyllästää muuntimen ja voi vaurioittaa nastaa — jaa korkeammat jännitteet alas ulkoisesti.

PWM

Nasta

Ajastin / kanava

P0

TIM0 T1

P1

TIM0 T0

P2

TIM1 T1

P3

TIM1 T0

P4

TIM2 T1

P5

TIM2 T0

P6

TIM9 T0 (vain B2B)

P7

TIM9 T1 (vain B2B)

P8

TIM5 T0 (vain B2B)

P9

TIM5 T1 (vain B2B)

Ohjaa mitä tahansa niistä machine.PWM:n kautta:

from machine import Pin, PWM

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

Ohjelmistopohjaiset bit‑bang ‑väylät

machine.SoftI2C ja machine.SoftSPI toimivat millä tahansa GPIO:lla, jos tarvitset ylimääräisen väylän.

Lämpösensori (kortin ulkopuolinen)

Laiteohjelmisto sisältää fir — lämpösensorin ajuri (fir == far infrared) ‑ajurin ulkoisesti kytketylle AMG8833 8 × 8 lämpökuvaimelle. Kytke moduuli alla lueteltuun I²C‑väylään, ja lue sitten kehyksiä komennoilla 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‑ajuri kommunikoi sensorin kanssa vain I²C 1:n kautta — kytke moduuli nastoihin P4 (SCL) ja P5 (SDA).

Ajoitus

time

time ‑moduuli kattaa estävät viiveet, monotoniset tikit ja kuluneen ajan mittauksen:

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)

Virtuaaliset ajastimet

machine.Timer ajastaa jaksottaisia tai kertaluonteisia takaisinkutsuja kuluttamatta laitteistoajastimen paikkaa. Välitä -1 id:ksi käyttääksesi virtuaalista (ohjelmistopohjaista) ajastinta:

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

Jaksoarvot ovat millisekunneissa. Kutsu deinit() pysäyttääksesi ja vapauttaaksesi paikan.

Reaaliaikakello

machine.RTC pitää kellonaikaa yllä nollausten yli, tukenaan 4 KB sisäänrakennettua varmistus‑RAM‑muistia, joka säilyy syväunen yli:

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

RTC toimii myös syväunen ajan, joten voit käyttää sitä herätyslähteenä funktiolle machine.deepsleep().

Käynnistys‑ ja ajonaikaiset tiedot

USB‑käynnistyslataimen ikkuna

Jokaisen käynnistyksen yhteydessä kamera ajaa lyhyttä käynnistyslatainta (muutaman sekunnin ajan), jonka avulla OpenMV IDE voi päivittää laiteohjelmiston ilman että käyttäjän tarvitsee siirtyä DFU‑tilaan. Ikkunan päätyttyä käynnistyslatain luovuttaa hallinnan boot.py:lle ja sitten main.py:lle.

Käynnissä oleva skripti voi siirtyä takaisin käynnistyslataimeen pyynnöstä kutsumalla machine.bootloader()

import machine

machine.bootloader()

Tiedostojärjestelmä ja käynnistysjärjestys

AE3‑laiteohjelmisto liittää käynnistyksessä enintään kaksi tiedostojärjestelmää:

  • Sisäinen flash‑muisti — aina liitetty kohtaan /flash. Sisältää oletuksena main.py:n ja README.txt:n; luodaan aivan ensimmäisellä käynnistyksellä.

  • ROMFS — vain luku ‑tyyppinen, muistiin kartoitettu tiedostojärjestelmä kohdassa /rom, jota käytetään suurten data‑aineistojen (esim. tekoälymallien) toimittamiseen, jotka hyötyvät zero‑copy‑käytöstä. MicroPython liittää sen automaattisesti käynnistyksessä, ennen kuin mikään käyttäjän Python ajetaan.

Liittämisen jälkeen työhakemistoksi asetetaan /flash. Tulkki ajaa sitten skriptit kyseisestä hakemistosta:

  • boot.py ajetaan jokaisen pehmeän nollauksen yhteydessä (kylmäkäynnistys, Ctrl‑D REPL:stä, tai aina kun käynnissä oleva skripti palaa).

  • main.py ajetaan vain kylmäkäynnistyksessä, heti boot.py:n jälkeen. Myöhemmät pehmeät nollaukset ajavat boot.py:n uudelleen mutta tippuvat suoraan REPL:iin — ajaaksesi main.py:n uudelleen sinun on nollattava kortti kokonaan.

Tuoreesti flashatulla kortilla toimitettava oletus‑main.py vain vilkuttaa käyttäjän RGB LED:n sinistä kanavaa sydämenlyöntinä (kaksi lyhyttä pulssia, lyhyt tauko), jotta voit todeta laiteohjelmiston käynnistyneen puhtaasti ilman mitään isäntälaitetta kytkettynä.

sys.path:ia laajennetaan kattamaan molemmat tiedostojärjestelmät ja niiden lib/‑alihakemistot, joten tuotavat moduulit voivat sijaita kohteessa /flash/lib tai /rom/lib.

Kun kortti on kytketty USB:n kautta, /flash luetteloituu myös USB‑massamuistiasemana isäntälaitteella, jolloin voit muokata boot.py:tä, main.py:tä ja muita tiedostoja suoraan. Poista asema turvallisesti ennen kameran nollausta, jotta isäntälaite tyhjentää välimuistiin tallennetut kirjoitukset.

Muista

Koska käyttöjärjestelmä käsittelee asemaa passiivisena lohkolaitteena, OpenMV Camilla ajettavan koodin luomat tai muokkaamat tiedostot eivät näy ennen kuin isäntälaite liittää aseman uudelleen. Jos sekä käyttöjärjestelmä että OpenMV Cam kirjoittavat samaan tiedostojärjestelmään samaan aikaan, käyttöjärjestelmä voittaa ja ylikirjoittaa kameran tekemät muutokset.

Muista

Käyttäjän RGB LED:n punainen kanava voi syttyä hetkellisesti, kun isäntälaite lukee USB‑massamuistiasemasta tai kirjoittaa siihen — tämä on laiteohjelmiston ohjaama aktiivisuusilmaisin, ei vika.

Tallennustilojen koot

AE3 toimitetaan seuraavasti:

  • /flash8 MB FAT‑tiedostojärjestelmä, luku/kirjoitus.

  • /rom HP‑ytimellä — 24 MB vain luku ‑tyyppinen, muistiin kartoitettu ROMFS skripteille ja datalle, jotka HP‑ydin lataa käynnistyksessä.

  • /rom HE‑ytimellä — 1 MB vain luku ‑tyyppinen ROMFS, jonka HE‑ydin omistaa. Moduulit ja ML‑mallit, jotka haluat @openamp.async_remote ‑tehtävien käyttöön, on leivottava tähän imageen, ei HP‑puolen.

Vakavan vian ilmaisin

Jos käyttäjän RGB LED kiertää nopeasti kaikkien värien läpi — niin nopeasti, että se näyttää pikemminkin tuikkivalta valkoiselta LEDiltä kuin erottuvilta sävyiltä — laiteohjelmisto on kohdannut palautumattoman vakavan vian. Uudelleenflashaa laiteohjelmisto toipuaksesi; jos uudelleenflashaus ei auta, kortti voi olla fyysisesti vaurioitunut.

Ohjelmistokirjastot

Katso kirjastohakemisto täydellisestä moduulilistasta — mukaan lukien mitkä ovat ainutlaatuisia AE3‑buildissa.