Arduino Portenta H7 MicroPython Cheat Sheet

Learn how to set up the Arduino Portenta H7 for OpenMV. Obtain information regarding pins and how to use OpenMV and MicroPython.

The Arduino Portenta H7
The Arduino Portenta H7

Goals

This article is a collection of mini-guides and API calls that can help you get started with the Arduino Portenta H7 board. You can also visit the documentation product page for more in-depth tutorials.

Core

The Portenta H7 uses the Arduino Mbed OS Portenta Boards core.

Installation

OpenMV

Arduino supports the OpenMV build of MicroPython to be used with the Portenta H7. To install it on your board, you can check out the guide below:

Potential Issues

Sometimes the board is not detected even when the board is connected to your computer. This can be solved through the following steps:

  1. Disconnect the board from your computer by removing the USB cable.
  2. Reconnect the board to your computer.
  3. If it still doesn't show up, double-press the reset button, to activate the bootloader mode.
  4. Re-install the OpenMV firmware

Libraries

Some really useful MicroPython libraries in OpenMV are

pyb
and
machine
. Within these two libraries, there are plenty of modules that will help make MicroPython scripting easier. These libraries do not need to be downloaded, they are installed with OpenMV. They only need to be included in your script.

Pins

The below graphic shows the MKR pins available on the board. For a more detailed view that also shows the pins available through the high density connector, please visit the product page.

Pinout for the Portenta H7.
Pinout for the Portenta H7.

Pins in OpenMV

Most of the pins are referred to via their port name or their function in OpenMV. Please refer to the list below to see which function corresponds to which port on the Portenta H7.

Pin/ FunctionPort
PA0PA0
PA1PA1
PA2PA2
PA3PA3
PA4PA4
PA5PA5
PA6PA6
PA7PA7
PA8PA8
PA9PA9
PA10PA10
PA11PA11
PA12PA12
PA13PA13
PA14PA14
PA15PA15
PB0PB0
PB1PB1
PB2PB2
PB3PB3
PB4PB4
PB5PB5
PB6PB6
PB7PB7
PB8PB8
PB9PB9
PB10PB10
PB11PB11
PB12PB12
PB13PB13
PB14PB14
PB15PB15
PC0PC0
PC1PC1
PC2PC2
PC3PC3
PC4PC4
PC5PC5
PC6PC6
PC7PC7
PC8PC8
PC9PC9
PC10PC10
PC11PC11
PC12PC12
PC13PC13
PC14PC14
PC15PC15
PD0PD0
PD1PD1
PD2PD2
PD3PD3
PD4PD4
PD5PD5
PD6PD6
PD7PD7
PD8PD8
PD9PD9
PD10PD10
PD11PD11
PD12PD12
PD13PD13
PD14PD14
PD15PD15
PE0PE0
PE1PE1
PE2PE2
PE3PE3
PE4PE4
PE5PE5
PE6PE6
PE7PE7
PE8PE8
PE9PE9
PE10PE10
PE11PE11
PE12PE12
PE13PE13
PE14PE14
PE15PE15
PF0PF0
PF1PF1
PF2PF2
PF3PF3
PF4PF4
PF5PF5
PF6PF6
PF7PF7
PF8PF8
PF9PF9
PF10PF10
PF11PF11
PF12PF12
PF13PF13
PF14PF14
PF15PF15
PG0PG0
PG1PG1
PG2PG2
PG3PG3
PG4PG4
PG5PG5
PG6PG6
PG7PG7
PG8PG8
PG9PG9
PG10PG10
PG11PG11
PG12PG12
PG13PG13
PG14PG14
PG15PG15
PH0PH0
PH1PH1
PH2PH2
PH3PH3
PH4PH4
PH5PH5
PH6PH6
PH7PH7
PH8PH8
PH9PH9
PH10PH10
PH11PH11
PH12PH12
PH13PH13
PH14PH14
PH15PH15
PI0PI0
PI1PI1
PI2PI2
PI3PI3
PI4PI4
PI5PI5
PI6PI6
PI7PI7
PI8PI8
PI9PI9
PI10PI10
PI11PI11
PI12PI12
PI13PI13
PI14PI14
PI15PI15
PJ0PJ0
PJ1PJ1
PJ2PJ2
PJ3PJ3
PJ4PJ4
PJ5PJ5
PJ6PJ6
PJ7PJ7
PJ8PJ8
PJ9PJ9
PJ10PJ10
PJ11PJ11
PJ12PJ12
PJ13PJ13
PJ14PJ14
PJ15PJ15
PK0PK0
PK1PK1
PK2PK2
PK3PK3
PK4PK4
PK5PK5
PK6PK6
PK7PK7
UART1_TXPA9
UART1_RXPA10
UART4_TXPA0
UART4_RXPI9
UART6_TXPG14
UART6_RXPG9
UART8_TXPJ8
UART8_RXPJ9
ETH_RMII_REF_CLKPA1
ETH_MDIOPA2
ETH_RMII_CRS_DVPA7
ETH_MDCPC1
ETH_RMII_RXD0PC4
ETH_RMII_RXD1PC5
ETH_RMII_TX_ENPG11
ETH_RMII_TXD0PG13
ETH_RMII_TXD1PG12
USB_HS_CLKPA5
USB_HS_STPPC0
USB_HS_NXTPH4
USB_HS_DIRPI11
USB_HS_D0PA3
USB_HS_D1PB0
USB_HS_D2PB1
USB_HS_D3PB10
USB_HS_D4PB11
USB_HS_D5PB12
USB_HS_D6PB13
USB_HS_D7PB5
USB_HS_RSTPJ4
USB_DMPA11
USB_DPPA12
BOOT0BOOT0
DAC1PA4
DAC2PA5
LEDRPK5
LEDGPK6
LEDBPK7
I2C1_SDAPB7
I2C1_SCLPB6
I2C3_SDAPH8
I2C3_SCLPH7
-WL_REG_ONPJ1
-WL_HOST_WAKEPJ5
-WL_SDIO_0PC8
-WL_SDIO_1PC9
-WL_SDIO_2PC10
-WL_SDIO_3PC11
-WL_SDIO_CMDPD2
-WL_SDIO_CLKPC12
-BT_RXDPF6
-BT_TXDPA15
-BT_CTSPF9
-BT_RTSPF8
-BT_REG_ONPJ12
-BT_HOST_WAKEPJ13
-BT_DEV_WAKEPJ14
-QSPI2_CSPG6
-QSPI2_CLKPF10
-QSPI2_D0PD11
-QSPI2_D1PD12
-QSPI2_D2PF7
-QSPI2_D3PD13

