Arduino Portenta H7

O Arduino Portenta H7 é uma placa de desenvolvimento industrial de 66 × 25 mm construída em torno do STMicroelectronics STM32H747XI — um SoC de núcleo duplo que combina um Cortex‑M7 a 400 MHz com um Cortex‑M4 a 200 MHz. O firmware OpenMV corre inteiramente no núcleo M7 e foi concebido para ser utilizado com o Portenta Vision Shield (edição Ethernet ou LoRa), que adiciona uma câmara Himax HM01B0 / HM0360, dois microfones PDM e um slot microSD à base Portenta H7.

Arduino Portenta H7

Para a ficha técnica completa, fotografias e dimensões, consulte a página de produto do Arduino Portenta H7.

Destaques

  • STMicroelectronics STM32H747XI com Cortex‑M7 duplo (400 MHz) + Cortex‑M4 (200 MHz). O firmware OpenMV corre apenas no núcleo M7; o núcleo M4 é exposto através do openamp para comunicação entre processadores.

  • 8 MB de SDRAM externa mais 2 MB de flash interna e 16 MB de flash QSPI externa.

  • Codificador/descodificador JPEG por hardware.

  • Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 através do módulo Murata 1DX (CYW4343W) — liga à antena fornecida via um conector U.FL na placa.

  • USB‑C de alta velocidade (480 Mb/s).

  • 22 pinos de E/S de utilizador nos cabeçalhos superiores estilo Arduino MKR — D0–D14 (digital) mais A0–A6 (analógico).

  • Dois conectores de alta densidade de 80 pinos na parte inferior expõem todo o tecido do STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UARTs, SPI/I²C/temporizadores adicionais, entre outros. Shields como o Vision Shield ligam-se a estes conectores.

  • JTAG / SWD disponível nos conectores HD inferiores para depuração avançada.

  • Suporte a bateria — conector JST Li‑Po de 3,7 V mais carregador e monitor de bateria integrados.

Pinout

Arduino Portenta H7 Pinout

Referência de pinos

22 pinos de utilizador são expostos nos cabeçalhos da aresta superior estilo Arduino MKR — 15 digitais (D0-D14) mais 7 analógicos (A0-A6). Muitos mais pinos do SoC estão disponíveis através dos conectores de alta densidade de 80 pinos inferiores para uso com shields; consulte o PDF de pinout completo do Arduino para esse mapeamento.

Nome do pino

Referência

Função

D0

3,3 V

TIM8 CH3N

D1

3,3 V

TIM1 CH1 / SPI5 NSS

D2

3,3 V

TIM1 CH2 / SPI5 MISO

D3

3,3 V

GPIO

D4

3,3 V

TIM3 CH2 / TIM8 CH2 / USART6 RX

D5

3,3 V

TIM3 CH1 / TIM8 CH1 / USART6 TX

D6

3,3 V

TIM1 CH1 / I2C3 SCL

D7

3,3 V

TIM5 CH4 / SPI2 NSS

D8

3,3 V

SPI2 MOSI (partilhado com A3 / A5)

D9

3,3 V

SPI2 SCK

D10

3,3 V

SPI2 MISO (partilhado com A2 / A4)

D11

3,3 V

I2C3 SDA

D12

3,3 V

I2C3 SCL

D13

3,3 V

USART1 RX / TIM1 CH3

D14

3,3 V

USART1 TX / TIM1 CH2

A0

3,3 V

ADC12 IN0 (apenas analógico)

A1

3,3 V

ADC12 IN1 (apenas analógico)

A2

3,3 V

ADC123 IN12 (apenas analógico; partilhado com D10)

A3

3,3 V

ADC12 IN13 (apenas analógico; partilhado com D8)

A4

3,3 V

ADC123 IN12 (partilhado com D10)

A5

3,3 V

ADC12 IN13 (partilhado com D8)

A6

3,3 V

DAC1 OUT1 / ADC12 IN18

A7

3,3 V

TIM3 CH1 / ADC12 IN3 (não exposto nos cabeçalhos)

D20

3,3 V

alias de D8 / A3 / A5

D21

3,3 V

alias de A6 — DAC1 OUT1

RESET

3,3 V

premir o interruptor integrado ou ligar a GND para reiniciar

LED_RED

3,3 V

