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 dual‑core que combina um Cortex‑M7 a 400 MHz com um Cortex‑M4 a 200 MHz. O firmware OpenMV roda inteiramente no núcleo M7 e foi projetado para ser usado com o Portenta Vision Shield (edição Ethernet ou LoRa), que adiciona uma câmera Himax HM01B0 / HM0360, dois microfones PDM e um slot microSD ao Portenta H7 básico.

Arduino Portenta H7

Para a folha de dados completa, fotos e dimensões, consulte a página do produto Arduino Portenta H7.

Destaques

  • STMicroelectronics STM32H747XI dual Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). O firmware OpenMV roda apenas no núcleo M7; o núcleo M4 é exposto através do openamp para Comunicação Inter‑Processadores.

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

  • Codificador/decodificador JPEG por hardware.

  • Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 via o módulo Murata 1DX (CYW4343W) — conecta-se à antena fornecida através de um conector U.FL integrado.

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

  • 22 pinos de I/O de usuário nos headers superiores estilo Arduino MKR — D0–D14 (digitais) mais A0–A6 (analógicos).

  • Dois conectores de alta densidade de 80 pinos na parte inferior expõem todo o fabric do STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UARTs, SPI/I²C/timers adicionais, e assim por diante. Shields como o Vision Shield se encaixam nesses conectores.

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

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

Pinagem

Pinagem do Arduino Portenta H7

Referência de pinos

22 pinos de usuário são expostos nos headers de borda superior estilo Arduino MKR — 15 digitais (D0-D14) mais 7 analógicos (A0-A6). Muitos outros pinos do SoC estão disponíveis através dos conectores de alta densidade de 80 pinos inferiores para trabalho com shields; consulte o PDF de pinagem completa da 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 (compartilhado com A3 / A5)

D9

3,3 V

SPI2 SCK

D10

3,3 V

SPI2 MISO (compartilhado 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; compartilhado com D10)

A3

3,3 V

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

A4

3,3 V

ADC123 IN12 (compartilhado com D10)

A5

3,3 V

ADC12 IN13 (compartilhado com D8)

A6

3,3 V

DAC1 OUT1 / ADC12 IN18

A7

3,3 V

TIM3 CH1 / ADC12 IN3 (não exposto nos headers)

D20

3,3 V

alias de D8 / A3 / A5

D21

3,3 V

alias de A6 — DAC1 OUT1

RESET

3,3 V

pressione o botão integrado ou puxe para GND para reiniciar

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

A0-A3 são pads apenas analógicos no STM32H747 sem função GPIO — trate-os apenas como entradas de ADC. A2/A4 e A3/A5 compartilham seus pinos físicos com D10 e D8 respectivamente, então você não pode acionar PWM ou SPI neles enquanto os lê como analógicos. A7 fica nos conectores HD inferiores.

Pinos de alimentação

Pinos do header MKR:

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

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

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

  • AREF — referência de tensão analógica para os pinos do ADC. O padrão é 3,3 V; acione externamente para usar uma referência diferente.

  • GND — terra comum.

Entrada de bateria:

  • JST Li‑Po na frente da placa aceita uma célula Li‑Po de 3,7 V. O PMIC a carrega sempre que +5V ou VIN estiver presente.

O Portenta H7 pode ser alimentado através de qualquer um destes caminhos:

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

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

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

  • Bateria Li‑Po — conecte ao JST na frente.

Conector ESLOV

Na lateral da placa há um conector ESLOV de 5 pinos sem solda:

Pino

Nome

Função

1

VESLOV

saída de alimentação de 5 V (mesmo barramento do +5V do header MKR)

2

INT

entrada de interrupção externa em D7

3

SCL_EXT

compartilhado com o pad D12 do header MKR — mesmo barramento I²C 3 do header de usuário

4

SDA_EXT

compartilhado com o pad D11 do header MKR — mesmo barramento I²C 3 do header de usuário

5

GND

terra comum

Os SCL_EXT/SDA_EXT do ESLOV e os D12/D11 do header MKR são os mesmos pinos — um barramento I²C 3 exposto em dois conectores.

Dica

