Arduino Portenta H7

Arduino Portenta H7 là bo mạch phát triển công nghiệp kích thước 66 × 25 mm được xây dựng xung quanh vi mạch STMicroelectronics STM32H747XI — một SoC lõi kép kết hợp Cortex‑M7 ở tốc độ 400 MHz với Cortex‑M4 ở tốc độ 200 MHz. Firmware OpenMV chạy hoàn toàn trên lõi M7 và được thiết kế để sử dụng với Portenta Vision Shield (phiên bản Ethernet hoặc LoRa), bổ sung camera Himax HM01B0 / HM0360, hai micro PDM và khe cắm microSD vào Portenta H7.

Arduino Portenta H7

Để xem datasheet đầy đủ, ảnh và kích thước, hãy truy cập trang sản phẩm Arduino Portenta H7.

Tính năng nổi bật

  • STMicroelectronics STM32H747XI lõi kép Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). Firmware OpenMV chạy trên lõi M7; lõi M4 được truy xuất qua openamp cho giao tiếp liên lõi.

  • 8 MB SDRAM ngoài cùng 2 MB flash nội16 MB flash QSPI ngoài.

  • Bộ mã hóa/giải mã JPEG phần cứng.

  • Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 qua module Murata 1DX (CYW4343W) — kết nối với ăng-ten đi kèm qua đầu nối U.FL trên bo.

  • USB‑C tốc độ cao (480 Mb/s).

  • 22 chân I/O người dùng trên các header kiểu Arduino MKR phía trên — D0–D14 (số) và A0–A6 (tương tự).

  • Hai đầu nối mật độ cao 80 chân ở phía dưới cung cấp toàn bộ tài nguyên STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UART, thêm SPI/I²C/bộ định thời, v.v. Các shield như Vision Shield kết nối qua các đầu nối này.

  • JTAG / SWD có thể truy xuất qua đầu nối HD phía dưới để debug nâng cao.

  • Hỗ trợ pin — đầu nối JST Li‑Po 3,7 V cùng bộ sạc và bộ theo dõi pin tích hợp.

Sơ đồ chân

Arduino Portenta H7 Pinout

Tham chiếu chân

22 chân người dùng được truy xuất trên các header cạnh trên kiểu Arduino MKR — 15 chân số (D0-D14) và 7 chân tương tự (A0-A6). Nhiều chân SoC hơn có sẵn qua các đầu nối mật độ cao 80 chân phía dưới cho các shield; xem tài liệu sơ đồ chân đầy đủ PDF của Arduino để biết thêm.

Tên chân

Tham chiếu

Chức năng

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 (dùng chung với A3 / A5)

D9

3.3 V

SPI2 SCK

D10

3.3 V

