Arduino Portenta H7¶
L’Arduino Portenta H7 è una scheda di sviluppo industriale di 66 × 25 mm costruita attorno allo STMicroelectronics STM32H747XI — un SoC dual‑core che combina un Cortex‑M7 a 400 MHz con un Cortex‑M4 a 200 MHz. Il firmware OpenMV gira interamente sul core M7 ed è progettato per essere usato con il Portenta Vision Shield (edizione Ethernet o LoRa), che aggiunge alla base Portenta H7 una camera Himax HM01B0 / HM0360, due microfoni PDM e uno slot microSD.
Per il datasheet completo, le foto e le dimensioni, vedere la pagina prodotto dell’Arduino Portenta H7.
Punti salienti¶
STMicroelectronics STM32H747XI dual Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). Il firmware OpenMV gira solo sul core M7; il core M4 è esposto tramite openamp per la comunicazione inter‑processore.
8 MB di SDRAM esterna più 2 MB di flash interna e 16 MB di flash QSPI esterna.
Encoder/decoder JPEG hardware.
Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 tramite il modulo Murata 1DX (CYW4343W) — si collega all’antenna fornita tramite un connettore U.FL integrato.
USB‑C ad alta velocità (480 Mb/s).
22 pin I/O utente sui connettori superiori in stile Arduino MKR — D0–D14 (digitali) più A0–A6 (analogici).
Due connettori ad alta densità a 80 pin sul lato inferiore espongono l’intero fabric dello STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UART, ulteriori SPI/I²C/timer e così via. Shield come il Vision Shield si accoppiano a questi connettori.
JTAG / SWD disponibili sui connettori HD inferiori per il debug avanzato.
Supporto batteria — connettore JST per Li‑Po da 3,7 V più caricabatterie e monitor della batteria integrati.
Pinout¶
Riferimento dei pin¶
22 pin utente sono esposti sui connettori del bordo superiore in stile Arduino MKR — 15 digitali (D0-D14) più 7 analogici (A0-A6). Molti altri pin del SoC sono disponibili tramite i connettori ad alta densità a 80 pin inferiori per il lavoro con gli shield; vedere il PDF del pinout completo di Arduino per quella mappatura.
Nome pin |
Riferimento |
Funzione |
|---|---|---|
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 (condiviso con A3 / A5) |
D9 |
3,3 V |
SPI2 SCK |
D10 |
3,3 V |
SPI2 MISO (condiviso con 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 (solo analogico) |
A1 |
3,3 V |
ADC12 IN1 (solo analogico) |
A2 |
3,3 V |
ADC123 IN12 (solo analogico; condiviso con D10) |
A3 |
3,3 V |
ADC12 IN13 (solo analogico; condiviso con D8) |
A4 |
3,3 V |
ADC123 IN12 (condiviso con D10) |
A5 |
3,3 V |
ADC12 IN13 (condiviso con D8) |
A6 |
3,3 V |
DAC1 OUT1 / ADC12 IN18 |
A7 |
3,3 V |
TIM3 CH1 / ADC12 IN3 (non esposto sui connettori) |
D20 |
3,3 V |
alias di |
D21 |
3,3 V |
alias di |
RESET |
3,3 V |
premere l’interruttore integrato o tirare a GND per il reset |
LED_RED |
3,3 V |
canale rosso del LED RGB (attivo basso) |
LED_GREEN |
3,3 V |
canale verde del LED RGB (attivo basso) |
LED_BLUE |
3,3 V |
canale blu del LED RGB (attivo basso) |
Nota
A0-A3 sono pad solo analogici sullo STM32H747 senza funzione GPIO — trattali esclusivamente come ingressi ADC. A2/A4 e A3/A5 condividono i loro pin fisici rispettivamente con D10 e D8, quindi non puoi pilotare PWM o SPI su di essi mentre li leggi come analogici. A7 si trova sui connettori HD inferiori.
Pin di alimentazione¶
Pin del connettore MKR:
VIN — rail principale del sistema verso il PMIC integrato. Alimentato tramite un diodo dal rail
+5V, dal pinVINMKR o dai connettori HD a 80 pin inferiori.+5V — rail a 5 V alimentato da USB, dal connettore ESLOV o dal pin
+5VMKR stesso.+3V3 — rail principale a 3,3 V (uscita del regolatore switching del PMIC).
AREF — riferimento di tensione analogico per i pin ADC. Predefinito a 3,3 V; pilotalo dall’esterno per usare un riferimento diverso.
GND — massa comune.
Ingresso batteria:
JST Li‑Po sul fronte della scheda accetta una cella Li‑Po da 3,7 V. Il PMIC la carica ogni volta che
+5VoVINè presente.
Il Portenta H7 può essere alimentato attraverso una qualsiasi di queste vie:
USB‑C — fornisce 5 V al PMIC integrato.
Connettore ESLOV — fino a 5 V su
VESLOV(vedere Connettore ESLOV).Pin VIN — fornisci direttamente un’alimentazione regolata a 5 V.
Batteria Li‑Po — collega al JST sul fronte.
Connettore ESLOV¶
Sul lato della scheda si trova un connettore ESLOV a 5 pin senza saldatura:
Pin |
Nome |
Funzione |
|---|---|---|
1 |
VESLOV |
uscita di alimentazione a 5 V (stesso rail del |
2 |
INT |
ingresso di interrupt esterno su |
3 |
SCL_EXT |
condiviso con il pad |
4 |
SDA_EXT |
condiviso con il pad |
5 |
GND |
massa comune |
I pin SCL_EXT/SDA_EXT dell’ESLOV e i pin D12/D11 del connettore MKR sono gli stessi pin — un unico bus I²C 3 esposto su due connettori.
Suggerimento
Usa lo stimatore della durata della batteria per modellare per quanto tempo il Portenta H7 funzionerà a batteria per un dato duty cycle attivo / deep-sleep.
Pin di recovery e debug¶
RESET — sia un pin esposto sul connettore superiore sia un interruttore momentaneo sul lato della scheda, collegati alla linea NRST del SoC. Tira a GND o premi il pulsante per il reset.
Il Portenta H7 usa il doppio tap di reset standard di Arduino per entrare nel bootloader di Arduino. Premi rapidamente due volte il pulsante di reset — la scheda si rienumera via USB come dispositivo DFU e OpenMV IDE può flashare una nuova immagine firmware.
I segnali SWD dello STM32 sono esposti sul connettore HD J1 inferiore:
J1‑73— NRSTJ1‑75— SWDIO (PA13)J1‑77— SWCLK (PA14)J1‑79— SWO (PB3)
Collegali tramite un Portenta Breakout, l’adattatore di debug ufficiale Arduino o un carrier personalizzato con un connettore da 1,27 mm. Tutti i segnali di debug sono riferiti a 3,3 V.
Nota
Quando è collegato il Portenta Vision Shield, gli stessi segnali SWD/JTAG vengono instradati verso lo standard connettore JTAG di debug ARM Cortex a 20 pin sullo shield (passo da 1,27 mm / 0,05″).
Periferiche integrate¶
LED¶
Il Portenta H7 ha un singolo LED RGB utente, controllabile via software tramite machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Un LED arancione di carica separato accanto al JST della batteria si accende quando il caricabatterie integrato eroga corrente verso una Li‑Po collegata; non è controllabile dall’utente.
Sensore camera (Vision Shield)¶
Con il Portenta Vision Shield (edizione Ethernet o LoRa) collegato, il sensore Himax viene pilotato tramite il modulo csi — sensori camera
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()
Sono supportate due revisioni del Vision Shield:
HM01B0 — 320 × 320 monocromatico.
HM0360 — 640 × 480 monocromatico.
Avvertimento
Mentre la camera del Vision Shield è inizializzata, i seguenti pin del connettore MKR sono riservati dal firmware e non possono essere usati:
Pin MKR |
Motivo |
|---|---|
|
TIM1 CH1 — clock master della camera |
|
TIM1 CH1 (alt) — clock master della camera |
|
I²C 3 SDA — condiviso con la camera; il bus è utilizzabile ma evita l’indirizzo I²C del sensore ( |
|
I²C 3 SCL — condiviso con la camera; il bus è utilizzabile ma evita l’indirizzo I²C del sensore ( |
|
DCMI HSYNC — disabilita anche il DAC |
|
DCMI PXCLK |
Machine learning¶
ml — Machine Learning esegue modelli TFLite quantizzati sul Cortex‑M7 con kernel CMSIS‑NN — abbastanza veloci per rilevatori compatti a qualche frame al secondo. I modelli sul filesystem di sola lettura /rom vengono caricati direttamente dalla flash senza copiarli in RAM. Ecco un rilevatore BlazeFace 128×128 che sovrappone il volto rilevato e i suoi sei landmark su ogni frame proveniente dalla camera del 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")
Core M4¶
Il core Cortex‑M4 è esposto tramite openamp per la comunicazione inter‑processore. Il firmware OpenMV gira solo sull’M7; l’M4 non ha un proprio runtime MicroPython, quindi usarlo significa compilare una separata immagine firmware C e caricarla dal filesystem tramite openamp.RemoteProc. Un firmware di esempio precompilato che implementa un endpoint UART virtuale è disponibile nel repository openamp_vuart — segui il suo README per compilare 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)
In pratica questo supporto è da considerare al meglio come una dimostrazione dell’interfaccia openamp piuttosto che come una piattaforma dual‑core funzionante — l’M4 non può essere resettato indipendentemente dall’M7, quindi fermare l’M4 forza un riavvio completo del sistema.
Microfono (Vision Shield)¶
Il Vision Shield monta due microfoni PDM acquisiti tramite audio — Modulo Audio attraverso la periferica SAI4 dello STM32. Ogni buffer arriva come PCM bytearray a 16 bit con segno, pronto per essere passato a ulab/numpy per il DSP — ad esempio, un semplice rilevatore di volume:
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
Passa channels=2 a audio.init per ricevere campioni interlacciati da entrambi i microfoni.
Indicatore di carica della batteria¶
Il fuel gauge Maxim MAX17262 ModelGauge m5 traccia la tensione, la corrente, la temperatura e lo stato di carica della batteria Li‑Po. Si trova sull”I²C 1 all’indirizzo 0x36.
Il MAX17262 ha il rilevamento della corrente interno, quindi il registro della corrente fornisce direttamente il valore in microampere senza alcun fattore Rsense esterno da applicare. Leggere il fuel gauge è innocuo — non viene fornito alcun driver, ma i registri documentati nel datasheet del MAX17262 possono essere letti direttamente:
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 è in complemento a due con segno: positivo durante la carica, negativo durante la scarica. TTE è significativo solo quando la corrente è negativa; TTF solo quando la corrente è positiva.
IC di gestione dell’alimentazione¶
Il PMIC NXP PF1550 gestisce ogni regolatore del Portenta H7 — il rail principale +3V3, il rail core / I/O del SoC +1V8 e il caricabatterie Li‑Po. Si trova sull”I²C 1 all’indirizzo 0x08.
Avvertimento
Leggere i registri del PMIC va bene; scriverci è pericoloso. Configurare in modo errato un regolatore buck o un’impostazione del caricabatterie può danneggiare permanentemente la scheda, la batteria o entrambi. Tratta il PMIC come di sola lettura a meno che tu non sappia esattamente cosa stai facendo.
La cosa più utile che il PMIC ti dice e che il fuel gauge non può è la macchina a stati del caricabatterie — se la scheda sta attualmente funzionando su USB / ESLOV / VIN, in quale fase del ciclo di carica si trova la Li‑Po e se il caricabatterie è in errore termico o di watchdog. I registri del caricabatterie risiedono a un offset di 0x80 nello spazio di indirizzamento I²C principale del PF1550 (vedere §22.2 del datasheet del PF1550), quindi ad esempio CHG_INT_OK all’indirizzo del caricabatterie 0x04 viene letto dal registro 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)
Altri registri di sola lettura che vale la pena consultare nel datasheet (tutti all’offset caricabatterie 0x80): 0x80 CHG_INT (interrupt latch del caricabatterie — flag di errore), 0x86 VBUS_SNS (lo stato VBUS multi‑bit incluso OVLO / UVLO / DPM) e 0x88 BATT_SNS (presenza della batteria e stato di sovracorrente).
Wi‑Fi¶
Il Murata 1DX (CYW4343W) integrato è esposto tramite network — configurazione di rete come interfaccia station. Collega l’antenna fornita al connettore U.FL integrato prima di attivare la radio:
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¶
Lo stesso Murata 1DX espone anche il Bluetooth LE 5.1. Usa aioble — BLE asincrono per il BLE compatibile con asyncio — ad esempio, fai l’advertising come periferica e attendi che un central si connetta:
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)¶
L”edizione LoRa del Vision Shield aggiunge un modulo LoRaWAN Murata CMWX1ZZABZ collegato al Portenta H7 tramite UART. Il modulo lora incapsula il firmware a comandi AT e supporta join OTAA o 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()
Usa BAND_US915 / BAND_AS923 / BAND_AU915 ecc. per le regioni non UE, e passa a lora.Lora.join_ABP() se il tuo network server usa l’attivazione ABP.
Avvertimento
Mentre il modulo LoRa è in uso, il driver riserva i seguenti pin del connettore MKR come linee di controllo per il Murata CMWX1ZZABZ — non possono essere usati:
Pin MKR |
Motivo |
|---|---|
|
pin BOOT del modulo LoRa |
|
pin RST del modulo LoRa |
Ethernet (Vision Shield)¶
L”edizione Ethernet del Vision Shield aggiunge una presa RJ45 con magnetics collegata al MAC Ethernet 10/100 dello STM32H747 tramite RMII. Collega un cavo Ethernet e la PHY appare come interfaccia LAN; il DHCP parte automaticamente non appena il link si attiva:
import network
import time
lan = network.LAN()
lan.active(True)
while not lan.isconnected():
time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])
Scheda microSD (Vision Shield)¶
Quando viene inserita una scheda, questa viene montata automaticamente su /sdcard ed è utilizzabile tramite il normale filesystem:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Riferimento dei bus¶
GPIO¶
Usa machine.Pin per leggere o pilotare uno qualsiasi dei pin serigrafati. Le uscite sono CMOS a 3,3 V e possono assorbire/erogare fino a 20 mA per pin (140 mA totali sull’intero connettore).
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())
Qualsiasi pin di ingresso può anche generare un interrupt sulle transizioni di fronte:
def handler(pin):
print("triggered:", pin)
Pin("D1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Bus |
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¶
Bus |
SCL |
SDA |
|---|---|---|
I2C3 |
D12 |
D11 |
from machine import I2C
i2c = I2C(3, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")
I pad D11/D12 sul connettore MKR e i pin SDA_EXT/SCL_EXT del connettore ESLOV si trovano sullo stesso bus I²C 3 — vedere Connettore ESLOV sopra per il pinout dell’ESLOV.
Lo stesso hardware può anche essere usato in modalità target (slave) tramite machine.I2CTarget per esporre una regione di memoria a un altro controller I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(3, addr=0x42, mem=buf)
SPI¶
Bus |
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¶
Il Portenta H7 espone otto canali ADC a 12 bit su A0–A7. Tutti sono riferiti a 3,3 V — read_u16 restituisce 0–65535 su 0–3,3 V al pin:
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¶
Un singolo canale DAC a 12 bit è esposto su DAC1 (A6 / D21) tramite pyb.DAC
from pyb import DAC
dac = DAC("DAC1")
dac.write(int(0.5 * 255)) # 8‑bit output, ~1.65 V
PWM¶
Pin |
Timer / canale |
|---|---|
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 |
Pilota uno qualsiasi di essi tramite machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("D4"), freq=1_000, duty_u16=32768)
Nota
Diversi pin condividono i canali del timer:
TIM1 CH1 è su
D1eD6.TIM1 CH2 è su
D2eD14.TIM8 CH3N è su
D0eD1.
Scegli un solo consumatore per canale del timer.
Avvertimento
TIM1 è riservato al clock master della camera quando il Vision Shield è inizializzato tramite csi — sensori camera — D1, D2, D6, D13 e D14 non possono essere pilotati in PWM mentre la camera è attiva.
Bus software bit‑banged¶
machine.SoftI2C e machine.SoftSPI funzionano su qualsiasi GPIO se ti serve un bus aggiuntivo.
Sensore termico (esterno alla scheda)¶
Il firmware include il driver fir — driver del sensore termico (fir == far infrared) per le termocamere collegate esternamente:
MLX90621 — array IR 16 × 4
MLX90640 — array IR 32 × 24
MLX90641 — array IR 16 × 12
AMG8833 — array IR 8 × 8
Collega il modulo al bus I²C della scheda e leggi i frame con 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())
Il driver fir comunica con il sensore solo tramite I²C 3 — collega il modulo a D12 (SCL) e D11 (SDA).
Temporizzazione¶
time¶
Il modulo time copre i ritardi bloccanti, i tick monotoni e la misura del tempo trascorso:
import time
time.sleep(1) # seconds
time.sleep_ms(500)
time.sleep_us(10)
start = time.ticks_ms()
# ...do work...
elapsed = time.ticks_diff(time.ticks_ms(), start)
Timer virtuali¶
machine.Timer pianifica callback periodiche o singole senza consumare uno slot di timer hardware. Passa -1 come id per usare un timer virtuale (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"))
I valori del periodo sono in millisecondi. Chiama deinit() per fermare e rilasciare lo slot.
Orologio in tempo reale¶
machine.RTC mantiene l’orario reale attraverso i reset. Il connettore HD espone anche un pad COINCELL che può alimentare l’RTC da una CR2032 in caso di mancanza di alimentazione:
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 resetta la scheda se l’applicazione si blocca. Una volta avviato non può essere fermato o riconfigurato — alimentalo periodicamente all’interno del tuo loop principale:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
Informazioni di boot e runtime¶
Aggiornamento del firmware (DFU)¶
Il Portenta H7 usa il doppio tap di reset standard di Arduino per entrare nel bootloader di Arduino. Premi rapidamente due volte il pulsante di reset — la scheda si rienumera via USB come dispositivo DFU e OpenMV IDE può flashare una nuova immagine firmware.
Uno script in esecuzione può rientrare nel bootloader su richiesta chiamando machine.bootloader()
import machine
machine.bootloader()
Filesystem e ordine di boot¶
Il firmware del Portenta H7 monta fino a tre filesystem all’avvio:
Flash interna — sempre montata su
/flash. Contiene per impostazione predefinitamain.pyeREADME.txt; creata al primissimo avvio.Scheda microSD — se è collegato un Vision Shield ed è inserita una scheda, viene montata su
/sdcard.ROMFS — filesystem di sola lettura mappato in memoria su
/rom, montato automaticamente da MicroPython all’avvio.
Dopo il montaggio, la directory di lavoro è impostata su /sdcard quando la scheda è presente, altrimenti su /flash. L’interprete esegue quindi gli script da quella directory:
boot.pyviene eseguito a ogni soft reset (cold boot,Ctrl‑Ddal REPL o ogni volta che lo script in esecuzione termina).main.pyviene eseguito solo al cold boot, immediatamente dopoboot.py. I soft reset successivi rieseguonoboot.pyma passano direttamente al REPL — per rieseguiremain.pydevi resettare completamente la scheda.
Posizionare un boot.py o un main.py sulla scheda SD sovrascrive la copia in flash senza toccarla — entrambi i file vengono cercati nella directory di boot (/sdcard quando la scheda è montata, altrimenti /flash).
Il main.py predefinito fornito su una scheda appena flashata si limita a far lampeggiare il canale blu del LED RGB utente come heartbeat (due brevi impulsi, breve pausa), così puoi capire che il firmware si è avviato correttamente senza alcun host collegato.
sys.path viene esteso per includere tutti e tre i filesystem e le loro sottodirectory lib/, così i moduli importabili possono risiedere in /flash/lib, /sdcard/lib o /rom/lib.
Per forzare il sistema a ignorare una scheda SD inserita (ad esempio per eseguire il main.py della flash anche con una scheda presente), crea un file vuoto chiamato SKIPSD nella radice di /flash.
Quando è connesso via USB, il filesystem di boot (/sdcard se è presente una scheda, altrimenti /flash) si enumera anche come unità di archiviazione di massa USB sull’host, permettendoti di modificare direttamente boot.py, main.py e qualsiasi altro file. Espelli l’unità prima di resettare la scheda così l’host scarica le sue scritture in cache.
Nota
Poiché il sistema operativo tratta l’unità come un dispositivo a blocchi passivo, i file creati o modificati dal codice in esecuzione sulla camera non appariranno finché l’host non rimonta l’unità. Se sia il sistema operativo sia la camera scrivono lo stesso filesystem nello stesso momento, il sistema operativo vincerà e sovrascriverà le modifiche fatte dalla camera. Usa la scheda SD per qualsiasi dato che lo script riscrive, e rimonta prima di leggere quei file dall’host.
Nota
Il canale rosso del LED RGB utente può accendersi brevemente mentre l’host legge da o scrive sull’unità di archiviazione di massa USB — questo è un indicatore di attività pilotato dal firmware, non un guasto.
Dimensioni di archiviazione¶
Il Portenta H7 viene fornito con:
/flash— filesystem FAT da 11 MB, lettura/scrittura./rom— ROMFS mappato in memoria di sola lettura da 4 MB, usato per fornire script e modelli ML che traggono vantaggio dall’accesso mmap zero-copy./sdcard— dimensione completa di qualsiasi scheda microSD inserita in un Vision Shield (quando presente), lettura/scrittura.
Indicatore di hard‑fault¶
Se il LED RGB utente sta ciclando rapidamente attraverso tutti i colori — abbastanza velocemente da sembrare un LED bianco scintillante piuttosto che tonalità distinte — il firmware ha riscontrato un hard fault irrecuperabile. Riflasha il firmware per ripristinare; se il riflash non aiuta, la scheda potrebbe essere fisicamente danneggiata.
Librerie software¶
Vedere l”indice della libreria per l’elenco completo dei moduli — incluso quali sono unici della build del Portenta H7.