Use o estimador de vida útil da bateria para modelar por quanto tempo o Portenta H7 funcionará com uma bateria para um determinado ciclo de trabalho ativo / deep-sleep.

Pinos de recuperação e depuração

  • RESET — tanto um pino exposto no header superior quanto um botão momentâneo na lateral da placa, ligados à linha NRST do SoC. Puxe para GND ou pressione o botão para reiniciar.

O Portenta H7 usa o reset por toque duplo padrão da Arduino para entrar no bootloader da Arduino. Pressione rapidamente o botão de reset duas vezes — a placa é re‑enumerada via USB como um dispositivo DFU e o OpenMV IDE pode gravar uma nova imagem de firmware.

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

  • J1‑73 — NRST

  • J1‑75 — SWDIO (PA13)

  • J1‑77 — SWCLK (PA14)

  • J1‑79 — SWO (PB3)

Conecte-os via um Portenta Breakout, o adaptador de depuração oficial da Arduino ou uma placa portadora personalizada com um header de 1,27 mm. Todos os sinais de depuração são referenciados a 3,3 V.

Nota

Quando o Portenta Vision Shield está conectado, os mesmos sinais SWD/JTAG são roteados até o header JTAG ARM Cortex Debug de 20 pinos padrão no shield (passo de 1,27 mm / 0,05″).

Periféricos integrados

LEDs

O Portenta H7 tem um único LED RGB de usuário, 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, ao lado do JST da bateria, acende quando o carregador integrado está fornecendo corrente a uma Li‑Po conectada; ele não é controlável pelo usuário.

Sensor de câmera (Vision Shield)

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

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

Duas revisões do Vision Shield são suportadas:

  • HM01B0 — monocromático 320 × 320.

  • HM0360 — monocromático 640 × 480.

Aviso

Enquanto a câmera do Vision Shield está inicializada, os seguintes pinos do header MKR são reservados pelo firmware e não podem ser usados:

Pino MKR

Motivo

D1

TIM1 CH1 — clock mestre da câmera

D6

TIM1 CH1 (alt) — clock mestre da câmera

D11

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

D12

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

A6 / D21

DCMI HSYNC — também desabilita o DAC

A7

DCMI PXCLK

Aprendizado de máquina

O ml — Aprendizado de Máquina executa modelos TFLite quantizados no Cortex‑M7 com kernels CMSIS‑NN — rápido o suficiente para detectores compactos a alguns quadros por segundo. Modelos no sistema de arquivos somente leitura /rom carregam diretamente da flash sem copiar para a RAM. Aqui está um detector BlazeFace de 128×128 sobrepondo o rosto detectado e seus seis pontos de referência em cada quadro da câmera 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 inter‑processadores. O firmware OpenMV roda apenas no M7; o M4 não tem runtime MicroPython próprio, então usá-lo significa compilar uma imagem de firmware C separada e carregá-la a partir do sistema de arquivos via openamp.RemoteProc. Um firmware de exemplo pré‑compilado que implementa um endpoint UART virtual está disponível no repositório openamp_vuart — siga seu README para compilar o 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, esse suporte é melhor tratado como uma demonstração da interface openamp do que como uma plataforma dual‑core funcional — o M4 não pode ser reiniciado independentemente do M7, então 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 pelo periférico SAI4 do STM32. Cada buffer chega como PCM de 16 bits com sinal em um bytearray, pronto para alimentar o ulab/numpy para DSP — por exemplo, um detector de intensidade sonora simples:

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 para audio.init para receber amostras intercaladas de ambos os microfones.

Medidor de carga da bateria

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

O MAX17262 tem detecção de corrente interna, então o registrador de corrente é lido diretamente em microamperes, sem fator de Rsense externo a aplicar. Ler o medidor de carga é inofensivo — não há driver fornecido, mas os registradores documentados na folha de dados 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 é um complemento de dois com sinal: positivo durante a carga, negativo durante a descarga. TTE só é significativo quando a corrente é negativa; TTF só quando a corrente é positiva.

CI de gerenciamento de energia