SPI2 MISO (dùng chung với 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 (chỉ tương tự)

A1

3.3 V

ADC12 IN1 (chỉ tương tự)

A2

3.3 V

ADC123 IN12 (chỉ tương tự; dùng chung với D10)

A3

3.3 V

ADC12 IN13 (chỉ tương tự; dùng chung với D8)

A4

3.3 V

ADC123 IN12 (dùng chung với D10)

A5

3.3 V

ADC12 IN13 (dùng chung với D8)

A6

3.3 V

DAC1 OUT1 / ADC12 IN18

A7

3.3 V

TIM3 CH1 / ADC12 IN3 (không hiển thị trên header)

D20

3.3 V

bí danh của D8 / A3 / A5

D21

3.3 V

bí danh của A6 — DAC1 OUT1

RESET

3.3 V

nhấn công tắc trên bo hoặc kéo xuống GND để reset

LED_RED

3.3 V

Kênh đỏ của LED RGB (tích cực mức thấp)

LED_GREEN

3.3 V

Kênh xanh lá của LED RGB (tích cực mức thấp)

LED_BLUE

3.3 V

Kênh xanh dương của LED RGB (tích cực mức thấp)

Ghi chú

A0-A3 là các chân chỉ tương tự trên STM32H747 không có chức năng GPIO — hãy dùng chúng chỉ là đầu vào ADC. A2/A4A3/A5 dùng chung chân vật lý với D10D8 tương ứng, vì vậy bạn không thể dùng PWM hay SPI trên đó trong khi đọc chúng dạng tương tự. A7 nằm trên các đầu nối HD phía dưới.

Chân nguồn

Các chân header MKR:

  • VIN — đường nguồn hệ thống chính vào PMIC trên bo. Được cấp qua diode từ đường +5V, chân MKR VIN, hoặc đầu nối HD 80 chân phía dưới.

  • +5V — đường 5 V được cấp từ USB, đầu nối ESLOV, hoặc chân MKR +5V.

  • +3V3 — đường 3,3 V chính (đầu ra bộ chuyển đổi switching của PMIC).

  • AREF — điện áp tham chiếu tương tự cho các chân ADC. Mặc định là 3,3 V; kết nối ngoài để dùng điện áp tham chiếu khác.

  • GND — nối đất chung.

Đầu vào pin:

  • JST Li‑Po ở mặt trước bo chấp nhận pin Li‑Po 3,7 V. PMIC sạc pin khi có +5V hoặc VIN.

Portenta H7 có thể được cấp nguồn qua bất kỳ đường nào sau đây:

  • USB‑C — cung cấp 5 V cho PMIC trên bo.

  • Đầu nối ESLOV — lên đến 5 V trên VESLOV (xem Đầu nối ESLOV).

  • Chân VIN — kết nối nguồn 5 V điều chỉnh trực tiếp.

  • Pin Li‑Po — kết nối với đầu nối JST ở mặt trước.

Đầu nối ESLOV

Ở bên cạnh bo có một đầu nối ESLOV 5 chân không cần hàn:

Chân

Tên

Chức năng

1

VESLOV

Đầu ra nguồn 5 V (cùng đường với +5V trên header MKR)

2

INT

Đầu vào ngắt ngoài trên D7

3

SCL_EXT

dùng chung với chân D12 trên header MKR — cùng bus I²C 3 với header người dùng

4

SDA_EXT

dùng chung với chân D11 trên header MKR — cùng bus I²C 3 với header người dùng

5

GND

nối đất chung

SCL_EXT/SDA_EXT của ESLOV và D12/D11 của header MKR là cùng một chân — một bus I²C 3 được hiển thị trên hai đầu nối.

Mẹo

Dùng công cụ ước tính thời lượng pin để mô phỏng thời gian hoạt động của Portenta H7 trên pin với chu kỳ hoạt động / ngủ sâu nhất định.

Chân phục hồi và debug

  • RESET — vừa là chân được truy xuất trên header phía trên vừa là công tắc nhấn tạm thời bên cạnh bo, nối với đường NRST của SoC. Kéo xuống GND hoặc nhấn nút để reset.

Portenta H7 sử dụng nhấp đôi reset chuẩn của Arduino để vào bootloader Arduino. Nhấn nút reset nhanh hai lần — bo sẽ liệt kê lại qua USB như một thiết bị DFU và OpenMV IDE có thể nạp firmware mới.

Tín hiệu SWD của STM32 được truy xuất trên đầu nối HD J1 phía dưới:

  • J1‑73 — NRST

  • J1‑75 — SWDIO (PA13)

  • J1‑77 — SWCLK (PA14)

  • J1‑79 — SWO (PB3)

Kết nối chúng qua Portenta Breakout, bộ debug chính thức của Arduino, hoặc carrier tùy chỉnh với header 1,27 mm. Tất cả tín hiệu debug đều tham chiếu 3,3 V.

Ghi chú

Khi Portenta Vision Shield được gắn vào, cùng các tín hiệu SWD/JTAG được dẫn lên header JTAG Cortex Debug ARM 20 chân chuẩn trên shield (bước 1,27 mm / 0,05″).

Ngoại vi tích hợp

LED

Portenta H7 có một LED RGB người dùng, có thể điều khiển bằng phần mềm qua machine.LED

from machine import LED

LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()

Một LED sạc màu cam riêng biệt cạnh đầu nối JST pin sáng khi bộ sạc tích hợp đang nạp dòng vào Li‑Po đã kết nối; nó không thể điều khiển bằng người dùng.

Cảm biến camera (Vision Shield)

Khi Portenta Vision Shield (phiên bản Ethernet hoặc LoRa) được gắn vào, cảm biến Himax được điều khiển qua module csi --- cảm biến 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()

Hỗ trợ hai phiên bản Vision Shield:

  • HM01B0 — 320 × 320 đơn sắc.

  • HM0360 — 640 × 480 đơn sắc.

Cảnh báo

Khi camera Vision Shield đang được khởi tạo, các chân header MKR sau bị firmware chiếm dụng và không thể sử dụng:

Chân MKR

Lý do

D1

TIM1 CH1 — xung clock chính camera

D6

TIM1 CH1 (alt) — xung clock chính camera

D11

I²C 3 SDA — dùng chung với camera; bus vẫn có thể dùng nhưng tránh địa chỉ I²C của cảm biến (0x24)

D12

I²C 3 SCL — dùng chung với camera; bus vẫn có thể dùng nhưng tránh địa chỉ I²C của cảm biến (0x24)

A6 / D21

DCMI HSYNC — cũng vô hiệu hóa DAC

A7

DCMI PXCLK

Học máy

ml --- Machine Learning chạy các mô hình TFLite lượng tử hóa trên Cortex‑M7 với các kernel CMSIS‑NN — đủ nhanh cho các bộ phát hiện nhỏ gọn ở vài khung hình mỗi giây. Các mô hình trên hệ thống tệp chỉ đọc /rom được tải trực tiếp từ flash mà không cần sao chép vào RAM. Đây là bộ phát hiện khuôn mặt BlazeFace 128×128 vẽ lớp phủ khuôn mặt và sáu điểm đặc trưng trên mỗi khung hình từ camera 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")

Lõi M4

Lõi Cortex‑M4 được truy xuất qua openamp cho giao tiếp liên lõi. Firmware OpenMV chạy chỉ trên M7; M4 không có runtime MicroPython riêng, vì vậy sử dụng nó có nghĩa là xây dựng firmware C riêng và tải từ hệ thống tệp qua openamp.RemoteProc. Firmware ví dụ dựng sẵn triển khai endpoint UART ảo có trong kho lưu trữ openamp_vuart — làm theo README của nó để build 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)

