OpenMV AE3

OpenMV AE3 dibangun di atas Alif Ensemble E3 — sebuah SoC dual ARM Cortex‑M55 (inti HP 400 MHz + inti HE 160 MHz) dengan dua NPU on‑chip (NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS). Board ini memadukan NPU dengan sensor global‑shutter PAG7936 1 MP, USB‑C kecepatan tinggi, Wi‑Fi, Bluetooth 5.1, IMU LSM6DSM, mikrofon, dan rangefinder time‑of‑flight VL53L8CX 8×8, semuanya pada papan berukuran 30 × 30 mm.

OpenMV AE3

Untuk datasheet lengkap, foto, dan dimensi, lihat halaman produk OpenMV AE3.

Sorotan

  • Alif Ensemble E3 — dual ARM Cortex‑M55 dengan Helium 128‑bit SIMD, inti HP 400 MHz + inti HE 160 MHz (~640 / ~256 DMIPS, CoreMark 1748 / 752).

  • Dual NPU: NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS untuk AI/ML — menjalankan deteksi objek YOLO bersamaan dengan beban kerja lainnya.

  • GPU 2D hardware untuk penskalaan.

  • SRAM internal 13,5 MB ditambah MRAM on‑chip 5,5 MB dan flash octal eksternal 32 MB (DDR 8‑bit 100 MHz, baca 200 MB/s).

  • RAM cadangan 4 KB dengan RTC on‑chip.

  • Sensor global‑shutter warna 1 MP PAG7936.

  • IMU onboard (akselerometer + giroskop LSM6DSM), mikrofon, dan sensor time‑of‑flight VL53L8CX 8×8 (hingga 4 m).

  • USB‑C kecepatan tinggi (480 Mb/s) dengan penyaringan EMI dan perlindungan TVS, Wi‑Fi a/b/g/n + Bluetooth 5.1 (antena chip atau opsi U.FL).

  • 10 pin I/O pengguna — P0–P3 pada header samping, P4–P5 pada konektor Qwiic, dan P6–P9 pada header B2B di bagian belakang. Jalur debug dan pemulihan tambahan juga diarahkan ke header B2B.

  • Semua pin keluaran 3,3 V / toleran 3,3 V, 25 mA per pin, mampu interupsi. Input ADC direferensikan pada 1,8 V.

  • LED RGB pengguna, tombol pengguna, sakelar pemulihan, konektor Qwiic.

  • Deep sleep 80 µA pada 3,3 V (24 mA diam, 50–60 mA aktif).

Peringatan

Pin I/O AE3 tidak toleran 5 V. Jangan menghubungkan perangkat langsung ke MCU 5 V seperti Arduino Mega — gunakan level shifter untuk sinyal 5 V apa pun.

Pinout

OpenMV AE3 PAG7936 Pinout

Referensi pin

AE3 mengekspos 10 pin pengguna pada header samping (P0–P9). Sinyal tambahan — termasuk JTAG dan jalur pemulihan — diarahkan ke header B2B (board‑to‑board) di bagian belakang papan untuk shield dan carrier board.

Nama pin

Referensi

Fungsi

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

P7

1,8 V

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

P8

1,8 V

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

P9

1,8 V

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

P10

1,8 V

GPIO / JTAG TCK (hanya B2B)

P11

1,8 V

GPIO / JTAG TDO (hanya B2B)

P13

1,8 V

GPIO / JTAG TMS (hanya B2B)

P14

1,8 V

GPIO / JTAG TDI (hanya B2B)

RESET

3,3 V

tarik ke GND untuk mereset papan

SW

3,3 V

tombol pengguna (aktif rendah)

LED_RED

3,3 V

saluran merah LED RGB (aktif rendah)

LED_GREEN

3,3 V

saluran hijau LED RGB (aktif rendah)

LED_BLUE

3,3 V

saluran biru LED RGB (aktif rendah)

Catatan

P0–P5 berada pada header samping (referensi 3,3 V); P6–P9 hanya terekspos pada header B2B di bagian belakang papan dan direferensikan pada 1,8 V. Menghantarkan 3,3 V ke pin bereferensi 1,8 V akan merusak SoC — pastikan sinyal apa pun yang terhubung ke header B2B berada pada tegangan 1,8 V.

