# BMM350 Molecule — Hardware Reference

Compact 9-contact breakout for the Bosch BMM350 3-axis magnetometer (WLCSP). Brings out separate VDD and VDDIO rails (the BMM350 has a stricter VDD range than most Bosch parts).

- **Source:** [adom-inc/bosch-molecules/Moecule_BMM350_Bosch_V1](https://github.com/adom-inc/bosch-molecules/tree/main/Moecule_BMM350_Bosch_V1) — imported 2026-04-17 (folder name misspelled `Moecule` upstream; we preserve that on disk)
- **KiCad project:** `Moecule_BMM350_Bosch_V1.kicad_pro`
- **Wiki page:** [molecules/bmm350-bosch-v1-075000](https://wiki-ufypy5dpx93o.adom.cloud/wiki/molecules/bmm350-bosch-v1-075000)
- **Board:** 9 contacts — 4 corner mount-pins carry I²C + VDDIO, 3 side contacts carry VDD / INT / address strap, silk revision `V1: 2025-09-03`
- **IC:** BMM350 (Bosch BGA-9, 1.28 × 1.28 × 0.5 mm WLCSP, U1)

## Component summary

| Ref | Part | Function |
|---|---|---|
| U1 | BMM350 | 3-axis magnetometer |
| C1 | 2.2 µF 0805 X7R | CRST reset / reservoir cap (schematic note: *"CRST 2.2uF Recommended, X7R"*) |
| C2 | 100 nF 0402 | VDDIO decoupling |
| C3 | 100 nF 0402 | VDD decoupling |
| R5 | 10 kΩ 0402 | **Default pull-up** from +VDDIO → `/0x15` strap net (→ default address **0x15**) |

## External contact map

Positions in mm on the front copper. **Two columns:** west (X=139.8) and east (X=147.8).

### West edge

| Ref | Silk | Net | Role |
|---|---|---|---|
| MP2 | `VDDIO` | `+VDDIO` | Logic rail — 1.72–3.6 V |
| MC6 | `VDD` *(silk `y`)* | `+VDD` | **Analog rail — 1.72–1.98 V only** (tight tolerance!) |
| MC4 | `INT` | `BMM_INT` | Interrupt (push-pull or open-drain, pull-up at host if OD) |
| MP1 | `GND` | `GND` | Ground |

### East edge

| Ref | Silk | Net | Role |
|---|---|---|---|
| MP3 | `SDA` *(silk `BMM350`)* | `BMM_SDA` | I²C SDA |
| MC12 | `BMM350` | `/0x15` | Strap test-point (pulled to +VDDIO via R5) |
| MC3 | `ADSEL` | `BMM_ADSEL/0x14/0x15` | **I²C address select** — routed to U1 pin B2 |
| MC10 | `0x14` | `GND` | Strap option: bridge MC3 ↔ MC10 for 0x14 |
| MP4 | `SCK` | `BMM_SCK` | I²C SCL |

## I²C address strap

BMM350 I²C slave address is set by ADSEL at power-up:

| ADSEL tied to | I²C address |
|---|---|
| GND (bridge MC3 ↔ MC10, silk `0x14`) | 0x14 |
| +VDDIO (default — R5 pull-up to `/0x15` net) | **0x15** (demo firmware target ✓) |

Schematic text: *"ADSEL (Legacy I2C, LSB): GND = 0x14, VDDIO = 0x15."*

**Default is 0x15** — matches the firmware. Unless you intend to run it at 0x14, leave MC3 / MC10 unbridged.

### Address conflict check on the arm bus

The arm I²C bus has: BMI270 @ 0x68, BMA400 @ 0x14, BMA580 @ 0x18, **BMM350 @ 0x15** (this molecule), BHI360 @ 0x28, BHI385 @ 0x29.

If you accidentally strap BMM350 to 0x14 it will collide with the BMA400 on the same bus.

## Power

| Rail | Voltage | Source |
|---|---|---|
| VDD (analog) | 1.72–1.98 V | **1.8 V supply required** — cannot run at 3.3 V |
| VDDIO | 1.72–3.6 V | Host via MP2 (3.3 V in demo) |

This is the one molecule in the arm bus that **needs a 1.8 V rail**. The HARDWARE_CONFIG.md power plan uses the 1.8 V LDO (fed from 3.3 V) for BMV080 core + BHI360 VDD + BHI385 VDD + **BMM350 VDD**. Do not accidentally tie MC6 (silk `y` = VDD) to 3.3 V — that exceeds the BMM350 absolute maximum.

Also from schematic: *"VDDIO is 300 mV max when VDD = 0 V."* If you shut off VDD during operation, VDDIO must drop too or the chip sustains stress. Not an issue if both rails come up together and stay up.

Typical active current: 200 µA.

## Interrupt

INT (MC4) is software-configurable for data-ready, FIFO watermark, or threshold events. Output can be push-pull or open-drain; if open-drain, supply an external pull-up on the host (not present on this molecule).

## Magnetic field range

Schematic annotation: *"Max ±2000 µT: (Bx, By, Bz < 0.75 × 2400 µT)."* The BMM350's full-scale is ±2400 µT on each axis, and for linear behavior Bosch recommends staying under 2000 µT. Keep magnets / motors / ferrous tooling away from the mounted sensor.

## Wiring to the Arm RM2 I²C bus

```
BMM350 MP2 (VDDIO) ──── RM2 +3V3
BMM350 MC6  (VDD)  ──── +1.8 V rail (NOT +3V3!)
BMM350 MP1 (GND)   ──── RM2 GND
BMM350 MP3 (SDA)   ──── RM2 GPIO4 (I²C0 SDA, shared bus)
BMM350 MP4 (SCK)   ──── RM2 GPIO5 (I²C0 SCL, shared bus)
BMM350 MC4 (INT)   ──── (optional; if open-drain, needs external pull-up)
BMM350 MC3 (ADSEL) ──── (leave floating — default 0x15 via R5 pull-up)
```

## Gotchas for firmware bring-up

- **VDD is 1.8 V only.** Do not feed 3.3 V into MC6 — the BMM350 will be damaged. This is the most common wiring mistake on the arm bus.
- **Default address is 0x15** (matches firmware). Only bridge MC3↔MC10 if you explicitly want 0x14.
- **CRST cap (C1, 2.2 µF X7R)** is on-board — no external reset circuitry needed. But if you see the sensor NACKing after a brown-out, verify C1 is charging properly and the supply is stable.
- **BMM350 OTP trim + self-test** must run at init before the first measurement — already handled in `firmware/sensors/bmm350.c`.
- **No 4.7 kΩ I²C pull-ups on this board** — provided by the RM2 carrier / main arm bus.
