Arduino Giga R1 WiFi

The Arduino Giga R1 WiFi is a 101 × 53 mm Mega‑form‑factor board built around the STMicroelectronics STM32H747XI — a dual‑core SoC combining a Cortex‑M7 at 480 MHz with a Cortex‑M4 at 240 MHz. The OpenMV firmware runs entirely on the M7 core. The Giga adds a 22‑pin Arducam camera flex connector, a MIPI‑DSI connector for the Arduino Giga Display Shield, and a 3.5 mm stereo audio jack to the standard Arduino Mega header layout.

Arduino Giga R1 WiFi

For full datasheet, photos, and dimensions see the Arduino Giga R1 WiFi product page.

Highlights

  • STMicroelectronics STM32H747XI dual Cortex‑M7 (480 MHz) + Cortex‑M4 (240 MHz). OpenMV firmware runs on the M7 core only; the M4 core is exposed through openamp for Inter‑Processor Communication.

  • 8 MB external SDRAM plus 2 MB internal flash and 16 MB external QSPI flash.

  • Hardware JPEG encoder/decoder.

  • 22‑pin Arducam‑compatible camera flex connector (J6) — driver support for OV5640 (5MP), OV7670, GC2145, HM01B0, and HM0360 sensor modules.

  • MIPI‑DSI display connector (J5) for the Arduino Giga Display Shield (480×800 capacitive touch panel) plus an LTDC RGB display engine for advanced carriers.

  • 3.5 mm audio jack with stereo line‑out and mic in.

  • Wi‑Fi b/g/n (2.4 GHz) + Bluetooth LE 5.1 via the Murata 1DX (CYW4343W) module — connects to the supplied antenna via an on‑board U.FL connector.

  • USB‑C (full‑speed) for power / serial / programming.

  • User I/O on the Mega‑style headers — D0D75 (digital), A0A11 (analog), DAC0/DAC1 (DAC outputs), CAN_RX/CAN_TX (FDCAN2), and the inner-row SDA1/SCL1 I²C pair. A separate 6‑pin SPI1 header on the front of the board breaks out CIPO/COPI/SCK (D89/D90/D91).

  • JTAG / SWD broken out on the top‑side debug header for advanced debug.

Pinout

Arduino Giga R1 WiFi Pinout

Pin reference

The Arduino Mega‑style headers expose 76 digital pins (D0D75), 12 analog pins (A0A11), two DAC outputs (DAC0/DAC1), a secondary I²C pair (SDA1/SCL1), and an FDCAN2 pair (CAN_RX/CAN_TX). A separate 6‑pin SPI1 header on the front of the board breaks out CIPO/COPI/SCK (D89/D90/D91).

Pin name

Reference

Function

D0

3.3 V

USART1 RX (Serial1) / TIM4 CH2

D1

3.3 V

USART1 TX (Serial1) / TIM1 CH2

D2

3.3 V

TIM2 CH4 / TIM5 CH4 / USART2 RX

D3

3.3 V

TIM2 CH3 / TIM5 CH3 / USART2 TX

D4

3.3 V

TIM8 CH1 / UART8 TX

D5

3.3 V

TIM3 CH2 / SPI1 MOSI / SPI6 MOSI

D6

3.3 V

TIM4 CH2

D7

3.3 V

TIM3 CH1 / SPI1 MISO / SPI3 MISO / SPI6 MISO

D8

3.3 V

TIM4 CH3 / I2C1 SCL / I2C4 SCL / UART4 RX

D9

3.3 V

TIM4 CH4 / I2C1 SDA / I2C4 SDA / UART4 TX

D10

3.3 V

TIM1 CH1 / TIM8 CH3N

D11

3.3 V

TIM8 CH2 / SPI5 MOSI

D12

3.3 V

TIM8 CH2N / SPI5 MISO

D13

3.3 V

TIM12 CH1 / SPI5 SCK

D14

3.3 V

USART6 TX (Serial2) / SPI6 MOSI

D15

3.3 V

USART6 RX (Serial2) / TIM3 CH2 / TIM8 CH2