Pin daya

  • 3,3 V — rel daya utama AE3. Rel 3,3 V yang sama terekspos pada pad solder header GPIO, konektor Qwiic, dan header B2B di bagian belakang papan.

  • 1,8 V — terekspos pada header B2B hanya sebagai keluaran. Gunakan untuk memberi daya pada periferal logika 1,8 V di carrier B2B; jangan dihantarkan dari luar papan.

  • GND — ground umum.

AE3 tidak memiliki pin VIN dan tidak ada pengisi daya LiPo. Papan dapat diberi daya melalui salah satu dari tiga jalur:

  • USB‑C — regulator on‑board menurunkan 5 V dari USB ke 3,3 V dan menyuntikkannya ke rel 3,3 V.

  • Konektor Qwiic — hantarkan suplai 3,3 V yang terregulasi ke header Qwiic untuk memberi daya pada papan dari modul Qwiic.

  • Header GPIO / pad B2B 3,3 V — hantarkan suplai 3,3 V yang terregulasi ke salah satu pad 3,3 V pada header I/O atau konektor B2B.

Regulator USB menyuplai rel melalui ideal diode, sehingga suplai 3,3 V eksternal pada sisi Qwiic / GPIO / B2B dapat memberi daya pada papan bahkan saat USB masih terhubung tanpa back‑driving regulator USB.

Tip

Gunakan estimator daya baterai untuk memodelkan berapa lama AE3 akan berjalan dengan baterai untuk siklus kerja aktif / deep-sleep tertentu.

Pin pemulihan dan debug

  • RESET — tarik ke GND untuk mereset papan. Melepasnya membiarkan SoC mulai berjalan secara normal.

Terdapat sakelar pemulihan pada permukaan depan (sisi kamera) papan, di sudut kiri bawah. Saat diaktifkan, sakelar ini memaksa SE UART AE3 keluar melalui USB sehingga OpenMV IDE dapat mem‑flash ulang bootloader on‑board. Mode pemulihan yang sama dapat dipicu dari jarak jauh dengan menarik pin RECOVERY pada konektor B2B ke posisi rendah.

AE3 mendukung debugging SWD maupun JTAG penuh:

  • Header SWD 1,8 V di samping papan digunakan untuk kabel Tag-Connect ECV3-06-CTX dan memecah empat sinyal SWD (TCK / TMS / TDO / RSTN) ditambah GND.

  • Header B2B di bagian belakang papan mengekspos pin debug yang sama (P10 = TCK, P11 = TDO, P13 = TMS, P14 = TDI) ditambah sistem RSTN dan JTAG RSTN terpisah. Pin‑pin ini dapat digunakan untuk SWD (TCK + TMS) atau JTAG penuh; jalur JTAG RSTN hanya diperlukan dalam mode JTAG penuh.

Semua sinyal debug direferensikan pada 1,8 V — pastikan adapter debug Anda dikonfigurasi untuk logika 1,8 V sebelum menghubungkan.

Periferal onboard

LED

AE3 memiliki satu LED RGB pengguna, dapat dikontrol melalui perangkat lunak menggunakan machine.LED

from machine import LED

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

Tombol pengguna

AE3 memiliki satu tombol pengguna (SW):

from machine import Pin

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

Untuk menempatkan papan ke dalam deep sleep dan membuat SW membangunkannya kembali, cukup panggil machine.deepsleep() — tidak diperlukan konfigurasi wakeup, tombol sudah terhubung langsung ke input wake:

import machine

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

Anda juga dapat menghubungkan SW sebagai sakelar daya soft. Picu pada tepi naik — jalur menetap tinggi setelah pengguna melepas tombol, sehingga penekanan berikutnya adalah event wake yang tidak ambigu:

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.

Sensor kamera

PAG7936 dikendalikan melalui modul csi --- sensor kamera

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 mendukung mode terpicu — integrasi piksel selaras persis dengan setiap panggilan csi.CSI.snapshot alih-alih clock bingkai yang berjalan bebas, berguna untuk menyinkronkan pengambilan gambar ke event eksternal atau sensor lain. Aktifkan melalui csi.CSI.ioctl dengan csi.IOCTL_SET_TRIGGERED_MODE. Frame rate turun hingga sekitar setengah dari mode bebas karena readout tidak lagi di-pipeline dengan integrasi bingkai berikutnya:

cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)

NPU