O PMIC NXP PF1550 gerencia todos os reguladores do Portenta H7 — o barramento principal +3V3, o barramento +1V8 do núcleo / I/O do SoC e o carregador Li‑Po. Ele fica no I²C 1 no endereço 0x08.

Aviso

Ler registradores do PMIC é seguro; escrever neles é perigoso. Configurar incorretamente um regulador buck ou uma definição do carregador pode danificar permanentemente a placa, a bateria, ou ambos. Trate o PMIC como somente leitura, a menos que você saiba exatamente o que está fazendo.

A coisa mais útil que o PMIC informa e que o medidor de carga não pode é a máquina de estados do carregador — se a placa está atualmente funcionando com USB / ESLOV / VIN, em que estágio do ciclo de carga a Li‑Po está e se o carregador está em uma falha térmica ou de watchdog. Os registradores do carregador ficam em um offset de 0x80 no espaço de endereços I²C principal do PF1550 (consulte §22.2 da folha de dados do PF1550), então, por exemplo, o CHG_INT_OK no endereço de carregador 0x04 é lido do registrador 0x84 do PMIC:

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 registradores somente leitura que vale a pena consultar na folha de dados (todos no offset de carregador 0x80): 0x80 CHG_INT (interrupções do carregador travadas — flags de falha), 0x86 VBUS_SNS (o estado VBUS de múltiplos bits, incluindo OVLO / UVLO / DPM) e 0x88 BATT_SNS (presença da bateria e estado de sobrecorrente).

Wi‑Fi

O Murata 1DX (CYW4343W) integrado é exposto via network — configuração de rede como uma interface de estação. Conecte a antena fornecida ao conector U.FL integrado 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 amigável a asyncio — por exemplo, anuncie como periférico e aguarde a conexã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 LoRaWAN Murata CMWX1ZZABZ conectado ao Portenta H7 via UART. O módulo lora encapsula o firmware de comandos AT e suporta join 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 header MKR como linhas de controle para o Murata CMWX1ZZABZ — eles não podem ser usados:

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 um conector RJ45 com magnetics conectado ao MAC Ethernet 10/100 do STM32H747 via RMII. Conecte um cabo Ethernet e o PHY aparece como uma interface LAN; o DHCP roda automaticamente assim que o link é estabelecido:

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, ele é montado automaticamente em /sdcard e fica utilizável através do sistema de arquivos normal:

import os

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

Referência de barramentos

GPIO

Use machine.Pin para ler ou acionar qualquer um dos pinos serigrafados. As saídas são CMOS de 3,3 V e podem drenar/fornecer até 20 mA por pino (140 mA no total em todo o header).

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 borda:

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 header MKR e os pinos SDA_EXT/SCL_EXT do conector ESLOV ficam no mesmo barramento I²C 3 — consulte Conector ESLOV acima para a pinagem do ESLOV.

O mesmo hardware também pode ser usado no 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 de ADC de 12 bits em A0–A7. Todos são referenciados a 3,3 Vread_u16 retorna de 0 a 65535 ao longo de 0 a 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 de DAC de 12 bits é 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

Timer / 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 via machine.PWM

from machine import Pin, PWM

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

Nota

Vários pinos compartilham canais de timer:

  • TIM1 CH1 está em D1 e D6.

  • TIM1 CH2 está em D2 e D14.

  • TIM8 CH3N está em D0 e D1.

Escolha um consumidor por canal de timer.

Aviso

TIM1 é reservado para o clock mestre da câmera quando o Vision Shield é inicializado através do csi — sensores de câmeraD1, D2, D6, D13 e D14 não podem ser acionados por PWM enquanto a câmera está ativa.

Barramentos por bit‑banging em software

O machine.SoftI2C e o machine.SoftSPI funcionam em qualquer GPIO caso você precise de um barramento extra.

Sensor térmico (externo)

O firmware inclui o driver fir — driver de sensor térmico (fir == far infrared) para imageadores térmicos conectados externamente:

  • MLX90621 — array IR de 16 × 4

  • MLX90640 — array IR de 32 × 24

  • MLX90641 — array IR de 16 × 12

  • AMG8833 — array IR de 8 × 8