D16

3.3 V

UART4 TX (Serial3) / TIM8 CH1N

D17

3.3 V

UART4 RX (Serial3)

D18

3.3 V

USART2 TX (Serial4)

D19

3.3 V

USART2 RX (Serial4) / SPI3 MOSI

D20

3.3 V

I2C2 SDA / TIM2 CH4 / USART3 RX

D21

3.3 V

I2C2 SCL

D22

3.3 V

GPIO

D23

3.3 V

GPIO / SPI6 SCK

D24

3.3 V

GPIO / SPI6 MISO

D25

3.3 V

GPIO

D26

3.3 V

GPIO

D27

3.3 V

GPIO

D28

3.3 V

GPIO

D29

3.3 V

GPIO

D30

3.3 V

GPIO

D31

3.3 V

GPIO

D32

3.3 V

GPIO

D33

3.3 V

GPIO

D34

3.3 V

GPIO

D35

3.3 V

GPIO

D36

3.3 V

GPIO

D37

3.3 V

TIM8 CH2

D38

3.3 V

TIM8 CH2N

D39

3.3 V

GPIO

D40

3.3 V

TIM15 CH2 / SPI4 MOSI

D41

3.3 V

GPIO

D42

3.3 V

GPIO

D43

3.3 V

GPIO

D44

3.3 V

GPIO

D45

3.3 V

GPIO

D46

3.3 V

TIM8 CH3N

D47

3.3 V

SPI3 MOSI

D48

3.3 V

TIM8 CH3 / SPI5 SCK

D49

3.3 V

GPIO

D50

3.3 V

GPIO

D51

3.3 V

TIM15 CH1 / SPI4 MISO

D52

3.3 V

GPIO

D53

3.3 V

GPIO

D54

3.3 V

TIM8 CH1 (camera DCMI VSYNC)

D55

3.3 V

I2C3 SDA (camera DCMI HSYNC)

D56

3.3 V

TIM3 CH1 / TIM13 CH1 (camera DCMI PXCLK)

D57

3.3 V

TIM8 CH1N / UART8 RX (camera master clock — TIM1 CH3)

D58

3.3 V

TIM8 CH3 (camera DCMI D7)

D59

3.3 V

TIM8 CH2 (camera DCMI D6)

D60

3.3 V

GPIO (camera DCMI D5)

D61

3.3 V

TIM8 CH2N / UART4 RX (camera DCMI D4)

D62

3.3 V

SPI1 SCK (camera DCMI D3)

D63

3.3 V

TIM5 CH2 / I2C4 SCL (display I²C)

D64

3.3 V

TIM5 CH1 (camera DCMI D1)

D65

3.3 V

TIM12 CH2 (camera DCMI D0)

D66

3.3 V

GPIO (camera reset — claimed when camera is active)

D67

3.3 V

GPIO (camera power‑down — claimed when camera is active)

D68

3.3 V

TIM3 CH1 / TIM8 CH1 / USART6 TX (Display Shield DSI RESET)

D69

3.3 V

TIM5 CH4 (Display Shield DSI TE)

D70

3.3 V

SPI2 SCK

D71

3.3 V

TIM8 CH4 / SPI2 MISO

D72

3.3 V

SPI2 MOSI

D73

3.3 V

ADC123 IN11 (Display Shield DFSDM mic data)

D74

3.3 V

GPIO (display backlight — claimed by the Giga Display Shield)

D75

3.3 V

SPI2 SCK (Display Shield DFSDM mic clock)

A0 / D76

3.3 V

ADC12 IN4

A1 / D77

3.3 V

ADC12 IN8

A2 / D78

3.3 V

ADC12 IN9 / TIM3 CH3 / TIM8 CH2N

A3 / D79

3.3 V

ADC12 IN5 / TIM3 CH4 / TIM8 CH3N

A4 / D80

3.3 V

ADC12 IN13 / SPI2 MOSI

A5 / D81

3.3 V

ADC123 IN12 / SPI2 MISO

A6 / D82

3.3 V

ADC123 IN10

A7 / D83

