Arduino Portenta H7¶
Arduino Portenta H7 — это промышленная плата для разработки размером 66 × 25 мм, построенная на базе STMicroelectronics STM32H747XI — двухъядерной SoC, объединяющей Cortex‑M7 на частоте 400 МГц с Cortex‑M4 на частоте 200 МГц. Прошивка OpenMV полностью выполняется на ядре M7 и предназначена для использования с Portenta Vision Shield (версия Ethernet или LoRa), который добавляет к базовому Portenta H7 камеру Himax HM01B0 / HM0360, два PDM-микрофона и слот microSD.
Полную техническую документацию, фотографии и размеры см. на странице продукта Arduino Portenta H7.
Основные характеристики¶
STMicroelectronics STM32H747XI — двойной Cortex‑M7 (400 МГц) + Cortex‑M4 (200 МГц). Прошивка OpenMV выполняется только на ядре M7; ядро M4 доступно через openamp для межпроцессорного взаимодействия.
8 МБ внешней SDRAM плюс 2 МБ встроенной флеш-памяти и 16 МБ внешней флеш-памяти QSPI.
Аппаратный кодер/декодер JPEG.
Wi‑Fi b/g/n (2,4 ГГц) + Bluetooth LE 5.1 через модуль Murata 1DX (CYW4343W) — подключается к прилагаемой антенне через установленный на плате разъём U.FL.
Высокоскоростной USB‑C (480 Мбит/с).
22 пользовательских вывода ввода-вывода на верхних разъёмах в стиле Arduino MKR — D0–D14 (цифровые) плюс A0–A6 (аналоговые).
Два 80‑контактных высокоплотных разъёма на нижней стороне открывают полную структуру STM32H747 — DCMI, DSI, Ethernet RMII, FDCAN, SDIO, SAI/I²S, UART, дополнительные SPI/I²C/таймеры и так далее. Шилды, такие как Vision Shield, подключаются к этим разъёмам.
JTAG / SWD выведены на нижние HD-разъёмы для продвинутой отладки.
Поддержка аккумулятора — разъём JST для 3,7 В Li‑Po плюс установленные на плате зарядное устройство и монитор аккумулятора.
Распиновка¶
Справочник по выводам¶
22 пользовательских вывода выведены на верхние краевые разъёмы в стиле Arduino MKR — 15 цифровых (D0-D14) плюс 7 аналоговых (A0-A6). Гораздо больше выводов SoC доступны через нижние 80‑контактные высокоплотные разъёмы для работы с шилдами; это сопоставление см. в полном PDF с распиновкой от Arduino.
Имя вывода |
Обозначение |
Функция |
|---|---|---|
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_GREEN |
3.3 V |
зелёный канал RGB-светодиода (активный низкий уровень) |
LED_BLUE |
3.3 V |
синий канал RGB-светодиода (активный низкий уровень) |
Примечание
A0-A3 — это только аналоговые контактные площадки на STM32H747 без функции GPIO; рассматривайте их исключительно как входы ADC. A2/A4 и A3/A5 делят свои физические выводы с D10 и D8 соответственно, поэтому вы не можете управлять PWM или SPI на них, считывая их как аналоговые. A7 находится на нижних HD-разъёмах.
Выводы питания¶
Выводы разъёма MKR:
VIN — основная системная шина, ведущая к установленному на плате PMIC. Питается через диод от шины
+5V, выводаVINразъёма MKR или нижних 80‑контактных HD-разъёмов.+5V — шина 5 В, питаемая от USB, разъёма ESLOV или самого вывода
+5Vразъёма MKR.+3V3 — основная шина 3,3 В (выход импульсного регулятора PMIC).
AREF — опорное аналоговое напряжение для выводов ADC. По умолчанию 3,3 В; подайте внешнее напряжение для использования другого опорного значения.
GND — общая земля.
Вход аккумулятора:
Li‑Po JST на передней стороне платы принимает элемент Li‑Po на 3,7 В. PMIC заряжает его всякий раз, когда присутствует
+5VилиVIN.
Portenta H7 можно запитать любым из следующих способов:
USB‑C — подаёт 5 В на установленный на плате PMIC.
Разъём ESLOV — до 5 В на
VESLOV(см. Разъём ESLOV).Вывод VIN — подайте напрямую стабилизированное напряжение 5 В.
Аккумулятор Li‑Po — подключите к разъёму JST на передней стороне.
Разъём ESLOV¶
На боковой стороне платы находится 5‑контактный беспаечный разъём ESLOV:
Вывод |
Имя |
Функция |
|---|---|---|
1 |
VESLOV |
выход питания 5 В (та же шина, что и |
2 |
INT |
вход внешнего прерывания на |
3 |
SCL_EXT |
общий с контактной площадкой |
4 |
SDA_EXT |
общий с контактной площадкой |
5 |
GND |
общая земля |
SCL_EXT/SDA_EXT разъёма ESLOV и D12/D11 разъёма MKR — это одни и те же выводы: одна шина I²C 3, выведенная на два разъёма.
Совет
Используйте оценщик времени работы от аккумулятора, чтобы смоделировать, как долго Portenta H7 будет работать от аккумулятора при заданном рабочем цикле активность / глубокий сон.
Выводы восстановления и отладки¶
RESET — это и выведенный вывод на верхнем разъёме, и кнопка без фиксации на боковой стороне платы, подключённые к линии NRST SoC. Подтяните к GND или нажмите кнопку для сброса.
Portenta H7 использует стандартный для Arduino двойной сброс для входа в загрузчик Arduino. Быстро нажмите кнопку сброса дважды — плата заново перечислится по USB как устройство DFU, и OpenMV IDE сможет прошить новый образ прошивки.
Сигналы SWD STM32 выведены на нижний HD-разъём J1:
J1‑73— NRSTJ1‑75— SWDIO (PA13)J1‑77— SWCLK (PA14)J1‑79— SWO (PB3)
Подключите их через Portenta Breakout, официальный отладочный адаптер Arduino или специальную плату-носитель с разъёмом 1,27 мм. Все отладочные сигналы имеют опорный уровень 3,3 В.
Примечание
Когда подключён Portenta Vision Shield, те же сигналы SWD/JTAG направляются на стандартный 20‑контактный разъём JTAG для отладки ARM Cortex на шилде (шаг 1,27 мм / 0,05″).
Периферия на плате¶
Светодиоды¶
Portenta H7 имеет один пользовательский RGB-светодиод, управляемый программно через machine.LED:
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
Отдельный оранжевый светодиод зарядки рядом с разъёмом JST аккумулятора загорается, когда установленное на плате зарядное устройство подаёт ток в подключённый Li‑Po; он не управляется пользователем.
Датчик камеры (Vision Shield)¶
При подключённом Portenta Vision Shield (версия Ethernet или 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 — Машинное обучение запускает квантованные модели TFLite на Cortex‑M7 с ядрами CMSIS‑NN — достаточно быстро для компактных детекторов с несколькими кадрами в секунду. Модели в файловой системе только для чтения /rom загружаются непосредственно из флеш-памяти без копирования в RAM. Вот детектор BlazeFace 128×128, накладывающий обнаруженное лицо и его шесть опорных точек на каждый кадр с камеры 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 — Модуль Audio по периферии SAI4 STM32. Каждый буфер поступает в виде знакового 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
Передайте channels=2 в audio.init для получения чередующихся сэмплов с обоих микрофонов.
Индикатор заряда аккумулятора¶
Индикатор заряда 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 — только когда ток положительный.
Микросхема управления питанием¶
PMIC NXP PF1550 управляет каждым регулятором на Portenta H7 — основной шиной +3V3, шиной ядра / ввода-вывода SoC +1V8 и зарядным устройством Li‑Po. Он находится на I²C 1 по адресу 0x08.
Предупреждение
Чтение регистров PMIC безопасно; запись в них опасна. Неправильная настройка понижающего регулятора или параметра зарядного устройства может необратимо повредить плату, аккумулятор или оба. Относитесь к PMIC как к доступному только для чтения, если только вы точно не знаете, что делаете.
Самое полезное, что PMIC может сообщить, а индикатор заряда — нет, это конечный автомат зарядного устройства — работает ли плата в данный момент от USB / ESLOV / VIN, на какой стадии цикла зарядки находится Li‑Po и находится ли зарядное устройство в состоянии теплового или сторожевого сбоя. Регистры зарядного устройства располагаются со смещением 0x80 в основном адресном пространстве I²C PF1550 (см. §22.2 технической документации PF1550), так что, например, CHG_INT_OK по адресу зарядного устройства 0x04 считывается из регистра 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 (многобитное состояние VBUS, включая OVLO / UVLO / DPM) и 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)¶
Версия LoRa Vision Shield добавляет модуль LoRaWAN Murata CMWX1ZZABZ, подключённый к Portenta H7 по UART. Модуль 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 и т. д. для регионов за пределами ЕС и переключитесь на lora.Lora.join_ABP(), если ваш сетевой сервер использует активацию ABP.
Предупреждение
Пока модуль LoRa используется, драйвер занимает следующие выводы разъёма MKR в качестве линий управления для Murata CMWX1ZZABZ — они не могут использоваться:
Вывод MKR |
Причина |
|---|---|
|
вывод BOOT модуля LoRa |
|
вывод RST модуля LoRa |
Ethernet (Vision Shield)¶
Версия Ethernet Vision Shield добавляет разъём RJ45 с трансформаторами, подключённый к 10/100 Ethernet MAC STM32H747 по RMII. Подключите кабель Ethernet, и 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 В CMOS и могут принимать/отдавать до 20 мА на вывод (140 мА суммарно по всему разъёму).
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")
Контактные площадки D11/D12 на разъёме MKR и выводы SDA_EXT/SCL_EXT разъёма ESLOV выходят на одну и ту же шину I²C 3 — см. распиновку ESLOV в Разъём ESLOV выше.
То же оборудование можно также использовать в режиме целевого устройства (slave) через 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 предоставляет восемь 12‑битных каналов ADC на A0–A7. Все имеют опорный уровень 3,3 В — read_u16 возвращает 0–65535 в диапазоне 0–3,3 В на выводе:
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¶
Один 12‑битный канал DAC предоставлен на DAC1 (A6 / D21) через pyb.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.
Выбирайте по одному потребителю на канал таймера.
Предупреждение
TIM1 зарезервирован для главного тактового сигнала камеры, когда Vision Shield инициализируется через csi — датчики камеры — 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 охватывает блокирующие задержки, монотонные тики и измерение прошедшего времени:
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, которая может питать RTC от CR2032 при потере питания:
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 двойной сброс для входа в загрузчик Arduino. Быстро нажмите кнопку сброса дважды — плата заново перечислится по USB как устройство DFU, и OpenMV IDE сможет прошить новый образ прошивки.
Выполняющийся скрипт может повторно войти в загрузчик по запросу, вызвав machine.bootloader():
import machine
machine.bootloader()
Файловая система и порядок загрузки¶
Прошивка Portenta H7 монтирует при загрузке до трёх файловых систем:
Встроенная флеш-память — всегда монтируется в
/flash. По умолчанию содержитmain.pyиREADME.txt; создаётся при самой первой загрузке.Карта microSD — если подключён Vision Shield и вставлена карта, она монтируется в
/sdcard.ROMFS — файловая система только для чтения, отображённая в память, в
/rom, монтируется автоматически MicroPython при запуске.
После монтирования рабочий каталог устанавливается в /sdcard, когда карта присутствует, иначе в /flash. Затем интерпретатор запускает скрипты из этого каталога:
boot.pyвыполняется при каждом программном сбросе (холодная загрузка,Ctrl‑Dиз REPL или всякий раз, когда выполняющийся скрипт завершается).main.pyвыполняется только при холодной загрузке, сразу послеboot.py. Последующие программные сбросы повторно запускаютboot.py, но переходят сразу к REPL — чтобы повторно запуститьmain.py, нужно полностью сбросить плату.
Размещение boot.py или main.py на SD-карте переопределяет копию во флеш-памяти, не затрагивая её — оба файла ищутся в загрузочном каталоге (/sdcard, когда карта смонтирована, иначе /flash).
Стандартный main.py, поставляемый на свежепрошитой плате, просто мигает синим каналом пользовательского RGB-светодиода в качестве сигнала работоспособности (два коротких импульса, короткая пауза), чтобы вы могли понять, что прошивка загрузилась корректно, без подключения какого-либо хоста.
sys.path расширяется, чтобы включить все три файловые системы и их подкаталоги lib/, поэтому импортируемые модули могут располагаться в /flash/lib, /sdcard/lib или /rom/lib.
Чтобы заставить систему игнорировать вставленную SD-карту (например, чтобы запустить main.py из флеш-памяти даже при наличии карты), создайте пустой файл с именем SKIPSD в корне /flash.
При подключении по USB загрузочная файловая система (/sdcard, если карта присутствует, иначе /flash) также перечисляется как USB-накопитель на хосте, позволяя вам редактировать boot.py, main.py и любые другие файлы напрямую. Извлеките накопитель перед сбросом платы, чтобы хост сбросил свои кэшированные записи.
Примечание
Поскольку ОС рассматривает накопитель как пассивное блочное устройство, файлы, созданные или изменённые кодом, выполняющимся на камере, не появятся, пока хост повторно не смонтирует накопитель. Если и ОС, и камера записывают в одну и ту же файловую систему одновременно, ОС победит и перезапишет изменения, сделанные камерой. Используйте SD-карту для любых данных, которые записывает скрипт, и повторно монтируйте перед чтением этих файлов с хоста.
Примечание
Красный канал пользовательского RGB-светодиода может кратковременно загораться, пока хост читает с USB-накопителя или записывает на него — это управляемый прошивкой индикатор активности, а не неисправность.
Размеры хранилища¶
Portenta H7 поставляется с:
/flash— файловая система FAT на 11 МБ, чтение/запись./rom— отображённая в память ROMFS на 4 МБ только для чтения, используется для поставки скриптов и моделей ML, которым выгоден доступ через mmap без копирования./sdcard— полный размер любой карты microSD, вставленной в Vision Shield (когда присутствует), чтение/запись.
Индикатор фатального сбоя¶
Если пользовательский RGB-светодиод быстро перебирает все цвета — настолько быстро, что это обычно выглядит как мерцающий белый светодиод, а не как отдельные оттенки — прошивка столкнулась с неустранимым фатальным сбоем. Перепрошейте прошивку для восстановления; если перепрошивка не помогает, плата может быть физически повреждена.
Программные библиотеки¶
См. индекс библиотек для полного списка модулей — включая те, которые уникальны для сборки Portenta H7.