Trên thực tế, hỗ trợ này nên được coi là minh họa về giao diện openamp hơn là nền tảng lõi kép thực sự — M4 không thể reset độc lập với M7, vì vậy dừng M4 buộc khởi động lại toàn bộ hệ thống.

Micro (Vision Shield)

Vision Shield mang hai micro PDM được thu qua audio --- Mô-đun Âm thanh qua ngoại vi SAI4 của STM32. Mỗi bộ đệm đến dưới dạng PCM 16-bit có dấu bytearray, sẵn sàng đưa vào ulab/numpy để xử lý DSP — ví dụ, một bộ phát hiện độ to đơn giản:

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

Truyền channels=2 vào audio.init để nhận mẫu xen kẽ từ cả hai micro.

Đồng hồ đo pin

Đồng hồ đo ModelGauge m5 MAX17262 của Maxim theo dõi điện áp, dòng điện, nhiệt độ và trạng thái sạc của pin Li‑Po. Nó nằm trên I²C 1 tại địa chỉ 0x36.

MAX17262 có khả năng cảm biến dòng điện nội bộ, vì vậy thanh ghi dòng điện đọc trực tiếp bằng microamp mà không cần áp dụng hệ số Rsense ngoài. Đọc đồng hồ đo pin là vô hại — không có driver đi kèm, nhưng các thanh ghi được ghi lại trong datasheet MAX17262 có thể đọc trực tiếp:

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 là số bù hai: dương khi sạc, âm khi xả. TTE chỉ có nghĩa khi dòng điện âm; TTF chỉ khi dòng điện dương.

IC quản lý nguồn

PF1550 của NXP PMIC xử lý mọi bộ điều chỉnh điện áp trên Portenta H7 — đường +3V3 chính, đường lõi SoC / I/O +1V8, và bộ sạc Li‑Po. Nó nằm trên I²C 1 tại địa chỉ 0x08.

