Arduino Portenta H7¶
Arduino Portenta H7 是一款 66 × 25 mm 的工業級開發板,以 STMicroelectronics STM32H747XI 為核心——這是一款雙核心 SoC,結合了 400 MHz 的 Cortex‑M7 與 200 MHz 的 Cortex‑M4。OpenMV 韌體完全執行於 M7 核心上,並設計為搭配 Portenta Vision Shield(乙太網路版或 LoRa 版)使用,該擴充板為基礎的 Portenta H7 加入了 Himax HM01B0 / HM0360 相機、雙 PDM 麥克風以及 microSD 插槽。
如需完整的資料手冊、照片與尺寸資訊,請參閱 Arduino Portenta H7 產品頁面。
重點特色¶
STMicroelectronics STM32H747XI 雙核心 Cortex‑M7(400 MHz)+ Cortex‑M4(200 MHz)。OpenMV 韌體僅執行於 M7 核心;M4 核心透過 openamp 公開以供處理器間通訊使用。
8 MB 外部 SDRAM 外加 2 MB 內部 flash 與 16 MB 外部 QSPI flash。
硬體 JPEG 編碼器/解碼器。
Wi‑Fi b/g/n(2.4 GHz)+ Bluetooth LE 5.1,透過 Murata 1DX(CYW4343W)模組提供——並透過板載的 U.FL 接頭 連接至隨附的天線。
高速 USB‑C(480 Mb/s)。
Arduino MKR 風格頂部排針上的 22 個使用者 I/O 接腳——D0–D14(數位)外加 A0–A6(類比)。
底部的 兩個 80 接腳高密度接頭 公開了完整的 STM32H747 訊號——DCMI、DSI、Ethernet RMII、FDCAN、SDIO、SAI/I²S、UART、額外的 SPI/I²C/計時器等等。像 Vision Shield 這類擴充板即透過這些接頭連接。
JTAG / SWD 引出於底部的 HD 接頭上,供進階除錯使用。
電池支援——3.7 V Li‑Po JST 接頭外加板載充電器與電池監控器。
接腳配置¶
接腳參考¶
在 Arduino MKR 風格的頂部邊緣排針上公開了 22 個使用者接腳——15 個數位(D0-D14)外加 7 個類比(A0-A6)。透過底部的 80 接腳高密度接頭 還可使用更多的 SoC 接腳供擴充板開發;該對應關係請參閱 Arduino 的 完整接腳配置 PDF。
接腳名稱 |
參考 |
功能 |
|---|---|---|
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(與 A3 / A5 共用) |
D9 |
3.3 V |
SPI2 SCK |
D10 |
3.3 V |
SPI2 MISO(與 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(僅類比) |
A1 |
3.3 V |
ADC12 IN1(僅類比) |
A2 |
3.3 V |
ADC123 IN12(僅類比;與 D10 共用) |
A3 |
3.3 V |
ADC12 IN13(僅類比;與 D8 共用) |
A4 |
3.3 V |
ADC123 IN12(與 D10 共用) |
A5 |
3.3 V |
ADC12 IN13(與 D8 共用) |
A6 |
3.3 V |
DAC1 OUT1 / ADC12 IN18 |
A7 |
3.3 V |
TIM3 CH1 / ADC12 IN3(未在排針上公開) |
D20 |
3.3 V |
|
D21 |
3.3 V |
|
RESET |
3.3 V |
按下板載開關或拉至 GND 以重置 |
LED_RED |
3.3 V |
RGB LED 紅色通道(低電位有效) |
LED_GREEN |
3.3 V |
RGB LED 綠色通道(低電位有效) |
LED_BLUE |
3.3 V |
RGB LED 藍色通道(低電位有效) |
備註
A0-A3 是 STM32H747 上的 僅類比 接點,沒有 GPIO 功能——請僅將其視為 ADC 輸入。A2/A4 與 A3/A5 分別與 D10 和 D8 共用其實體接腳,因此在將它們作為類比讀取的同時,無法在這些接腳上驅動 PWM 或 SPI。A7 位於底部的 HD 接頭上。
電源接腳¶
MKR 排針接腳:
VIN——進入板載 PMIC 的主系統電源軌。透過二極體由
+5V電源軌、MKR 的VIN接腳或底部的 80 接腳 HD 接頭供電。+5V——由 USB、ESLOV 接頭或 MKR 的
+5V接腳本身供電的 5 V 電源軌。+3V3——主 3.3 V 電源軌(PMIC 切換式穩壓器輸出)。
AREF——ADC 接腳的類比電壓參考。預設為 3.3 V;若要使用不同的參考,請從外部驅動。
GND——共用接地。
電池輸入:
板子正面的 Li‑Po JST 接受 3.7 V Li‑Po 電池。只要存在
+5V或VIN,PMIC 即會為其充電。
Portenta H7 可透過以下任一路徑供電:
USB‑C——向板載 PMIC 提供 5 V。
ESLOV 接頭——
VESLOV上最高 5 V(參閱 ESLOV 接頭)。VIN 接腳——直接驅動一個經穩壓的 5 V 電源。
Li‑Po 電池——連接至正面的 JST。
ESLOV 接頭¶
板子側面是一個 5 接腳免焊的 ESLOV 接頭:
接腳 |
名稱 |
功能 |
|---|---|---|
1 |
VESLOV |
5 V 電源輸出(與 MKR 排針的 |
2 |
INT |
|
3 |
SCL_EXT |
與 MKR 排針的 |
4 |
SDA_EXT |
與 MKR 排針的 |
5 |
GND |
共用接地 |
ESLOV 的 SCL_EXT/SDA_EXT 與 MKR 排針的 D12/D11 是同一組接腳——同一條 I²C 3 匯流排公開於兩個接頭上。
小訣竅
使用 電池續航估算工具 來推估在給定的作用中/深度睡眠工作週期下,Portenta H7 以電池供電可執行多久。
復原與除錯接腳¶
RESET——既是頂部排針上公開的一個接腳,也是板子側面的一個瞬時開關,連接至 SoC 的 NRST 線。拉至 GND 或按下按鈕即可重置。
Portenta H7 使用 Arduino 標準的 連按兩次重置(double‑tap reset) 來進入 Arduino 的開機載入程式。快速按下重置按鈕兩次——板子會以 DFU 裝置的身分透過 USB 重新列舉,OpenMV IDE 即可燒錄新的韌體映像。
STM32 的 SWD 訊號公開於底部的 HD 接頭 J1 上:
J1‑73——NRSTJ1‑75——SWDIO(PA13)J1‑77——SWCLK(PA14)J1‑79——SWO(PB3)
可透過 Portenta Breakout、官方的 Arduino 除錯轉接器,或具有 1.27 mm 排針的自訂載板將其接線。所有除錯訊號皆以 3.3 V 為參考。
備註
當接上 Portenta Vision Shield 時,同樣的 SWD/JTAG 訊號會被導引至擴充板上標準的 20 接腳 ARM Cortex Debug JTAG 排針(1.27 mm / 0.05″ 間距)。
板載周邊裝置¶
LED¶
Portenta H7 具有單一使用者 RGB LED,可透過 machine.LED 以軟體控制:
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
電池 JST 旁有一個獨立的橙色 充電 LED,當板載充電器正向所連接的 Li‑Po 供應電流時會亮起;它無法由使用者控制。
相機感測器(Vision Shield)¶
在接上 Portenta Vision Shield(乙太網路版或 LoRa 版)後,Himax 感測器會透過 csi --- 相機感測器 模組驅動:
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()
支援兩種 Vision Shield 版本:
HM01B0——320 × 320 單色。
HM0360——640 × 480 單色。
警告
在 Vision Shield 相機初始化期間,下列 MKR 排針接腳會被韌體佔用且 無法使用:
MKR 接腳 |
原因 |
|---|---|
|
TIM1 CH1——相機主時脈 |
|
TIM1 CH1(替代)——相機主時脈 |
|
I²C 3 SDA——與相機共用;匯流排可使用,但請避開感測器的 I²C 位址( |
|
I²C 3 SCL——與相機共用;匯流排可使用,但請避開感測器的 I²C 位址( |
|
DCMI HSYNC——同時也會停用 DAC |
|
DCMI PXCLK |
機器學習¶
ml --- 機器學習 在 Cortex‑M7 上以 CMSIS‑NN 核心執行量化的 TFLite 模型——其速度足以讓精簡型偵測器以每秒數影格的速率運作。位於唯讀 /rom 檔案系統上的模型可直接從 flash 載入而無需複製到 RAM。以下是一個 128×128 的 BlazeFace 偵測器,會在來自 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")
M4 核心¶
Cortex‑M4 核心透過 openamp 公開以供處理器間通訊使用。OpenMV 韌體僅執行於 M7 上;M4 本身沒有自己的 MicroPython 執行環境,因此要使用它就意味著要建置一個獨立的 C 韌體映像,並透過 openamp.RemoteProc 從檔案系統載入它。一個實作了虛擬 UART 端點的預先建置範例韌體可在 openamp_vuart 儲存庫中取得——請依照其 README 來建置 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)
實務上,這項支援最好被視為 openamp 介面的一項示範,而非一個可運作的雙核心平台——M4 無法獨立於 M7 之外重置,因此停止 M4 會強制整個系統重新開機。
麥克風(Vision Shield)¶
Vision Shield 搭載 雙 PDM 麥克風,透過 audio --- 音訊模組 經由 STM32 的 SAI4 周邊裝置擷取。每個緩衝區皆以帶正負號的 16 位元 PCM bytearray 形式抵達,可直接饋入 ulab/numpy 進行 DSP——例如一個簡單的音量偵測器:
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
向 audio.init 傳入 channels=2 即可接收來自兩個麥克風的交錯取樣。
電池電量計¶
Maxim MAX17262 ModelGauge m5 電量計會追蹤 Li‑Po 電池的電壓、電流、溫度與充電狀態。它位於 I²C 1 的位址 0x36 上。
MAX17262 具有 內部 電流感測功能,因此電流暫存器會直接以微安培讀出,無需套用任何外部 Rsense 係數。讀取電量計不會有任何危害——雖然並未隨附驅動程式,但 MAX17262 資料手冊 中所記載的暫存器可直接讀取:
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 為帶正負號的二補數:充電時為正,放電時為負。TTE 僅在電流為負時才有意義;TTF 則僅在電流為正時有意義。
電源管理 IC¶
NXP PF1550 PMIC 負責處理 Portenta H7 上的每一個穩壓器——+3V3 主電源軌、+1V8 SoC 核心/I/O 電源軌,以及 Li‑Po 充電器。它位於 I²C 1 的位址 0x08 上。
警告
讀取 PMIC 暫存器沒有問題;對其寫入則很危險。 錯誤設定降壓穩壓器或充電器設定可能會永久損壞板子、電池或兩者。除非你確切知道自己在做什麼,否則請將 PMIC 視為唯讀。
PMIC 能告訴你而電量計做不到的、最有用的資訊就是 充電器狀態機——板子目前是以 USB/ESLOV/VIN 在運作、Li‑Po 處於充電週期的哪個階段,以及充電器是否處於熱保護或看門狗故障。充電器暫存器位於 PF1550 主 I²C 位址空間中偏移 0x80 之處(參閱 PF1550 資料手冊 §22.2),因此舉例來說,位於充電器位址 0x04 的 CHG_INT_OK 即從 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)
資料手冊中其他值得一看的唯讀暫存器(全部位於充電器偏移 0x80):0x80 CHG_INT(已鎖存的充電器中斷——故障旗標)、0x86 VBUS_SNS(包含 OVLO / UVLO / DPM 的多位元 VBUS 狀態),以及 0x88 BATT_SNS(電池存在與否及過電流狀態)。
Wi‑Fi¶
板載的 Murata 1DX(CYW4343W)透過 network --- 網路設定 以工作站介面公開。在啟用無線電之前,請先將隨附的天線連接至板載的 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¶
同一個 Murata 1DX 也公開了 Bluetooth LE 5.1。請使用 aioble --- 非同步 BLE 來進行對 asyncio 友善的 BLE——例如,以周邊裝置身分廣播並等待中央裝置連線:
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)¶
Vision Shield 的 LoRa 版 加入了一個 Murata CMWX1ZZABZ LoRaWAN 模組,透過 UART 連接至 Portenta H7。lora 模組包裝了 AT 命令韌體,並支援 OTAA 或 ABP 加入、上行與下行:
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()
對於非歐盟地區請使用 BAND_US915 / BAND_AS923 / BAND_AU915 等,若你的網路伺服器使用 ABP 啟用方式,請改用 lora.Lora.join_ABP()。
警告
在 LoRa 模組使用期間,驅動程式會佔用下列 MKR 排針接腳作為 Murata CMWX1ZZABZ 的控制線——它們 無法使用:
MKR 接腳 |
原因 |
|---|---|
|
LoRa 模組 BOOT 接腳 |
|
LoRa 模組 RST 接腳 |
Ethernet(Vision Shield)¶
Vision Shield 的 乙太網路版 加入了一個帶磁性元件的 RJ45 插孔,透過 RMII 連接至 STM32H747 的 10/100 Ethernet MAC。插入乙太網路線後,PHY 即會以 LAN 介面的形式出現;連線一旦建立,DHCP 便會自動執行:
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 卡(Vision Shield)¶
插入卡片後,它會自動掛載於 /sdcard,並可透過一般的檔案系統使用:
import os
for entry in os.listdir("/sdcard"):
print(entry)
匯流排參考¶
GPIO¶
使用 machine.Pin 來讀取或驅動任何有絲印標示的接腳。輸出為 3.3 V CMOS,每個接腳可灌入/拉出最高 20 mA(整個排針合計 140 mA)。
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())
任何輸入接腳也都能在邊緣轉態時觸發中斷:
def handler(pin):
print("triggered:", pin)
Pin("D1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
匯流排 |
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¶
匯流排 |
SCL |
SDA |
|---|---|---|
I2C3 |
D12 |
D11 |
from machine import I2C
i2c = I2C(3, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")
MKR 排針上的 D11/D12 接點與 ESLOV 接頭的 SDA_EXT/SCL_EXT 接腳落在同一條 I²C 3 匯流排上——ESLOV 接腳配置請參閱上方的 ESLOV 接頭。
同樣的硬體也可透過 machine.I2CTarget 以目標(從屬)模式使用,以向另一個 I²C 控制器公開一塊記憶體區域:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(3, addr=0x42, mem=buf)
SPI¶
匯流排 |
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 在 A0–A7 上公開了八個 12 位元的 ADC 通道。全部皆以 3.3 V 為參考——read_u16 會在接腳的 0–3.3 V 範圍內回傳 0–65535:
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¶
透過 pyb.DAC 在 DAC1(A6 / D21)上公開了單一個 12 位元的 DAC 通道:
from pyb import DAC
dac = DAC("DAC1")
dac.write(int(0.5 * 255)) # 8‑bit output, ~1.65 V
PWM¶
接腳 |
計時器 / 通道 |
|---|---|
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 |
透過 machine.PWM 驅動其中任一個:
from machine import Pin, PWM
pwm = PWM(Pin("D4"), freq=1_000, duty_u16=32768)
備註
有數個接腳共用計時器通道:
TIM1 CH1 同時位於
D1和D6上。TIM1 CH2 同時位於
D2和D14上。TIM8 CH3N 同時位於
D0和D1上。
每個計時器通道請只挑選一個使用者。
警告
當 Vision Shield 透過 csi --- 相機感測器 初始化時,TIM1 會保留作為 相機主時脈——在相機作用期間,D1、D2、D6、D13 與 D14 無法被 PWM 驅動。
軟體位元觸發匯流排¶
若你需要額外的匯流排,machine.SoftI2C 與 machine.SoftSPI 可在任何 GPIO 上運作。
熱感測器(板外)¶
韌體內含 fir --- 熱感測器驅動程式 (fir == far infrared,遠紅外線) 驅動程式,供外部接線的熱成像儀使用:
MLX90621——16 × 4 紅外線陣列
MLX90640——32 × 24 紅外線陣列
MLX90641——16 × 12 紅外線陣列
AMG8833——8 × 8 紅外線陣列
將模組接線至板子的 I²C 匯流排,並以 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())
fir 驅動程式僅透過 I²C 3 與感測器通訊——請將模組接線至 D12(SCL)與 D11(SDA)。
時序¶
time¶
time 模組涵蓋阻塞式延遲、單調遞增刻度(monotonic ticks)以及經過時間量測:
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)
虛擬計時器¶
machine.Timer 可排程週期性或單次的回呼函式,而不會佔用硬體計時器插槽。將 -1 作為 id 傳入即可使用虛擬(軟體)計時器:
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"))
週期值的單位為毫秒。呼叫 deinit() 以停止並釋放該插槽。
即時時鐘¶
machine.RTC 會在重置間維持掛鐘時間。HD 接頭也公開了一個 COINCELL 接點,可在斷電期間以 CR2032 為 RTC 供電:
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())
看門狗¶
machine.WDT 會在應用程式當機時重置板子。一旦啟動,它便無法停止或重新設定——請在你的主迴圈內定期餵食它:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
開機與執行階段資訊¶
韌體更新(DFU)¶
Portenta H7 使用 Arduino 標準的 連按兩次重置(double‑tap reset) 來進入 Arduino 的開機載入程式。快速按下重置按鈕兩次——板子會以 DFU 裝置的身分透過 USB 重新列舉,OpenMV IDE 即可燒錄新的韌體映像。
執行中的指令碼可透過呼叫 machine.bootloader() 隨需重新進入開機載入程式:
import machine
machine.bootloader()
檔案系統與開機順序¶
Portenta H7 韌體在開機時最多會掛載三個檔案系統:
內部 flash——一律掛載於
/flash。預設保存main.py與README.txt;在最初的第一次開機時建立。microSD 卡——若接上了 Vision Shield 且插入了卡片,便會掛載於
/sdcard。ROMFS——唯讀、記憶體映射的檔案系統,位於
/rom,由 MicroPython 在啟動時自動掛載。
掛載後,工作目錄會在卡片存在時設為 /sdcard,否則為 /flash。直譯器接著會從該目錄執行指令碼:
boot.py會在 每一次 軟重置時執行(冷開機、從 REPL 按Ctrl‑D,或每當執行中的指令碼返回時)。main.py僅在冷開機時 執行,緊接在boot.py之後。後續的軟重置會重新執行boot.py,但會直接落到 REPL——若要重新執行main.py,你必須完整地重置板子。
將 boot.py 或 main.py 放入 SD 卡會覆蓋 flash 中的副本而不會更動到它——這兩個檔案都會在開機目錄中查找(卡片掛載時為 /sdcard,否則為 /flash)。
剛燒錄完的板子上隨附的預設 main.py 僅會閃爍使用者 RGB LED 的 藍色 通道作為心跳指示(兩次短脈衝、一段短間隔),讓你即使未連接任何主機也能得知韌體已乾淨地開機。
sys.path 經過擴充以納入全部三個檔案系統及其 lib/ 子目錄,因此可匯入的模組可以放在 /flash/lib、/sdcard/lib 或 /rom/lib 中。
若要強制系統忽略已插入的 SD 卡(例如即使有卡片存在也要執行 flash 中的 main.py),請在 /flash 的根目錄建立一個名為 SKIPSD 的空檔案。
透過 USB 連接時,開機檔案系統(有卡片時為 /sdcard,否則為 /flash)也會在主機上列舉為一個 USB 大容量儲存裝置磁碟機,讓你可以直接編輯 boot.py、main.py 及任何其他檔案。在重置板子前請先退出磁碟機,好讓主機清空其快取的寫入。
備註
由於作業系統將該磁碟機視為被動式區塊裝置,由相機上執行的程式所建立或修改的檔案在主機重新掛載磁碟機之前不會顯示出來。若作業系統與相機同時寫入同一個檔案系統,作業系統會勝出並覆蓋掉相機所做的變更。對於指令碼寫回的任何資料請使用 SD 卡,並在從主機讀取那些檔案前先重新掛載。
備註
當主機正在從 USB 大容量儲存裝置磁碟機讀取或對其寫入時,使用者 RGB LED 的 紅色 通道可能會短暫亮起——這是韌體驅動的活動指示,並非故障。
儲存容量¶
Portenta H7 出貨時配備:
/flash——11 MB FAT 檔案系統,可讀寫。/rom——4 MB 唯讀的記憶體映射 ROMFS,用於隨附那些受益於零複製 mmap 存取的指令碼與 ML 模型。/sdcard——插入 Vision Shield 的任何 microSD 卡的完整容量(在有卡片時),可讀寫。
硬性錯誤指示¶
若使用者 RGB LED 正快速地循環顯示所有色彩——快到看起來往往像是一顆 閃爍的白色 LED 而非個別的色相——則表示韌體遇到了無法復原的硬性錯誤(hard fault)。請重新燒錄韌體以復原;若重新燒錄沒有幫助,板子可能已實體損壞。
軟體程式庫¶
完整的模組清單——包括哪些是 Portenta H7 版本所獨有的——請參閱 程式庫索引。