Canal vermelho do LED RGB (activo em baixo)

LED_GREEN

3,3 V

Canal verde do LED RGB (activo em baixo)

LED_BLUE

3,3 V

Canal azul do LED RGB (activo em baixo)

Nota

A0-A3 são pads apenas analógicos no STM32H747 sem função GPIO — trate-os apenas como entradas ADC. A2/A4 e A3/A5 partilham os seus pinos físicos com D10 e D8 respectivamente, pelo que não é possível acionar PWM ou SPI nesses pinos enquanto se fazem leituras analógicas. A7 encontra-se nos conectores HD inferiores.

Pinos de alimentação

Pinos do cabeçalho MKR:

  • VIN — rail principal do sistema para o PMIC integrado. Alimentado via díodo a partir do rail +5V, do pino VIN MKR, ou dos conectores HD de 80 pinos inferiores.

  • +5V — rail de 5 V alimentado por USB, pelo conector ESLOV, ou pelo próprio pino +5V MKR.

  • +3V3 — rail principal de 3,3 V (saída do regulador comutado do PMIC).

  • AREF — referência de tensão analógica para os pinos ADC. Por defeito 3,3 V; aplique externamente para utilizar uma referência diferente.

  • GND — massa comum.

Entrada de bateria:

  • Li‑Po JST na face frontal da placa aceita uma célula Li‑Po de 3,7 V. O PMIC carrega-a sempre que +5V ou VIN estão presentes.

O Portenta H7 pode ser alimentado por qualquer um destes caminhos:

  • USB‑C — fornece 5 V ao PMIC integrado.

  • Conector ESLOV — até 5 V em VESLOV (ver Conector ESLOV).

  • Pino VIN — aplique diretamente uma fonte regulada de 5 V.

  • Bateria Li‑Po — ligue ao JST na parte frontal.

Conector ESLOV

Na lateral da placa encontra-se um conector ESLOV de 5 pinos sem soldadura:

Pino

Nome

Função

1

VESLOV

Saída de 5 V (mesmo rail que o +5V do cabeçalho MKR)

2

INT

entrada de interrupção externa em D7

3

SCL_EXT

partilhado com o pad D12 do cabeçalho MKR — mesmo barramento I²C 3 que o cabeçalho de utilizador

4

SDA_EXT

partilhado com o pad D11 do cabeçalho MKR — mesmo barramento I²C 3 que o cabeçalho de utilizador

5

GND

massa comum

SCL_EXT/SDA_EXT do ESLOV e D12/D11 do cabeçalho MKR são os mesmos pinos — um único barramento I²C 3 exposto em dois conectores.

Dica

Utilize o estimador de autonomia de bateria para modelar durante quanto tempo o Portenta H7 funcionará com uma bateria para um dado ciclo de trabalho activo / sono profundo.

Pinos de recuperação e depuração

  • RESET — tanto um pino exposto no cabeçalho superior como um interruptor momentâneo na lateral da placa, ligado à linha NRST do SoC. Ligue a GND ou pressione o botão para reiniciar.

O Portenta H7 utiliza o duplo toque no reset padrão do Arduino para entrar no bootloader do Arduino. Prima rapidamente o botão de reset duas vezes — a placa reenumera sobre USB como dispositivo DFU e o OpenMV IDE pode instalar uma nova imagem de firmware.

Os sinais SWD do STM32 estão expostos no conector HD J1 inferior:

  • J1‑73 — NRST

  • J1‑75 — SWDIO (PA13)

  • J1‑77 — SWCLK (PA14)

  • J1‑79 — SWO (PB3)

Ligue-os através de um Portenta Breakout, do adaptador de depuração oficial do Arduino, ou de um carrier personalizado com um cabeçalho de 1,27 mm. Todos os sinais de depuração têm referência a 3,3 V.

Nota

Quando o Portenta Vision Shield está ligado, os mesmos sinais SWD/JTAG são encaminhados para o cabeçalho padrão JTAG ARM Cortex Debug de 20 pinos no shield (passo de 1,27 mm / 0,05″).

Periféricos integrados

LEDs

O Portenta H7 possui um único LED RGB de utilizador, controlável por software através do machine.LED

from machine import LED

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

Um LED de carga laranja separado junto ao JST da bateria acende quando o carregador integrado está a fornecer corrente a uma célula Li‑Po ligada; não é controlável pelo utilizador.