I/O Pins

To access the I/O pins, you can use the

Pin
module from the
pyb
library.

1from pyb import Pin

To reference a pin on the Portenta, you can use the

Pin()
constructor. The first argument you have to provide is the pin you want to use. The second parameter,
mode
, can be set as:
Pin.IN
,
Pin.OUT_PP
,
Pin.OUT_OD
,
Pin.AF_PP
,
Pin.AF_OD
or
Pin.ANALOG
. An explanation of the pin modes can be found here. The third parameter,
pull
, represents the pull mode. It can be set to:
Pin.PULL_NONE
,
Pin.PULL_UP
or
Pin.PULL_DOWN
. E.g.:

1pin0 = Pin('P0', mode, pull)

To get the logic level of a pin, call

.value()
. It will return a 0 or a 1. This corresponds to
LOW
and
HIGH
in Arduino terminology.

1pin0.value()

PWM

To use PWM, you import the

pyb
,
time
,
Pin
,
Timer
modules.

1import pyb
2import time
3from pyb import Pin, Timer

First you need to choose the pin you want to use PWM with.

1pin1 = Pin("PC6", Pin.OUT_PP, Pin.PULL_NONE)

Create a timer for the PWM, where you set the ID and the frequency.

1timer1 = Timer(3, freq=1000)

Then you need to start a PWM channel with the timer object.

1channel1 = timer1.channel(1, Timer.PWM, pin=pin1, pulse_width=0)

Get or set the pulse width value on a channel. To get, pass no arguments. To set, give a value as an argument.

1channel1.pulse_width(Width)

RGB LED

The Portenta H7 has built-in RGB that can be used as feedback for applications. Using the