Dua NPU on‑chip AE3 (NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS) diekspos melalui modul ml --- Machine Learning. Model yang disimpan pada filesystem /rom hanya‑baca dimuat langsung dari flash tanpa menyalin ke RAM, sehingga bahkan detektor besar pun dapat muat dengan nyaman bersama framebuffer langsung. Jalankan detektor YOLOv8 pada setiap bingkai dan gambar prediksi di atas citra langsung:

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

Inti HE

AE3 mengemas dua inti Cortex‑M55 dalam satu MCU: inti high-performance (HP) yang menjalankan instansi MicroPython utama, kamera, HP NPU, USB, dan sebagainya; dan inti high-efficiency (HE) yang beroperasi dengan daya jauh lebih rendah dan boot ke instansi MicroPython kecilnya sendiri. Kedua inti berbagi bus pesan Open-AMP / RPMsg, sehingga inti HP dapat mengirimkan fungsi Python ke inti HE, mendapatkan hasil kembali, dan menjaga kedua bagian tetap terpisah.

Titik masuk paling sederhana adalah dekorator @openamp.async_remote. Ia mem-marshal fungsi Python, mengirimkannya ke inti HE, dan inti HE menjalankannya sebagai task asyncio. Setelah mendaftarkan task, buat instansi openamp.RemoteProc dengan alamat flash firmware HE dan panggil rproc.start() untuk mem-boot inti kedua. Tanpa callback, output print() fungsi yang didekorasi diteruskan melalui endpoint default ke stdout inti HP — berguna untuk "hello world":

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)

Untuk pesan dua arah, berikan callback ke dekorator. Callback berjalan pada inti HP setiap kali task HE memanggil 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)

Inti HE memiliki HE NPU‑nya sendiri (160 MHz, 46 GOPS), sehingga dapat menjalankan model ML kedua secara paralel dengan apa pun yang sedang dikerjakan HP NPU inti HP. Pembagian yang berguna adalah menempatkan model trigger / classifier kecil yang selalu aktif di sisi HE dan membiarkan inti HP bereaksi hanya ketika sesuatu yang menarik ditandai — keyword spotting dari mikrofon on‑board sangat cocok karena bersifat kontinu, bandwidth rendah, dan inti HE tetap pada daya jauh lebih rendah dari HP. Helper ml.apps.MicroSpeech yang terbekukan mengenali "Yes" dan "No" secara langsung — ucapkan kata-kata tersebut dengan keras dan jelas ke mikrofon on‑board untuk memicu deteksi:

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)

Untuk pembagian yang lebih kaya, jalankan BlazeFace pada HP NPU sementara inti HE menangani keyword spotting di latar belakang — loop HP melapisi keyword yang paling baru didengar pada bingkai kamera:

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

Inti HE sangat cocok untuk beban kerja selalu aktif atau laju rendah yang tidak ingin Anda bersaingkan dengan pipeline kamera/NPU di sisi HP — inferensi ML kecil, DSP ringan pada data mikrofon atau IMU, dan pekerjaan latar belakang serupa.

Beberapa batasan yang perlu diingat:

  • Gunakan mikrofon dan IMU saat mengendalikan periferal dari inti HE — itulah yang dirancang untuk sisi HE. Setiap periferal hanya dapat dimiliki oleh satu inti pada satu waktu, jadi pilih HP atau HE untuknya dan pertahankan pilihan itu selama masa hidup skrip.

  • Setiap badan task @openamp.async_remote harus ter-marshal menjadi kurang dari 500 byte bytecode mpy — jaga agar fungsi tetap kecil dan faktorkan logika yang lebih berat ke dalam modul pustaka terpisah yang dibekukan ke dalam firmware.

  • Impor di dalam fungsi yang dikirimkan hanya melihat modul yang ada di filesystem inti HE. Inti HE memiliki /rom ROMFS‑nya sendiri — terpisah dari /rom inti HP — sehingga modul dan model ML yang ingin Anda sediakan di HE perlu dipanggang ke dalam citra ROMFS sisi HE, bukan yang HP.

Mikrofon

Mikrofon on‑board direkam melalui audio --- Modul Audio. Setiap buffer tiba sebagai bytearray PCM bertanda 16‑bit, sehingga mudah dimasukkan ke ulab/numpy untuk DSP cepat. Detektor kekerasan sederhana — cetak setiap kali volume RMS melewati ambang batas:

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

Akselerometer + giroskop LSM6DSM on‑board diekspos melalui imu --- sensor imu

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)

Sensor time‑of‑flight