3.3 V

ADC1 IN16 / TIM2 CH1 / TIM5 CH1 (audio jack mic input)

A8

3.3 V

ADC3 IN0 (analog only)

A9

3.3 V

ADC3 IN1 (analog only)

A10

3.3 V

ADC12 IN1 (analog only)

A11

3.3 V

ADC12 IN0 (analog only)

DAC0 / A12 / D84

3.3 V

DAC1 OUT1 / ADC12 IN18 (audio jack line‑out L)

DAC1 / A13 / D85

3.3 V

DAC1 OUT2 / TIM2 CH1 / SPI1 SCK / ADC12 IN19 (audio jack line‑out R)

D89

3.3 V

SPI1 MISO (CIPO on the front SPI header)

D90

3.3 V

SPI1 MOSI (COPI on the front SPI header)

D91

3.3 V

SPI1 SCK (SCK on the front SPI header)

CAN_RX / D93

3.3 V

FDCAN2 RX / TIM3 CH2 / UART5 RX

CAN_TX / D94

3.3 V

FDCAN2 TX / SPI2 SCK / UART5 TX

SDA1 / D102

3.3 V

I2C4 SDA (display touch / camera control bus)

SCL1 / D101

3.3 V

I2C4 SCL (display touch / camera control bus)

RESET

3.3 V

press the on‑board RESET button or pull to GND to reset

LED_RED

3.3 V

RGB LED red channel (active low)

LED_GREEN

3.3 V

RGB LED green channel (active low)

LED_BLUE

3.3 V

RGB LED blue channel (active low)

Note

A8A11 are analog‑only pads on the STM32H747’s _C pins — they have no GPIO function and can only be read through the ADC.

Power pins

Mega header pins:

  • VIN — 6–32 V input. Powers the board through the on‑board buck regulator.

  • +5V — 5 V rail fed from USB via a diode or the on‑board buck regulator.

  • +3V3 — main 3.3 V rail.

  • IOREF — reflects the I/O voltage of the board (3.3 V).

  • AREF — analog voltage reference for the ADC pins. Defaults to 3.3 V; drive externally to use a different reference.

  • OFF — pull to GND to turn off the +3.3 V rail and shut the system down.

  • VRTC — 3.0 V coin‑cell input (3.3 V max) that keeps the on‑chip RTC running while the rest of the board is powered off.

  • GND — common ground.

The Giga R1 can be powered through any of these paths:

  • USB‑C — supplies 5 V to the on‑board buck regulator.

  • VIN pin — drive a regulated 6–32 V supply directly.

Tip

Use the battery life estimator to model how long the Giga R1 will run on a battery for a given active / deep-sleep duty cycle.

Recovery and debug pins

  • RESET — both an exposed pin on the power header and a momentary switch on the top of the board, tied to the SoC’s NRST line. Pull to GND or press the button to reset.

The Giga R1 uses Arduino’s standard double‑tap reset to enter Arduino’s bootloader. Quickly press the RESET button twice — the board re‑enumerates over USB as a DFU device and OpenMV IDE can flash a new firmware image.

If the bootloader is missing entirely, hold the BOOT0 button while pressing RESET to force the SoC into ROM bootloader mode.

The STM32 SWD signals are exposed on the 10‑pin 1.27 mm Cortex Debug header on the front of the board. Wire them up via a SEGGER J‑Link, ST‑Link, or any standard ARM JTAG/SWD probe. All debug signals are 3.3 V referenced.

Onboard peripherals

LEDs

The Giga R1 has a single user RGB LED, software‑controllable through machine.LED:

from machine import LED

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

A separate power LED on the board lights whenever the +3.3 V rail is up and is not user‑controllable.

Camera connector (J6)

J6 is a 22‑pin Arducam‑compatible camera flex connector. Plug in any of the supported sensor modules and the firmware probes them automatically through the csi — camera sensors module:

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