Cảnh báo

Đọc thanh ghi PMIC là an toàn; ghi vào chúng là nguy hiểm. Cấu hình sai bộ chuyển đổi buck hay cài đặt bộ sạc có thể gây hỏng vĩnh viễn bo, pin, hoặc cả hai. Hãy xem PMIC chỉ đọc trừ khi bạn biết chính xác mình đang làm gì.

Điều hữu ích nhất mà PMIC cho bạn biết mà đồng hồ đo pin không thể là máy trạng thái bộ sạc — liệu bo hiện đang chạy trên USB / ESLOV / VIN, giai đoạn nào của chu kỳ sạc Li‑Po, và liệu bộ sạc có đang ở trạng thái lỗi nhiệt hay watchdog không. Các thanh ghi bộ sạc nằm ở offset 0x80 trong không gian địa chỉ I²C chính của PF1550 (xem §22.2 của datasheet PF1550), vì vậy ví dụ CHG_INT_OK tại địa chỉ bộ sạc 0x04 được đọc từ thanh ghi 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)

Các thanh ghi chỉ đọc khác đáng xem trong datasheet (tất cả ở offset bộ sạc 0x80): 0x80 CHG_INT (các ngắt bộ sạc đã chốt — cờ lỗi), 0x86 VBUS_SNS (trạng thái VBUS nhiều bit bao gồm OVLO / UVLO / DPM), và 0x88 BATT_SNS (trạng thái hiện diện pin và quá dòng).

Wi‑Fi

Murata 1DX (CYW4343W) tích hợp trên bo được truy xuất qua network --- cấu hình mạng như một giao diện trạm. Kết nối ăng-ten đi kèm với đầu nối U.FL trên bo trước khi bật 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

Cùng Murata 1DX cũng cung cấp Bluetooth LE 5.1. Dùng aioble --- Async BLE cho BLE thân thiện với asyncio — ví dụ, quảng bá như một ngoại vi và chờ kết nối từ thiết bị trung tâm:

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)

Phiên bản LoRa của Vision Shield thêm module LoRaWAN Murata CMWX1ZZABZ kết nối với Portenta H7 qua UART. Module lora bọc firmware lệnh AT và hỗ trợ tham gia OTAA hoặc ABP, uplink và 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()

Dùng BAND_US915 / BAND_AS923 / BAND_AU915 v.v. cho các khu vực ngoài EU, và chuyển sang lora.Lora.join_ABP() nếu máy chủ mạng của bạn sử dụng kích hoạt ABP.

Cảnh báo

Khi module LoRa đang được sử dụng, driver chiếm dụng các chân header MKR sau làm đường điều khiển cho Murata CMWX1ZZABZ — chúng không thể sử dụng:

Chân MKR

Lý do

D3

Chân BOOT của module LoRa

D5

Chân RST của module LoRa

Ethernet (Vision Shield)

Phiên bản Ethernet của Vision Shield thêm đầu nối RJ45 có biến áp cách ly kết nối với MAC Ethernet 10/100 của STM32H747 qua RMII. Cắm cáp Ethernet và PHY xuất hiện như giao diện LAN; DHCP chạy tự động khi kết nối được thiết lập:

import network
import time

lan = network.LAN()
lan.active(True)
while not lan.isconnected():
    time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])

Thẻ microSD (Vision Shield)

Khi thẻ được lắp vào, nó tự động được gắn kết tại /sdcard và có thể dùng qua hệ thống tệp thông thường:

import os

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

Tham chiếu bus

GPIO

Dùng machine.Pin để đọc hoặc điều khiển bất kỳ chân nào trên silkscreen. Đầu ra là 3,3 V CMOS và có thể nhận/cấp đến 20 mA mỗi chân (140 mA tổng cộng trên toàn bộ 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())

Bất kỳ chân đầu vào nào cũng có thể kích hoạt ngắt khi chuyển cạnh:

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

Các chân D11/D12 trên header MKR và các chân SDA_EXT/SCL_EXT của đầu nối ESLOV đều nằm trên cùng bus I²C 3 — xem Đầu nối ESLOV ở trên để biết sơ đồ chân ESLOV.