Sensor de câmara (Vision Shield)

Com o Portenta Vision Shield (edição Ethernet ou LoRa) ligado, o sensor Himax é controlado através do módulo csi — sensores de câmara

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.GRAYSCALE)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

São suportadas duas revisões do Vision Shield:

  • HM01B0 — 320 × 320 monocromático.

  • HM0360 — 640 × 480 monocromático.

Aviso

Enquanto a câmara do Vision Shield está inicializada, os seguintes pinos do cabeçalho MKR são utilizados pelo firmware e não podem ser usados:

Pino MKR

Motivo

D1

TIM1 CH1 — relógio mestre da câmara

D6

TIM1 CH1 (alt) — relógio mestre da câmara

D11

I²C 3 SDA — partilhado com a câmara; o barramento é utilizável mas evite o endereço I²C do sensor (0x24)

D12

I²C 3 SCL — partilhado com a câmara; o barramento é utilizável mas evite o endereço I²C do sensor (0x24)

A6 / D21

DCMI HSYNC — também desativa o DAC

A7

DCMI PXCLK

Aprendizagem automática

ml — Machine Learning corre modelos TFLite quantizados no Cortex‑M7 com kernels CMSIS‑NN — rápido o suficiente para detetores compactos a alguns fotogramas por segundo. Os modelos no sistema de ficheiros apenas de leitura /rom carregam diretamente a partir da flash sem cópia para RAM. Aqui está um detetor BlazeFace de 128×128 que sobrepõe a face detetada e os seus seis pontos de referência em cada fotograma da câmara do Vision Shield:

import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace

# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)
csi0.window((240, 240))

# Load built-in face detection model
model = ml.Model("/rom/blazeface_front_128.tflite", postprocess=BlazeFace(threshold=0.4))
print(model)

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()

    # faces is a list of ((x, y, w, h), score, keypoints) tuples
    for r, score, keypoints in model.predict([img]):
        ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)

        # keypoints is a ndarray of shape (6, 2)
        ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))

    print(clock.fps(), "fps")

Núcleo M4

O núcleo Cortex‑M4 é exposto através do openamp para comunicação entre processadores. O firmware OpenMV corre apenas no M7; o M4 não possui um runtime MicroPython próprio, pelo que a sua utilização implica construir uma imagem de firmware C separada e carregá-la a partir do sistema de ficheiros via openamp.RemoteProc. Firmware de exemplo pré-compilado que implementa um endpoint UART virtual está disponível no repositório openamp_vuart — siga o seu README para compilar vuart.elf

import openamp
import time

def ept_recv_callback(src_addr, data):
    print("Received:", data.decode())

ept = openamp.Endpoint("vuart-channel", callback=ept_recv_callback)

rproc = openamp.RemoteProc("vuart.elf")
rproc.start()

count = 0
while True:
    if ept.is_ready():
        ept.send("Hello World %d!" % count, timeout=1000)
        count += 1
    time.sleep_ms(1000)

Na prática, este suporte é melhor tratado como uma demonstração da interface openamp do que como uma plataforma de núcleo duplo funcional — o M4 não pode ser reiniciado independentemente do M7, pelo que parar o M4 força uma reinicialização completa do sistema.

Microfone (Vision Shield)

O Vision Shield possui dois microfones PDM capturados através do audio — Módulo de Áudio sobre o periférico SAI4 do STM32. Cada buffer chega como bytearray PCM de 16 bits com sinal, pronto para ser processado com ulab/numpy para DSP — por exemplo, um simples detetor de intensidade sonora:

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

Passe channels=2 a audio.init para receber amostras intercaladas de ambos os microfones.

Medidor de carga da bateria

O medidor de carga Maxim MAX17262 ModelGauge m5 rastreia a tensão, corrente, temperatura e estado de carga da bateria Li‑Po. Encontra-se no I²C 1 com endereço 0x36.

O MAX17262 possui deteção de corrente interna, pelo que o registo de corrente lê diretamente em microamperes sem necessidade de aplicar um fator Rsense externo. Ler o medidor de carga é inócuo — não existe driver incluído, mas os registos documentados na ficha técnica do MAX17262 podem ser lidos diretamente:

import time
import struct
from machine import I2C