AE3 membawa sensor time‑of‑flight multi‑zona VL53L8CX 8×8 yang mengembalikan hingga 64 pembacaan jarak per bingkai, dengan jangkauan maksimum ~4 m. Sensor ini diekspos melalui modul tof --- driver sensor time-of-flight — panggil tof.init() untuk memulai sensor dan tof.read_depth() untuk mengambil bingkai kedalaman sebagai daftar milimeter datar (satu per zona):

import tof

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

Array kedalaman juga dapat digambar di atas bingkai warna dari sensor utama — tof.draw_depth() melukiskannya pada image.Image yang ada, sementara tof.snapshot() mengembalikan citra kedalaman yang baru dirender:

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

CYW43439 on‑board diekspos melalui network --- konfigurasi jaringan sebagai antarmuka station. Setelah terhubung, ipconfig("addr4") mengembalikan pasangan (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

CYW43439 yang sama juga mengekspos Bluetooth 5.1. Gunakan aioble --- Async BLE untuk BLE yang ramah asyncio — misalnya, iklankan sebagai peripheral dan tunggu central untuk terhubung:

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

Referensi bus

GPIO

Gunakan machine.Pin untuk membaca atau mengendalikan salah satu pin yang tercetak pada papan. Keluaran adalah CMOS 3,3 V dan dapat tenggelam/bersumber hingga 25 mA per pin.

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

Pin input apa pun juga dapat memicu interupsi pada transisi tepi:

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

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 adalah satu-satunya bus dengan kontrol aliran hardware. Karena P6–P9 berada di header B2B dan direferensikan pada 1,8 V, UART3 hanya berfungsi melalui level shifter atau carrier B2B — jangan hubungkan logika 3,3 V langsung ke sana.

I²C

Bus

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

Konektor Qwiic on‑board memecah I2C2 pada 3,3 V.

I2C1 dan I2C2 juga dapat digunakan dalam mode target (slave) melalui machine.I2CTarget untuk mengekspos region memori ke kontroler I²C lain:

from machine import I2CTarget

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

Catatan

Periferal LPI2C tidak diekspos dalam firmware. Jika diekspos, hanya akan mendukung mode target (slave), dan I2C1 serta I2C2 sudah mencakup operasi kontroler maupun target.

SPI

Bus

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 mengekspos dua saluran ADC 12‑bit pada P8 dan P9 (hanya header B2B). Kedua input direferensikan pada 1,8 Vread_u16 mengembalikan 0–65535 untuk rentang 0–1,8 V pada pin:

from machine import ADC
import time

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

Peringatan

Input ADC AE3 direferensikan pada 1,8 V, bukan 3,3 V. Menghantarkan sinyal 3,3 V mentah akan menjenuhkan konverter dan dapat merusak pin — bagi tegangan yang lebih tinggi secara eksternal.

PWM

Pin

Timer / saluran

P0

TIM0 T1

P1

TIM0 T0

P2

TIM1 T1

P3

TIM1 T0

P4

TIM2 T1

P5

TIM2 T0

P6

TIM9 T0 (hanya B2B)

P7

TIM9 T1 (hanya B2B)

P8

TIM5 T0 (hanya B2B)

P9

TIM5 T1 (hanya B2B)

Kendalikan salah satunya melalui machine.PWM

from machine import Pin, PWM

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

Bus bit-banged perangkat lunak

machine.SoftI2C dan machine.SoftSPI bekerja pada GPIO apa pun jika Anda membutuhkan bus tambahan.

Sensor termal (eksternal)

Firmware mencakup driver fir --- driver sensor termal (fir == far infrared) untuk AMG8833 8 × 8 thermal imager yang dihubungkan secara eksternal. Hubungkan modul ke bus I²C yang tercantum di bawah ini, lalu baca bingkai dengan 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())

Driver fir hanya berkomunikasi dengan sensor melalui I²C 1 — hubungkan modul ke P4 (SCL) dan P5 (SDA).

Waktu

waktu

Modul time mencakup penundaan blocking, penghitungan tik monoton, dan pengukuran waktu yang telah berlalu:

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)

Timer virtual

machine.Timer menjadwalkan callback periodik atau sekali pakai tanpa mengonsumsi slot timer hardware. Berikan -1 sebagai id untuk menggunakan timer virtual (perangkat lunak):

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

Nilai periode dalam milidetik. Panggil deinit() untuk menghentikan dan membebaskan slot.

