OpenMV AE3¶
A OpenMV AE3 é construída em torno do Alif Ensemble E3 — um SoC dual ARM Cortex‑M55 (núcleo HP a 400 MHz + núcleo HE a 160 MHz) com dois NPUs integrados (NPU HP a 400 MHz / 204 GOPS + NPU HE a 160 MHz / 46 GOPS). A placa combina os NPUs com o sensor PAG7936 de 1 MP com obturador global, USB‑C de alta velocidade, Wi‑Fi, Bluetooth 5.1, um IMU LSM6DSM, um microfone e um telémetro VL53L8CX de tempo de voo 8×8, tudo numa placa de 30 × 30 mm.
Para a ficha técnica completa, fotos e dimensões, consulte a página do produto OpenMV AE3.
Destaques¶
Alif Ensemble E3 — dual ARM Cortex‑M55 com Helium SIMD de 128 bits, núcleo HP a 400 MHz + núcleo HE a 160 MHz (~640 / ~256 DMIPS, CoreMark 1748 / 752).
NPUs duplos: NPU HP a 400 MHz / 204 GOPS + NPU HE a 160 MHz / 46 GOPS para IA/ML — executa deteção de objetos YOLO em paralelo com outras cargas de trabalho.
GPU 2D por hardware para escalonamento.
13,5 MB de SRAM interna mais 5,5 MB de MRAM integrada e 32 MB de flash octal externo (DDR 8‑bit a 100 MHz, leitura a 200 MB/s).
4 KB de RAM de reserva com o RTC integrado.
Sensor de cor com obturador global de 1 MP PAG7936.
IMU integrado (acelerómetro + giroscópio LSM6DSM), microfone e sensor de tempo de voo VL53L8CX 8×8 (até 4 m).
USB‑C de alta velocidade (480 Mb/s) com filtragem EMI e proteção TVS, Wi‑Fi a/b/g/n + Bluetooth 5.1 (antena de chip ou opção U.FL).
10 pinos de I/O para o utilizador — P0–P3 nos conectores laterais, P4–P5 no conector Qwiic e P6–P9 no conector B2B na parte de trás. Linhas adicionais de depuração e recuperação também são encaminhadas para o conector B2B.
Todos os pinos com saída de 3,3 V / tolerantes a 3,3 V, 25 mA por pino, com suporte a interrupções. As entradas ADC são referenciadas a 1,8 V.
LED RGB para o utilizador, botão do utilizador, interruptor de recuperação, conector Qwiic.
Suspensão profunda a 80 µA a 3,3 V (24 mA em repouso, 50–60 mA em funcionamento).
Aviso
Os pinos de I/O da AE3 não são tolerantes a 5 V. Não ligue o dispositivo diretamente a um MCU de 5 V como o Arduino Mega — utilize um conversor de nível para qualquer sinal de 5 V.
Pinagem¶
Referência dos pinos¶
A AE3 expõe 10 pinos de utilizador nos conectores laterais (P0–P9). Sinais adicionais — incluindo JTAG e a linha de recuperação — são encaminhados para um conector B2B (board‑to‑board) na parte de trás da placa, destinado a módulos de expansão e placas portadoras.
Nome do pino |
Referência |
Função |
|---|---|---|
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 (apenas B2B) |
P7 |
1,8 V |
I2C1 SCL / UART3 RTS / TIM9 T1 (apenas B2B) |
P8 |
1,8 V |
I3C SDA / UART3 RX / TIM5 T0 / ADC ch S10 (apenas B2B) |
P9 |
1,8 V |
I3C SCL / UART3 TX / TIM5 T1 / ADC ch S11 (apenas B2B) |
P10 |
1,8 V |
GPIO / JTAG TCK (apenas B2B) |
P11 |
1,8 V |
GPIO / JTAG TDO (apenas B2B) |
P13 |
1,8 V |
GPIO / JTAG TMS (apenas B2B) |
P14 |
1,8 V |
GPIO / JTAG TDI (apenas B2B) |
RESET |
3,3 V |
ligar ao GND para reiniciar a placa |
SW |
3,3 V |
botão do utilizador (ativo em nível baixo) |
LED_RED |
3,3 V |
canal vermelho do LED RGB (ativo em nível baixo) |
LED_GREEN |
3,3 V |
canal verde do LED RGB (ativo em nível baixo) |
LED_BLUE |
3,3 V |
canal azul do LED RGB (ativo em nível baixo) |
Nota
P0–P5 estão nos conectores laterais (referenciados a 3,3 V); P6–P9 estão expostos apenas no conector B2B na parte de trás da placa e são referenciados a 1,8 V. Aplicar 3,3 V num pino referenciado a 1,8 V danifica o SoC — certifique-se de que qualquer sinal ligado ao conector B2B está a 1,8 V.
Pinos de alimentação¶
3.3V — o rail de alimentação principal da AE3. O mesmo rail de 3,3 V está exposto nos pads de solda do conector GPIO, no conector Qwiic e no conector B2B na parte de trás da placa.
1.8V — exposto no conector B2B apenas como saída. Utilize-o para alimentar periféricos com lógica a 1,8 V numa placa portadora B2B; não o alimente a partir do exterior da placa.
GND — massa comum.
A AE3 não tem pino VIN nem carregador de LiPo. Pode ser alimentada por três caminhos:
USB‑C — o regulador integrado reduz os 5 V do USB para 3,3 V e injeta-os no rail de 3,3 V.
Conector Qwiic — aplique uma alimentação regulada de 3,3 V no conector Qwiic para alimentar a placa a partir de um módulo Qwiic.
Pads GPIO / B2B a 3,3 V — aplique uma alimentação regulada de 3,3 V em qualquer um dos pads de 3,3 V no conector de I/O ou no conector B2B.
O regulador USB alimenta o rail através de um díodo ideal, para que as fontes de 3,3 V externas no lado Qwiic / GPIO / B2B possam alimentar a placa mesmo com o USB ligado, sem reabastecer o regulador USB.
Dica
Utilize o estimador de autonomia de bateria para modelar por quanto tempo a AE3 funcionará com bateria para um determinado ciclo de funcionamento activo / suspensão profunda.
Pinos de recuperação e depuração¶
RESET — ligar ao GND para reiniciar a placa. Ao libertar, o SoC arranca normalmente.
Existe um interruptor de recuperação na face frontal (lado da câmara) da placa, no canto inferior esquerdo. Quando ativado, força a saída UART SE da AE3 sobre USB para que o OpenMV IDE possa reflashear o bootloader integrado. O mesmo modo de recuperação pode ser ativado remotamente colocando o pino RECOVERY no conector B2B em nível baixo.
A AE3 suporta depuração tanto por SWD como por JTAG completo:
O conector SWD a 1,8 V no lado da placa é para um cabo Tag-Connect ECV3-06-CTX e expõe os quatro sinais SWD (TCK / TMS / TDO / RSTN) mais GND.
O conector B2B na parte de trás da placa expõe os mesmos pinos de depuração (P10 = TCK, P11 = TDO, P13 = TMS, P14 = TDI) mais o RSTN do sistema e um JTAG RSTN separado. Estes pinos podem ser utilizados tanto para SWD (TCK + TMS) como para JTAG completo; a linha JTAG RSTN só é necessária no modo JTAG completo.
Todos os sinais de depuração são referenciados a 1,8 V — certifique-se de que o seu adaptador de depuração está configurado para lógica a 1,8 V antes de ligar.
Periféricos integrados¶
LEDs¶
A AE3 possui um único LED RGB de utilizador, controlável por software através de machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Sensor de câmara¶
O PAG7936 é controlado através do módulo csi — sensores de câmara
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()
O PAG7936 suporta o modo disparado — a integração de pixéis alinha-se exatamente com cada chamada a csi.CSI.snapshot, em vez do relógio de fotogramas em modo livre, o que é útil para sincronizar a captura com um evento externo ou outro sensor. Ative-o através de csi.CSI.ioctl com csi.IOCTL_SET_TRIGGERED_MODE. A taxa de fotogramas cai para cerca de metade do modo de funcionamento livre porque a leitura deixa de ser encadeada com a integração do fotograma seguinte:
cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)
NPU¶
Os dois NPUs integrados da AE3 (NPU HP a 400 MHz / 204 GOPS + NPU HE a 160 MHz / 46 GOPS) estão expostos através do módulo ml — Machine Learning. Os modelos armazenados no sistema de ficheiros de leitura exclusiva /rom carregam diretamente a partir da flash sem cópia para RAM, pelo que até detetores de grande dimensão cabem confortavelmente junto ao buffer de fotograma em direto. Execute um detetor YOLOv8 em cada fotograma e desenhe as previsões sobre a imagem ao vivo:
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")
Núcleo HE¶
A AE3 integra dois núcleos Cortex‑M55 num único MCU: o núcleo de alto desempenho (HP) que executa a instância principal do MicroPython, a câmara, o NPU HP, USB e restantes funções; e o núcleo de alta eficiência (HE) que funciona com muito menos energia e arranca numa pequena instância do MicroPython própria. Ambos os núcleos partilham um barramento de mensagens Open-AMP / RPMsg, permitindo ao núcleo HP despachar funções Python para o núcleo HE, obter resultados de volta e manter as duas metades desacopladas.
O ponto de entrada mais simples é o decorador @openamp.async_remote. Ele empacota uma função Python, envia-a para o núcleo HE, e o núcleo HE executa-a como uma tarefa asyncio. Após registar as tarefas, instancie openamp.RemoteProc com o endereço flash do firmware do núcleo HE e chame rproc.start() para arrancar o segundo núcleo. Sem callback, a saída print() da função decorada é reencaminhada pelo endpoint predefinido para o stdout do núcleo HP — prático para um «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)
Para mensagens bidirecionais, passe um callback ao decorador. O callback é executado no núcleo HP sempre que a tarefa HE chama 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)
O núcleo HE tem o seu próprio NPU HE (160 MHz, 46 GOPS), pelo que pode executar um segundo modelo de ML em paralelo com o que o NPU HP do núcleo HP estiver a processar. Uma divisão útil é colocar um pequeno modelo de trigger/classificação sempre ativo no lado HE e deixar o núcleo HP reagir apenas quando algo interessante é sinalizado — a deteção de palavras-chave a partir do microfone integrado é uma boa escolha porque é contínua, de baixa largura de banda e o núcleo HE permanece com muito menor consumo do que o HP. O auxiliar congelado ml.apps.MicroSpeech reconhece «Yes» e «No» de origem — diga as palavras em voz alta e claramente para o microfone integrado para acionar a deteção:
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)
Para uma divisão mais rica, execute BlazeFace no NPU HP enquanto o núcleo HE trata da deteção de palavras-chave em segundo plano — o ciclo HP sobrepõe a última palavra-chave detetada ao fotograma da câmara:
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")
O núcleo HE é adequado para cargas de trabalho sempre ativas ou de baixa frequência que não se pretende que concorram com o pipeline câmara/NPU no lado HP — inferência de ML de pequena dimensão, DSP ligeiro sobre dados do microfone ou IMU, e tarefas de fundo semelhantes.
Algumas restrições a ter em conta:
Utilize o microfone e o IMU ao controlar periféricos a partir do núcleo HE — são os que o lado HE foi concebido para utilizar. Cada periférico só pode ser detido por um núcleo de cada vez, por isso escolha HP ou HE para ele e mantenha essa escolha durante toda a vida útil do script.
Cada corpo de tarefa
@openamp.async_remotedeve serializar para menos de 500 bytes de bytecode mpy — mantenha a função pequena e extraia a lógica mais pesada para módulos de biblioteca separados que são congelados no firmware.As importações dentro da função despachada apenas veem os módulos que existem no sistema de ficheiros do núcleo HE. O núcleo HE tem o seu próprio ROMFS
/rom— separado do/romdo núcleo HP — por isso os módulos e modelos de ML que pretende disponibilizar no HE precisam de ser incorporados na imagem ROMFS do lado HE, não na do HP.
Microfone¶
O microfone integrado é capturado através de audio — Módulo de Áudio. Cada buffer chega como um bytearray PCM com sinal de 16 bits, o que facilita a sua introdução em ulab/numpy para DSP rápido. Um detetor de volume simples — imprime sempre que o volume RMS ultrapassa um limiar:
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¶
O acelerómetro + giroscópio LSM6DSM integrado está exposto através de 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 de tempo de voo¶
A AE3 integra um sensor de tempo de voo multi-zona VL53L8CX 8×8 que devolve até 64 leituras de distância por fotograma, com um alcance máximo de ~4 m. Está exposto através do módulo tof — controlador de sensor time-of-flight — chame tof.init() para iniciar o sensor e tof.read_depth() para obter um fotograma de profundidade como uma lista plana de leituras em milímetros (uma por zona):
import tof
tof.init()
while True:
depth, depth_min, depth_max = tof.read_depth()
print("min:", depth_min, "mm max:", depth_max, "mm")
O array de profundidade também pode ser desenhado sobre um fotograma a cores proveniente do sensor principal — tof.draw_depth() pinta-o sobre uma image.Image existente, enquanto tof.snapshot() devolve uma imagem de profundidade recém-renderizada:
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¶
O CYW43439 integrado está exposto via network — configuração de rede como interface de estação. Após a ligação, ipconfig("addr4") devolve o par (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¶
O mesmo CYW43439 também expõe Bluetooth 5.1. Utilize aioble — BLE Assíncrono para BLE com suporte a asyncio — por exemplo, anuncie como periférico e aguarde a ligação de um central:
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())
Referência de barramentos¶
GPIO¶
Utilize machine.Pin para ler ou controlar qualquer um dos pinos identificados na serigrafia. As saídas são CMOS a 3,3 V e conseguem drenar/fornecer até 25 mA por pino.
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())
Qualquer pino de entrada pode também acionar uma interrupção em transições de flanco:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Barramento |
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 é o único barramento com controlo de fluxo por hardware. Como P6–P9 estão no conector B2B e são referenciados a 1,8 V, o UART3 só funciona através de um conversor de nível ou de uma placa portadora B2B — não ligue lógica a 3,3 V diretamente.
I²C¶
Barramento |
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")
O conector Qwiic integrado expõe o I2C2 a 3,3 V.
I2C1 e I2C2 também podem ser utilizados em modo alvo (escravo) através de machine.I2CTarget para expor uma região de memória a outro controlador I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(1, addr=0x42, mem=buf)
Nota
O periférico LPI2C não está exposto no firmware. Apenas suportaria o modo alvo (escravo) se fosse exposto, e I2C1 e I2C2 já cobrem tanto o modo controlador como o modo alvo.
SPI¶
Barramento |
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¶
O Alif Ensemble E3 expõe dois canais ADC de 12 bits em P8 e P9 (apenas no conector B2B). Ambas as entradas são referenciadas a 1,8 V — read_u16 devolve 0–65535 para 0–1,8 V no pino:
from machine import ADC
import time
adc = ADC("P8")
while True:
voltage = adc.read_u16() * 1.8 / 65535
print(voltage)
time.sleep_ms(100)
Aviso
As entradas ADC da AE3 são referenciadas a 1,8 V, não a 3,3 V. Aplicar um sinal em bruto de 3,3 V saturará o conversor e pode danificar o pino — divida externamente tensões mais elevadas.
PWM¶
Pino |
Temporizador / canal |
|---|---|
P0 |
TIM0 T1 |
P1 |
TIM0 T0 |
P2 |
TIM1 T1 |
P3 |
TIM1 T0 |
P4 |
TIM2 T1 |
P5 |
TIM2 T0 |
P6 |
TIM9 T0 (apenas B2B) |
P7 |
TIM9 T1 (apenas B2B) |
P8 |
TIM5 T0 (apenas B2B) |
P9 |
TIM5 T1 (apenas B2B) |
Controle qualquer um deles através de machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P0"), freq=1_000, duty_u16=32768)
Barramentos por software (bit-banging)¶
machine.SoftI2C e machine.SoftSPI funcionam em qualquer GPIO se precisar de um barramento adicional.
Sensor térmico (externo)¶
O firmware inclui o controlador fir — driver de sensor térmico (fir == infravermelho longínquo) para um imager térmico AMG8833 8 × 8 ligado externamente. Ligue o módulo ao barramento I²C indicado abaixo e depois leia os fotogramas com 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())
O controlador fir só comunica com o sensor através de I²C 1 — ligue o módulo a P4 (SCL) e P5 (SDA).
Temporização¶
time¶
O módulo time cobre atrasos bloqueantes, ticks monotónicos e medição de tempo decorrido:
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)
Temporizadores virtuais¶
machine.Timer agenda callbacks periódicos ou de disparo único sem consumir um slot de temporizador de hardware. Passe -1 como id para utilizar um temporizador virtual (por software):
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"))
Os valores de período são em milissegundos. Chame deinit() para parar e libertar o slot.
Relógio de tempo real¶
machine.RTC mantém a hora do relógio de parede entre reinicializações, suportado por 4 KB de RAM de reserva integrada que sobrevive à suspensão profunda:
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())
O RTC também funciona durante a suspensão profunda, pelo que pode utilizá-lo como fonte de despertar para machine.deepsleep().
Informações de arranque e de execução¶
Janela do bootloader USB¶
Em cada ligação, a câmara executa um bootloader breve (alguns segundos) que permite ao OpenMV IDE atualizar o firmware sem que o utilizador precise de entrar no modo DFU. Após expirar a janela, o bootloader cede o controlo ao boot.py e depois ao main.py.
Um script em execução pode reentrar no bootloader a pedido chamando machine.bootloader()
import machine
machine.bootloader()
Sistema de ficheiros e ordem de arranque¶
O firmware da AE3 monta até dois sistemas de ficheiros no arranque:
Flash interna — montada sempre em
/flash. Contémmain.pyeREADME.txtpor defeito; criada no primeiro arranque.ROMFS — sistema de ficheiros de leitura exclusiva e mapeado em memória em
/rom, utilizado para distribuir grandes recursos de dados (p. ex., modelos de IA) que beneficiam de acesso sem cópia. Montado automaticamente pelo MicroPython na inicialização, antes de qualquer código Python do utilizador ser executado.
Após a montagem, o diretório de trabalho é definido como /flash. O interpretador executa então scripts a partir desse diretório:
boot.pyé executado em cada reinicialização suave (arranque a frio,Ctrl‑Dno REPL ou sempre que o script em execução terminar).main.pyé executado apenas no arranque a frio, imediatamente após oboot.py. As reinicializações suaves subsequentes reexecutam oboot.py, mas passam diretamente para o REPL — para reexecutar omain.pyé necessário reinicializar completamente a placa.
O main.py predefinido fornecido com uma placa recém-flasheada apenas pisca o canal azul do LED RGB do utilizador como sinal de funcionamento (dois pulsos curtos, pausa curta), para que possa verificar que o firmware arrancou corretamente sem qualquer host ligado.
sys.path é expandido para incluir ambos os sistemas de ficheiros e os seus subdiretórios lib/, pelo que os módulos importáveis podem residir em /flash/lib ou /rom/lib.
Quando ligado via USB, /flash também enumera como uma unidade de armazenamento de massa USB no host, permitindo editar boot.py, main.py e quaisquer outros ficheiros diretamente. Ejete a unidade antes de reinicializar a câmara para que o host escreva as suas alterações em cache.
Nota
Como o sistema operativo trata a unidade como um dispositivo de blocos passivo, os ficheiros criados ou modificados por código em execução na OpenMV Cam não aparecerão enquanto o host não remontar a unidade. Se tanto o sistema operativo como a OpenMV Cam escreverem no mesmo sistema de ficheiros ao mesmo tempo, o sistema operativo prevalecerá e sobrescreverá as alterações feitas pela câmara.
Nota
O canal vermelho do LED RGB do utilizador pode acender brevemente enquanto o host está a ler ou escrever na unidade de armazenamento de massa USB — trata-se de um indicador de atividade controlado pelo firmware, não de uma falha.
Tamanhos de armazenamento¶
A AE3 é fornecida com:
/flash— sistema de ficheiros FAT de 8 MB, leitura/escrita./romno núcleo HP — ROMFS de leitura exclusiva mapeado em memória de 24 MB para scripts e dados que o núcleo HP carrega na inicialização./romno núcleo HE — ROMFS de leitura exclusiva de 1 MB pertencente ao núcleo HE. Os módulos e modelos de ML que pretende disponibilizar às tarefas@openamp.async_remotetêm de ser incorporados nesta imagem, não na do HP.
Indicador de falha grave¶
Se o LED RGB do utilizador estiver a ciclar rapidamente por todas as cores — rápido o suficiente para parecer um LED branco a tremeluzir em vez de matizes distintos — o firmware atingiu uma falha grave irrecuperável. Reflasheie o firmware para recuperar; se o reflash não ajudar, a placa pode estar fisicamente danificada.
Bibliotecas de software¶
Consulte o índice de bibliotecas para a lista completa de módulos — incluindo quais são exclusivos da compilação AE3.