Supported sensors:

  • OV5640 — 5 MP colour, up to QSXGA (2592 × 1944).

  • OV7670 — 0.3 MP colour, up to VGA (640 × 480).

  • GC2145 — 2 MP colour, up to UXGA (1600 × 1200).

  • HM01B0 — 320 × 320 monochrome.

  • HM0360 — VGA (640 × 480) monochrome.

Warning

While the camera is initialised, the following Mega header pins are claimed by the firmware and cannot be used:

Pin

Reason

D54D65

DCMI data + sync signals on the camera flex connector

D57

TIM1 CH3 — camera master clock

D66

Camera reset GPIO

D67

Camera power‑down GPIO

SDA1 / SCL1

I²C 4 — shared with the camera; bus is usable but avoid the sensor’s I²C address

Machine learning

ml — Machine Learning runs quantised TFLite models on the Cortex‑M7 with CMSIS‑NN kernels — fast enough for compact detectors at a few frames per second. Models on the read‑only /rom filesystem load directly from flash without copying to RAM. Here’s a 128×128 BlazeFace detector overlaying the detected face and its six landmarks on every frame:

import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace

# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))

# 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()

    for r, score, keypoints in model.predict([img]):
        ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)
        ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))

    print(clock.fps(), "fps")

M4 core

The Cortex‑M4 core is exposed through openamp for inter‑processor communication. The OpenMV firmware runs on the M7 only; the M4 has no MicroPython runtime of its own, so using it means building a separate C firmware image and loading it from the filesystem via openamp.RemoteProc. Pre‑built example firmware that implements a virtual UART endpoint is available in the openamp_vuart repository — follow its README to 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)

In practice this support is best treated as a demonstration of the openamp interface rather than a working dual‑core platform — the M4 cannot be reset independently of the M7, so stopping the M4 forces a full system reboot.

Display (J5)

J5 is a MIPI‑DSI connector for the Arduino Giga Display Shield — a 480 × 800 capacitive touch panel built around the ST7701 panel driver and the GT911 touch controller. Both drivers ship frozen with the firmware. Use display — display driver to push framebuffers and gt911.GT911 for touch input.

The example below mirrors the camera into a portrait 800 × 480 display window and overlays each touch contact as a coloured circle:

import csi
import time
import image
import display
from gt911 import GT911
from machine import I2C

IMG_OFFSET = 80
touch_detected = False
points_colors = ((255, 0, 0), (0, 255, 0), (0, 0, 255),
                 (0, 255, 255), (255, 255, 0))

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)

lcd = display.DSIDisplay(
    framesize=display.FWVGA,
    portrait=True,
    refresh=60,
    controller=display.ST7701(),
)

# Pass pin names (not Pin objects) so the driver can flip
# the reset pin's direction during start-up.
touch = GT911(
    I2C(4, freq=400_000),
    reset_pin="D71",
    irq_pin="D70",
    touch_points=5,
    refresh_rate=240,
    reverse_x=True,
    touch_callback=lambda pin: globals().update(touch_detected=True),
)

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()

    if touch_detected:
        n, points = touch.read_points()
        for i in range(n):
            img.draw_circle(
                (points[i][0] - IMG_OFFSET,
                 points[i][1],
                 points[i][2] * 3),
                color=points_colors[points[i][3]],
                thickness=2,
            )
        touch_detected = False

    lcd.write(img, y=IMG_OFFSET, hint=image.TRANSPOSE | image.VFLIP)
    print(clock.fps())

Warning

The Giga Display Shield uses the same I²C 4 bus (SDA1/SCL1) as the camera, D74 for the LCD backlight enable, D70/D71 for the GT911 touch IRQ and reset, and D68/D69 for the DSI panel’s TE and RESET signals.

Microphone (Display Shield)

The Arduino Giga Display Shield carries a digital microphone wired to the STM32H747’s DFSDM peripheral (mic clock on D75, mic data on D73). The microphone is captured through audio — Audio Module. Each buffer arrives as signed‑16‑bit PCM bytearray, ready to feed into ulab/numpy for 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

IMU (Display Shield)

The Arduino Giga Display Shield carries a Bosch BMI270 6‑axis IMU (3D accelerometer + 3D gyroscope) on the same I²C 4 bus at address 0x68. Use the community micropython_bmi270 driver to read it:

import time
from machine import I2C
from micropython_bmi270 import bmi270

sensor = bmi270.BMI270(I2C(4, freq=400_000))
sensor.load_config_file()

while True:
    ax, ay, az = sensor.acceleration   # m/s²
    gx, gy, gz = sensor.gyro
    print(ax, ay, az, gx, gy, gz)
    time.sleep_ms(100)

The full register map is in the BMI270 datasheet.

RGB LED (Display Shield)

The Arduino Giga Display Shield carries an on‑board RGB LED driven by an ISSI IS31FL3197 3‑channel LED driver on the same I²C 4 bus. The driver’s AD pin is tied to GND, so it sits at I²C address 0x50. Use the community IS31FL3197 driver to control the LED:

from machine import I2C
from is31fl3197 import IS31FL3197

led = IS31FL3197(I2C(4, freq=400_000))
led.set_color(255, 0, 0)   # full red

The full register map is in the IS31FL3197 datasheet.

Wi‑Fi

The on‑board Murata 1DX (CYW4343W) is exposed via network — network configuration as a station interface. Connect the supplied antenna to the on‑board U.FL connector before bringing up the 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

The same Murata 1DX also exposes Bluetooth LE 5.1. Use aioble — Async BLE for asyncio‑friendly BLE — for example, advertise as a peripheral and wait for a central to connect:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="Giga-R1")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

Bus reference

GPIO

Use machine.Pin to read or drive any of the silkscreened pins. Outputs are 3.3 V CMOS and can sink/source up to 20 mA per pin (140 mA total across the whole header).

from machine import Pin

out = Pin("D2", Pin.OUT)
out.on()
out.off()
out.value(1)

inp = Pin("D3", Pin.IN, Pin.PULL_UP)
print(inp.value())

Any input pin can also fire an interrupt on edge transitions:

def handler(pin):
    print("triggered:", pin)

Pin("D3", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

Bus

TX

RX

Arduino name

UART1

D1

D0

Serial1

UART6

D14

D15

Serial2

UART4

D16

D17

Serial3

UART2

D18

D19

Serial4

from machine import UART

uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)

I²C

Bus

SCL

SDA

I2C2

D21

D20

I2C1

D8

D9

I2C4

SCL1

SDA1

from machine import I2C

i2c = I2C(2, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")

Bus 2 (D20/D21, the silkscreened SCL/SDA) is the default Arduino Wire bus. Bus 4 (SCL1/SDA1) is shared with the camera and the Giga Display Shield’s GT911 touch controller — user devices on this bus must avoid the following addresses (7‑bit):

  • 0x3C — OV5640 / GC2145

  • 0x24 — HM01B0 / HM0360

  • 0x21 — OV7670

  • 0x5D — GT911 touch controller (Giga Display Shield)

The same hardware can also be used in target (slave) mode through machine.I2CTarget to expose a memory region to another I²C controller:

from machine import I2CTarget

buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)

SPI

Bus

MOSI

MISO

SCK

SPI1

D90

D89

D91

SPI5

D11

D12

D13

SPI1 is exposed on a dedicated 6‑pin header on the front of the board. SPI5 is exposed on the silkscreened COPI/CIPO/SCK labels on D11/D12/D13.

Note

Pinout of the front 6‑pin SPI1 header (J7):

Pin

Signal

1

D89 (CIPO)

2

+5V

3

D91 (SCK)

4

D90 (COPI)

5

NRST

6

GND

from machine import SPI
from machine import Pin

spi = SPI(5, baudrate=10_000_000)
cs = Pin("D10", Pin.OUT, value=1)   # CS is not driven by the SPI peripheral

cs.value(0)
spi.write(b"hello")
cs.value(1)

CAN (FDCAN)

Bus

TX

RX

FDCAN2

D94

D93

from machine import CAN

can = CAN(2, 500_000)
can.send([0xDE, 0xAD, 0xBE, 0xEF], 0x123)
print(can.recv())

ADC