Jam waktu nyata

machine.RTC menjaga waktu jam dinding sepanjang reset, didukung oleh 4 KB RAM cadangan on‑chip yang bertahan saat deep sleep:

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 juga berjalan saat deep sleep, sehingga Anda dapat menggunakannya sebagai sumber wakeup untuk machine.deepsleep().

Info boot dan runtime

Jendela bootloader USB

Pada setiap penyalaan, kamera menjalankan bootloader singkat (beberapa detik) yang memungkinkan OpenMV IDE memperbarui firmware tanpa pengguna harus memasuki mode DFU. Setelah jendela berakhir, bootloader menyerahkan kendali ke boot.py lalu ke main.py.

Skrip yang berjalan dapat masuk kembali ke bootloader sesuai permintaan dengan memanggil machine.bootloader()

import machine

machine.bootloader()

Filesystem dan urutan boot

Firmware AE3 me-mount hingga dua filesystem saat boot:

  • Flash internal — selalu di-mount pada /flash. Berisi main.py dan README.txt secara default; dibuat pada boot pertama kali.

  • ROMFS — filesystem read-only yang dipetakan ke memori di /rom, digunakan untuk mengemas aset data besar (misalnya model AI) yang mendapat manfaat dari akses zero-copy. Di-mount secara otomatis oleh MicroPython saat startup, sebelum Python pengguna apa pun berjalan.

Setelah di-mount, direktori kerja diatur ke /flash. Interpreter kemudian menjalankan skrip dari direktori tersebut:

  • boot.py dijalankan pada setiap soft reset (boot dingin, Ctrl‑D dari REPL, atau setiap kali skrip yang berjalan kembali).

  • main.py dijalankan hanya saat boot dingin, segera setelah boot.py. Soft reset berikutnya menjalankan ulang boot.py tetapi langsung ke REPL — untuk menjalankan ulang main.py Anda harus mereset penuh papan.

main.py default yang dikirimkan pada papan yang baru di-flash hanya berkedip saluran biru LED RGB pengguna sebagai detak jantung (dua pulsa pendek, jeda pendek), sehingga Anda dapat mengetahui firmware boot dengan bersih tanpa host terpasang.

sys.path diperluas untuk menyertakan kedua filesystem dan subdirektori lib/‑nya, sehingga modul yang dapat diimpor dapat berada di /flash/lib atau /rom/lib.

Saat terhubung melalui USB, /flash juga dienumerasikan sebagai drive penyimpanan massal USB pada host, memungkinkan Anda mengedit boot.py, main.py, dan file lainnya secara langsung. Keluarkan drive sebelum mereset kamera agar host membuang penulisan yang di-cache.

Catatan

Karena OS memperlakukan drive sebagai perangkat blok pasif, file yang dibuat atau dimodifikasi oleh kode yang berjalan di OpenMV Cam tidak akan muncul sampai host me-mount ulang drive. Jika OS dan OpenMV Cam menulis ke filesystem yang sama pada saat yang bersamaan, OS akan menang dan menimpa perubahan yang dibuat oleh kamera.

Catatan

Saluran merah LED RGB pengguna mungkin menyala sebentar saat host membaca dari atau menulis ke drive penyimpanan massal USB — ini adalah indikator aktivitas yang dikendalikan firmware, bukan kesalahan.

Ukuran penyimpanan

AE3 dikirimkan dengan:

  • /flash — filesystem FAT 8 MB, baca/tulis.

  • /rom pada inti HP — ROMFS 24 MB read-only yang dipetakan ke memori untuk skrip dan data yang dimuat inti HP saat startup.

  • /rom pada inti HE — ROMFS 1 MB read-only yang dimiliki inti HE. Modul dan model ML yang ingin Anda sediakan untuk task @openamp.async_remote harus dipanggang ke dalam citra ini, bukan yang HP.

Indikator hard‑fault

Jika LED RGB pengguna berputar cepat melalui semua warna — cukup cepat sehingga cenderung terlihat seperti LED putih berkedip daripada corak warna yang berbeda — firmware telah mengalami hard fault yang tidak dapat dipulihkan. Flash ulang firmware untuk memulihkan; jika flash ulang tidak membantu, papan mungkin mengalami kerusakan fisik.

Pustaka perangkat lunak

Lihat indeks pustaka untuk daftar lengkap modul — termasuk mana yang unik untuk build AE3.