FUEL_GAUGE = 0x36   # MAX17262

def read_reg(bus, addr, reg):
    return struct.unpack("<H", bus.readfrom_mem(addr, reg, 2))[0]

def read_signed(bus, addr, reg):
    v = read_reg(bus, addr, reg)
    return v - 0x10000 if v & 0x8000 else v

bus = I2C(1)

while True:
    # 0x05 RepCap — remaining capacity, raw × 0.5 mAh
    rep_cap   = read_reg(bus, FUEL_GAUGE, 0x05) * 0.5
    # 0x06 RepSOC — state of charge, raw / 256 %
    soc       = read_reg(bus, FUEL_GAUGE, 0x06) / 256
    # 0x08 Temp — die temperature, signed, raw / 256 °C
    temp      = read_signed(bus, FUEL_GAUGE, 0x08) / 256
    # 0x09 VCell — battery voltage, raw × 78.125 µV
    vcell     = read_reg(bus, FUEL_GAUGE, 0x09) * 78.125 / 1_000_000
    # 0x0A Current — signed, raw × 156.25 µA
    current   = read_signed(bus, FUEL_GAUGE, 0x0A) * 156.25 / 1000
    # 0x0B AvgCurrent — averaged current
    avg_curr  = read_signed(bus, FUEL_GAUGE, 0x0B) * 156.25 / 1000
    # 0x10 FullCapRep — learned full capacity, raw × 0.5 mAh
    full_cap  = read_reg(bus, FUEL_GAUGE, 0x10) * 0.5
    # 0x11 TTE — time-to-empty (valid while discharging), raw × 5.625 s
    tte_s     = read_reg(bus, FUEL_GAUGE, 0x11) * 5.625
    # 0x20 TTF — time-to-full   (valid while charging),  raw × 5.625 s
    ttf_s     = read_reg(bus, FUEL_GAUGE, 0x20) * 5.625
    # 0x17 Cycles — charge-cycle counter, 1% per LSB
    cycles    = read_reg(bus, FUEL_GAUGE, 0x17) / 100

    print("V:        %.3f V" % vcell)
    print("Capacity: %.1f / %.1f mAh (%.1f %%)" % (rep_cap, full_cap, soc))
    print("Temp:     %.1f C" % temp)
    print("Current:  %.1f mA  (avg %.1f mA)" % (current, avg_curr))
    print("TTE:      %.0f s   TTF: %.0f s" % (tte_s, ttf_s))
    print("Cycles:   %.2f" % cycles)
    print()
    time.sleep_ms(1000)

Current é complemento para dois com sinal: positivo durante a carga, negativo durante a descarga. TTE só é significativo quando a corrente é negativa; TTF apenas quando a corrente é positiva.

CI de gestão de energia

O PF1550 da NXP gere todos os reguladores do Portenta H7 — o rail principal +3V3, o rail de núcleo/E/S +1V8 do SoC, e o carregador Li‑Po. Encontra-se no I²C 1 com endereço 0x08.

Aviso

Ler registos do PMIC é seguro; escrever neles é perigoso. Configurar incorretamente um regulador buck ou as definições do carregador pode danificar permanentemente a placa, a bateria, ou ambos. Trate o PMIC como apenas de leitura a menos que saiba exatamente o que está a fazer.

A informação mais útil que o PMIC fornece e que o medidor de carga não fornece é a máquina de estados do carregador — se a placa está a funcionar com USB / ESLOV / VIN, em que fase do ciclo de carga se encontra a Li‑Po, e se o carregador está num estado de falha térmica ou watchdog. Os registos do carregador encontram-se num deslocamento de 0x80 no espaço de endereços I²C principal do PF1550 (ver §22.2 da ficha técnica do PF1550), pelo que, por exemplo, CHG_INT_OK no endereço do carregador 0x04 é lido do registo PMIC 0x84

import time
from machine import I2C

PMIC = 0x08

# Charger state machine (low nibble of CHG_SNS, register 0x87)
CHG_STATES = {
    0x0: "precharge",
    0x1: "fast charge (constant current)",
    0x2: "fast charge (constant voltage)",
    0x3: "end of charge",
    0x4: "done",
    0x6: "timer fault",
    0x7: "thermistor suspend",
    0x8: "off — input invalid or charger disabled",
    0x9: "battery overvoltage",
    0xA: "thermal shutdown",
    0xC: "linear mode (not charging)",
}