The Giga R1 exposes twelve 12‑bit ADC channels on A0–A11, all 3.3 V referencedread_u16 returns 0–65535 across 0–3.3 V at the pin. A8A11 are analog‑only _C pads with no GPIO peripheral:

from machine import ADC
import time

adc = ADC("A0")
while True:
    voltage = adc.read_u16() * 3.3 / 65535
    print(voltage)
    time.sleep_ms(100)

Note

A7 is also wired to the microphone input on the 3.5 mm TRRS audio jack — when a headset is plugged in, ADC("A7") reads the analog mic signal directly.

DAC

Two 12‑bit DAC channels are exposed on DAC0 and DAC1 through pyb.DAC. Both are wired to the 3.5 mm TRRS audio jack as the left and right line‑out channels:

from pyb import DAC

left  = DAC("DAC0")
right = DAC("DAC1")

left.write(int(0.5 * 255))    # 8‑bit, ~1.65 V
right.write(int(0.5 * 255))

PWM

Pin

Timer / channel

D0

TIM4 CH2 / TIM17 CH1N

D1

TIM1 CH2

D2

TIM2 CH4 / TIM5 CH4 / TIM15 CH2

D3

TIM2 CH3 / TIM5 CH3 / TIM15 CH1

D4

TIM1 CH3N / TIM8 CH1

D5

TIM1 CH1N / TIM3 CH2 / TIM8 CH1N / TIM14 CH1

D6

TIM4 CH2

D7

TIM3 CH1

D8

TIM4 CH3 / TIM16 CH1

D9

TIM4 CH4 / TIM17 CH1

D10

TIM1 CH1 / TIM8 CH3N

D11

TIM1 CH2N / TIM8 CH2

D12

TIM1 CH2 / TIM8 CH2N

D13

TIM12 CH1

D15

TIM3 CH2 / TIM8 CH2

D16

TIM8 CH1N

D20

TIM2 CH4

D37

TIM8 CH2

D38

TIM8 CH2N

D40

TIM15 CH2

D46

TIM8 CH3N

D48

TIM1 CH1N / TIM8 CH3

D51

TIM15 CH1

D54

TIM8 CH1

D56

TIM3 CH1 / TIM13 CH1

D57

TIM1 CH3 / TIM8 CH1N

D58

TIM8 CH3

D59

TIM8 CH2

D61

TIM8 CH2N

D63

TIM5 CH2

D64

TIM5 CH1

D65

TIM12 CH2

D68

TIM3 CH1 / TIM8 CH1

D69

TIM5 CH4

D71

TIM8 CH4

D78 / A2

TIM1 CH2N / TIM3 CH3 / TIM8 CH2N

D79 / A3

TIM1 CH3N / TIM3 CH4 / TIM8 CH3N

D83 / A7

TIM2 CH1 / TIM5 CH1

D85 / A13

TIM2 CH1 / TIM8 CH1N

Drive any of them via machine.PWM:

from machine import Pin, PWM

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

Warning

TIM1 is reserved for the camera master clock when the camera is initialised through csi — camera sensors. Pins whose only PWM function is on TIM1 — D1, D10, D11, D12 — cannot be PWM‑driven while the camera is active. The other listed pins all have non‑TIM1 alternates.

Note

Several pins share timer channels:

  • TIM2 CH4 is on D2 and D20.

  • TIM2 CH1 is on D83/A7 and D85/A13.

  • TIM3 CH1 is on D7, D56, and D68.

  • TIM3 CH2 is on D5 and D15.

  • TIM4 CH2 is on D0 and D6.

  • TIM5 CH1 is on D64 and D83/A7.

  • TIM5 CH4 is on D2 and D69.

  • TIM8 CH1 is on D4, D54, and D68.

  • TIM8 CH1N is on D5, D16, D57, and D85/A13.

  • TIM8 CH2 is on D11, D15, D37, and D59.

  • TIM8 CH2N is on D12, D38, D61, and D78/A2.

  • TIM8 CH3 is on D48 and D58.

  • TIM8 CH3N is on D10, D46, and D79/A3.

  • TIM15 CH1 is on D3 and D51.

  • TIM15 CH2 is on D2 and D40.

