OpenMV AE3

OpenMV AE3 được xây dựng dựa trên Alif Ensemble E3 — một SoC ARM Cortex‑M55 kép (lõi HP 400 MHz + lõi HE 160 MHz) với hai NPU tích hợp trên chip (NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS). Board kết hợp các NPU với cảm biến global‑shutter 1 MP PAG7936, USB‑C tốc độ cao, Wi‑Fi, Bluetooth 5.1, IMU LSM6DSM, microphone và cảm biến đo khoảng cách thời gian bay VL53L8CX 8×8, tất cả trên một board 30 × 30 mm.

OpenMV AE3

Để xem datasheet đầy đủ, ảnh và kích thước, hãy truy cập trang sản phẩm OpenMV AE3.

Điểm nổi bật

  • Alif Ensemble E3 — ARM Cortex‑M55 kép với Helium 128‑bit SIMD, lõi HP 400 MHz + lõi HE 160 MHz (~640 / ~256 DMIPS, CoreMark 1748 / 752).

  • NPU kép: NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS cho AI/ML — chạy phát hiện đối tượng YOLO song song với các tác vụ khác.

  • GPU 2D phần cứng để thu phóng.

  • 13.5 MB SRAM nội bộ cùng với 5.5 MB MRAM trên chip32 MB flash octal ngoài (DDR 8‑bit 100 MHz, đọc 200 MB/s).

  • 4 KB backup RAM với RTC trên chip.

  • Cảm biến global‑shutter màu 1 MP PAG7936.

  • IMU tích hợp (gia tốc kế + con quay hồi chuyển LSM6DSM), microphone và cảm biến thời gian bay VL53L8CX 8×8 (lên đến 4 m).

  • USB‑C tốc độ cao (480 Mb/s) với bộ lọc EMI và bảo vệ TVS, Wi‑Fi a/b/g/n + Bluetooth 5.1 (anten chip hoặc tùy chọn U.FL).

  • 10 chân (pin) I/O người dùng — P0–P3 trên các header bên cạnh, P4–P5 trên đầu nối Qwiic và P6–P9 trên B2B header ở mặt sau. Các đường debug và recovery bổ sung cũng được dẫn đến B2B header.

  • Tất cả các chân (pin) đầu ra 3.3 V / chịu được 3.3 V, 25 mA mỗi chân (pin), có khả năng ngắt. Đầu vào ADC được tham chiếu 1.8 V.

  • RGB LED người dùng, nút người dùng, công tắc recovery, đầu nối Qwiic.

  • Deep sleep 80 µA ở 3.3 V (24 mA khi rảnh, 50–60 mA khi hoạt động).

Cảnh báo

Các chân (pin) I/O của AE3 không chịu được 5 V. Không kết nối thiết bị trực tiếp với MCU 5 V như Arduino Mega — sử dụng bộ chuyển mức cho bất kỳ tín hiệu 5 V nào.

Sơ đồ chân (Pinout)

OpenMV AE3 PAG7936 Pinout

Tham chiếu chân (pin)

AE3 cung cấp 10 chân (pin) người dùng trên các header bên cạnh (P0–P9). Các tín hiệu bổ sung — bao gồm JTAG và đường recovery — được dẫn đến B2B (board‑to‑board) header ở mặt sau của board cho các shield và carrier board.

Tên chân (pin)

Tham chiếu

Chức năng

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 (chỉ B2B)

P7

1.8 V

I2C1 SCL / UART3 RTS / TIM9 T1 (chỉ B2B)

P8

1.8 V

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

P9

1.8 V

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

P10

1.8 V

GPIO / JTAG TCK (chỉ B2B)

P11

1.8 V

GPIO / JTAG TDO (chỉ B2B)

P13

1.8 V

GPIO / JTAG TMS (chỉ B2B)

P14

1.8 V

GPIO / JTAG TDI (chỉ B2B)

RESET

3.3 V

kéo xuống GND để reset board

