Circuit review & bench-test guide
AXS-009 — BME280 environment sensor PMOD module
Document purpose#
This document explains the axs-009-bme280 prototype at component level and turns the design evidence into a practical manual-review and bench-test plan. It is based on the generated schematic (generate_design.py, rev 0.1-schematic), the module README, and the Bosch BME280 datasheet.
The board is a schematic-only prototype: ERC is clean (0/0), but no PCB has been laid out and no board has ever been fabricated or powered. There are no recorded bench results. Every numeric value in this guide — voltages, currents, register contents, timings, compensation results — is a verification target taken from the schematic and the manufacturer datasheet, not a measured result. Nothing below proves that an assembled board works or is safe.
1. What the board does#
The board puts a Bosch BME280 combined temperature / humidity / barometric- pressure sensor on the AruviX PMOD template (Type 6 extended, I2C). The PMOD host supplies the single 3.3 V rail. CSB is hard-wired to 3V3 so the part latches into I2C mode; SDO is the I2C address bit, driven by solder jumper JP3 (default 1-2 = GND = 0x76; 2-3 = 3V3 = 0x77). The 4.7 kΩ bus pull-ups R1/R2 sit behind solder jumpers JP1/JP2 (bridged by default) so they can be removed when another chained module provides the pull-ups. Pins 9/10 repeat SCL/SDA for daisy-chaining; pins 1/2/7/8 are NC.
The BME280 is register-compatible with the BMP280 (AXS-008) for pressure and temperature; humidity adds the ctrl_hum register, a second calibration block, and a third compensation formula — the lesson is multi-register I2C reads and heavier fixed-point arithmetic in fabric.
Functional block diagram#
PMOD host (3.3 V) axs-009-bme280
┌──────────────┐ J1
│ 3V3 ─────────┼── 6/12 ──┬───────────────┬───────────────┐
│ GND ─────────┼── 5/11 ──┼───────┐ │ │
│ │ │ │ C1,C2 JP3 2-3 (0x77)
│ SCL ─────────┼── 3/9 ───┼──┬────┼──── U1 BME280 │
│ SDA ─────────┼── 4/10 ──┼──┼─┬──┼──── (CSB=3V3, I2C) │
└──────────────┘ │ │ │ │ │ SDO ── JP3 ── GND (1-2, 0x76)
│ │ │ GND
R2 4.7k ── JP2 │ │
(3V3→SCL_PU) │ R1 4.7k ── JP1
│ (3V3→SDA_PU)
└── bus repeated on J1 pins 9/10 for chaining
2. Safety and scope boundaries#
- 3.3 V logic only. Power only from a PMOD host or a current-limited bench supply at 3.30 V. BME280 absolute maximum on any supply pin is 4.25 V and on any interface pin VDDIO + 0.3 V; the board has no protection or regulation of its own.
- Current-limit the first power-on to ≈20 mA; the sensor draws microamps when healthy.
- ESD: HBM ±2 kV; use normal precautions on the LGA-8 pads.
- The humidity element is a protected polymer film but it is still exposed through the vent: no solvents, no conformal coating over the vent, no condensing environments during bring-up (operating range is 0–100 %RH non-condensing). Storage above 65 %RH degrades it; the datasheet's reconditioning procedure applies after soldering or humid storage.
- Absolute-maximum pressure 0–20000 hPa; do not pressure-blast the vent.
- Working I2C traffic is not an accuracy claim. ±3 %RH, ±1 hPa, ±0.5 °C are datasheet figures for correctly assembled production parts; this prototype has never been assembled or measured.
3. Power and control sequence#
- The PMOD host (or bench supply) applies 3V3/GND on J1 pins 6/12 and 5/11. U1's VDD and VDDIO share the rail; C1/C2 decouple them.
#FLG01/#FLG02are ERC-only power-flag artifacts (no physical parts). - CSB tied to 3V3 selects and holds I2C mode (once CSB is ever pulled low the part locks into SPI until the next POR — tying it high removes that hazard). SDO is at GND via JP3 default → address 0x76.
- Start-up ≤2 ms to first communication (VDD > 1.58 V, VDDIO > 0.65 V). During POR the NVM calibration is copied to registers (status 0xF3 bit 0
im_update). - The device wakes in sleep mode; sleep current 0.1 µA typical. Bus idles high through R1/JP1 and R2/JP2.
- Configuration order is mandatory: write ctrl_hum (0xF2) first, then ctrl_meas (0xF4) — per datasheet §5.4.3, changes to ctrl_hum only become effective after a write to ctrl_meas. Then poll status 0xF3 or wait out the conversion, burst-read 0xF7–0xFE, and run the three compensation formulas.
4. Interfaces: PMOD pin map, jumpers, test points#
PMOD plug J1 (Type 6 extended)#
| PMOD pin | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Net | NC | NC | SCL | SDA | GND | 3V3 | NC | NC | SCL | SDA | GND | 3V3 |
Solder jumpers#
| Ref. | Function | Default | Alternative |
|---|---|---|---|
| JP1 | Connects R1 (4.7 kΩ) to SDA | Bridged (pull-up fitted) | Cut when another chained module provides the SDA pull-up |
| JP2 | Connects R2 (4.7 kΩ) to SCL | Bridged (pull-up fitted) | Cut when another chained module provides the SCL pull-up |
| JP3 | 3-pad SDO address select | 1-2: SDO = GND → 0x76 | 2-3: SDO = 3V3 → 0x77. Never leave SDO floating — address undefined |
Test points#
None on this design. Probe at the J1 pins, the jumper pads (JP1/JP2 bus, JP3 centre pad for SDO), and the C1/C2 pads for the rail. Add test points at layout time if bench work shows the need.
5. Component-by-component review#
Every reference designator in generate_design.py is covered.
| Ref. | Part / key datasheet facts | Function and why needed | If absent/open | If shorted, wrong, or misassembled |
|---|---|---|---|---|
| J1 | 12-pin PMOD plug, 2×6 | Sole power and I2C interface; bus repeated on 9/10 for chaining | No power/communication; one open redundant rail pin (6 or 12) can hide a solder defect | Swapped 3V3/GND is destructive to U1; SCL/SDA swap = no ACKs |
| U1 | Bosch BME280, LGA-8 2.5×2.5 mm. VDD 1.71–3.6 V, VDDIO 1.2–3.6 V; abs max 4.25 V; −40…+85 °C, 0–100 %RH, 300–1100 hPa; I2C to 3.4 MHz; sleep 0.1 µA typ; 1.8 µA @1 Hz H+T, 3.6 µA @1 Hz H+P+T; humidity measurement current 340 µA typ, pressure 714 µA typ; start-up ≤2 ms; chip ID 0x60 | The sensor: humidity + pressure + temperature elements with factory calibration in NVM | Board is inert; address scan finds nothing | Rotated LGA-8 puts 3V3 on GND pins (destructive); solder in or flux under the vent kills humidity/pressure sensing; excessive reflow shifts pressure offset (solder drift −0.5…+2 hPa is a datasheet parameter) |
| C1 | 100 nF 16 V X7R 0603 (Murata GRM188R71C104KA01D) | U1 VDD decoupling for the ~340–714 µA conversion current peaks | Supply bounce during conversions, possible resets | Shorted C1 = 3V3–GND short, rail collapse |
| C2 | 100 nF 16 V X7R 0603 (Murata GRM188R71C104KA01D) | U1 VDDIO decoupling for I2C pad switching | Interface noise sensitivity on long chains | Same — hard rail short |
| R1 | 4.7 kΩ 0603 1% (Yageo RC0603FR-074K7L) | SDA pull-up via JP1; idle-high bus, ~0.7 mA sink at logic low | SDA floats (if the host has no pull-ups): bus hangs | 3V3-to-SDA short prevents any device pulling low: bus stuck high |
| R2 | 4.7 kΩ 0603 1% (Yageo RC0603FR-074K7L) | SCL pull-up via JP2 | SCL floats: no clock seen | Same failure class on the clock |
| JP1 | 2-pad solder jumper, factory-bridged | Removable SDA pull-up for chained stacks | Cut with no other pull-up present: SDA floats | Solder blob to adjacent copper can short SDA to 3V3/GND |
| JP2 | 2-pad solder jumper, factory-bridged | Same, SCL | Same as JP1, on SCL | Same as JP1 |
| JP3 | 3-pad solder jumper, 1-2 bridged | Drives SDO, the address LSB (SDO=GND → 0x76, SDO=VDDIO → 0x77; floating = undefined address) | SDO floats: intermittent/undefined ACK | Bridging 1-2 and 2-3 together shorts 3V3 to GND |
| #FLG01, #FLG02 | KiCad PWR_FLAG on 3V3 and GND | ERC-only artifacts marking the host as rail source | Not physical parts; nothing to assemble | n/a |
6. Datasheet summary and design interpretation#
| Device | Key manufacturer facts used here | Board-specific interpretation |
|---|---|---|
| BME280 (datasheet rev 1.24, Feb 2024, BST-BME280-DS001) | Chip ID 0xD0 = 0x60; soft reset 0xE0 ← 0xB6; calibration in two blocks: 0x88–0xA1 (dig_T1…dig_P9, dig_H1 at 0xA1) and 0xE1–0xE7 (dig_H2…dig_H6, with dig_H4/dig_H5 sharing 0xE5's nibbles); ctrl_hum 0xF2 effective only after a ctrl_meas 0xF4 write; status 0xF3; config 0xF5; data burst 0xF7–0xFE (press 20-bit, temp 20-bit, hum 16-bit); reset states press_msb/temp_msb/hum_msb = 0x80; skipped-measurement markers 0x80000 (P/T) and 0x8000 (H); I2C address 111011x via SDO; no clock stretching | The single 3.3 V rail fits both supply ranges. CSB tied high enforces I2C permanently. The two-block calibration layout and the dig_H4/H5 nibble packing are the classic implementation traps — the bring-up test in section 9 checks them explicitly. The ctrl_hum-before-ctrl_meas ordering is a hard functional requirement, not a style choice |
| Yageo RC0603 / Murata GRM188 passives | Generic thick-film resistors and X7R MLCCs (Yageo RC series) | Non-critical values; verify orderable MPNs at BOM time — no availability check has been run |
Official references: BME280 datasheet (BST-BME280-DS002) and the Bosch Sensortec BME280 product page. Check the latest revision before procurement.
7. Expected values before bench testing#
All targets, no measurements exist.
| Quantity | Target / calculated | Source |
|---|---|---|
| Rail | 3.30 V ±5% at C1/C2 | PMOD spec / bench supply |
| Idle board current (sleep, bus idle) | ~0.1–0.5 µA + meter floor; >1 mA is a fault | datasheet IDDSL 0.1 µA typ, 0.3 µA max |
| Current during conversions | brief peaks: ~340 µA (humidity), ~714 µA (pressure), ~350 µA (temperature) | datasheet Table 1 |
| SDA, SCL idle | 3.3 V through R1/JP1, R2/JP2 | design |
| Driven-low level | <0.4 V at ~0.7 mA | I2C convention |
| 7-bit address ACK | 0x76 only (JP3 1-2); 0x77 only (JP3 2-3) | datasheet §6.2 |
| Chip ID 0xD0 | 0x60 (0x58 means a BMP280 was fitted) | datasheet §5.4.1, Table 17 |
| Reset 0xE0 readback | always 0x00 | datasheet §5.4.2 |
| press_msb 0xF7 / temp_msb 0xFA / hum_msb 0xFD before any measurement | 0x80 / 0x80 / 0x80 | datasheet Table 18 |
| Humidity raw output if ctrl_hum ordering was violated (osrs_h=0) | 0x8000 | datasheet Table 20 |
| dig_T1/dig_P1 plausibility | tens of thousands, not 0/65535 (BMP280-family example: 27504 / 36477) | datasheet family example |
| dig_H1, dig_H3 (unsigned char) | typically ~75 and ~0…50 region; must not be 0xFF | plausibility bound — verify against your part |
| Compensated temperature, indoor bench | ~15–35 °C (slightly above ambient from self-heating) | plausibility bound |
| Compensated pressure, low altitude | ~950–1050 hPa | plausibility bound |
| Compensated humidity, indoors | ~20–80 %RH | plausibility bound |
| SDA/SCL-to-3V3 resistance, unpowered, jumpers bridged | ≈4.7 kΩ each | R1/R2 |
| Same with JP1/JP2 cut | open (>1 MΩ) | jumper function |
8. Manual schematic and assembly review checklist#
- Confirm U1 orientation against the clockwise-numbered LGA-8 footprint (
Bosch_LGA-8_2.5x2.5mm_P0.65mm_ClockwisePinNumbering); the rotated-LGA error is destructive. - Verify the net mapping recorded in
generate_design.py: CSB → 3V3, SDI → SDA, SCK → SCL, SDO → JP3 common, VDD/VDDIO → 3V3, both GND pins → GND. Note this board's symbol pin placement differs from AXS-008 (Sensor:BME280 vs Sensor_Pressure:BMP280) — check nets, not positions. - JP3 bridged 1-2 only; JP1/JP2 bridged; no double bridge on JP3.
- Buzz J1: 5/11 → GND, 6/12 → 3V3, 3–9, 4–10 continuity; 1/2/7/8 isolated.
- 3V3-to-GND resistance in both meter polarities: no hard short.
- Vent hole clear of solder, flux, and (later) conformal coating; humidity element requires airflow to the vent to respond within its ~1 s τ63.
- At layout time: C1/C2 within a few mm of U1; keep heat sources away from U1 (self-heating biases both temperature and RH readings). Cannot be closed until layout exists.
9. Ordered bench-test procedure#
Assumed setup: a PMOD host (3.3 V) or a current-limited 3.3 V bench supply on J1 pins 6/12 and 5/11, plus any I2C master on pins 3/4. Stop at the first abnormal result; record serials, equipment, ambient temperature/RH/pressure.
A. Unpowered inspection and resistance tests#
- Complete the section 8 checklist under magnification.
- 3V3-to-GND in both meter polarities: no hard short.
- SDA-to-3V3 ≈ 4.7 kΩ; SCL-to-3V3 ≈ 4.7 kΩ.
- JP3 common (SDO) to GND ≈ 0 Ω; to 3V3 open.
- SDA-to-SCL open.
B. First power-on#
- 3.30 V, ~20 mA current limit, no I2C master attached.
- Supply current at the meter floor (sub-µA); >1 mA = fault, power off.
- SDA and SCL both idle at 3.3 V. JP3 common at 0 V.
C. Bus idle and address-ACK scan#
- Attach the master at 100 kHz. Idle levels remain 3.3 V.
- Full scan 0x08–0x77: exactly one ACK at 0x76 (wire byte 0xEC).
- Move JP3 to 2-3: exactly one ACK at 0x77 (wire byte 0xEE). Restore JP3 to 1-2 and rescan.
- Extra ACKs indicate a bus bridge or master fault.
D. Chip-ID read and soft reset#
- Read 0xD0: S 0xEC A 0xD0 A Sr 0xED A 0x60 N P. Exactly 0x60. 0x58 means a BMP280 was assembled instead — usable for P/T but the humidity lesson is gone; disposition the board.
- Write 0xE0 ← 0xB6, wait ≥2 ms, re-read 0xD0 → 0x60; 0xF2 → 0x00; 0xF4 → 0x00; 0xF7/0xFA/0xFD → 0x80 each (reset states).
E. Calibration read: both blocks, including the H4/H5 nibble trap#
- Burst-read 26 bytes from 0x88 (dig_T1…dig_P9 LSB-first, then 0xA1 = dig_H1). Then burst-read 7 bytes from 0xE1 (dig_H2…dig_H6).
- Decode per datasheet Table 16, including the packed pair:
- dig_H4 = (0xE4 << 4) | (0xE5 & 0x0F) (signed 12-bit, sign-extended)
- dig_H5 = (0xE6 << 4) | (0xE5 >> 4) (signed 12-bit, sign-extended)
- Reject all-0x00 / all-0xFF blocks. Plausibility: dig_T1 and dig_P1 unsigned in the tens of thousands; dig_H1/dig_H3 not 0xFF; signed words within a few times the BMP280-family example magnitudes. Two consecutive reads must match exactly.
F. First measurement — ctrl_hum ordering, then compensation sanity#
- Write in this order: ctrl_hum 0xF2 = 0x01 (osrs_h ×1), then ctrl_meas 0xF4 = 0x27 (osrs_t ×1, osrs_p ×1, normal mode), then config 0xF5 = 0x00. The 0xF2 write takes effect only on the 0xF4 write.
- Poll status 0xF3 bit 3 (
measuring) until 0, or wait ~10 ms (exact maximum conversion time at ×1 oversampling: verify against datasheet chapter 9 measurement-time formula — not extracted into this guide). - Burst-read 8 bytes from 0xF7 (press msb/lsb/xlsb, temp msb/lsb/xlsb, hum msb/lsb). Assemble adc_P/adc_T (20-bit) and adc_H (16-bit).
- Negative test of the ordering rule: soft-reset, write only 0xF4 = 0x27 (never touching 0xF2), measure — the humidity output must read 0x8000 (osrs_h still 0 = skipped). This confirms you can detect the classic bug. Reset and restore the correct order afterwards.
- Cross-check your compensation implementation against the datasheet reference code (§4.2.3): the P/T formulas are identical to the BMP280's, whose worked example (adc_T=519888, adc_P=415148 with the example trim set → T=25.08 °C, P=100653.27 Pa) must be reproduced by your pipeline. For humidity the datasheet documents the output format by example: compensate_H returning 47445/1024 = 46.333 %RH (Q22.10). There is no full worked humidity input example in the datasheet — validate against the Bosch reference API (bme280_compensate_H_int32) with your part's own trim words.
- Plausibility of live readings, indoor bench: temperature 15–35 °C, pressure 950–1050 hPa (adjust for lab altitude), humidity 20–80 %RH.
- Stimulus checks: breathe gently from ~10 cm — RH must rise by tens of %RH within ~1 s (τ63 = 1 s) and decay back. Fingertip warmth raises temperature. A ~1 m altitude change moves pressure ~0.12 hPa.
G. JP1/JP2 pull-up jumper verification (chaining)#
- Unpowered, jumpers bridged: SDA-to-3V3 ≈ 4.7 kΩ, SCL-to-3V3 ≈ 4.7 kΩ.
- Cut JP1/JP2, verify under magnification: both lines to 3V3 now open (>1 MΩ; any slow drift is ESD-structure leakage, not a resistor).
- Powered, pull-ups cut, no external pull-ups: scan fails (expected signature of an unpaired chained module).
- Provide external 4.7 kΩ pull-ups (or a bridged partner module) and re-run C–F with identical expected results.
- Re-bridge with solder to restore single-module default; re-verify step 1.
H. Chain test with AXS-008 (optional)#
- Chain a BMP280 module on pins 9/10, this board's JP3 at 1-2 (0x76) and the partner at 2-3 (0x77), exactly one module keeping pull-up jumpers bridged.
- Scan shows 0x76 and 0x77; chip IDs distinguish them: 0x60 here, 0x58 on the BMP280 — a deliberate lesson in identifying register-compatible siblings.
10. Troubleshooting map#
| Symptom | First measurements | Likely areas |
|---|---|---|
| Supply current at bench limit | 3V3-GND ohms, C1/C2, JP3 pads | shorted decoupler, JP3 double bridge, rotated U1 |
| Bus line not 3.3 V idle | jumper continuity, R1/R2 | JP1/JP2 cut/unsoldered, line shorted to GND |
| No ACK anywhere | SCL at U1 SCK pin, SDO level | SDA/SCL swap, U1 unpowered/rotated/dead |
| ACK at wrong address | JP3 common voltage | JP3 position or open (floating SDO) |
| Chip ID 0x58 not 0x60 | none — conclusive | BMP280 assembled instead of BME280 |
| Humidity always 0x8000 | 0xF2 readback after 0xF4 write | ctrl_hum written after ctrl_meas (ordering bug) or never written |
| P/T fine, humidity absurd | dig_H4/H5 decode by hand | nibble-packing bug at 0xE4–0xE6, sign extension missing |
| All calibration bytes 0x00/0xFF | repeat read at 100 kHz | burst-read logic, bus integrity |
| Data stuck at reset values 0x80… | 0xF4 readback, mode bits | ctrl_meas write path, still in sleep |
| Compensated values implausible | rerun math on reference vectors | endianness, signed/unsigned, t_fine propagation across the three formulas |
| RH pinned at 0 or 100 % | vent inspection, reconditioning | contaminated/soldered vent, condensation history |
11. Bench record template#
| Field | Record |
|---|---|
| Board revision / serial | |
| JP1/JP2/JP3 state as tested | |
| Host / supply, current limit, equipment IDs, calibration dates | |
| Ambient T / RH / P references and lab altitude | |
| Unpowered resistance results | |
| Idle and conversion currents | |
| Address scan (both JP3 positions) | |
| Chip-ID value | |
| Calibration dump: 0x88–0xA1 and 0xE1–0xE7, decoded dig_ words | |
| dig_H4/H5 nibble-decode check | |
| ctrl_hum ordering negative-test result (0x8000 observed?) | |
| Raw adc_T/adc_P/adc_H and compensated T/P/RH | |
| Breath / warmth / altitude stimulus response | |
| Pull-up cut/restore verification | |
| Deviations, photos, raw-file paths | |
| Reviewer / date / disposition |
12. Review conclusion#
The schematic is the same deliberately minimal I2C-module pattern as AXS-008 with the BME280 substituted: single rail, both supplies decoupled, CSB tied high so the interface can never latch into SPI, SDO pinned by JP3, and removable bus pull-ups for chaining. The design's correctness therefore hinges almost entirely on firmware/gateware discipline: the ctrl_hum-before- ctrl_meas write ordering, the two-block calibration readout with the dig_H4/dig_H5 nibble packing, and three chained fixed-point compensation formulas sharing t_fine.
Principal open risks: schematic-only status (no layout, DRC, fab outputs, or bench evidence); LGA-8 orientation and vent handling at assembly; humidity- element care (storage RH, reconditioning after reflow); and the unwritten fabric compensation pipeline, which must reproduce the datasheet reference vectors before any live reading is trusted.