Pick one consumer per timer channel.

Software bit‑banged buses

machine.SoftI2C and machine.SoftSPI work on any GPIO if you need an extra bus.

Thermal sensor (off‑board)

The firmware includes the fir — thermal sensor driver (fir == far infrared) driver for externally wired thermal imagers:

  • MLX90621 — 16 × 4 IR array

  • MLX90640 — 32 × 24 IR array

  • MLX90641 — 16 × 12 IR array

  • AMG8833 — 8 × 8 IR array

Wire the module to the board’s I²C bus and read frames with 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())

The fir driver only talks to the sensor over I²C 1 — wire the module to D8 (SCL) and D9 (SDA).

Timing

time

The time module covers blocking delays, monotonic ticks, and elapsed‑time measurement:

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)

Virtual timers

machine.Timer schedules periodic or one‑shot callbacks without consuming a hardware timer slot. Pass -1 as the id to use a virtual (software) timer:

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

Period values are in milliseconds. Call deinit() to stop and release the slot.

Real‑time clock

machine.RTC keeps wall‑clock time across resets — and across full power‑off when a coin cell is connected to the VRTC pin:

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 resets the board if the application hangs. Once started it can’t be stopped or reconfigured — feed it periodically inside your main loop:

from machine import WDT

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

Boot and runtime info

Firmware update (DFU)

The Giga R1 uses Arduino’s standard double‑tap reset to enter Arduino’s bootloader. Quickly press the RESET button twice — the board re‑enumerates over USB as a DFU device and OpenMV IDE can flash a new firmware image. If the bootloader is missing entirely, hold the BOOT0 button while pressing RESET to force the SoC into ROM bootloader mode.

A running script can re‑enter the bootloader on demand by calling machine.bootloader():

import machine

machine.bootloader()

Filesystem and boot order

The Giga R1 firmware mounts up to two filesystems on boot:

  • Internal flash — always mounted at /flash. Holds main.py and README.txt by default; created on the very first boot.

  • ROMFS — read‑only, memory‑mapped filesystem at /rom mounted automatically by MicroPython at startup.

After mounting, the working directory is set to /flash. The interpreter then runs scripts from that directory:

  • boot.py is executed on every soft reset (cold boot, Ctrl‑D from the REPL, or whenever the running script returns).

  • main.py is executed only on cold boot, immediately after boot.py. Subsequent soft resets re‑run boot.py but drop straight to the REPL — to re‑run main.py you have to fully reset the board.

The default main.py shipped on a freshly flashed board just blinks the user RGB LED’s blue channel as a heartbeat (two short pulses, short gap), so you can tell the firmware booted cleanly without any host attached.

sys.path is extended to include both filesystems and their lib/ subdirectories, so importable modules can live in /flash/lib or /rom/lib.

When connected over USB, /flash also enumerates as a USB mass‑storage drive on the host, letting you edit boot.py, main.py, and any other files directly. Eject the drive before resetting the board so the host flushes its cached writes.

Note

Because the OS treats the drive as a passive block device, files created or modified by code running on the camera will not show up until the host re‑mounts the drive. If both the OS and the camera write the same filesystem at the same time, the OS will win and overwrite changes made by the camera.

Note

The user RGB LED’s red channel may briefly light up while the host is reading from or writing to the USB mass‑storage drive — this is a firmware‑driven activity indicator, not a fault.

Storage sizes

The Giga R1 ships with:

  • /flash11 MB FAT filesystem, read/write.

  • /rom4 MB read-only memory-mapped ROMFS, used to ship scripts and ML models that benefit from zero-copy mmap access.

Hard‑fault indicator

If the user RGB LED is rapidly cycling through all colours — fast enough that it tends to look like a twinkling white LED rather than distinct hues — the firmware has hit an unrecoverable hard fault. Reflash the firmware to recover; if reflashing doesn’t help, the board may be physically damaged.

Software libraries

See the library index for the full list of modules — including which ones are unique to the Giga R1 build.