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.
Để 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 chip và 32 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)¶
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 Qwiic và B2B 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 SWD và JTAG đầ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()
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_remotephả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ó
/romROMFS riêng — tách biệt với/romcủ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 I2C2 ở 3.3 V.
I2C1 và I2C2 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à I2C1 và I2C2 đã 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 P8 và P9 (chỉ B2B header). Cả hai đầu vào đều được tham chiếu 1.8 V — read_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.SoftI2C và machine.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ứamain.pyvàREADME.txttheo 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
/romdù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‑Dtừ 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 sauboot.py. Các lần soft reset tiếp theo chạy lạiboot.pynhưng đi thẳng đến REPL — để chạy lạimain.pybạ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./romtrê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./romtrê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_remotephả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.