SW

3.3 V

nút người dùng (tích cực mức thấp)

LED_RED

3.3 V

kênh đỏ RGB LED (tích cực mức thấp)

LED_GREEN

3.3 V

kênh xanh lá RGB LED (tích cực mức thấp)

LED_BLUE

3.3 V

kênh xanh dương RGB LED (tích cực mức thấp)

Ghi chú

P0–P5 nằm trên các header bên cạnh (tham chiếu 3.3 V); P6–P9 chỉ được cung cấp trên B2B header ở mặt sau của board và được tham chiếu 1.8 V. Đưa 3.3 V vào chân (pin) tham chiếu 1.8 V sẽ làm hỏng SoC — đảm bảo bất kỳ tín hiệu nào kết nối với B2B header đều ở mức 1.8 V.

Chân (pin) nguồn

  • 3.3V — đường nguồn chính của AE3. Cùng một đường 3.3 V được cung cấp trên các pad hàn GPIO header, đầu nối QwiicB2B header ở mặt sau của board.

  • 1.8V — được cung cấp trên B2B header chỉ dưới dạng đầu ra. Sử dụng để cấp nguồn cho các ngoại vi logic 1.8 V trên B2B carrier; không đưa tín hiệu từ bên ngoài board vào.

  • GND — đất chung.

AE3 không có chân (pin) VIN và không có bộ sạc LiPo. Nó có thể được cấp nguồn qua một trong ba đường:

  • USB‑C — bộ điều chỉnh điện áp trên board hạ 5 V từ USB xuống 3.3 V và đưa vào đường 3.3 V.

  • Đầu nối Qwiic — đưa nguồn 3.3 V ổn định vào Qwiic header để cấp nguồn cho board từ một module Qwiic.

  • GPIO header / B2B pad 3.3 V — đưa nguồn 3.3 V ổn định vào bất kỳ pad 3.3 V nào trên I/O header hoặc đầu nối B2B.

Bộ điều chỉnh USB cấp nguồn cho đường qua một diode lý tưởng, vì vậy các nguồn 3.3 V bên ngoài trên phía Qwiic / GPIO / B2B có thể cấp nguồn cho board ngay cả khi USB vẫn còn kết nối mà không cần back‑driving bộ điều chỉnh USB.

Mẹo

Sử dụng công cụ ước tính thời lượng pin để mô phỏng thời gian AE3 hoạt động trên pin với chu kỳ làm việc active / deep-sleep nhất định.

Chân (pin) recovery và debug

  • RESET — kéo xuống GND để reset board. Nhả ra để SoC khởi động bình thường.

Có một công tắc recovery trên mặt trước (phía camera) của board, góc dưới bên trái. Khi được bật, nó buộc SE UART của AE3 ra ngoài qua USB để OpenMV IDE có thể nạp lại bootloader trên board. Cùng chế độ recovery có thể được kích hoạt từ xa bằng cách kéo chân (pin) RECOVERY trên đầu nối B2B xuống mức thấp.

AE3 hỗ trợ cả giao thức debug SWDJTAG đầy đủ:

  • SWD header 1.8 V ở bên cạnh board dành cho cáp Tag-Connect ECV3-06-CTX và dẫn ra bốn tín hiệu SWD (TCK / TMS / TDO / RSTN) cùng GND.

  • B2B header ở mặt sau board cung cấp các chân (pin) debug tương tự (P10 = TCK, P11 = TDO, P13 = TMS, P14 = TDI) cùng với RSTN hệ thống và JTAG RSTN riêng. Các chân (pin) này có thể dùng cho cả SWD (TCK + TMS) hoặc JTAG đầy đủ; đường JTAG RSTN chỉ cần trong chế độ JTAG đầy đủ.

Tất cả các tín hiệu debug đều tham chiếu 1.8 V — đảm bảo bộ chuyển đổi debug của bạn được cấu hình cho logic 1.8 V trước khi kết nối.