pyb
library, you can easily define the different LED colors on the Portenta.

For this you will use the

pyb
library.

1import pyb

Now you can easily define the different colors of the built in LED.

1redLED = pyb.LED(1)
2greenLED = pyb.LED(2)
3blueLED = pyb.LED(3)

And then control them in our script.

1redLED.on()
2redLED.off()
3
4greenLED.on()
5greenLED.off()
6
7blueLED.on()
8blueLED.off()

You could also set a custom intensity for our LED lights. This ranges between the values 0 (off) and 255 (full on). Below you can see an example of how to set the intensity on our different LED lights.

1redLED.intensity(128)
2greenLED.intensity(64)
3blueLED.intensity(50)

If no argument is given in the

.intensity()
function, it will return the LED intensity.

Communication

Like other Arduino® products, the Portenta H7 features dedicated pins for different protocols.

SPI

The pins used for SPI on the Portenta H7 are the following:

PinFunction
PI0CS
PC3COPI
PI1CK
PC2CIPO

You can refer to the pinout above to find them on the board.

First, you have to import the relevant module from

pyb
.

1from pyb import SPI

When you initialize SPI, the only thing you need to state is the bus, which will always be

2
on the Portenta H7; this is the only available bus. The rest of the arguments are optional. But if it is needed, you can state the mode of the SPI device as either
SPI.MASTER
or
SPI.SLAVE
, you can also manually set the
baudrate
of the device.
Polarity
can be set to 0 or 1, and is the logic level the idle clock line sits at (HIGH or LOW).
Phase
can be 0 or 1 to sample data on the first (0) or second (1) clock edge.

1spi = SPI(2, SPI.MASTER, baudrate=100000, polarity=0, phase=0)

Now, if you want to send data over SPI, you simply call

.send()
inside the arguments you want to send.
data
is the data to send, which could be an integer (dataInt) or a buffer object (dataBuffer). It is optional to set the
timeout
, it indicates the timeout in milliseconds to wait for the send.

1dataInt = 21
2dataBuffer = bytearray(4)
3spi.send(data, timeout=5000)

Similarly, if you want to receive data over SPI, you call

.recv()
.
data
indicates the number of bytes to receive, this can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes. It is optional to set the
timeout
, which is the time in milliseconds to wait for the receive.

1dataInt = 0
2dataBuffer = bytearray(4)
3SPI.recv(data, timeout=5000)

I2C

The pins used for I2C (Inter-Integrated Circuit) on the Portenta H7 are the following:

PinFunction
PH8SDA
PH7SCL

You can refer to the pinout above to find them on the board.

To use the I2C, you import the relevant module.

1from pyb import I2C

You can now create the I2C object. To create an I2C object you need to state the bus, this indicates what pins you will use for I2C. Giving bus a value of

3
starts I2C on the SCL and SDA pins on the Portenta H7. There are 4 I2C buses on the Portenta H7.

1i2c = I2C(3)

Now that the object is created, you can initialize it. You need to decide if your device is going to be a controller (I2C.MASTER) or a reader (I2C.SLAVE). If it is a reader device, you also need to set the

address
. You can then set a baudrate if you need to.

1i2c.init(I2C.MASTER, addr=address, baudrate=100000)

To receive data on the bus, you call the

.recv()
function. In the functions arguments
data
is the number of bytes to receive, it can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes.
addr
is the address to receive from, this is only required in controller mode.
timeout
indicates how many milliseconds to wait for the receive. The code below shows how to receive and print your data in the OpenMV serial terminal.

1dataInt = 0
2dataBuffer = bytearray(4)
3receivedData = i2c.recv(data, addr=0, timeout=5000)
4Print(receivedData)

To send data on the bus, you can call the

.send()
function. In the functions arguments
data
is the data to send, an integer (dataInt) or a buffer object (dataBuffer).
addr
is the address to send to, this is only required in controller mode.
timeout
indicates how many milliseconds to wait for the send.

1dataInt = 412
2dataBuffer = bytearray(4)
3i2c.send(data, addr=0, timeout=5000)

If you need to make sure that devices are connected to the I2C bus, you can use the

.scan()
function. It will scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. It only works when in controller mode.

1i2c.scan()

