M5Stick S3 · Volume 3

M5Stack M5StickS3 Volume 3 — Pinout and Expansion Buses

GPIO map, Hat2 16-pin top header, Grove HY2.0-4P side port, USB-C OTG, bus sharing

Contents

SectionTopic
1About this volume
2GPIO map
3Grove HY2.0-4P port (side)
· 3.1Default function — PortC UART
· 3.2Re-tasking to I²C
· 3.3Secondary I²C bus considerations
· 3.4Power rail (5V output)
4Hat2 16-pin header (top)
· 4.1Pinout (TBD pending vendor PDF)
· 4.2Signal groups
· 4.3Power budget
5USB-C OTG (side)
6SPI + I²C + I²S bus sharing
7Bus-conflict reference
8Practical wiring examples
9Resources

1. About this volume

Vol 3 documents the expansion surfaces of the M5StickS3 — every pin you can touch from outside the enclosure, every bus that’s exposed, every pin assignment you need to write Arduino/PlatformIO code that wires to external hardware.

Three expansion paths: Grove HY2.0-4P (side, primary for quick I²C / UART sensors), Hat2 16-pin (top, primary for Hat-class accessories), USB-C OTG (side, for HID + mass-storage + serial console).

Honest disclosure about depth: as of project authoring (2026-05-13), the M5StickS3 Hat2 pinout PDF from M5Stack’s docs site may not be fully published. This volume describes the intended pinout based on:

  1. M5Stack’s vendor pinout conventions for similar devices (Cardputer ADV EXT, M5Atom HAT)
  2. M5Unified library source code (which encodes the pin assignments)
  3. Community teardowns and forum discussion

Verify against actual hardware on receipt before deploying any custom firmware that depends on specific pin numbers. The functional-block-level descriptions here are accurate; specific GPIO numbers may need adjustment.


2. GPIO map

The ESP32-S3-PICO-1-N8R8 SIP exposes ~47 GPIOs externally; the M5StickS3 routes them across the internal peripherals and the external expansion buses.

Likely GPIO assignments (subject to verification on hardware via M5Unified source or vendor pinout PDF):

GPIOFunctionNotes
0BOOT buttonHold during USB plug-in for download mode
1, 2Grove TX / RX (UART default) or I²C secondary (re-tasked)Grove HY2.0-4P pins 3/4
3-4Hat2 pins or buttonsVerify
5-7Hat2 control pinsVerify against M5Unified
8, 9Primary I²C SDA / SCL (shared bus)Codec + IMU + Hat2 I²C
10Battery ADC / statusVoltage divider for battery telemetry
11, 12Hat2 spare GPIOsVerify
13IR RX photodiodeTSOP-class receiver output
14SPI MOSI (display)Shared with Hat2 SPI
15Display CSInternal — not user-routable
16, 17Display DC / RSTInternal — not user-routable
18, 19USB D-/D+Native USB peripheral
19IR TX LED drive940 nm consumer IR transmit
21IR RX (alternate position — verify)
33-38Display backlight, LCD bus auxiliaryInternal
39SPI MISO (display)Shared with Hat2 SPI
40SPI SCKShared
41-43, 46I²S audio (codec)ES8311 + AW8737 + speaker chain
ButtonsA, B, Power on dedicated GPIOs (verify)Long-press power is HW-level shutdown

Caveats:

  • Many assignments are firmware-conventional rather than hardware-fixed. The M5Unified library establishes the canonical pin → peripheral mapping; custom firmware can re-task spare GPIOs.
  • Internal-only GPIOs (display backlight, power management) are not exposed externally.
  • Specific GPIO numbers may shift between hardware revisions — verify on the production unit.

For Arduino sketches, use M5Unified named constants rather than hardcoded GPIO numbers:

#include <M5Unified.h>
M5.begin(cfg);
// M5.Display, M5.Mic, M5.Speaker, M5.Imu, M5.BtnA, M5.BtnB
// All wired internally to the correct GPIOs by M5Unified at init.

Direct GPIO usage is only needed when wiring to Hat2 / Grove peripherals or writing bare-metal ESP-IDF code.


3. Grove HY2.0-4P port (side)

3.1 Default function — PortC UART

The Grove HY2.0-4P connector on the side of the M5StickS3 follows M5Stack’s standard PortC UART convention:

Grove pinWire colorGPIO (verify)Default function
1BlackGNDGround
2Red5V boost output (USB or battery)
3WhiteGPIO 2 (likely)UART RX
4YellowGPIO 1 (likely)UART TX

Standard wiring for serial peripherals — GPS modules, RS232/RS485 adapters, modems, etc. The 5 V rail powers small peripherals directly.

3.2 Re-tasking to I²C

Firmware can re-task G1 / G2 to I²C by switching the pin mux and using a separate Wire1 instance (not the default Wire which is on G8 / G9):

#include <Wire.h>

void setup() {
    Wire1.begin(2, 1);   // SDA = G2, SCL = G1 — verify color/pin mapping
    // ... use Wire1 for Grove I²C peripherals
}

Bruce and several M5StickS3 firmwares do this for Grove I²C peripherals — PN532 NFC readers, environmental sensors, etc.

Pin-direction caveat: verify the actual SDA/SCL pin assignment with a multimeter or the M5Unified source. Grove cables follow color conventions but variants exist.

3.3 Secondary I²C bus considerations

The Grove-rebound G1 / G2 secondary I²C is completely separate from the primary I²C bus (G8 / G9):

  • Different Wire instances in Arduino — Wire1 not Wire
  • Different physical ESP32-S3 I²C peripheral — uses I²C1 not I²C0
  • No address conflicts between primary and secondary buses — a device at 0x18 on Grove is independent of the ES8311 at 0x18 on the primary bus

Pull-up resistors: add 4.7 kΩ to 3.3 V on SDA and SCL if the Grove peripheral lacks integrated pull-ups (most modern breakouts include them).

Speed: 100 kHz or 400 kHz standard. Faster (1 MHz Fast Mode Plus) works on capable chips but verify per-chip.

3.4 Power rail (5V output)

Grove pin 2 outputs 5 V sourced from USB-C (when plugged in) or from a battery boost converter (when on battery).

Budget: ~250-500 mA shared with on-board peripherals. The M5StickS3’s 5V boost is smaller than the Cardputer ADV’s — drawing too much on Grove will brownout the device. Conservative estimate:

Grove peripheral drawRisk level
< 50 mA (typical sensor)Safe
50-150 mA (some actuators)Borderline; tested OK on USB power
> 150 mARisky on battery; OK on USB
> 300 mAWill brownout regardless of USB / battery

For high-current Grove peripherals (servos, motors, high-current LEDs), use an external power supply rather than the M5StickS3’s 5V rail.

For 3.3 V-only peripherals, use a small linear regulator (AMS1117-3.3) between Grove 5V and the sensor’s VCC.


4. Hat2 16-pin header (top)

4.1 Pinout (TBD pending vendor PDF)

The Hat2 16-pin header is on top of the M5StickS3 — a 2.54 mm 2-row header (8 × 2 = 16 positions).

Likely pinout (based on M5Stack vendor conventions; verify against the M5StickS3-specific Hat2 PDF when published):

PinSignalFunction
13V33.3 V power rail (system rail)
25V5V rail (USB or battery boost)
3GNDGround
4GNDGround
5RESETHat2 reset (active-low)
6INTHat2 interrupt input
7I²C SDA (G8)Shared primary I²C
8I²C SCL (G9)Shared primary I²C
9UART TXUART2 TX (for serial Hat2 modules)
10UART RXUART2 RX
11SPI MISO (G39)Shared SPI MISO
12SPI MOSI (G14)Shared SPI MOSI
13SPI SCK (G40)Shared SPI SCK
14SPI CSHat2-specific CS
15GPIOSpare GPIO
16GPIOSpare GPIO

(Verify pinout — this is an educated guess based on M5Stack conventions, not a vendor-confirmed mapping.)

4.2 Signal groups

The Hat2 bus is organized by functional groups:

  • Power (pins 1, 2, 3, 4): 3V3 + 5V + 2× GND
  • Control bundle (pins 5, 6): RESET + INT — for SPI peripherals that need reset and interrupt
  • I²C (pins 7, 8): primary shared I²C bus
  • UART (pins 9, 10): UART for serial Hat2 modules
  • SPI (pins 11, 12, 13, 14): MISO + MOSI + SCK + dedicated CS
  • Spare GPIOs (pins 15, 16): general-purpose for custom Hat2 designs