Ngoại vi tích hợp

LED

AE3 có một RGB LED người dùng duy nhất, có thể điều khiển bằng phần mềm qua machine.LED

from machine import LED

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

Nút người dùng

AE3 có một nút người dùng duy nhất (SW):

from machine import Pin

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

Để đặt board vào chế độ deep sleep và để SW đánh thức nó, chỉ cần gọi machine.deepsleep() — không cần cấu hình wakeup, nút được kết nối trực tiếp vào đầu vào wakeup:

import machine

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

Bạn cũng có thể kết nối SW như một công tắc nguồn mềm. Kích hoạt trên cạnh rising — đường ổn định mức cao sau khi người dùng nhả nút, vì vậy lần nhấn tiếp theo rõ ràng là một sự kiện wakeup:

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.

Cảm biến camera

PAG7936 được điều khiển qua module csi --- cảm biến camera

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 hỗ trợ chế độ kích hoạt — tích hợp điểm ảnh căn chỉnh chính xác với mỗi lần gọi csi.CSI.snapshot thay vì xung nhịp khung hình tự do, hữu ích để đồng bộ hóa capture với một sự kiện bên ngoài hoặc cảm biến khác. Bật qua csi.CSI.ioctl với csi.IOCTL_SET_TRIGGERED_MODE. Tốc độ khung hình giảm xuống còn khoảng một nửa so với chế độ tự do vì quá trình đọc không còn pipeline với tích hợp khung hình tiếp theo:

cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)

NPU

Hai NPU trên chip của AE3 (NPU HP 400 MHz / 204 GOPS + NPU HE 160 MHz / 46 GOPS) được cung cấp qua module ml --- Machine Learning. Các mô hình (ML) được lưu trữ trên filesystem /rom read-only tải trực tiếp từ flash mà không cần sao chép vào RAM, vì vậy ngay cả các bộ phát hiện lớn cũng vừa vặn bên cạnh bộ đệm khung hình trực tiếp. Chạy bộ phát hiện YOLOv8 trên mọi khung hình và vẽ các dự đoán lên trên ảnh trực tiếp:

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

Lõi HE

AE3 đóng gói hai lõi Cortex‑M55 trong một MCU: lõi hiệu suất cao (HP) chạy phiên bản MicroPython chính, camera, NPU HP, USB và các thành phần khác; và lõi hiệu quả cao (HE) hoạt động ở mức năng lượng thấp hơn nhiều và khởi động thành phiên bản MicroPython nhỏ của riêng nó. Cả hai lõi chia sẻ bus thông điệp Open-AMP / RPMsg, vì vậy lõi HP có thể gửi các hàm Python tới lõi HE, nhận kết quả trở lại và giữ cho hai phần được tách biệt.

Điểm vào đơn giản nhất là decorator @openamp.async_remote. Nó marshal một hàm Python, gửi đến lõi HE, và lõi HE chạy nó như một tác vụ asyncio. Sau khi đăng ký các tác vụ, khởi tạo openamp.RemoteProc với địa chỉ flash của firmware HE và gọi rproc.start() để khởi động lõi thứ hai. Khi không có callback, đầu ra print() của hàm được trang trí được chuyển tiếp qua endpoint mặc định đến stdout của lõi HP — tiện dụng cho "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)

Để nhắn tin hai chiều, truyền callback cho decorator. Callback chạy trên lõi HP bất cứ khi nào tác vụ HE gọi 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)

Lõi HE có NPU HE riêng (160 MHz, 46 GOPS), vì vậy nó có thể chạy mô hình (ML) thứ hai song song với bất cứ điều gì NPU HP của lõi HP đang bận. Một cách phân chia hữu ích là đặt mô hình (ML) trigger / phân loại nhỏ luôn bật ở phía HE và để lõi HP phản ứng chỉ khi có điều gì đó thú vị được đánh dấu — nhận dạng từ khóa từ microphone trên board là phù hợp vì nó liên tục, băng thông thấp và lõi HE duy trì năng lượng thấp hơn nhiều so với HP. Helper ml.apps.MicroSpeech đã được tích hợp sẵn nhận dạng "Yes" và "No" ngay lập tức — hãy nói to và rõ ràng vào mic trên board để kích hoạt phát hiện:

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)

