Arduino Portenta H7¶
De Arduino Portenta H7 is een industrieel ontwikkelbord van 66 × 25 mm, opgebouwd rond de STMicroelectronics STM32H747XI — een dual‑core SoC die een Cortex‑M7 op 400 MHz combineert met een Cortex‑M4 op 200 MHz. De OpenMV-firmware draait volledig op de M7-kern en is ontworpen om gebruikt te worden met het Portenta Vision Shield (Ethernet- of LoRa-editie), dat een Himax HM01B0 / HM0360 camera, dubbele PDM-microfoons en een microSD-slot toevoegt aan de basis-Portenta H7.
Voor de volledige datasheet, foto’s en afmetingen, zie de Arduino Portenta H7 productpagina.
Hoogtepunten¶
STMicroelectronics STM32H747XI dual Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). De OpenMV-firmware draait alleen op de M7-kern; de M4-kern wordt blootgesteld via openamp voor communicatie tussen processoren.
8 MB extern SDRAM plus 2 MB intern flashgeheugen en 16 MB extern QSPI-flashgeheugen.
Hardware JPEG-encoder/decoder.
Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 via de Murata 1DX (CYW4343W) module — verbindt via een U.FL-connector op het bord met de meegeleverde antenne.
High‑speed USB‑C (480 Mb/s).
22 gebruikers-I/O-pinnen op de Arduino MKR‑stijl bovenste headers — D0–D14 (digitaal) plus A0–A6 (analoog).
Twee 80‑pins high‑density-connectoren aan de onderkant stellen de volledige STM32H747-fabric bloot — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UART’s, extra SPI/I²C/timers, enzovoort. Shields zoals het Vision Shield koppelen aan deze connectoren.
JTAG / SWD uitgebracht op de onderste HD-connectoren voor geavanceerd debuggen.
Accu-ondersteuning — 3,7 V Li‑Po JST-connector plus oplader en accumonitor op het bord.
Pinout¶
Pinreferentie¶
22 gebruikerspinnen worden blootgesteld op de Arduino MKR‑stijl bovenrand-headers — 15 digitale (D0-D14) plus 7 analoge (A0-A6). Veel meer SoC-pinnen zijn beschikbaar via de onderste 80‑pins high‑density-connectoren voor shieldwerk; zie Arduino’s volledige pinout-PDF voor die toewijzing.
Pinnaam |
Referentie |
Functie |
|---|---|---|
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 (gedeeld met A3 / A5) |
D9 |
3,3 V |
SPI2 SCK |
D10 |
3,3 V |
SPI2 MISO (gedeeld met 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 (alleen analoog) |
A1 |
3,3 V |
ADC12 IN1 (alleen analoog) |
A2 |
3,3 V |
ADC123 IN12 (alleen analoog; gedeeld met D10) |
A3 |
3,3 V |
ADC12 IN13 (alleen analoog; gedeeld met D8) |
A4 |
3,3 V |
ADC123 IN12 (gedeeld met D10) |
A5 |
3,3 V |
ADC12 IN13 (gedeeld met D8) |
A6 |
3,3 V |
DAC1 OUT1 / ADC12 IN18 |
A7 |
3,3 V |
TIM3 CH1 / ADC12 IN3 (niet blootgesteld op de headers) |
D20 |
3,3 V |
alias van |
D21 |
3,3 V |
alias van |
RESET |
3,3 V |
druk op de schakelaar op het bord of trek naar GND om te resetten |
LED_RED |
3,3 V |
rode kanaal van de RGB-LED (actief laag) |
LED_GREEN |
3,3 V |
groene kanaal van de RGB-LED (actief laag) |
LED_BLUE |
3,3 V |
blauwe kanaal van de RGB-LED (actief laag) |
Notitie
A0-A3 zijn alleen-analoge pads op de STM32H747 zonder GPIO-functie — behandel ze uitsluitend als ADC-ingangen. A2/A4 en A3/A5 delen hun fysieke pinnen met respectievelijk D10 en D8, dus je kunt er geen PWM of SPI op aansturen terwijl je ze als analoog uitleest. A7 bevindt zich op de onderste HD-connectoren.
Voedingspinnen¶
MKR-headerpinnen:
VIN — hoofdsysteemrail naar de PMIC op het bord. Gevoed via een diode vanaf de
+5V-rail, de MKRVIN-pin, of de onderste 80‑pins HD-connectoren.+5V — 5 V-rail gevoed vanaf USB, de ESLOV-connector, of de MKR
+5V-pin zelf.+3V3 — hoofd 3,3 V-rail (uitgang van de PMIC-schakelregelaar).
AREF — analoge spanningsreferentie voor de ADC-pinnen. Standaard 3,3 V; stuur deze extern aan om een andere referentie te gebruiken.
GND — gemeenschappelijke massa.
Accu-ingang:
Li‑Po JST aan de voorkant van het bord accepteert een 3,7 V Li‑Po-cel. De PMIC laadt deze op zodra
+5VofVINaanwezig is.
De Portenta H7 kan via elk van deze paden van stroom worden voorzien:
USB‑C — levert 5 V aan de PMIC op het bord.
ESLOV-connector — tot 5 V op
VESLOV(zie ESLOV-connector).VIN-pin — stuur er rechtstreeks een gereguleerde 5 V-voeding op.
Li‑Po-accu — sluit aan op de JST aan de voorkant.
ESLOV-connector¶
Aan de zijkant van het bord bevindt zich een 5‑pins soldeervrije ESLOV-connector:
Pin |
Naam |
Functie |
|---|---|---|
1 |
VESLOV |
5 V voedingsuitgang (dezelfde rail als de |
2 |
INT |
externe interrupt-ingang op |
3 |
SCL_EXT |
gedeeld met de MKR-header |
4 |
SDA_EXT |
gedeeld met de MKR-header |
5 |
GND |
gemeenschappelijke massa |
De SCL_EXT/SDA_EXT van ESLOV en de D12/D11 van de MKR-header zijn dezelfde pinnen — één I²C 3-bus blootgesteld op twee connectoren.
Tip
Gebruik de accu-levensduurschatter om te modelleren hoe lang de Portenta H7 op een accu zal draaien voor een gegeven actieve / deepsleep-bedrijfscyclus.
Herstel- en debug-pinnen¶
RESET — zowel een blootgestelde pin op de bovenste header als een drukschakelaar aan de zijkant van het bord, verbonden met de NRST-lijn van de SoC. Trek naar GND of druk op de knop om te resetten.
De Portenta H7 gebruikt Arduino’s standaard dubbele-tik-reset om de bootloader van Arduino te betreden. Druk snel tweemaal op de resetknop — het bord wordt opnieuw geënumereerd via USB als een DFU-apparaat en OpenMV IDE kan een nieuwe firmware-image flashen.
De STM32 SWD-signalen zijn blootgesteld op de onderste HD-connector J1:
J1‑73— NRSTJ1‑75— SWDIO (PA13)J1‑77— SWCLK (PA14)J1‑79— SWO (PB3)
Sluit ze aan via een Portenta Breakout, de officiële Arduino debug-adapter, of een aangepaste carrier met een 1,27 mm header. Alle debug-signalen zijn 3,3 V gerefereerd.
Notitie
Wanneer het Portenta Vision Shield is aangesloten, worden dezelfde SWD/JTAG-signalen doorgeleid naar de standaard 20‑pins ARM Cortex Debug JTAG-header op het shield (1,27 mm / 0,05″ steek).
Randapparaten op het bord¶
LED’s¶
De Portenta H7 heeft één RGB-gebruikers-LED, softwarematig bestuurbaar via machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Een aparte oranje laad-LED naast de accu-JST gaat branden wanneer de oplader op het bord stroom levert aan een aangesloten Li‑Po; deze is niet door de gebruiker bestuurbaar.
Camerasensor (Vision Shield)¶
Met het Portenta Vision Shield (Ethernet- of LoRa-editie) aangesloten, wordt de Himax-sensor aangestuurd via de csi — camerasensoren module:
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()
Twee Vision Shield-revisies worden ondersteund:
HM01B0 — 320 × 320 monochroom.
HM0360 — 640 × 480 monochroom.
Waarschuwing
Terwijl de Vision Shield-camera geïnitialiseerd is, worden de volgende MKR-headerpinnen door de firmware geclaimd en kunnen ze niet worden gebruikt:
MKR-pin |
Reden |
|---|---|
|
TIM1 CH1 — master-klok van de camera |
|
TIM1 CH1 (alt) — master-klok van de camera |
|
I²C 3 SDA — gedeeld met de camera; de bus is bruikbaar maar vermijd het I²C-adres van de sensor ( |
|
I²C 3 SCL — gedeeld met de camera; de bus is bruikbaar maar vermijd het I²C-adres van de sensor ( |
|
DCMI HSYNC — schakelt ook de DAC uit |
|
DCMI PXCLK |
Machine learning¶
ml — Machine Learning draait gekwantiseerde TFLite-modellen op de Cortex‑M7 met CMSIS‑NN-kernels — snel genoeg voor compacte detectoren bij enkele frames per seconde. Modellen op het alleen-lezen /rom-bestandssysteem worden rechtstreeks vanuit flash geladen zonder kopiëren naar RAM. Hier is een 128×128 BlazeFace-detector die het gedetecteerde gezicht en de zes oriëntatiepunten ervan op elk frame van de Vision Shield-camera overlayt:
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")
M4-kern¶
De Cortex‑M4-kern wordt blootgesteld via openamp voor communicatie tussen processoren. De OpenMV-firmware draait alleen op de M7; de M4 heeft geen eigen MicroPython-runtime, dus het gebruik ervan betekent dat je een aparte C-firmware-image bouwt en deze vanaf het bestandssysteem laadt via openamp.RemoteProc. Vooraf gebouwde voorbeeldfirmware die een virtueel UART-eindpunt implementeert, is beschikbaar in de openamp_vuart repository — volg de README ervan om vuart.elf te bouwen:
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 de praktijk kan deze ondersteuning het best worden beschouwd als een demonstratie van de openamp-interface in plaats van een werkend dual‑core-platform — de M4 kan niet onafhankelijk van de M7 worden gereset, dus het stoppen van de M4 dwingt een volledige systeem-herstart af.
Microfoon (Vision Shield)¶
Het Vision Shield draagt dubbele PDM-microfoons die worden vastgelegd via audio — Audio Module over het SAI4-randapparaat van de STM32. Elke buffer arriveert als signed‑16‑bit PCM bytearray, klaar om in te voeren in ulab/numpy voor DSP — bijvoorbeeld een eenvoudige luidheidsdetector:
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
Geef channels=2 door aan audio.init om geïnterleavede samples van beide microfoons te ontvangen.
Accu-brandstofmeter¶
De Maxim MAX17262 ModelGauge m5 brandstofmeter houdt de spanning, stroom, temperatuur en laadtoestand van de Li‑Po-accu bij. Deze bevindt zich op I²C 1 op adres 0x36.
De MAX17262 heeft interne stroommeting, dus het stroomregister leest rechtstreeks in microampère uit zonder dat er een externe Rsense-factor toegepast hoeft te worden. Het uitlezen van de brandstofmeter is onschadelijk — er wordt geen driver meegeleverd, maar de registers gedocumenteerd in de MAX17262 datasheet kunnen rechtstreeks worden uitgelezen:
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 is signed two’s-complement: positief tijdens het opladen, negatief tijdens het ontladen. TTE is alleen zinvol wanneer de stroom negatief is; TTF alleen wanneer de stroom positief is.
Voedingsbeheer-IC¶
De NXP PF1550 PMIC beheert elke regelaar op de Portenta H7 — de +3V3 hoofdrail, de +1V8 SoC-kern / I/O-rail, en de Li‑Po-oplader. Deze bevindt zich op I²C 1 op adres 0x08.
Waarschuwing
PMIC-registers uitlezen is prima; ernaar schrijven is gevaarlijk. Het verkeerd configureren van een buck-regelaar of een opladerinstelling kan het bord, de accu, of beide permanent beschadigen. Behandel de PMIC als alleen-lezen, tenzij je precies weet wat je doet.
Het nuttigste dat de PMIC je vertelt en wat de brandstofmeter niet kan, is de toestandsmachine van de oplader — of het bord momenteel draait op USB / ESLOV / VIN, in welke fase van de laadcyclus de Li‑Po zich bevindt, en of de oplader in een thermische of watchdog-fout zit. De opladerregisters bevinden zich op een offset van 0x80 in de hoofd-I²C-adresruimte van de PF1550 (zie §22.2 van de PF1550 datasheet), dus bijvoorbeeld CHG_INT_OK op opladeradres 0x04 wordt uitgelezen uit PMIC-register 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)
Andere alleen-lezen registers die de moeite waard zijn om in de datasheet te bekijken (alle op opladeroffset 0x80): 0x80 CHG_INT (vergrendelde opladerinterrupts — foutvlaggen), 0x86 VBUS_SNS (de multi‑bit VBUS-toestand inclusief OVLO / UVLO / DPM), en 0x88 BATT_SNS (aanwezigheid van de accu en overstroomtoestand).
Wi‑Fi¶
De Murata 1DX (CYW4343W) op het bord wordt blootgesteld via network — netwerkconfiguratie als een station-interface. Sluit de meegeleverde antenne aan op de U.FL-connector op het bord voordat je de radio inschakelt:
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¶
Dezelfde Murata 1DX stelt ook Bluetooth LE 5.1 bloot. Gebruik aioble — Async BLE voor asyncio‑vriendelijke BLE — bijvoorbeeld, adverteren als randapparaat en wachten tot een central verbinding maakt:
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)¶
De LoRa-editie van het Vision Shield voegt een Murata CMWX1ZZABZ LoRaWAN-module toe die via UART aan de Portenta H7 is bedraad. De lora-module omhult de AT‑command-firmware en ondersteunt OTAA- of ABP-join, uplink en 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()
Gebruik BAND_US915 / BAND_AS923 / BAND_AU915 enz. voor niet‑EU-regio’s, en schakel over naar lora.Lora.join_ABP() als je netwerkserver ABP-activering gebruikt.
Waarschuwing
Terwijl de LoRa-module in gebruik is, claimt de driver de volgende MKR-headerpinnen als stuurlijnen voor de Murata CMWX1ZZABZ — ze kunnen niet worden gebruikt:
MKR-pin |
Reden |
|---|---|
|
LoRa-module BOOT-pin |
|
LoRa-module RST-pin |
Ethernet (Vision Shield)¶
De Ethernet-editie van het Vision Shield voegt een RJ45-aansluiting met magnetics toe die via RMII aan de 10/100 Ethernet-MAC van de STM32H747 is bedraad. Sluit een Ethernet-kabel aan en de PHY verschijnt als een LAN-interface; DHCP draait automatisch zodra de link tot stand komt:
import network
import time
lan = network.LAN()
lan.active(True)
while not lan.isconnected():
time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])
microSD-kaart (Vision Shield)¶
Wanneer een kaart wordt ingestoken, wordt deze automatisch gemount op /sdcard en is bruikbaar via het reguliere bestandssysteem:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Busreferentie¶
GPIO¶
Gebruik machine.Pin om elk van de op de zeefdruk aangegeven pinnen uit te lezen of aan te sturen. Uitgangen zijn 3,3 V CMOS en kunnen tot 20 mA per pin opnemen/leveren (140 mA totaal over de hele 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())
Elke ingangspin kan ook een interrupt afvuren bij randovergangen:
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")
De D11/D12-pads op de MKR-header en de SDA_EXT/SCL_EXT-pinnen van de ESLOV-connector landen op dezelfde I²C 3-bus — zie ESLOV-connector hierboven voor de ESLOV-pinout.
Dezelfde hardware kan ook in target- (slave-) modus worden gebruikt via machine.I2CTarget om een geheugengebied bloot te stellen aan een andere I²C-controller:
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¶
De Portenta H7 stelt acht 12‑bit ADC-kanalen bloot op A0–A7. Alle zijn 3,3 V gerefereerd — read_u16 geeft 0–65535 terug over 0–3,3 V op de 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¶
Eén 12‑bit DAC-kanaal wordt blootgesteld op DAC1 (A6 / D21) via pyb.DAC
from pyb import DAC
dac = DAC("DAC1")
dac.write(int(0.5 * 255)) # 8‑bit output, ~1.65 V
PWM¶
Pin |
Timer / kanaal |
|---|---|
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 |
Stuur ze aan via machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("D4"), freq=1_000, duty_u16=32768)
Notitie
Verschillende pinnen delen timerkanalen:
TIM1 CH1 zit op
D1enD6.TIM1 CH2 zit op
D2enD14.TIM8 CH3N zit op
D0enD1.
Kies één verbruiker per timerkanaal.
Waarschuwing
TIM1 is gereserveerd voor de master-klok van de camera wanneer het Vision Shield wordt geïnitialiseerd via csi — camerasensoren — D1, D2, D6, D13 en D14 kunnen niet PWM‑aangestuurd worden terwijl de camera actief is.
Softwarematig bit‑banged bussen¶
machine.SoftI2C en machine.SoftSPI werken op elke GPIO als je een extra bus nodig hebt.
Thermische sensor (extern)¶
De firmware bevat de fir — thermische sensor-driver (fir == far infrared) driver voor extern bedrade thermische beeldsensoren:
MLX90621 — 16 × 4 IR-array
MLX90640 — 32 × 24 IR-array
MLX90641 — 16 × 12 IR-array
AMG8833 — 8 × 8 IR-array
Bedraad de module naar de I²C-bus van het bord en lees frames met 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())
De fir-driver communiceert alleen met de sensor over I²C 3 — bedraad de module naar D12 (SCL) en D11 (SDA).
Timing¶
time¶
De time module dekt blokkerende vertragingen, monotone ticks en het meten van verstreken tijd:
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)
Virtuele timers¶
machine.Timer plant periodieke of eenmalige callbacks zonder een hardware-timerslot te verbruiken. Geef -1 door als id om een virtuele (software-) timer te gebruiken:
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"))
Periodewaarden zijn in milliseconden. Roep deinit() aan om te stoppen en het slot vrij te geven.
Realtimeklok¶
machine.RTC houdt de kloktijd bij over resets heen. De HD-connector stelt ook een COINCELL-pad bloot die de RTC vanaf een CR2032 kan voeden bij stroomuitval:
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 reset het bord als de applicatie vastloopt. Eenmaal gestart kan deze niet worden gestopt of opnieuw geconfigureerd — voed hem periodiek binnen je hoofdlus:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
Boot- en runtime-informatie¶
Firmware-update (DFU)¶
De Portenta H7 gebruikt Arduino’s standaard dubbele-tik-reset om de bootloader van Arduino te betreden. Druk snel tweemaal op de resetknop — het bord wordt opnieuw geënumereerd via USB als een DFU-apparaat en OpenMV IDE kan een nieuwe firmware-image flashen.
Een draaiend script kan op verzoek opnieuw de bootloader betreden door machine.bootloader() aan te roepen:
import machine
machine.bootloader()
Bestandssysteem en bootvolgorde¶
De Portenta H7-firmware mount bij het opstarten maximaal drie bestandssystemen:
Intern flashgeheugen — altijd gemount op
/flash. Bevat standaardmain.pyenREADME.txt; aangemaakt bij de allereerste boot.microSD-kaart — als een Vision Shield is aangesloten en een kaart is ingestoken, wordt deze gemount op
/sdcard.ROMFS — alleen-lezen, in geheugen gemapt bestandssysteem op
/romdat automatisch door MicroPython bij het opstarten wordt gemount.
Na het mounten wordt de werkmap ingesteld op /sdcard wanneer de kaart aanwezig is, anders op /flash. De interpreter draait vervolgens scripts vanuit die map:
boot.pywordt uitgevoerd bij elke soft reset (koude boot,Ctrl‑Dvanaf de REPL, of telkens wanneer het draaiende script terugkeert).main.pywordt alleen bij een koude boot uitgevoerd, onmiddellijk naboot.py. Daaropvolgende soft resets voerenboot.pyopnieuw uit maar vallen direct terug naar de REPL — ommain.pyopnieuw uit te voeren moet je het bord volledig resetten.
Het neerzetten van een boot.py of main.py op de SD-kaart overschrijft de kopie in flash zonder deze aan te raken — beide bestanden worden opgezocht in de bootmap (/sdcard wanneer de kaart is gemount, anders /flash).
De standaard main.py die op een vers geflasht bord wordt meegeleverd, laat alleen het blauwe kanaal van de RGB-gebruikers-LED knipperen als een hartslag (twee korte pulsen, korte pauze), zodat je kunt zien dat de firmware schoon is opgestart zonder dat er een host is aangesloten.
sys.path wordt uitgebreid om alle drie de bestandssystemen en hun lib/-submappen te bevatten, zodat importeerbare modules in /flash/lib, /sdcard/lib of /rom/lib kunnen staan.
Om het systeem te dwingen een ingestoken SD-kaart te negeren (bijvoorbeeld om de flash-main.py te draaien zelfs met een kaart aanwezig), maak je een leeg bestand met de naam SKIPSD aan in de hoofdmap van /flash.
Wanneer verbonden via USB, wordt het bootbestandssysteem (/sdcard als er een kaart aanwezig is, anders /flash) ook geënumereerd als een USB-massaopslagstation op de host, zodat je boot.py, main.py en alle andere bestanden rechtstreeks kunt bewerken. Werp het station uit voordat je het bord reset zodat de host zijn gebufferde schrijfacties doorvoert.
Notitie
Omdat het besturingssysteem het station als een passief blokapparaat behandelt, zullen bestanden die zijn aangemaakt of gewijzigd door code die op de camera draait, niet verschijnen totdat de host het station opnieuw mount. Als zowel het besturingssysteem als de camera tegelijkertijd naar hetzelfde bestandssysteem schrijven, wint het besturingssysteem en overschrijft het de wijzigingen die door de camera zijn aangebracht. Gebruik de SD-kaart voor alle gegevens die het script terugschrijft, en mount opnieuw voordat je die bestanden vanaf de host leest.
Notitie
Het rode kanaal van de RGB-gebruikers-LED kan kort oplichten terwijl de host van of naar het USB-massaopslagstation leest of schrijft — dit is een door de firmware aangestuurde activiteitsindicator, geen fout.
Opslaggroottes¶
De Portenta H7 wordt geleverd met:
/flash— 11 MB FAT-bestandssysteem, lezen/schrijven./rom— 4 MB alleen-lezen in geheugen gemapt ROMFS, gebruikt om scripts en ML-modellen te leveren die profiteren van zero-copy mmap-toegang./sdcard— volledige grootte van welke microSD-kaart dan ook is ingestoken in een Vision Shield (indien aanwezig), lezen/schrijven.
Hard‑fault-indicator¶
Als de RGB-gebruikers-LED snel door alle kleuren cycelt — snel genoeg dat het eerder op een fonkelende witte LED lijkt dan op afzonderlijke tinten — dan heeft de firmware een onherstelbare hard fault bereikt. Flash de firmware opnieuw om te herstellen; als opnieuw flashen niet helpt, is het bord mogelijk fysiek beschadigd.
Softwarebibliotheken¶
Zie de bibliotheekindex voor de volledige lijst met modules — inclusief welke uniek zijn voor de Portenta H7-build.