This organization is less specialized than the Cardputer ADV’s Cap LoRa-1262-optimized EXT bus — the Hat2 is more generic, supporting a wider variety of Hat2 modules.

4.3 Power budget

RailPinBudgetNotes
3V31~100-200 mALow-current MCU-class chips
5V2~250-500 mA (shared with Grove)Higher-current actuators, RF modules
GND3, 4Multiple ground pins reduce return-path noise

Total Hat2 budget is shared with Grove and on-board peripherals. Drawing high current on Hat2 can brownout the M5StickS3 (Vol 11 § 4).

For low-current Hats (sensor breakouts, small displays, RTC modules): no issue. For high-current Hats (LoRa modules at +22 dBm TX, motor drivers, etc.): use USB-C-tethered operation.


5. USB-C OTG (side)

USB-C connector. Native ESP32-S3 USB peripheral. Two modes:

Device mode (default) — M5StickS3 is a USB peripheral to a host computer:

  • USB CDC serial (/dev/ttyACM0 on Linux, COM-N on Windows, /dev/cu.usbmodem-* on macOS)
  • USB HID keyboard / mouse (when running BadUSB firmwares)
  • USB Mass Storage (when explicitly configured)

Host mode (OTG) — with a USB-C-to-A adapter, M5StickS3 enumerates USB peripherals:

  • USB keyboards (less useful here than on Cardputer ADV due to small screen)
  • USB-to-Serial console adapters (FTDI / CH340 / CP210x / PL2303) — M5StickS3 becomes a portable serial console for field debugging
  • USB mass-storage thumb drives — read/write
  • USB MIDI controllers — feed audio codec
  • USB HID inspection — BadUSB Hunter

Mode selection at build time:

build_flags =
    -DARDUINO_USB_MODE=1                  ; Device mode (most common)
    -DARDUINO_USB_CDC_ON_BOOT=1           ; Native USB-CDC at boot
    ; OR
    -DARDUINO_USB_MODE=0                  ; Host OTG mode

Power-budget caveat: M5StickS3 in host mode has limited 5V output (~250-500 mA budget). High-current USB peripherals (USB Wi-Fi, large external HDDs) will brownout. Use a powered USB-C hub for high-current setups.


6. SPI + I²C + I²S bus sharing

The M5StickS3 hosts three buses internally + the exposed Grove/Hat2 surfaces:

SPI bus

Shared between:

PeripheralCS lineNotes
Display (ST7789P3)Internal CS on SIP packageNot user-routable
Hat2 SPI peripheralsHat2 pin 14When Hat2 modules present

Bus arbitration via chip-select discipline. Long display refreshes don’t block Hat2 SPI peripherals (different CS lines).

Primary I²C bus (G8/G9)

Shared between:

DeviceAddressNotes
ES8311 audio codec0x18Always present
IMU (BMI270 or MPU6886)0x68 (or 0x69)Always present
Hat2 I²C peripheralsvariesWhen Hat2 modules present
Grove-I²C peripherals (when Grove is in I²C mode)NO — Grove I²C is the secondary bus, not the primary

The 400 kHz bus speed handles all three peripherals comfortably. Address-scan utility: M5Unified’s Wire.beginTransmission(addr); err = Wire.endTransmission(); pattern sweeps 0x03-0x77 to discover devices.

Secondary I²C bus (G1/G2 — Grove-only)

When Grove port is re-tasked from UART to I²C (Wire1.begin(2, 1)):

  • Independent bus from primary
  • No address conflicts with primary
  • 100 kHz or 400 kHz speed

I²S audio bus

Dedicated to ES8311 codec:

  • Pins 41-43 + 46 typically
  • Sample rates 8-96 kHz, 24-bit
  • Bidirectional: MEMS mic in, speaker out

I²S is not shared with other peripherals (not enough peripheral instances on ESP32-S3 for sharing).


7. Bus-conflict reference

Compatible combinations table for typical use cases:

CombinationCompatible?Notes
Hat2 SPI peripheral + displayDifferent CS lines
Hat2 I²C device + on-board codec/IMUProvided no address collision
Hat2 I²C device at 0x18 (collides with ES8311)Same primary I²C bus
Hat2 I²C device at 0x68 (collides with IMU)Same primary I²C bus — use 0x69 alternate or different address
Grove I²C peripheral + Hat2 I²C peripheralDifferent buses (secondary vs primary)
Grove UART + Hat2 SPIIndependent peripherals
Grove UART + on-board I²C peripheralsIndependent
Grove I²C + USB-CDC consoleIndependent
Hat2 module + USB OTG hostIndependent
USB-OTG to USB-MIDI keyboard + on-board ES8311 audio outMIDI data via USB → ES8311 → speaker (same data path, no conflict)
Audio playback at full volume + Wi-Fi TXBoth high-current — risk of brownout on weak battery