Cùng phần cứng cũng có thể được dùng ở chế độ mục tiêu (slave) qua machine.I2CTarget để hiển thị vùng bộ nhớ cho bộ điều khiển I²C khá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

Portenta H7 cung cấp tám kênh ADC 12-bit trên A0–A7. Tất cả đều tham chiếu 3,3 Vread_u16 trả về 0–65535 trên dải 0–3,3 V tại chân:

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

Một kênh DAC 12-bit duy nhất được truy xuất trên DAC1 (A6 / D21) qua pyb.DAC

from pyb import DAC

dac = DAC("DAC1")
dac.write(int(0.5 * 255))   # 8‑bit output, ~1.65 V

PWM

Chân

Bộ định thời / kênh

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

Điều khiển bất kỳ chân nào trong số đó qua machine.PWM

from machine import Pin, PWM

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

Ghi chú

Một số chân dùng chung kênh bộ định thời:

  • TIM1 CH1 nằm trên D1 D6.

  • TIM1 CH2 nằm trên D2 D14.

  • TIM8 CH3N nằm trên D0 D1.

Chọn một đối tượng duy nhất cho mỗi kênh bộ định thời.

Cảnh báo

TIM1 được dành riêng cho xung clock chính camera khi Vision Shield được khởi tạo qua csi --- cảm biến cameraD1, D2, D6, D13, và D14 không thể dùng PWM khi camera đang hoạt động.

Bus bit-bang bằng phần mềm

machine.SoftI2Cmachine.SoftSPI hoạt động trên bất kỳ GPIO nào nếu bạn cần thêm bus.

Cảm biến nhiệt (ngoài bo)

Firmware bao gồm driver fir --- trình điều khiển cảm biến nhiệt (fir == hồng ngoại xa) cho các thiết bị chụp ảnh nhiệt kết nối ngoài:

  • MLX90621 — mảng IR 16 × 4

  • MLX90640 — mảng IR 32 × 24

  • MLX90641 — mảng IR 16 × 12

  • AMG8833 — mảng IR 8 × 8

Kết nối module với bus I²C của bo và đọc khung hình bằng 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())

Driver fir chỉ giao tiếp với cảm biến qua I²C 3 — kết nối module với D12 (SCL) và D11 (SDA).

Định thời

time

Module time bao gồm trì hoãn chặn, tick đơn điệu và đo thời gian trôi qua:

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)

Bộ định thời ảo

machine.Timer lên lịch các hàm gọi lại định kỳ hoặc một lần mà không tiêu thụ khe cắm bộ định thời phần cứng. Truyền -1 làm id để dùng bộ định thời ảo (phần mềm):

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

Giá trị chu kỳ tính bằng mili giây. Gọi deinit() để dừng và giải phóng khe cắm.

Đồng hồ thời gian thực

machine.RTC giữ thời gian thực qua các lần reset. Đầu nối HD cũng có chân COINCELL có thể dự phòng RTC từ pin CR2032 khi mất nguồn:

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 bo nếu ứng dụng bị treo. Một khi đã khởi động, nó không thể dừng hay cấu hình lại — hãy feed nó định kỳ trong vòng lặp chính:

from machine import WDT

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

Thông tin khởi động và runtime

Cập nhật firmware (DFU)

Portenta H7 sử dụng nhấp đôi reset chuẩn của Arduino để vào bootloader Arduino. Nhấn nút reset nhanh hai lần — bo sẽ liệt kê lại qua USB như một thiết bị DFU và OpenMV IDE có thể nạp firmware mới.

Một tập lệnh đang chạy có thể vào lại bootloader theo yêu cầu bằng cách gọi machine.bootloader()

import machine

machine.bootloader()

Hệ thống tệp và thứ tự khởi động

Firmware Portenta H7 gắn kết tối đa ba hệ thống tệp khi khởi động:

  • Flash nội — luôn được gắn kết tại /flash. Mặc định chứa main.pyREADME.txt; được tạo trong lần khởi động đầu tiên.

  • Thẻ microSD — nếu Vision Shield được gắn và thẻ được lắp vào, nó được gắn kết tại /sdcard.

  • ROMFS — hệ thống tệp ánh xạ bộ nhớ chỉ đọc tại /rom được MicroPython gắn kết tự động khi khởi động.

