OpenMV AE3¶
OpenMV AE3 побудований на основі Alif Ensemble E3 — двоядерного ARM Cortex‑M55 SoC (ядро HP на 400 МГц + ядро HE на 160 МГц) із двома вбудованими NPU (NPU HP на 400 МГц / 204 GOPS + NPU HE на 160 МГц / 46 GOPS). Плата поєднує NPU із датчиком PAG7936 1 МП із глобальним затвором, USB‑C високої швидкості, Wi‑Fi, Bluetooth 5.1, IMU LSM6DSM, мікрофоном та 8×8 далекоміром часу прольоту VL53L8CX — усе це на платі розміром 30 × 30 мм.
Повну специфікацію, фотографії та розміри дивіться на сторінці продукту OpenMV AE3.
Основні характеристики¶
Alif Ensemble E3 — подвійний ARM Cortex‑M55 із Helium 128‑bit SIMD, ядро HP 400 МГц + ядро HE 160 МГц (~640 / ~256 DMIPS, CoreMark 1748 / 752).
Подвійні NPU: NPU HP 400 МГц / 204 GOPS + NPU HE 160 МГц / 46 GOPS для AI/ML — виконує виявлення об’єктів YOLO паралельно з іншими задачами.
Апаратний 2D GPU для масштабування.
13,5 МБ внутрішньої SRAM плюс 5,5 МБ вбудованої MRAM і 32 МБ зовнішньої окталної флеш-пам’яті (100 МГц 8‑bit DDR, швидкість читання 200 МБ/с).
4 КБ резервної RAM із вбудованим RTC.
Кольоровий датчик із глобальним затвором PAG7936 1 МП.
Вбудований IMU (акселерометр + гіроскоп LSM6DSM), мікрофон і датчик часу прольоту VL53L8CX 8×8 (до 4 м).
Високошвидкісний USB‑C (480 Мб/с) із фільтрацією EMI та захистом TVS, Wi‑Fi a/b/g/n + Bluetooth 5.1 (чипова антена або варіант U.FL).
10 контактів вводу/виводу — P0–P3 на бічних роз’ємах, P4–P5 на роз’ємі Qwiic, а P6–P9 на B2B-роз’ємі на зворотній стороні. Додаткові лінії відлагодження та відновлення також виведені на B2B-роз’єм.
Усі виводи: 3,3 В на виході / сумісні з 3,3 В, 25 мА на вивід, підтримують переривання. Входи ADC мають опорну напругу 1,8 В.
Призначений для користувача RGB LED, кнопка користувача, перемикач відновлення, роз’єм Qwiic.
Глибокий сон 80 мкА при 3,3 В (24 мА у режимі очікування, 50–60 мА у активному режимі).
Попередження
Виводи вводу/виводу AE3 не сумісні з 5 В. Не підключайте пристрій безпосередньо до мікроконтролера з напругою 5 В, наприклад Arduino Mega — використовуйте перетворювач рівнів для будь-якого сигналу 5 В.
Розпіновка¶
Довідник по виводах¶
AE3 має 10 призначених для користувача виводів на бічних роз’ємах (P0–P9). Додаткові сигнали — включаючи JTAG та лінію відновлення — виведені на B2B (плата-до-плати) роз’єм на зворотній стороні плати для розширювальних та несучих плат.
Назва виводу |
Довідник |
Функція |
|---|---|---|
P0 |
3,3 В |
SPI0 MOSI / I2C2 SCL / UART4 TX / TIM0 T1 / PDM D3 |
P1 |
3,3 В |
SPI0 MISO / I2C2 SDA / UART4 RX / TIM0 T0 |
P2 |
3,3 В |
SPI0 SCLK / LPI2C SDA / UART5 TX / TIM1 T1 |
P3 |
3,3 В |
SPI0 SS / LPI2C SCL / UART5 RX / TIM1 T0 / PDM C3 |
P4 |
3,3 В |
I2C1 SCL / UART1 TX / TIM2 T1 / PDM C0 / CAN TX |
P5 |
3,3 В |
I2C1 SDA / UART1 RX / TIM2 T0 / PDM D0 / CAN RX |
P6 |
1,8 В |
I2C1 SDA / UART3 CTS / TIM9 T0 (лише B2B) |
P7 |
1,8 В |
I2C1 SCL / UART3 RTS / TIM9 T1 (лише B2B) |
P8 |
1,8 В |
I3C SDA / UART3 RX / TIM5 T0 / ADC ch S10 (лише B2B) |
P9 |
1,8 В |
I3C SCL / UART3 TX / TIM5 T1 / ADC ch S11 (лише B2B) |
P10 |
1,8 В |
GPIO / JTAG TCK (лише B2B) |
P11 |
1,8 В |
GPIO / JTAG TDO (лише B2B) |
P13 |
1,8 В |
GPIO / JTAG TMS (лише B2B) |
P14 |
1,8 В |
GPIO / JTAG TDI (лише B2B) |
RESET |
3,3 В |
підключіть до GND для скидання плати |
SW |
3,3 В |
кнопка користувача (активна при низькому рівні) |
LED_RED |
3,3 В |
червоний канал RGB LED (активний при низькому рівні) |
LED_GREEN |
3,3 В |
зелений канал RGB LED (активний при низькому рівні) |
LED_BLUE |
3,3 В |
синій канал RGB LED (активний при низькому рівні) |
Примітка
P0–P5 розташовані на бічних роз’ємах (опорна напруга 3,3 В); P6–P9 доступні лише через B2B-роз’єм на зворотній стороні плати й мають опорну напругу 1,8 В. Подача 3,3 В на вивід із опорною напругою 1,8 В пошкодить SoC — переконайтеся, що будь-який сигнал, підключений до B2B-роз’єму, має рівень 1,8 В.
Виводи живлення¶
3,3V — основна шина живлення AE3. Та сама шина 3,3 В виведена на контактні майданчики GPIO-роз’єму, роз’єм Qwiic і B2B-роз’єм на зворотній стороні плати.
1,8V — виведена на B2B-роз’єм лише як вихід. Використовуйте для живлення периферійних пристроїв із логікою 1,8 В на несучій платі B2B; не подавайте напругу ззовні плати.
GND — загальна земля.
AE3 не має виводу VIN та зарядника LiPo. Живлення можна подати трьома способами:
USB‑C — вбудований стабілізатор знижує 5 В з USB до 3,3 В і подає їх на шину 3,3 В.
Роз’єм Qwiic — подайте стабілізоване живлення 3,3 В на роз’єм Qwiic для живлення плати від модуля Qwiic.
Контактні майданчики GPIO / B2B 3,3 В — подайте стабілізоване живлення 3,3 В на будь-який із майданчиків 3,3 В на роз’ємі вводу/виводу або роз’ємі B2B.
Регулятор USB живить шину через ідеальний діод, тому зовнішні джерела живлення 3,3 В на стороні Qwiic / GPIO / B2B можуть живити плату навіть при підключеному USB, не подаючи зворотний струм на регулятор USB.
Порада
Використовуйте калькулятор часу роботи від батареї, щоб змоделювати, як довго AE3 працюватиме від батареї при заданому робочому циклі активного режиму / глибокого сну.
Виводи відновлення та відлагодження¶
RESET — підключіть до GND для скидання плати. Після відпускання SoC запускається в штатному режимі.
На передній (з боку камери) стороні плати, у нижньому лівому куті розташований перемикач відновлення. Коли він увімкнений, SE UART AE3 примусово виводиться через USB, щоб OpenMV IDE міг перепрошити вбудований завантажувач. Той самий режим відновлення можна активувати віддалено, підтягнувши вивід RECOVERY на B2B-роз’ємі до низького рівня.
AE3 підтримує відлагодження як через SWD, так і через повний JTAG:
Роз’єм SWD 1,8 В на бічній стороні плати призначений для кабелю Tag-Connect ECV3-06-CTX і виводить чотири сигнали SWD (TCK / TMS / TDO / RSTN) плюс GND.
B2B-роз’єм на зворотній стороні плати виводить ті самі виводи відлагодження (P10 = TCK, P11 = TDO, P13 = TMS, P14 = TDI) плюс системний RSTN і окремий JTAG RSTN. Ці виводи можна використовувати як для SWD (TCK + TMS), так і для повного JTAG; лінія JTAG RSTN потрібна лише в режимі повного JTAG.
Усі сигнали відлагодження мають опорну напругу 1,8 В — переконайтеся, що адаптер відлагодження налаштований на логіку 1,8 В перед підключенням.
Вбудовані периферійні пристрої¶
Світлодіоди¶
AE3 має один призначений для користувача RGB LED, керований програмно через machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Датчик камери¶
PAG7936 керується через модуль csi — датчики камери
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 підтримує режим тригерування — інтегрування пікселів точно синхронізується з кожним викликом csi.CSI.snapshot, а не з вільнотекучим кадровим тактуванням, що корисно для синхронізації захоплення із зовнішньою подією або іншим датчиком. Увімкніть через csi.CSI.ioctl із csi.IOCTL_SET_TRIGGERED_MODE. Частота кадрів падає приблизно до половини від вільного режиму, оскільки зчитування більше не конвеєризується з інтегруванням наступного кадру:
cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)
NPU¶
Два вбудованих NPU AE3 (NPU HP 400 МГц / 204 GOPS + NPU HE 160 МГц / 46 GOPS) доступні через модуль ml — Машинне навчання. Моделі, збережені у файловій системі лише для читання /rom, завантажуються безпосередньо з флеш-пам’яті без копіювання в RAM, тому навіть великі детектори легко поміщаються поруч із живим кадровим буфером. Запустіть детектор YOLOv8 на кожному кадрі та намалюйте передбачення поверх живого зображення:
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¶
AE3 об’єднує два ядра Cortex‑M55 в одному мікроконтролері: ядро високої продуктивності (HP), що виконує основний екземпляр MicroPython, камеру, NPU HP, USB тощо; і ядро високої ефективності (HE), що працює при значно нижчому споживанні й завантажується у власний невеликий екземпляр MicroPython. Обидва ядра спільно використовують шину повідомлень Open-AMP / RPMsg, тому ядро HP може передавати функції Python ядру HE, отримувати результати назад і тримати обидві частини незалежними.
Найпростіша точка входу — декоратор @openamp.async_remote. Він маршалює функцію Python, відправляє її ядру HE, і ядро HE виконує її як задачу asyncio. Після реєстрації задач створіть екземпляр openamp.RemoteProc з адресою мікропрограми HE у флеш-пам’яті та викличте rproc.start() для завантаження другого ядра. Без зворотного виклику виведення print() декорованої функції пересилається через стандартний кінцевий пристрій на стандартний вивід ядра HP — зручно для «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)
Для двонаправленого обміну повідомленнями передайте зворотний виклик декоратору. Зворотний виклик виконується на ядрі HP щоразу, коли задача HE викликає 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 має власний NPU HE (160 МГц, 46 GOPS), тому воно може паралельно виконувати другу модель МН з тим, чим зайнятий NPU HP ядра HP. Корисним розподілом є розміщення невеликої моделі тригера/класифікатора, що постійно працює, на стороні HE, щоб ядро HP реагувало лише на цікаві події — розпізнавання ключових слів із вбудованого мікрофона добре підходить, оскільки воно безперервне, низькошвидкісне, а ядро HE залишається при значно нижчому енергоспоживанні, ніж HP. Заморожений помічник ml.apps.MicroSpeech розпізнає «Yes» і «No» з коробки — вимовляйте слова голосно та чітко в вбудований мікрофон для спрацьовування виявлення:
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)
Для більш багатого розподілу запустіть BlazeFace на NPU HP, поки ядро HE обробляє розпізнавання ключових слів у фоні — цикл HP накладає останнє почуте ключове слово на кадр камери:
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 добре підходить для постійно увімкнених або низькочастотних задач, які ви не хочете змагатися з конвеєром камери/NPU на стороні HP — невеликий інференс МН, легка обробка сигналів з мікрофона або IMU та подібні фонові задачі.
Кілька обмежень, які варто пам’ятати:
При керуванні периферійними пристроями з ядра HE обмежтеся мікрофоном і IMU — саме для цього призначена сторона HE. Кожен периферійний пристрій може належати лише одному ядру одночасно, тому оберіть HP або HE і дотримуйтеся цього вибору протягом усього часу роботи скрипта.
Тіло кожної задачі
@openamp.async_remoteповинне маршалюватися у менш ніж 500 байт байткоду mpy — тримайте функцію малою та виносьте важчу логіку в окремі бібліотечні модулі, що заморожуються в мікропрограму.Імпорти всередині відправленої функції бачать лише модулі, що існують у файловій системі ядра HE. Ядро HE має власну
/romROMFS — окрему від/romядра HP — тому модулі та моделі МН, які мають бути доступні на HE, потрібно включити в образ ROMFS для HE, а не для HP.
Мікрофон¶
Захоплення вбудованого мікрофона здійснюється через audio — Аудіомодуль. Кожен буфер надходить як знаковий 16-бітний PCM bytearray, що дозволяє легко подавати його в ulab/numpy для швидкої обробки сигналів. Простий детектор гучності — виводити повідомлення щоразу, коли RMS-гучність перевищує поріг:
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¶
Вбудований акселерометр + гіроскоп LSM6DSM доступний через imu — датчик 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)
Датчик часу прольоту¶
AE3 оснащений 8×8 багатозонним датчиком часу прольоту VL53L8CX, що повертає до 64 показань відстані на кадр із максимальним діапазоном ~4 м. Він доступний через модуль tof — Драйвер датчика часу прольоту — викличте tof.init() для запуску датчика та tof.read_depth() для отримання кадру глибини у вигляді плаского списку значень у міліметрах (по одному на зону):
import tof
tof.init()
while True:
depth, depth_min, depth_max = tof.read_depth()
print("min:", depth_min, "mm max:", depth_max, "mm")
Масив глибини також можна накласти на кольоровий кадр із основного датчика — tof.draw_depth() малює його на існуючому image.Image, тоді як tof.snapshot() повертає щойно відрендерене зображення глибини:
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 доступний через network — налаштування мережі як інтерфейс станції. Після підключення ipconfig("addr4") повертає пару (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 також підтримує Bluetooth 5.1. Використовуйте aioble — Async BLE для asyncio‑сумісного BLE — наприклад, рекламуйте як периферійний пристрій і чекайте підключення центрального пристрою:
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())
Довідник по шинах¶
GPIO¶
Використовуйте machine.Pin для читання або керування будь-яким із позначених виводів. Виходи є 3,3 В CMOS і можуть поглинати/генерувати до 25 мА на вивід.
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())
Будь-який вхідний вивід також може генерувати переривання при фронтах сигналу:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Шина |
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 — єдина шина з апаратним керуванням потоком. Оскільки P6–P9 розташовані на B2B-роз’ємі та мають опорну напругу 1,8 В, UART3 працює лише через перетворювач рівнів або несучу плату B2B — не підключайте до неї логіку 3,3 В напряму.
I²C¶
Шина |
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")
Вбудований роз’єм Qwiic виводить I2C2 при напрузі 3,3 В.
I2C1 і I2C2 також можна використовувати в режимі відомого (slave) через machine.I2CTarget для надання доступу до ділянки пам’яті іншому контролеру I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(1, addr=0x42, mem=buf)
Примітка
Периферійний пристрій LPI2C не виведений у мікропрограмі. Якби він був виведений, він підтримував би лише режим відомого (slave), а I2C1 і I2C2 вже охоплюють роботу як контролера, так і відомого.
SPI¶
Шина |
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 виводить два канали 12‑бітного ADC на P8 та P9 (лише B2B-роз’єм). Обидва входи мають опорну напругу 1,8 В — read_u16 повертає 0–65535 у діапазоні 0–1,8 В на виводі:
from machine import ADC
import time
adc = ADC("P8")
while True:
voltage = adc.read_u16() * 1.8 / 65535
print(voltage)
time.sleep_ms(100)
Попередження
Входи ADC AE3 мають опорну напругу 1,8 В, а не 3,3 В. Подача сигналу 3,3 В безпосередньо насичить перетворювач і може пошкодити вивід — зменшуйте вищі напруги зовнішнім дільником.
PWM¶
Вивід |
Таймер / канал |
|---|---|
P0 |
TIM0 T1 |
P1 |
TIM0 T0 |
P2 |
TIM1 T1 |
P3 |
TIM1 T0 |
P4 |
TIM2 T1 |
P5 |
TIM2 T0 |
P6 |
TIM9 T0 (лише B2B) |
P7 |
TIM9 T1 (лише B2B) |
P8 |
TIM5 T0 (лише B2B) |
P9 |
TIM5 T1 (лише B2B) |
Керуйте будь-яким з них через machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P0"), freq=1_000, duty_u16=32768)
Програмні шини з побітовим маніпулюванням¶
machine.SoftI2C і machine.SoftSPI працюють на будь-якому GPIO, якщо потрібна додаткова шина.
Тепловий датчик (зовнішній)¶
Мікропрограма включає драйвер fir — драйвер теплового датчика (fir == далекий інфрачервоний діапазон) для зовнішнього AMG8833 теплового датчика 8×8. Підключіть модуль до зазначеної шини I²C, після чого зчитуйте кадри за допомогою 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 зв’язується з датчиком лише через I²C 1 — підключіть модуль до P4 (SCL) та P5 (SDA).
Час¶
time¶
Модуль time охоплює блокуючі затримки, монотонні лічильники та вимірювання часу, що минув:
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)
Віртуальні таймери¶
machine.Timer планує periodичні або одноразові зворотні виклики без використання слоту апаратного таймера. Передайте -1 як ідентифікатор для використання віртуального (програмного) таймера:
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"))
Значення періоду задаються в мілісекундах. Викличте deinit() для зупинки та звільнення слоту.
Годинник реального часу¶
machine.RTC зберігає час реального часу між скиданнями, підтримуваний 4 КБ вбудованої резервної RAM, що зберігається в режимі глибокого сну:
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 також працює під час глибокого сну, тому його можна використовувати як джерело пробудження для machine.deepsleep().
Інформація про завантаження та час виконання¶
Вікно USB завантажувача¶
При кожному увімкненні камера виконує короткий завантажувач (кілька секунд), що дозволяє OpenMV IDE оновлювати мікропрограму без необхідності вручну входити в режим DFU. Після закінчення вікна завантажувач передає керування boot.py, а потім main.py.
Запущений скрипт може повторно увійти в завантажувач на вимогу, викликавши machine.bootloader()
import machine
machine.bootloader()
Файлова система та порядок завантаження¶
Мікропрограма AE3 монтує до двох файлових систем при завантаженні:
Внутрішня флеш-пам’ять — завжди монтується в
/flash. За замовчуванням міститьmain.pyтаREADME.txt; створюється при першому завантаженні.ROMFS — файлова система лише для читання з відображенням у пам’ять за адресою
/rom, що використовується для зберігання великих даних (наприклад, моделей AI), які отримують вигоду від доступу без копіювання. Монтується автоматично MicroPython при запуску, до виконання будь-якого Python користувача.
Після монтування поточний каталог встановлюється в /flash. Потім інтерпретатор виконує скрипти з цього каталогу:
boot.pyвиконується при кожному м’якому скиданні (холодне завантаження,Ctrl‑Dз REPL або щоразу, коли запущений скрипт завершується).main.pyвиконується лише при холодному завантаженні, одразу післяboot.py. Подальші м’які скидання повторно виконуютьboot.py, але переходять безпосередньо до REPL — щоб повторно виконатиmain.py, потрібно повністю скинути плату.
Стандартний main.py, що поставляється на свіжо прошитій платі, просто блимає синім каналом RGB LED користувача як сердцебиття (два короткі імпульси, короткий проміжок), щоб можна було переконатися, що мікропрограма завантажилась без помилок без підключеного хоста.
sys.path розширений для включення обох файлових систем та їхніх підкаталогів lib/, тому імпортовані модулі можуть знаходитися в /flash/lib або /rom/lib.
При підключенні через USB, /flash також відображається як USB-накопичувач на хості, що дозволяє редагувати boot.py, main.py та будь-які інші файли безпосередньо. Від’єднайте диск перед скиданням камери, щоб хост записав кешовані зміни.
Примітка
Оскільки ОС розглядає диск як пасивний блоковий пристрій, файли, створені або змінені кодом, що виконується на OpenMV Cam, не відображатимуться до повторного монтування диска хостом. Якщо і ОС, і OpenMV Cam одночасно записують в одну файлову систему, ОС переможе та перезапише зміни, зроблені камерою.
Примітка
Червоний канал RGB LED користувача може ненадовго засвітитися, поки хост читає з або записує на USB-накопичувач — це індикатор активності, керований мікропрограмою, а не помилка.
Розміри сховища¶
AE3 поставляється з:
/flash— 8 МБ файлова система FAT, читання/запис./romна ядрі HP — 24 МБ файлова система ROMFS лише для читання з відображенням у пам’ять для скриптів і даних, що завантажуються ядром HP при запуску./romна ядрі HE — 1 МБ файлова система ROMFS лише для читання, що належить ядру HE. Модулі та моделі МН, які мають бути доступні задачам@openamp.async_remote, потрібно включити в цей образ, а не в образ HP.
Індикатор апаратної помилки¶
Якщо RGB LED користувача швидко циклічно перемикається між усіма кольорами — достатньо швидко, що виглядає як мерехтливий білий LED замість окремих відтінків — мікропрограма зіткнулась з невідновлюваною апаратною помилкою. Перепрошийте мікропрограму для відновлення; якщо перепрошивка не допомагає, плата може бути фізично пошкоджена.
Програмні бібліотеки¶
Дивіться індекс бібліотек для повного списку модулів — включаючи ті, що є унікальними для збірки AE3.