For multi-functional builds: prefer Grove I²C for I²C peripherals (uses secondary bus, no primary-bus contention with on-board codec/IMU). Reserve Hat2 for higher-bandwidth modules (SPI peripherals, additional radios, accessories that need the extra GPIOs).


8. Practical wiring examples

Example A — Wiring a BME280 environmental sensor via Grove (I²C)

BME280 breakout         Grove HY2.0-4P (M5StickS3 side)
─────────────         ─────────────────────────────
VCC (3.3V)  ── via AMS1117-3.3 reg ── Red (5V)
GND         ─────────────────────── Black (GND)
SDA         ─────────────────────── White (G2)
SCL         ─────────────────────── Yellow (G1)

(Most modern BME280 breakouts have integrated pull-ups + 3.3V regulator;
 in that case wire VCC directly to Red, skip the AMS1117.)

Arduino code:
    Wire1.begin(2, 1);    // SDA=G2, SCL=G1 on Wire1
    bme.begin(0x76, &Wire1);

Example B — Wiring a PN532 NFC reader via Grove (I²C)

PN532 module            Grove HY2.0-4P
─────────────         ─────────────────
VCC (5V or 3.3V) ──── Red
GND               ──── Black
SDA               ──── White (G2)
SCL               ──── Yellow (G1)

(PN532 module DIP switches: I²C mode = Switch 0: ON, Switch 1: OFF.)

Use RFID-PN532-i2c-CARDPUTER firmware (Jojorel) or Adafruit_PN532 library
with Wire1.begin(2, 1) reroute.

Example C — Hat2 SPI peripheral (when using a custom Hat2 SD card holder)

SD card holder Hat2      M5StickS3 Hat2 header
──────────────────       ──────────────────────
VCC (3V3)        ────── Pin 1 (3V3)
GND              ────── Pin 3 or 4 (GND)
CS               ────── Pin 14 (Hat2 CS)
SCK              ────── Pin 13 (SCK)
MOSI             ────── Pin 12 (MOSI)
MISO             ────── Pin 11 (MISO)

Arduino code:
    SPI.begin(40, 39, 14);     // SCK, MISO, MOSI per Hat2 conventions
    SD.begin(14);              // CS pin

(Verify Hat2 pin numbers against actual hardware before deploying.)

Example D — Wearable battery monitor

Reading battery voltage (via internal G10 ADC):

    int raw = analogRead(10);
    float voltage = (raw / 4095.0) * 3.3 * (R1+R2)/R2;
    // For M5StickS3 voltage divider, (R1+R2)/R2 is the divider ratio.
    // Use M5.Power.getBatteryVoltage() for the M5Unified-calibrated value.

    int percent = M5.Power.getBatteryLevel();
    M5.Display.printf("Battery: %d%%", percent);

M5Unified’s M5.Power.getBatteryLevel() is calibrated for the M5StickS3’s specific voltage divider — prefer it over raw ADC reads unless you’ve calibrated the divider yourself.


9. Resources

  • M5Stack M5StickS3 pinout PDF: https://docs.m5stack.com/ (search for M5StickS3 pinout once page exists)
  • ESP32-S3 GPIO matrix: ESP32-S3 datasheet § 5
  • HY2.0-4P connector spec: JST documentation
  • M5Unified library (source of canonical GPIO mappings): https://github.com/m5stack/M5Unified
  • Cardputer ADV pinout (sibling reference): ../../../M5Stack Cardputer ADV/03-outputs/Cardputer_ADV_Complete.html Vol 3

Forward references

  • Hat + Unit ecosystem (what plugs into these buses): Vol 4
  • Custom Hat2 daughterboard design: Vol 10
  • USB-OTG BadUSB use cases: Vol 9 § 6

This is Volume 3 of a twelve-volume series. Next: Vol 4 catalogs the Hat + Unit ecosystem — what fits the M5StickS3, the family-compatibility map across M5Stack form factors.