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.
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¶
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()
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
/romROMFS — 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ää oletuksenamain.py:n jaREADME.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.pyajetaan jokaisen pehmeän nollauksen yhteydessä (kylmäkäynnistys,Ctrl‑DREPL:stä, tai aina kun käynnissä oleva skripti palaa).main.pyajetaan vain kylmäkäynnistyksessä, hetiboot.py:n jälkeen. Myöhemmät pehmeät nollaukset ajavatboot.py:n uudelleen mutta tippuvat suoraan REPL:iin — ajaaksesimain.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:
/flash— 8 MB FAT‑tiedostojärjestelmä, luku/kirjoitus./romHP‑ytimellä — 24 MB vain luku ‑tyyppinen, muistiin kartoitettu ROMFS skripteille ja datalle, jotka HP‑ydin lataa käynnistyksessä./romHE‑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.