bus = I2C(1)

while True:
    # 0x84 CHG_INT_OK — single-bit indicators
    ok = bus.readfrom_mem(PMIC, 0x84, 1)[0]
    vbus_ok = bool(ok & (1 << 5))   # bit 5 — VBUS valid (USB/VIN)
    bat_ok  = bool(ok & (1 << 2))   # bit 2 — battery OK
    chg_ok  = bool(ok & (1 << 3))   # bit 3 — charger actively charging
    thm_ok  = bool(ok & (1 << 7))   # bit 7 — thermistor in normal range

    # 0x87 CHG_SNS — charger state + thermal regulation flag
    chg_sns = bus.readfrom_mem(PMIC, 0x87, 1)[0]
    state   = CHG_STATES.get(chg_sns & 0x0F, "reserved")
    treg    = bool(chg_sns & (1 << 7))   # thermal regulation active

    print("VBUS valid:         ", vbus_ok)
    print("battery OK:         ", bat_ok)
    print("charger active:     ", chg_ok)
    print("thermistor normal:  ", thm_ok)
    print("thermal reg active: ", treg)
    print("state:              ", state)
    print()
    time.sleep_ms(1000)

Outros registos apenas de leitura que vale a pena consultar na ficha técnica (todos com deslocamento de carregador 0x80): 0x80 CHG_INT (interrupções do carregador latched — flags de falha), 0x86 VBUS_SNS (o estado VBUS multi-bit incluindo OVLO / UVLO / DPM), e 0x88 BATT_SNS (presença de bateria e estado de sobrecorrente).

Wi‑Fi

O Murata 1DX (CYW4343W) integrado é exposto via network — configuração de rede como interface de estação. Ligue a antena fornecida ao conector U.FL da placa antes de ativar o rádio:

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 Murata 1DX também expõe Bluetooth LE 5.1. Use o aioble — BLE Assíncrono para BLE compatível com asyncio — por exemplo, anunciar como periférico e aguardar a ligação de um central:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="Portenta-H7")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

LoRa (Vision Shield)

A edição LoRa do Vision Shield adiciona um módulo Murata CMWX1ZZABZ LoRaWAN ligado ao Portenta H7 via UART. O módulo lora encapsula o firmware de comandos AT e suporta adesão OTAA ou ABP, uplink e downlink:

from lora import Lora
from lora import BAND_EU868
from lora import LoraErrorTimeout

lora = Lora(band=BAND_EU868, poll_ms=60000)
print("Device EUI:", lora.get_device_eui())

appEui = "1234567890123456"
appKey = "12345678901234567890123456789012"

try:
    lora.join_OTAA(appEui, appKey)
except LoraErrorTimeout as e:
    print("Join timed out — try moving near a window:", e)

lora.set_port(3)
lora.send_data("HeLoRA world!", True)

while True:
    if lora.available():
        data = lora.receive_data()
        if data:
            print("Port:", data["port"], "Data:", data["data"])
    lora.poll()

Use BAND_US915 / BAND_AS923 / BAND_AU915 etc. para regiões fora da UE, e mude para lora.Lora.join_ABP() se o seu servidor de rede usar ativação ABP.

Aviso

Enquanto o módulo LoRa está em uso, o driver reserva os seguintes pinos do cabeçalho MKR como linhas de controlo para o Murata CMWX1ZZABZ — não podem ser utilizados:

Pino MKR

Motivo

D3

Pino BOOT do módulo LoRa

D5

Pino RST do módulo LoRa

Ethernet (Vision Shield)

A edição Ethernet do Vision Shield adiciona uma ficha RJ45 com magnéticos ligada ao MAC Ethernet 10/100 do STM32H747 via RMII. Ligue um cabo Ethernet e o PHY aparece como interface LAN; o DHCP corre automaticamente assim que a ligação é estabelecida:

import network
import time

lan = network.LAN()
lan.active(True)
while not lan.isconnected():
    time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])

Cartão microSD (Vision Shield)

Quando um cartão é inserido, é montado automaticamente em /sdcard e é utilizável através do sistema de ficheiros regular:

import os

for entry in os.listdir("/sdcard"):
    print(entry)

Referência de barramentos