Conecte o módulo ao barramento I²C da placa e leia quadros 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 só se comunica com o sensor pelo I²C 3 — conecte 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)

Timers virtuais

O machine.Timer agenda callbacks periódicos ou únicos sem consumir um slot de timer de hardware. Passe -1 como id para usar um timer virtual (de 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 liberar o slot.

Relógio de tempo real

O machine.RTC mantém a hora do relógio de parede ao longo de reinicializações. O conector HD também expõe um pad COINCELL que pode alimentar o RTC a partir de uma CR2032 em caso de perda 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

O machine.WDT reinicia a placa se a aplicação travar. Uma vez iniciado, ele não pode ser parado ou reconfigurado — alimente-o periodicamente dentro do seu loop principal:

from machine import WDT

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

Informações de boot e tempo de execução

Atualização de firmware (DFU)

O Portenta H7 usa o reset por toque duplo padrão da Arduino para entrar no bootloader da Arduino. Pressione rapidamente o botão de reset duas vezes — a placa é re‑enumerada via USB como um dispositivo DFU e o OpenMV IDE pode gravar uma nova imagem de firmware.

Um script em execução pode re‑entrar no bootloader sob demanda chamando machine.bootloader()

import machine

machine.bootloader()

Sistema de arquivos e ordem de boot

O firmware do Portenta H7 monta até três sistemas de arquivos no boot:

  • Flash interna — sempre montada em /flash. Contém main.py e README.txt por padrão; criada no primeiro boot.

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

  • ROMFS — sistema de arquivos somente leitura, mapeado em memória em /rom, montado automaticamente pelo MicroPython na inicialização.

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

  • boot.py é executado em cada soft reset (cold boot, Ctrl‑D do REPL ou sempre que o script em execução retorna).

  • main.py é executado apenas no cold boot, imediatamente após o boot.py. Soft resets subsequentes re‑executam o boot.py mas vão direto para o REPL — para re‑executar o main.py você precisa reiniciar completamente a placa.

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

O main.py padrão fornecido em uma placa recém‑gravada apenas pisca o canal azul do LED RGB de usuário como um heartbeat (dois pulsos curtos, pequeno intervalo), para que você possa saber que o firmware inicializou corretamente sem nenhum host conectado.

O sys.path é estendido para incluir todos os três sistemas de arquivos e seus subdiretórios lib/, então módulos importáveis podem ficar 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 arquivo vazio chamado SKIPSD na raiz de /flash.

Quando conectado via USB, o sistema de arquivos de boot (/sdcard se um cartão estiver presente, caso contrário /flash) também é enumerado como uma unidade de armazenamento em massa USB no host, permitindo que você edite boot.py, main.py e quaisquer outros arquivos diretamente. Ejete a unidade antes de reiniciar a placa para que o host descarregue suas escritas em cache.

Nota

Como o SO trata a unidade como um dispositivo de bloco passivo, arquivos criados ou modificados por código em execução na câmera não aparecerão até que o host remonte a unidade. Se tanto o SO quanto a câmera escreverem no mesmo sistema de arquivos ao mesmo tempo, o SO vencerá e sobrescreverá as alterações feitas pela câmera. Use o cartão SD para quaisquer dados que o script grave de volta, e remonte antes de ler esses arquivos a partir do host.

Nota

O canal vermelho do LED RGB de usuário pode acender brevemente enquanto o host está lendo ou gravando na unidade de armazenamento em massa USB — isso é um indicador de atividade controlado pelo firmware, não uma falha.

Tamanhos de armazenamento

O Portenta H7 vem com:

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

  • /rom — ROMFS somente leitura mapeado em memória de 4 MB, usado para fornecer scripts e modelos de ML que se beneficiam de acesso mmap com zero cópia.

  • /sdcard — tamanho completo de qualquer cartão microSD inserido em um Vision Shield (quando presente), leitura/escrita.

Indicador de hard fault

Se o LED RGB de usuário estiver ciclando rapidamente por todas as cores — rápido o suficiente para parecer um LED branco cintilante em vez de tons distintos — o firmware atingiu um hard fault irrecuperável. Regrave o firmware para recuperar; se a regravação 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 do build do Portenta H7.