Để phân chia phong phú hơn, chạy BlazeFace trên NPU HP trong khi lõi HE xử lý nhận dạng từ khóa ở nền — vòng lặp HP hiển thị từ khóa nghe được gần đây nhất lên khung hình camera:

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

Lõi HE phù hợp với các tác vụ luôn bật hoặc tốc độ thấp mà bạn không muốn cạnh tranh với pipeline camera/NPU ở phía HP — suy luận ML nhỏ, DSP nhẹ trên dữ liệu microphone hoặc IMU, và các công việc nền tương tự.

Một số ràng buộc cần lưu ý:

  • Chỉ dùng microphone và IMU khi điều khiển ngoại vi từ lõi HE — đây là những gì phía HE được thiết kế cho. Mỗi ngoại vi chỉ có thể được sở hữu bởi một lõi tại một thời điểm, vì vậy hãy chọn HP hoặc HE cho nó và giữ nguyên trong suốt thời gian tồn tại của tập lệnh.

  • Mỗi thân tác vụ @openamp.async_remote phải marshal xuống dưới 500 byte bytecode mpy — giữ hàm nhỏ gọn và tách logic nặng hơn vào các module thư viện riêng biệt được đóng gói vào firmware.

  • Các import bên trong hàm được gửi đi chỉ thấy các module tồn tại trên filesystem của lõi HE. Lõi HE có /rom ROMFS riêng — tách biệt với /rom của lõi HP — vì vậy các module và mô hình (ML) bạn muốn có sẵn trên HE cần được tích hợp vào image ROMFS phía HE, không phải phía HP.

Microphone

Microphone trên board được capture qua audio --- Mô-đun Âm thanh. Mỗi bộ đệm đến dưới dạng bytearray PCM 16‑bit có dấu, giúp dễ dàng đưa vào ulab/numpy để xử lý DSP nhanh. Một bộ phát hiện độ to đơn giản — in ra khi âm lượng RMS vượt ngưỡng:

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

Gia tốc kế + con quay hồi chuyển LSM6DSM trên board được cung cấp qua imu --- cảm biến 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)

Cảm biến thời gian bay

AE3 mang theo cảm biến thời gian bay đa vùng VL53L8CX 8×8 trả về tới 64 số đọc khoảng cách mỗi khung hình, với tầm đo tối đa ~4 m. Nó được cung cấp qua module tof --- Trình điều khiển cảm biến đo khoảng cách bằng thời gian bay — gọi tof.init() để khởi động cảm biến và tof.read_depth() để lấy khung hình độ sâu dưới dạng danh sách phẳng các số đọc mili mét (một số mỗi vùng):

import tof

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

