Arduino Portenta H7¶
Arduino Portenta H7 to przemysłowa płytka deweloperska o wymiarach 66 × 25 mm zbudowana wokół układu STMicroelectronics STM32H747XI — dwurdzeniowego SoC łączącego rdzeń Cortex‑M7 taktowany 400 MHz z rdzeniem Cortex‑M4 taktowanym 200 MHz. Oprogramowanie układowe OpenMV działa w całości na rdzeniu M7 i jest przeznaczone do użycia z nakładką Portenta Vision Shield (w wersji Ethernet lub LoRa), która dodaje do bazowej płytki Portenta H7 kamerę Himax HM01B0 / HM0360, dwa mikrofony PDM oraz gniazdo microSD.
Pełną kartę katalogową, zdjęcia i wymiary znajdziesz na stronie produktu Arduino Portenta H7.
Najważniejsze cechy¶
STMicroelectronics STM32H747XI dwurdzeniowy Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). Oprogramowanie układowe OpenMV działa wyłącznie na rdzeniu M7; rdzeń M4 jest udostępniany przez openamp na potrzeby komunikacji międzyprocesorowej.
8 MB zewnętrznej pamięci SDRAM oraz 2 MB wewnętrznej pamięci flash i 16 MB zewnętrznej pamięci flash QSPI.
Sprzętowy koder/dekoder JPEG.
Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 poprzez moduł Murata 1DX (CYW4343W) — łączy się z dołączoną anteną przez umieszczone na płytce złącze U.FL.
Wysokoprędkościowe USB‑C (480 Mb/s).
22 piny użytkownika I/O na górnych goldpinach w stylu Arduino MKR — D0–D14 (cyfrowe) plus A0–A6 (analogowe).
Dwa 80‑pinowe złącza o dużej gęstości na spodzie udostępniają pełną strukturę STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UART‑y, dodatkowe SPI/I²C/liczniki czasu itd. Nakładki takie jak Vision Shield łączą się z tymi złączami.
JTAG / SWD wyprowadzone na dolne złącza HD na potrzeby zaawansowanego debugowania.
Obsługa akumulatora — złącze JST dla ogniwa Li‑Po 3,7 V plus wbudowana ładowarka i monitor akumulatora.
Wyprowadzenia (pinout)¶
Opis pinów¶
Na górnych goldpinach w stylu Arduino MKR wyprowadzono 22 piny użytkownika — 15 cyfrowych (D0-D14) plus 7 analogowych (A0-A6). Znacznie więcej pinów SoC jest dostępnych przez dolne 80‑pinowe złącza o dużej gęstości na potrzeby pracy z nakładkami; to mapowanie znajdziesz w pełnym pliku PDF z wyprowadzeniami od Arduino.
Nazwa pinu |
Oznaczenie |
Funkcja |
|---|---|---|
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 (współdzielony z A3 / A5) |
D9 |
3.3 V |
SPI2 SCK |
D10 |
3.3 V |
SPI2 MISO (współdzielony z 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 (tylko analogowy) |
A1 |
3.3 V |
ADC12 IN1 (tylko analogowy) |
A2 |
3.3 V |
ADC123 IN12 (tylko analogowy; współdzielony z D10) |
A3 |
3.3 V |
ADC12 IN13 (tylko analogowy; współdzielony z D8) |
A4 |
3.3 V |
ADC123 IN12 (współdzielony z D10) |
A5 |
3.3 V |
ADC12 IN13 (współdzielony z D8) |
A6 |
3.3 V |
DAC1 OUT1 / ADC12 IN18 |
A7 |
3.3 V |
TIM3 CH1 / ADC12 IN3 (niewyprowadzony na goldpiny) |
D20 |
3.3 V |
alias |
D21 |
3.3 V |
alias |
RESET |
3.3 V |
naciśnij wbudowany przełącznik lub zewrzyj do GND, aby zresetować |
LED_RED |
3.3 V |
czerwony kanał diody RGB (aktywny stanem niskim) |
LED_GREEN |
3.3 V |
zielony kanał diody RGB (aktywny stanem niskim) |
LED_BLUE |
3.3 V |
niebieski kanał diody RGB (aktywny stanem niskim) |
Informacja
A0-A3 to pady wyłącznie analogowe na STM32H747 bez funkcji GPIO — traktuj je jako wejścia ADC. A2/A4 oraz A3/A5 współdzielą swoje fizyczne piny odpowiednio z D10 i D8, więc nie możesz na nich sterować PWM ani SPI w trakcie odczytu jako analogowe. A7 znajduje się na dolnych złączach HD.
Piny zasilania¶
Piny goldpinów MKR:
VIN — główna szyna systemowa wprowadzana do wbudowanego PMIC. Zasilana przez diodę z szyny
+5V, pinuVINMKR lub dolnych 80‑pinowych złączy HD.+5V — szyna 5 V zasilana z USB, złącza ESLOV lub samego pinu
+5VMKR.+3V3 — główna szyna 3,3 V (wyjście przetwornicy PMIC).
AREF — analogowe napięcie odniesienia dla pinów ADC. Domyślnie 3,3 V; podaj zewnętrznie, aby użyć innego odniesienia.
GND — wspólna masa.
Wejście akumulatora:
Złącze JST Li‑Po z przodu płytki przyjmuje ogniwo Li‑Po 3,7 V. PMIC ładuje je zawsze, gdy obecne jest
+5VlubVIN.
Portenta H7 może być zasilana którąkolwiek z tych dróg:
USB‑C — dostarcza 5 V do wbudowanego PMIC.
Złącze ESLOV — do 5 V na
VESLOV(zob. Złącze ESLOV).Pin VIN — podaj bezpośrednio stabilizowane zasilanie 5 V.
Akumulator Li‑Po — podłącz do złącza JST z przodu.
Złącze ESLOV¶
Z boku płytki znajduje się 5‑pinowe, lutowane bez konieczności lutowania złącze ESLOV:
Pin |
Nazwa |
Funkcja |
|---|---|---|
1 |
VESLOV |
wyjście zasilania 5 V (ta sama szyna co |
2 |
INT |
wejście przerwania zewnętrznego na |
3 |
SCL_EXT |
współdzielony z padem |
4 |
SDA_EXT |
współdzielony z padem |
5 |
GND |
wspólna masa |
Piny SCL_EXT/SDA_EXT złącza ESLOV oraz D12/D11 goldpinów MKR to te same piny — jedna magistrala I²C 3 wyprowadzona na dwa złącza.
Wskazówka
Użyj kalkulatora żywotności akumulatora, aby oszacować, jak długo Portenta H7 będzie działać na akumulatorze przy zadanym cyklu pracy aktywny / głęboki uśpienie.
Piny do odzyskiwania i debugowania¶
RESET — zarówno wyprowadzony pin na górnym goldpinie, jak i chwilowy przełącznik z boku płytki, połączone z linią NRST układu SoC. Zewrzyj do GND lub naciśnij przycisk, aby zresetować.
Portenta H7 wykorzystuje standardowy podwójny stuknięcie resetu Arduino, aby wejść do bootloadera Arduino. Szybko naciśnij dwukrotnie przycisk resetu — płytka ponownie wyliczy się przez USB jako urządzenie DFU, a OpenMV IDE może wgrać nowy obraz oprogramowania układowego.
Sygnały SWD STM32 są wyprowadzone na dolnym złączu HD J1:
J1‑73— NRSTJ1‑75— SWDIO (PA13)J1‑77— SWCLK (PA14)J1‑79— SWO (PB3)
Podłącz je przez Portenta Breakout, oficjalny adapter debugowania Arduino lub własną płytkę nośną z goldpinem o rastrze 1,27 mm. Wszystkie sygnały debugowania są odniesione do 3,3 V.
Informacja
Gdy podłączona jest nakładka Portenta Vision Shield, te same sygnały SWD/JTAG są wyprowadzone na standardowy 20‑pinowy goldpin debugowania ARM Cortex Debug JTAG na nakładce (raster 1,27 mm / 0,05″).
Wbudowane urządzenia peryferyjne¶
Diody LED¶
Portenta H7 ma pojedynczą diodę RGB użytkownika, sterowaną programowo przez machine.LED
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Osobna pomarańczowa dioda ładowania obok złącza JST akumulatora świeci, gdy wbudowana ładowarka dostarcza prąd do podłączonego ogniwa Li‑Po; nie podlega sterowaniu przez użytkownika.
Sensor kamery (Vision Shield)¶
Po podłączeniu nakładki Portenta Vision Shield (w wersji Ethernet lub LoRa) sensor Himax jest sterowany przez moduł csi — sensory kamery
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()
Obsługiwane są dwie wersje Vision Shield:
HM01B0 — 320 × 320 monochromatyczny.
HM0360 — 640 × 480 monochromatyczny.
Ostrzeżenie
Gdy kamera Vision Shield jest zainicjalizowana, następujące piny goldpinów MKR są zajmowane przez oprogramowanie układowe i nie mogą być używane:
Pin MKR |
Przyczyna |
|---|---|
|
TIM1 CH1 — zegar główny kamery |
|
TIM1 CH1 (alt) — zegar główny kamery |
|
I²C 3 SDA — współdzielony z kamerą; magistrala jest używalna, ale unikaj adresu I²C sensora ( |
|
I²C 3 SCL — współdzielony z kamerą; magistrala jest używalna, ale unikaj adresu I²C sensora ( |
|
DCMI HSYNC — wyłącza również DAC |
|
DCMI PXCLK |
Uczenie maszynowe¶
ml — Uczenie maszynowe uruchamia skwantyzowane modele TFLite na rdzeniu Cortex‑M7 z jądrami CMSIS‑NN — wystarczająco szybko dla kompaktowych detektorów przy kilku klatkach na sekundę. Modele w systemie plików tylko do odczytu /rom ładują się bezpośrednio z pamięci flash bez kopiowania do RAM. Oto detektor BlazeFace 128×128 nakładający wykrytą twarz i jej sześć punktów charakterystycznych na każdą ramkę z kamery 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")
Rdzeń M4¶
Rdzeń Cortex‑M4 jest udostępniany przez openamp na potrzeby komunikacji międzyprocesorowej. Oprogramowanie układowe OpenMV działa wyłącznie na M7; M4 nie ma własnego środowiska uruchomieniowego MicroPython, więc jego użycie oznacza zbudowanie osobnego obrazu oprogramowania w C i załadowanie go z systemu plików przez openamp.RemoteProc. Gotowe przykładowe oprogramowanie implementujące wirtualny punkt końcowy UART jest dostępne w repozytorium openamp_vuart — postępuj zgodnie z jego plikiem README, aby zbudować 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)
W praktyce tę obsługę najlepiej traktować jako demonstrację interfejsu openamp, a nie działającą platformę dwurdzeniową — M4 nie może być resetowany niezależnie od M7, więc zatrzymanie M4 wymusza pełny restart systemu.
Mikrofon (Vision Shield)¶
Vision Shield jest wyposażony w dwa mikrofony PDM przechwytywane przez audio — Moduł Audio za pośrednictwem peryferium SAI4 układu STM32. Każdy bufor dociera jako 16‑bitowy ze znakiem PCM bytearray, gotowy do podania do ulab/numpy w celu przetwarzania DSP — na przykład prosty detektor głośności:
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
Przekaż channels=2 do audio.init, aby otrzymywać przeplecione próbki z obu mikrofonów.
Wskaźnik naładowania akumulatora¶
Wskaźnik paliwa Maxim MAX17262 ModelGauge m5 śledzi napięcie, prąd, temperaturę i stan naładowania akumulatora Li‑Po. Znajduje się na I²C 1 pod adresem 0x36.
MAX17262 ma wewnętrzny pomiar prądu, więc rejestr prądu odczytuje się bezpośrednio w mikroamperach, bez konieczności stosowania zewnętrznego współczynnika Rsense. Odczyt wskaźnika paliwa jest nieszkodliwy — nie dostarczono sterownika, ale rejestry udokumentowane w karcie katalogowej MAX17262 można odczytywać bezpośrednio:
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 to wartość ze znakiem w kodzie uzupełnień do dwóch: dodatnia podczas ładowania, ujemna podczas rozładowywania. TTE ma sens tylko wtedy, gdy prąd jest ujemny; TTF tylko gdy prąd jest dodatni.
Układ zarządzania zasilaniem¶
PMIC NXP PF1550 obsługuje każdy stabilizator na płytce Portenta H7 — główną szynę +3V3, szynę rdzenia / I/O SoC +1V8 oraz ładowarkę Li‑Po. Znajduje się na I²C 1 pod adresem 0x08.
Ostrzeżenie
Odczyt rejestrów PMIC jest bezpieczny; zapis do nich jest niebezpieczny. Błędna konfiguracja przetwornicy obniżającej lub ustawienia ładowarki może trwale uszkodzić płytkę, akumulator lub oba. Traktuj PMIC jako tylko do odczytu, chyba że dokładnie wiesz, co robisz.
Najbardziej przydatną rzeczą, którą PMIC ujawnia, a której nie potrafi wskaźnik paliwa, jest maszyna stanów ładowarki — czy płytka jest aktualnie zasilana z USB / ESLOV / VIN, na jakim etapie cyklu ładowania znajduje się Li‑Po oraz czy ładowarka jest w stanie awarii termicznej lub watchdog. Rejestry ładowarki znajdują się z przesunięciem 0x80 w głównej przestrzeni adresowej I²C układu PF1550 (zob. §22.2 karty katalogowej PF1550), więc na przykład CHG_INT_OK pod adresem ładowarki 0x04 odczytuje się z rejestru 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)
Inne rejestry tylko do odczytu warte sprawdzenia w karcie katalogowej (wszystkie z przesunięciem ładowarki 0x80): 0x80 CHG_INT (zatrzaśnięte przerwania ładowarki — flagi awarii), 0x86 VBUS_SNS (wielobitowy stan VBUS, w tym OVLO / UVLO / DPM) oraz 0x88 BATT_SNS (obecność akumulatora i stan przeciążenia prądowego).
Wi‑Fi¶
Wbudowany Murata 1DX (CYW4343W) jest udostępniany przez network — konfiguracja sieci jako interfejs stacji. Przed uruchomieniem radia podłącz dołączoną antenę do wbudowanego złącza U.FL
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¶
Ten sam Murata 1DX udostępnia również Bluetooth LE 5.1. Użyj aioble — Asynchroniczne BLE dla przyjaznego dla asyncio BLE — na przykład rozgłaszaj jako urządzenie peryferyjne i czekaj na połączenie urządzenia centralnego:
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)¶
Wersja LoRa nakładki Vision Shield dodaje moduł LoRaWAN Murata CMWX1ZZABZ podłączony do Portenta H7 przez UART. Moduł lora opakowuje oprogramowanie układowe sterowane komendami AT i obsługuje dołączanie OTAA lub ABP, łącze w górę (uplink) i łącze w dół (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()
Dla regionów spoza UE użyj BAND_US915 / BAND_AS923 / BAND_AU915 itd. i przełącz się na lora.Lora.join_ABP(), jeśli twój serwer sieciowy korzysta z aktywacji ABP.
Ostrzeżenie
Gdy moduł LoRa jest w użyciu, sterownik zajmuje następujące piny goldpinów MKR jako linie sterujące dla Murata CMWX1ZZABZ — nie mogą one być używane:
Pin MKR |
Przyczyna |
|---|---|
|
Pin BOOT modułu LoRa |
|
Pin RST modułu LoRa |
Ethernet (Vision Shield)¶
Wersja Ethernet nakładki Vision Shield dodaje gniazdo RJ45 z transformatorem podłączone do kontrolera MAC Ethernet 10/100 układu STM32H747 przez RMII. Podłącz kabel Ethernet, a PHY pojawi się jako interfejs LAN; DHCP uruchamia się automatycznie po nawiązaniu łącza:
import network
import time
lan = network.LAN()
lan.active(True)
while not lan.isconnected():
time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])
Karta microSD (Vision Shield)¶
Po włożeniu karty jest ona montowana automatycznie pod /sdcard i jest używalna przez zwykły system plików:
import os
for entry in os.listdir("/sdcard"):
print(entry)
Opis magistral¶
GPIO¶
Użyj machine.Pin, aby odczytywać lub sterować dowolnym z opisanych na płytce pinów. Wyjścia są typu CMOS 3,3 V i mogą pochłaniać/dostarczać do 20 mA na pin (140 mA łącznie dla całego goldpinu).
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())
Dowolny pin wejściowy może również wyzwalać przerwanie przy zmianach na zboczu:
def handler(pin):
print("triggered:", pin)
Pin("D1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
Magistrala |
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¶
Magistrala |
SCL |
SDA |
|---|---|---|
I2C3 |
D12 |
D11 |
from machine import I2C
i2c = I2C(3, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")
Pady D11/D12 na goldpinie MKR oraz piny SDA_EXT/SCL_EXT złącza ESLOV trafiają na tę samą magistralę I²C 3 — zobacz Złącze ESLOV powyżej, aby poznać wyprowadzenia ESLOV.
Ten sam sprzęt może być również używany w trybie urządzenia docelowego (slave) przez machine.I2CTarget, aby udostępnić obszar pamięci innemu kontrolerowi I²C:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(3, addr=0x42, mem=buf)
SPI¶
Magistrala |
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¶
Portenta H7 udostępnia osiem 12‑bitowych kanałów ADC na A0–A7. Wszystkie są odniesione do 3,3 V — read_u16 zwraca 0–65535 w zakresie 0–3,3 V na pinie:
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¶
Pojedynczy 12‑bitowy kanał DAC jest udostępniany na DAC1 (A6 / D21) przez pyb.DAC
from pyb import DAC
dac = DAC("DAC1")
dac.write(int(0.5 * 255)) # 8‑bit output, ~1.65 V
PWM¶
Pin |
Licznik czasu / kanał |
|---|---|
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 |
Steruj którymkolwiek z nich przez machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("D4"), freq=1_000, duty_u16=32768)
Informacja
Kilka pinów współdzieli kanały licznika czasu:
TIM1 CH1 jest na
D1orazD6.TIM1 CH2 jest na
D2orazD14.TIM8 CH3N jest na
D0orazD1.
Wybierz jednego odbiorcę na kanał licznika czasu.
Ostrzeżenie
TIM1 jest zarezerwowany dla zegara głównego kamery, gdy Vision Shield jest inicjalizowany przez csi — sensory kamery — D1, D2, D6, D13 i D14 nie mogą być sterowane PWM, gdy kamera jest aktywna.
Programowe magistrale bit‑bang¶
machine.SoftI2C i machine.SoftSPI działają na dowolnym GPIO, jeśli potrzebujesz dodatkowej magistrali.
Sensor termiczny (zewnętrzny)¶
Oprogramowanie układowe zawiera sterownik fir — sterownik sensora termicznego (fir == far infrared, daleka podczerwień) dla zewnętrznie podłączonych kamer termowizyjnych:
MLX90621 — matryca IR 16 × 4
MLX90640 — matryca IR 32 × 24
MLX90641 — matryca IR 16 × 12
AMG8833 — matryca IR 8 × 8
Podłącz moduł do magistrali I²C płytki i odczytuj ramki za pomocą 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())
Sterownik fir komunikuje się z sensorem wyłącznie przez I²C 3 — podłącz moduł do D12 (SCL) i D11 (SDA).
Pomiar czasu¶
time¶
Moduł time obejmuje blokujące opóźnienia, monotoniczne tyknięcia oraz pomiar upływającego czasu:
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)
Wirtualne liczniki czasu¶
machine.Timer planuje okresowe lub jednorazowe wywołania zwrotne bez zajmowania sprzętowego slotu licznika czasu. Przekaż -1 jako id, aby użyć wirtualnego (programowego) licznika czasu:
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"))
Wartości okresu są podawane w milisekundach. Wywołaj deinit(), aby zatrzymać i zwolnić slot.
Zegar czasu rzeczywistego¶
machine.RTC utrzymuje czas zegara ściennego pomiędzy resetami. Złącze HD udostępnia również pad COINCELL, który może podtrzymywać RTC z ogniwa CR2032 podczas zaniku zasilania:
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 resetuje płytkę, jeśli aplikacja się zawiesi. Po uruchomieniu nie można go zatrzymać ani ponownie skonfigurować — karm go okresowo wewnątrz swojej głównej pętli:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
Informacje o rozruchu i czasie wykonania¶
Aktualizacja oprogramowania układowego (DFU)¶
Portenta H7 wykorzystuje standardowy podwójny stuknięcie resetu Arduino, aby wejść do bootloadera Arduino. Szybko naciśnij dwukrotnie przycisk resetu — płytka ponownie wyliczy się przez USB jako urządzenie DFU, a OpenMV IDE może wgrać nowy obraz oprogramowania układowego.
Działający skrypt może ponownie wejść do bootloadera na żądanie, wywołując machine.bootloader()
import machine
machine.bootloader()
System plików i kolejność rozruchu¶
Oprogramowanie układowe Portenta H7 montuje przy rozruchu do trzech systemów plików:
Wewnętrzna pamięć flash — zawsze montowana pod
/flash. Domyślnie przechowujemain.pyiREADME.txt; tworzona przy pierwszym rozruchu.Karta microSD — jeśli podłączony jest Vision Shield i włożona jest karta, jest ona montowana pod
/sdcard.ROMFS — system plików tylko do odczytu, mapowany w pamięci pod
/rom, montowany automatycznie przez MicroPython przy starcie.
Po zamontowaniu katalog roboczy jest ustawiany na /sdcard, gdy karta jest obecna, w przeciwnym razie na /flash. Interpreter uruchamia następnie skrypty z tego katalogu:
boot.pyjest wykonywany przy każdym miękkim resecie (zimny rozruch,Ctrl‑Dz REPL lub za każdym razem, gdy działający skrypt zakończy działanie).main.pyjest wykonywany tylko przy zimnym rozruchu, bezpośrednio poboot.py. Kolejne miękkie resety ponownie uruchamiająboot.py, ale przechodzą prosto do REPL — aby ponownie uruchomićmain.py, musisz w pełni zresetować płytkę.
Umieszczenie pliku boot.py lub main.py na karcie SD nadpisuje kopię w pamięci flash bez jej naruszania — oba pliki są wyszukiwane w katalogu rozruchowym (/sdcard, gdy karta jest zamontowana, w przeciwnym razie /flash).
Domyślny main.py dostarczany na świeżo wgranej płytce po prostu miga niebieskim kanałem diody RGB użytkownika jako sygnał życia (dwa krótkie impulsy, krótka przerwa), dzięki czemu możesz stwierdzić, że oprogramowanie układowe uruchomiło się poprawnie bez podłączonego hosta.
sys.path jest rozszerzane o wszystkie trzy systemy plików i ich podkatalogi lib/, więc importowalne moduły mogą znajdować się w /flash/lib, /sdcard/lib lub /rom/lib.
Aby zmusić system do ignorowania włożonej karty SD (na przykład w celu uruchomienia main.py z pamięci flash nawet przy obecnej karcie), utwórz pusty plik o nazwie SKIPSD w katalogu głównym /flash.
Po podłączeniu przez USB rozruchowy system plików (/sdcard, jeśli karta jest obecna, w przeciwnym razie /flash) wylicza się również na hoście jako dysk pamięci masowej USB, umożliwiając bezpośrednią edycję boot.py, main.py i wszelkich innych plików. Wysuń dysk przed zresetowaniem płytki, aby host opróżnił buforowane zapisy.
Informacja
Ponieważ system operacyjny traktuje dysk jako pasywne urządzenie blokowe, pliki utworzone lub zmodyfikowane przez kod działający na kamerze nie pojawią się, dopóki host nie zamontuje dysku ponownie. Jeśli zarówno system operacyjny, jak i kamera zapisują ten sam system plików w tym samym czasie, system operacyjny wygra i nadpisze zmiany wprowadzone przez kamerę. Używaj karty SD do wszelkich danych, które skrypt zapisuje, i montuj ponownie przed odczytaniem tych plików z hosta.
Informacja
Czerwony kanał diody RGB użytkownika może na chwilę się zaświecić, gdy host odczytuje lub zapisuje dysk pamięci masowej USB — jest to sterowany przez oprogramowanie układowe wskaźnik aktywności, a nie awaria.
Rozmiary pamięci masowej¶
Portenta H7 jest dostarczana z:
/flash— system plików FAT o pojemności 11 MB, do odczytu/zapisu./rom— 4 MB mapowanego w pamięci ROMFS tylko do odczytu, używanego do dostarczania skryptów i modeli ML korzystających z dostępu mmap bez kopiowania (zero-copy)./sdcard— pełna pojemność dowolnej karty microSD włożonej do Vision Shield (gdy jest obecna), do odczytu/zapisu.
Wskaźnik krytycznej awarii (hard fault)¶
Jeśli dioda RGB użytkownika szybko przełącza się przez wszystkie kolory — na tyle szybko, że zwykle wygląda jak migotliwa biała dioda LED, a nie odrębne barwy — oznacza to, że oprogramowanie układowe napotkało nieodwracalną krytyczną awarię (hard fault). Aby przywrócić działanie, wgraj ponownie oprogramowanie układowe; jeśli ponowne wgranie nie pomaga, płytka może być fizycznie uszkodzona.
Biblioteki programowe¶
Pełną listę modułów — w tym te unikalne dla wersji Portenta H7 — znajdziesz w indeksie bibliotek.