GPIO

Use o machine.Pin para ler ou acionar qualquer um dos pinos identificados na serigrafía. As saídas são CMOS de 3,3 V e podem absorver/fornecer até 20 mA por pino (140 mA no total por todo o cabeçalho).

from machine import Pin

out = Pin("D0", Pin.OUT)
out.on()
out.off()
out.value(1)

inp = Pin("D1", Pin.IN, Pin.PULL_UP)
print(inp.value())

Qualquer pino de entrada também pode disparar uma interrupção em transições de flanco:

def handler(pin):
    print("triggered:", pin)

Pin("D1", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

Barramento

TX

RX

UART1

D14

D13

UART6

D5

D4

from machine import UART

uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)

I²C

Barramento

SCL

SDA

I2C3

D12

D11

from machine import I2C

i2c = I2C(3, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")

Os pads D11/D12 no cabeçalho MKR e os pinos SDA_EXT/SCL_EXT do conector ESLOV estão no mesmo barramento I²C 3 — ver Conector ESLOV acima para o pinout do ESLOV.

O mesmo hardware também pode ser utilizado em modo target (escravo) através do machine.I2CTarget para expor uma região de memória a outro controlador I²C:

from machine import I2CTarget

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

SPI

Barramento

MOSI

MISO

SCK

CS

SPI2

D8

D10

D9

D7

from machine import SPI
from machine import Pin

spi = SPI(2, baudrate=10_000_000)
cs = Pin("D7", Pin.OUT, value=1)   # CS is not driven by the SPI peripheral

cs.value(0)
spi.write(b"hello")
cs.value(1)

ADC

O Portenta H7 expõe oito canais ADC de 12 bits em A0–A7. Todos têm referência a 3,3 Vread_u16 retorna 0–65535 para 0–3,3 V no pino:

from machine import ADC
import time

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

DAC

Um único canal DAC de 12 bits está exposto em DAC1 (A6 / D21) através do pyb.DAC

from pyb import DAC

dac = DAC("DAC1")
dac.write(int(0.5 * 255))   # 8‑bit output, ~1.65 V

PWM

Pino

Temporizador / canal

D0

TIM8 CH3N

D1

TIM1 CH1, TIM8 CH3N

D2

TIM1 CH2, TIM8 CH2N

D4

TIM3 CH2, TIM8 CH2

D5

TIM3 CH1, TIM8 CH1

D6

TIM1 CH1

D7

TIM5 CH4

D13

TIM1 CH3

D14

TIM1 CH2

A7

TIM3 CH1

Acione qualquer um deles através do machine.PWM

from machine import Pin, PWM

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

Nota

Vários pinos partilham canais de temporizador:

  • TIM1 CH1 está em D1 e D6.

  • TIM1 CH2 está em D2 e D14.

  • TIM8 CH3N está em D0 e D1.

Escolha um único utilizador por canal de temporizador.

Aviso

TIM1 está reservado para o relógio mestre da câmara quando o Vision Shield é inicializado através do csi — sensores de câmaraD1, D2, D6, D13 e D14 não podem ser acionados por PWM enquanto a câmara está activa.

Barramentos por software (bit-banging)

machine.SoftI2C e machine.SoftSPI funcionam em qualquer GPIO se necessitar de um barramento adicional.

Sensor térmico (externo)

O firmware inclui o driver fir — driver de sensor térmico (fir == infravermelho longínquo) para imagiologistas térmicos ligados externamente:

  • MLX90621 — matriz IR 16 × 4

  • MLX90640 — matriz IR 32 × 24

  • MLX90641 — matriz IR 16 × 12

  • AMG8833 — matriz IR 8 × 8

Ligue o módulo ao barramento I²C da placa e leia 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 driver fir comunica com o sensor apenas via I²C 3 — ligue o módulo a D12 (SCL) e D11 (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 (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 em tempo real

machine.RTC mantém a hora do relógio de parede entre reinicializações. O conector HD também expõe um pad COINCELL que pode alimentar o RTC a partir de um CR2032 durante perdas de energia:

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

Watchdog

machine.WDT reinicia a placa se a aplicação ficar suspensa. Uma vez iniciado não pode ser parado nem reconfigurado — alimente-o periodicamente dentro do seu ciclo principal:

from machine import WDT

wdt = WDT(timeout=5_000)   # 5 second window
while True:
    # ...do work...
    wdt.feed()

Informações de arranque e runtime

Atualização de firmware (DFU)

O Portenta H7 utiliza o duplo toque no reset padrão do Arduino para entrar no bootloader do Arduino. Prima rapidamente o botão de reset duas vezes — a placa reenumera sobre USB como dispositivo DFU e o OpenMV IDE pode instalar uma nova imagem de firmware.

Um script em execução pode voltar ao bootloader a pedido chamando machine.bootloader()

import machine

machine.bootloader()

Sistema de ficheiros e ordem de arranque

O firmware do Portenta H7 monta até três sistemas de ficheiros no arranque:

  • Flash interna — montada sempre em /flash. Contém main.py e README.txt por defeito; criada no primeiro arranque.

  • Cartão microSD — se um Vision Shield estiver ligado e um cartão inserido, é montado em /sdcard.

  • ROMFS — sistema de ficheiros mapeado em memória apenas de leitura em /rom, montado automaticamente pelo MicroPython no arranque.

Após a montagem, o diretório de trabalho é definido como /sdcard quando o cartão está presente, caso contrário /flash. O interpretador executa então scripts desse diretório:

  • boot.py é executado em cada reset suave (arranque a frio, Ctrl‑D no REPL, ou sempre que o script em execução termina).

  • main.py é executado apenas no arranque a frio, imediatamente após boot.py. Os resets suaves subsequentes executam novamente boot.py mas vão directamente para o REPL — para voltar a executar main.py tem de reiniciar completamente a placa.

Colocar um boot.py ou main.py no cartão SD substitui a cópia na flash sem a alterar — ambos os ficheiros são procurados no diretório de arranque (/sdcard quando o cartão está montado, caso contrário /flash).

O main.py predefinido fornecido numa placa recém-instalada faz piscar o canal azul do LED RGB de utilizador como batimento cardíaco (dois pulsos curtos, intervalo curto), para poder verificar que o firmware arrancou corretamente sem nenhum host ligado.

sys.path é estendido para incluir os três sistemas de ficheiros e os seus subdiretórios lib/, pelo que os módulos importáveis podem residir em /flash/lib, /sdcard/lib ou /rom/lib.

Para forçar o sistema a ignorar um cartão SD inserido (por exemplo, para executar o main.py da flash mesmo com um cartão presente), crie um ficheiro vazio chamado SKIPSD na raiz de /flash.

Quando ligado via USB, o sistema de ficheiros de arranque (/sdcard se houver cartão presente, caso contrário /flash) também é enumerado como unidade de armazenamento em massa USB no host, permitindo editar boot.py, main.py e quaisquer outros ficheiros diretamente. Ejete a unidade antes de reiniciar a placa para que o host descarregue as escritas em cache.

Nota

Como o SO trata a unidade como um dispositivo de bloco passivo, os ficheiros criados ou modificados por código a correr na câmara não aparecerão até o host remontar a unidade. Se tanto o SO como a câmara escreverem no mesmo sistema de ficheiros ao mesmo tempo, o SO prevalecerá e sobreporá as alterações feitas pela câmara. Utilize o cartão SD para quaisquer dados que o script escreva, e remonte antes de ler esses ficheiros a partir do host.

Nota

O canal vermelho do LED RGB de utilizador pode acender brevemente enquanto o host está a ler ou escrever na unidade de armazenamento em massa USB — é um indicador de actividade controlado pelo firmware, não uma falha.

Tamanhos de armazenamento

O Portenta H7 é fornecido com:

  • /flash — sistema de ficheiros FAT de 11 MB, leitura/escrita.

  • /rom — ROMFS apenas de leitura mapeada em memória de 4 MB, utilizado para distribuir scripts e modelos ML que beneficiam de acesso mmap sem cópia.

  • /sdcard — tamanho completo do cartão microSD inserido num Vision Shield (quando presente), leitura/escrita.

Indicador de hard fault

Se o LED RGB de utilizador estiver a ciclar rapidamente por todas as cores — rápido o suficiente para parecer um LED branco a tremeluzir em vez de matizes distintas — o firmware atingiu um hard fault irrecuperável. Reinstale o firmware para recuperar; se a reinstalação não resolver, 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 para o Portenta H7.