Mảng độ sâu cũng có thể được vẽ lên khung hình màu từ cảm biến chính — tof.draw_depth() vẽ nó lên một image.Image hiện có, trong khi tof.snapshot() trả về một ảnh độ sâu được render mới:

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 trên board được cung cấp qua network --- cấu hình mạng như một giao diện station. Sau khi kết nối, ipconfig("addr4") trả về cặp (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 tương tự cũng cung cấp Bluetooth 5.1. Sử dụng aioble --- Async BLE cho BLE thân thiện asyncio — ví dụ, quảng bá như một peripheral và chờ central kết nối:

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

Tham chiếu bus

GPIO

Sử dụng machine.Pin để đọc hoặc điều khiển bất kỳ chân (pin) nào được in silk. Đầu ra là CMOS 3.3 V và có thể sink/source tới 25 mA mỗi chân (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())

Bất kỳ chân (pin) đầu vào nào cũng có thể kích hoạt ngắt trên các chuyển tiếp cạnh:

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 là bus duy nhất có điều khiển luồng phần cứng. Vì P6–P9 nằm trên B2B header và được tham chiếu 1.8 V, UART3 chỉ hoạt động qua bộ chuyển mức hoặc B2B carrier — không kết nối logic 3.3 V trực tiếp vào nó.

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

Đầu nối Qwiic trên board dẫn ra I2C23.3 V.

I2C1I2C2 cũng có thể được sử dụng ở chế độ target (slave) qua machine.I2CTarget để cung cấp một vùng bộ nhớ cho bộ điều khiển I²C khác:

from machine import I2CTarget

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

Ghi chú

Ngoại vi LPI2C không được cung cấp trong firmware. Nó chỉ hỗ trợ chế độ target (slave) nếu được cung cấp, và I2C1I2C2 đã bao gồm cả hoạt động controller và 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 cung cấp hai kênh ADC 12‑bit trên P8P9 (chỉ B2B header). Cả hai đầu vào đều được tham chiếu 1.8 Vread_u16 trả về 0–65535 trong phạm vi 0–1.8 V tại chân (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)

Cảnh báo

Đầu vào ADC của AE3 được tham chiếu 1.8 V, không phải 3.3 V. Đưa tín hiệu 3.3 V trực tiếp vào sẽ bão hòa bộ chuyển đổi và có thể làm hỏng chân (pin) — chia điện áp cao hơn xuống từ bên ngoài.

PWM

Chân (Pin)

Timer / kênh

P0

TIM0 T1

P1

TIM0 T0

P2

TIM1 T1

P3

TIM1 T0

P4

TIM2 T1

P5

TIM2 T0

P6

TIM9 T0 (chỉ B2B)

P7

TIM9 T1 (chỉ B2B)

P8

TIM5 T0 (chỉ B2B)

P9

TIM5 T1 (chỉ B2B)

Điều khiển bất kỳ chân (pin) nào trong số chúng qua machine.PWM

from machine import Pin, PWM

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

Bus bit-bang phần mềm

machine.SoftI2Cmachine.SoftSPI hoạt động trên bất kỳ GPIO nào nếu bạn cần thêm bus.

Cảm biến nhiệt (ngoài board)

Firmware bao gồm driver fir --- trình điều khiển cảm biến nhiệt (fir == hồng ngoại xa) cho AMG8833 8 × 8 thermal imager được kết nối bên ngoài. Kết nối module với bus I²C được liệt kê bên dưới, sau đó đọc khung hình bằng 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 chỉ giao tiếp với cảm biến qua I²C 1 — kết nối module với P4 (SCL) và P5 (SDA).

Thời gian

time

Module time bao gồm độ trễ chặn, tích tắc đơn điệu và đo thời gian đã trôi qua:

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 ảo

machine.Timer lên lịch các hàm gọi lại định kỳ hoặc một lần mà không chiếm dụng slot bộ định thời phần cứng. Truyền -1 làm id để sử dụng timer ảo (phần mềm):

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

Giá trị period tính bằng mili giây. Gọi deinit() để dừng và giải phóng slot.

Đồng hồ thời gian thực

machine.RTC duy trì thời gian đồng hồ tường qua các lần reset, được hỗ trợ bởi 4 KB backup RAM trên chip tồn tại qua 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 cũng chạy qua deep sleep, vì vậy bạn có thể sử dụng nó làm nguồn wakeup cho machine.deepsleep().

Thông tin khởi động và runtime

Cửa sổ USB bootloader

Mỗi lần khởi động camera chạy một bootloader ngắn (vài giây) cho phép OpenMV IDE cập nhật firmware mà không cần người dùng vào chế độ DFU. Sau khi cửa sổ hết hạn, bootloader chuyển giao cho boot.py và sau đó main.py.

Một tập lệnh đang chạy có thể vào lại bootloader theo yêu cầu bằng cách gọi machine.bootloader()

import machine

machine.bootloader()

Filesystem và thứ tự khởi động

Firmware AE3 mount tới hai filesystem khi khởi động:

  • Flash nội bộ — luôn được mount tại /flash. Chứa main.pyREADME.txt theo mặc định; được tạo trong lần khởi động đầu tiên.

  • ROMFS — filesystem read-only, ánh xạ bộ nhớ tại /rom dùng để cung cấp các tài sản dữ liệu lớn (ví dụ: mô hình AI) được hưởng lợi từ truy cập zero-copy. Được mount tự động bởi MicroPython khi khởi động, trước khi bất kỳ Python người dùng nào chạy.

Sau khi mount, thư mục làm việc được đặt thành /flash. Trình thông dịch sau đó chạy các tập lệnh từ thư mục đó:

  • boot.py được thực thi trong mỗi lần soft reset (khởi động lạnh, Ctrl‑D từ REPL, hoặc bất cứ khi nào tập lệnh đang chạy kết thúc).

  • main.py được thực thi chỉ khi khởi động lạnh, ngay sau boot.py. Các lần soft reset tiếp theo chạy lại boot.py nhưng đi thẳng đến REPL — để chạy lại main.py bạn phải reset hoàn toàn board.

main.py mặc định được cung cấp trên board mới flash chỉ nhấp nháy kênh blue của RGB LED người dùng như nhịp tim (hai xung ngắn, khoảng cách ngắn), để bạn có thể biết firmware đã khởi động sạch mà không cần host kết nối.

sys.path được mở rộng để bao gồm cả hai filesystem và các thư mục con lib/ của chúng, vì vậy các module có thể import được có thể nằm trong /flash/lib hoặc /rom/lib.

Khi kết nối qua USB, /flash cũng được liệt kê dưới dạng ổ đĩa USB mass‑storage trên host, cho phép bạn chỉnh sửa boot.py, main.py và bất kỳ file nào khác trực tiếp. Eject ổ đĩa trước khi reset camera để host flush các lần ghi đã cache.

Ghi chú

Vì hệ điều hành coi ổ đĩa là thiết bị block thụ động, các file được tạo hoặc sửa đổi bởi code chạy trên OpenMV Cam sẽ không hiển thị cho đến khi host mount lại ổ đĩa. Nếu cả hệ điều hành và OpenMV Cam đều ghi cùng filesystem cùng một lúc, hệ điều hành sẽ thắng và ghi đè các thay đổi do camera thực hiện.

Ghi chú

Kênh đỏ của RGB LED người dùng có thể sáng ngắn trong khi host đang đọc hoặc ghi vào ổ đĩa USB mass‑storage — đây là chỉ báo hoạt động do firmware điều khiển, không phải lỗi.

Kích thước lưu trữ

AE3 được cung cấp với:

  • /flash — filesystem FAT 8 MB, đọc/ghi.

  • /rom trên lõi HP — ROMFS read-only ánh xạ bộ nhớ 24 MB cho các tập lệnh và dữ liệu lõi HP tải khi khởi động.

  • /rom trên lõi HE — ROMFS read-only 1 MB thuộc sở hữu của lõi HE. Các module và mô hình (ML) bạn muốn có sẵn cho các tác vụ @openamp.async_remote phải được tích hợp vào image này, không phải image HP.

Chỉ báo hard‑fault

Nếu RGB LED người dùng đang chuyển đổi nhanh qua tất cả các màu sắc — đủ nhanh để nó có xu hướng trông như LED trắng nhấp nháy thay vì các màu sắc riêng biệt — firmware đã gặp hard fault không thể phục hồi. Hãy nạp lại firmware để phục hồi; nếu nạp lại không giúp ích, board có thể bị hỏng vật lý.

Thư viện phần mềm

Xem chỉ mục thư viện để biết danh sách đầy đủ các module — bao gồm cả những module duy nhất cho bản dựng AE3.