UART

The pins used for UART on the Portenta H7 are the following:

PinFunction
PA10RX
PA9TX

You can refer to the pinout above to find them on the board.

To use the UART, you need to import the relevant module.

1from pyb import UART

To create the UART object, you need to indicate the UART bus, the Portenta has 3 UART buses, but there is only on UART bus available to use with OpenMV through the boards pins.

1uart = UART(1)

With the object created, you can initialize it with

init
. When initilazing, you can set the
baudrate
.
bits
is the number of bits per character (7, 8 or 9).
parity
can be set to
None
,
0
(even) or
1
(odd).
stop
is the number of stop bits, 1 or 2.
flow
sets the flow control type, can be 0, UART.RTS, UART.CTS or UART.RTS | UART.CTS. More information on this can be found here.
timeout
is the time in milliseconds to wait for writing/reading the first character.
timeout_char
is the timeout in milliseconds to wait between characters while writing or reading.
read_buf_len
is the character length of the read buffer (0 to disable).

1uart.init(baudrate, bits=8, parity=None, stop=1, timeout=0, flow=0, timeout_char=0, read_buf_len=64)

To read from UART, you can call

.read()
. If
bytes
is specified then read at most that many bytes. If
bytes
is not given then the method reads as much data as possible. It returns after the timeout has elapsed. The example code below will read bytes received through uart into an array and then print it in the serial terminal.

1array = bytearray(5)
2uart.read(array)
3print(array)

If you intend to write over UART, you can call

.write()
. The function writes
buffer
of bytes to the bus. If characters are 7 or 8 bits wide then each byte is one character. If characters are 9 bits wide then two bytes are used for each character and
buffer
must contain an even number of bytes.

1uart.write(buffer)

WIFI

To use Wi-Fi you first need to import the relevant library.

1import network

Then you need to define the Wi-Fi networks SSID and put that in a variable. You must do the same for the networks password.

1SSID=''
2PASSWORD=''

Next, you can create a WLAN network interface object. In the argument you can enter

network.STA_IF
, which indicates that your device will be a client and connect to a Wi-Fi access point.

1wlan = network.WLAN(network.STA_IF)

To activate the network interface, you can simply call

.activate
with the argument
True
.

1wlan.active(True)

Now you can decide which network to connect to. Here it is where the

SSID
and
PASSWORD
variables come in handy.

1wlan.connect(SSID, PASSWORD, timeout=30000)

If you need to troubleshoot, the connection

.status()
can be used. This function will return a value that describes the connection status. It will also let you know what went wrong with the connection in case it failed.

1wlan.status()

Audio

If you want to use audio with the Portenta H7, you first need to include the

audio
module. Another helpful module is
micro_speech
, this runs Google's TensorFlow Lite for Microcontrollers Micro Speech framework for voice recognition.

1import audio, micro_speech

Next you need to initialize the audio object. In the initialization you can decide how many

channels
to use, it is possible to use either 1 or 2 channels. Frequency decides the sample frequency. Using a higher sample frequency results in a higher noise flow, meaning less effective bits per sample. By default audio samples are 8-bits with 7-bits of effective dynamic range.
gain_db
sets the microphone gain to use.
highpass
is the high pass filter cut off given the target sample frequency.

1audio.init(channels=2, frequency=16000, gain_db=24, highpass=0.9883)

If you need to deinitialize the audio object, you can simply call

deint()
.

1audio.deint()

To use micro_speech, you first need to create a micro_speech object. You can create this object in the variable

speech
.

1speech = micro_speech.MicroSpeech()

Next you can start streaming audio into the

micro_speech
object, to do this you can call
audio.start_streaming()
. Here you can pass the
micro_speech
object as the argument, this will fill the object with audio samples. The MicroSpeech module will compute the FFT of the audio samples and keep a sliding window internally of the FFT the last 100ms or so of audio samples received as features for voice recognition.

1audio.start_streaming(speech.audio_callback)

If you need to stop the audio streaming, you can call

.stop_streaming()
.

1audio.stop_streaming()

Conclusion

This cheat sheet is written as a quick reference mainly to look up the features of this product. For a more in-depth walk though experience please have a look at the other tutorials.

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.