Sau khi gắn kết, thư mục làm việc được đặt thành /sdcard khi có thẻ, ngược lại là /flash. Trình thông dịch sau đó chạy các tập lệnh từ thư mục đó:

  • boot.py được thực thi trong mỗi lần reset mềm (khởi động lạnh, Ctrl‑D từ REPL, hoặc khi tập lệnh đang chạy trả về).

  • main.py chỉ được thực thi khi khởi động lạnh, ngay sau boot.py. Các lần reset mềm tiếp theo chạy lại boot.py nhưng chuyển thẳng đến REPL — để chạy lại main.py bạn phải reset hoàn toàn bo.

Đặt boot.py hoặc main.py lên thẻ SD sẽ ghi đè bản sao trong flash mà không làm ảnh hưởng nó — cả hai tệp đều được tìm trong thư mục khởi động (/sdcard khi thẻ được gắn kết, ngược lại là /flash).

Tệp main.py mặc định được cài sẵn trên bo mới flash chỉ nhấp nháy kênh xanh dương của LED RGB người dùng như nhịp tim (hai xung ngắn, khoảng ngừng ngắn), để bạn biết firmware đã khởi động thành công mà không cần kết nối host.

sys.path được mở rộng để bao gồm cả ba hệ thống tệp và các thư mục con lib/ của chúng, vì vậy các module có thể nhập nằm trong /flash/lib, /sdcard/lib, hoặc /rom/lib.

Để buộc hệ thống bỏ qua thẻ SD đã lắp (ví dụ để chạy main.py trong flash ngay cả khi có thẻ), tạo một tệp rỗng tên SKIPSD ở thư mục gốc của /flash.

Khi kết nối qua USB, hệ thống tệp khởi động (/sdcard nếu có thẻ, ngược lại là /flash) cũng liệt kê như ổ đĩa lưu trữ USB trên host, cho phép bạn chỉnh sửa boot.py, main.py và các tệp khác trực tiếp. Eject ổ đĩa trước khi reset bo để host đẩy các ghi được cache.

Ghi chú

Vì hệ điều hành xử lý ổ đĩa như một thiết bị khối thụ động, các tệp được tạo hoặc sửa đổi bởi code chạy trên camera sẽ không hiển thị cho đến khi host gắn lại ổ đĩa. Nếu cả hệ điều hành và camera cùng ghi lên cùng một hệ thống tệp, hệ điều hành sẽ thắng và ghi đè các thay đổi từ camera. Dùng thẻ SD cho bất kỳ dữ liệu nào tập lệnh ghi lại, và gắn lại trước khi đọc các tệp đó từ host.

Ghi chú

Kênh đỏ của LED RGB người dùng có thể sáng thoáng trong khi host đang đọc từ hoặc ghi vào ổ đĩa lưu trữ USB — đây là chỉ báo hoạt động do firmware điều khiển, không phải lỗi.

Kích thước bộ nhớ

Portenta H7 được cung cấp kèm theo:

  • /flash — hệ thống tệp FAT 11 MB, đọc/ghi.

  • /rom — ROMFS ánh xạ bộ nhớ chỉ đọc 4 MB, dùng để cung cấp tập lệnh và mô hình ML hưởng lợi từ truy cập mmap sao chép bằng không.

  • /sdcard — toàn bộ dung lượng của thẻ microSD được lắp vào Vision Shield (khi có), đọc/ghi.

Chỉ báo hard‑fault

Nếu LED RGB người dùng đang chuyển đổi nhanh qua tất cả các màu — nhanh đến mức trông giống LED trắng nhấp nháy hơn là các màu riêng biệt — firmware đã gặp hard fault không thể phục hồi. Nạp lại firmware để khôi phục; nếu nạp lại không giúp được, bo có thể bị hỏng vật lý.

Thư viện phần mềm

Xem chỉ mục thư viện để có danh sách đầy đủ các module — bao gồm cả những module độc đáo với bản build Portenta H7.