Circuit review & bench-test guide
AXS-012 — APDS-9301 ambient-light PMOD module
Document purpose#
This document explains the axs-012-ambient-light 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 APDS-9301 manufacturer datasheet.
The board is an unfabricated, schematic-only prototype: ERC is clean (0 errors / 0 warnings) and the netlist has been reviewed, but no PCB layout exists, no board has been built, and no bench measurement has ever been taken. Every numeric value in this guide is a verification target taken from the schematic or the datasheet — it is not a measured result and is not proof that an assembled board will work.
1. What the board does#
The board is a 12-pin PMOD (Type 6 extended, I2C) module carrying a Broadcom APDS-9301 ambient-light sensor. The sensor integrates light on two photodiode channels — CH0 (visible + IR) and CH1 (IR only) — with two 16-bit ADCs, and the host computes lux from the two raw counts using the datasheet's empirical piecewise formula. A programmable threshold interrupt (on CH0) is brought out to PMOD pin 1 as LIGHT_INT. A three-way solder jumper selects one of three I2C addresses; two solder jumpers make the on-module 4.7 kΩ bus pull-ups removable for chained-module use.
It does not regulate power (the PMOD host supplies 3.3 V), does not level-shift (3.3 V logic only), and computes nothing on-module: lux math is host firmware.
Functional block diagram#
PMOD J1 (2x6, Type 6 ext.)
6/12 3V3 ─────────────┬──────────────┬──────────────┬───────────────┐
│ │ │ │
C1 100nF R1 4.7k R2 4.7k R3 10k
(U1 VDD │ SDA_PU │ SCL_PU │
decouple) JP1 ═╗ JP2 ═╗ │
5/11 GND ────────────┐ (cut to (cut to │
│ unchain) unchain) │
3/9 SCL ────────────┼───────────────┼──────────────┘ │
4/10 SDA ────────────┼───────────────┘ ALS_INT ───────┤
│ │ │
v │ R4 100R │
┌─────────────┐ SCL/SDA ─────────────────┤ │
GND ── JP3:1 │ APDS-9301 │ INT (open drain) ────────┴──> pin 1 │
3V3 ── JP3:3 │ U1 │ LIGHT_INT │
ADDR_SEL JP3:2 ─│ ADR_SEL │ CH0 (vis+IR) + CH1 (IR) photodiodes │
(1-2=0x29, └─────────────┘ dual integrating 16-bit ADCs │
2-3=0x49, open=0x39) │
2. Safety and scope boundaries#
- This is a 3.3 V logic-only module. Never apply 5 V to any pin; the APDS-9301 absolute maximum supply and pin voltage is 3.8 V.
- Power it from a PMOD host 3.3 V rail or a bench supply current-limited to about 50 mA at 3.3 V. The whole module should draw well under 3 mA; a higher reading indicates a fault, and a tight limit protects the sensor.
- The APDS-9301 is a small ChipLED-package optical part (MSL 3). Handle with ESD precautions and do not touch or scratch the optical surface.
- Do not hot-plug the PMOD connector while measurements are in progress; misaligned insertion can momentarily short 3V3 to signal pins.
- Do not connect this module and another pull-up-fitted module on the same chained bus without first deciding which module keeps its pull-ups (section 4, JP1/JP2). Stacked pull-ups may overload open-drain drivers.
- Sensor lux is an estimate: the datasheet states the (sensor lux)/(actual lux) ratio can range 0.65–1.35 (fluorescent) or 0.60–1.40 (incandescent). Do not treat this module as a calibrated photometer.
- Passing these bench tests demonstrates prototype function only. It is not EMC, safety, or environmental qualification.
3. Power and control sequence#
- The PMOD host (or bench supply) applies 3.3 V to pins 6/12 and ground to pins 5/11. C1 decouples U1's VDD. There is no on-module regulator or sequencing element; U1 powers up directly.
- On power-up the APDS-9301 is in its power-down state (CONTROL register 0h resets to 00h). Supply current should be in the power-down range (3.2 µA typical, 15 µA maximum for U1 alone).
- R1/R2 (through JP1/JP2) hold SDA and SCL at 3.3 V. JP3's factory 1-2 bridge grounds ADR_SEL, selecting 7-bit address 0x29.
- The host powers the device up by writing 0x03 to CONTROL (command byte 0x80, data 0x03). Active current rises to the 0.24 mA-typical / 0.6 mA-maximum range.
- The TIMING register (1h) resets to 0x02: low gain (1×) and the 402 ms integration time. Both ADCs free-run; results transfer to the double-buffered DATA0/DATA1 registers at the end of each integration. The first read is only meaningful after one full integration period (402 ms at default settings).
- If thresholds and the INTERRUPT register (6h) are configured, U1 pulls its open-drain INT pin low when CH0 leaves the threshold window; R3 pulls the net to 3.3 V otherwise, and R4 couples it to PMOD pin 1. The interrupt is level-style and is cleared by writing the COMMAND register with the CLEAR bit (bit 6) set.
4. Interfaces#
PMOD pin map (J1, Type 6 extended)#
| PMOD pin | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Net | LIGHT_INT | NC | SCL | SDA | GND | 3V3 | NC | NC | SCL | SDA | GND | 3V3 |
Pins 9/10 duplicate SCL/SDA so a second I2C module can be chained.
Jumpers#
| Ref. | Type | Factory state | Function |
|---|---|---|---|
| JP1 | 2-pad solder jumper, bridged | Bridged | Connects R1 (4.7 kΩ) to SDA. Cut when another module in the chain provides the bus pull-ups. |
| JP2 | 2-pad solder jumper, bridged | Bridged | Connects R2 (4.7 kΩ) to SCL. Cut together with JP1. |
| JP3 | 3-pad solder jumper, 1-2 bridged | 1-2 bridged | I2C address: 1-2 (ADR_SEL→GND) = 0x29 (default); 2-3 (ADR_SEL→3V3) = 0x49; fully open (cut the factory 1-2 bridge, bridge nothing) = float = 0x39. |
The three address codes come straight from the datasheet's slave-address table: GND = 0101001, float = 0111001, VDD = 1001001.
Test points#
None are defined in the rev 0.1 schematic. Until the layout adds test points, probe SCL/SDA/INT at the J1 pins and 3V3/GND at pins 6/5. Flag this as a layout-review item if hand probing proves awkward.
5. Component-by-component review#
Every reference designator in the generated schematic is listed.
| Ref. | Part / value | Function and why needed | If absent / open | If shorted, wrong, or misassembled | Key datasheet parameters |
|---|---|---|---|---|---|
| J1 | 2x6 right-angle PMOD male header (Conn_02x06_Odd_Even) | Host connection: power, ground, I2C, INT, and the chained-bus pins | No power or communication; a single open pin loses that function (e.g. open pin 4 = no SDA) | Reversed/offset insertion can put 3.3 V on signal pins; solder bridges between adjacent pins short SDA/SCL or power | PMOD Type 6 extended assignment; 3.3 V rail defined by host |
| U1 | Broadcom APDS-9301-020 ambient-light sensor, ChipLED-6 | The measurement device: dual photodiodes, dual 16-bit ADCs, I2C interface, threshold interrupt | Board is inert; bus scans show no ACK at any address | Wrong orientation swaps VDD/GND and can destroy the part; solder on the optical face degrades response; a VDD–GND short pulls down the rail | VDD 2.7–3.6 V (abs max 3.8 V); active 0.24 mA typ / 0.6 mA max; power-down 3.2 µA typ / 15 µA max; I2C ≤400 kHz; integration 13.7/101/402 ms; ID reg part nibble 0x5 |
| C1 | 100 nF 16 V X7R 0603 (Murata GRM188R71C104KA01D) | U1 VDD high-frequency decoupling, the datasheet's required 0.1 µF bypass | Supply bounce during ADC/logic switching; possible flaky I2C or noisy counts | A shorted C1 is a 3V3–GND short: rail collapses, supply current limit trips | Datasheet application circuit calls for 0.1 µF close to the package, low-ESR ceramic |
| R1 | 4.7 kΩ 0603 (Yageo RC0603FR-074K7L) | SDA bus pull-up (via JP1) | With JP1 cut or R1 open and no other pull-up on the bus, SDA floats: no I2C traffic possible | Too-low value overloads open-drain drivers; a short from 3V3 to SDA prevents anyone pulling the line low (bus stuck high) | Pull-up sized for 400 kHz on a short PMOD bus; ~0.7 mA sink per line when low |
| R2 | 4.7 kΩ 0603 (Yageo RC0603FR-074K7L) | SCL bus pull-up (via JP2) | Same as R1 but for SCL: clock floats, no transactions | Same failure modes as R1 | Same as R1 |
| R3 | 10 kΩ 0603 (Yageo RC0603FR-0710KL) | Pull-up for U1's open-drain INT output (net ALS_INT) | INT floats; host sees noise or a stuck level on LIGHT_INT | Short to 3V3 masks all interrupts (line can never go low); wrong low value exceeds INT sink spec | Datasheet recommends 10–100 kΩ on INT; VOL ≤ 0.4 V at 3 mA sink |
| R4 | 100 Ω 0603 (Yageo RC0603FR-07100RL) | Series protection between the sensor-driven ALS_INT and PMOD pin 1 | Interrupt does not reach the host (pin 1 floats via R3? No — pin 1 is then disconnected: LIGHT_INT open) | Shorted = no protection but functional; wrong high value with host input capacitance slows edges (usually harmless for a level interrupt) | Limits current if the host drives pin 1 against U1 |
| JP1 | 2-pad solder jumper, factory bridged | Makes the SDA pull-up removable for chained buses | Cut: module relies on external pull-ups — correct only in a chain | Re-bridged with solder blob including nearby copper could short SDA to 3V3 or GND | See section 4 |
| JP2 | 2-pad solder jumper, factory bridged | Makes the SCL pull-up removable | As JP1, for SCL | As JP1 | See section 4 |
| JP3 | 3-pad solder jumper, factory 1-2 bridged | Sets ADR_SEL: GND / VDD / float → I2C address 0x29 / 0x49 / 0x39 | Fully open is a valid state (0x39), so "absent" is not a fault — but an unintentionally lifted bridge silently moves the device to 0x39 | Bridging 1-2 and 2-3 shorts 3V3 to GND through the jumper — rail collapse; wrong side bridged = wrong address | Slave address table: GND 0x29, float 0x39, VDD 0x49 |
| #FLG01 | PWR_FLAG on 3V3 | ERC-only artifact: tells KiCad the 3V3 net is power-driven | Not a physical part; absence only causes ERC "no driver" warnings | Not applicable — never fitted, not in BOM/POS | — |
| #FLG02 | PWR_FLAG on GND | ERC-only artifact for GND | As #FLG01 | Not applicable | — |
6. Datasheet summary and design interpretation#
Primary reference: APDS-9301 datasheet (Avago/Broadcom AV02-2315EN). Passives: Yageo RC thick-film series, Murata GRM188R71C104KA01D (100 nF X7R) via murata.com product search.
| Manufacturer fact (AV02-2315EN) | Board-specific interpretation |
|---|---|
| VDD 2.7–3.6 V recommended, 3.8 V absolute maximum | 3.3 V PMOD rail sits comfortably in range; never probe with 5 V logic |
| Supply current 0.24 mA typ active, 3.2 µA typ power-down | Whole-module idle draw is dominated by nothing (pull-ups idle at ~0); use these as bench sanity numbers |
| Three slave addresses via ADR_SEL: GND 0x29, float 0x39, VDD 0x49 | JP3 implements exactly this; float requires the 1-2 bridge cut and nothing bridged |
| Command byte: bit7 CMD (must be 1), bit6 CLEAR, bit5 WORD, bits3:0 register address | ID read uses 0x8A; word reads of DATA0/DATA1 use 0xAC/0xAE (that is 0x8C/0x8E with the WORD bit 0x20 added) |
| CONTROL (0h): write 0x03 to power up; reads back 0x03 as a comms check | This read-back is the designed first-transaction bring-up test |
| TIMING (1h) resets to 0x02: low gain (1×), 402 ms integration | First data read must wait ≥402 ms; for the datasheet lux formula, scale low-gain counts ×16 (high gain is 16× low gain) |
| ID (Ah): bits7:4 part number = 0101, bits3:0 revision | Expect 0x5x; record the revision nibble, do not fail on it |
| Full-scale counts: 5047 (13.7 ms), 37177 (101 ms), 65535 (Tint ≥ 178 ms); dark count ≤ 4 | Saturation and covered-sensor targets in section 7 |
| Empirical lux formula, piecewise in CH1/CH0 (table below) | Host firmware implements this; the worked example in section 7 is the acceptance math |
| Sensor-lux accuracy 0.65–1.35 (fluorescent) / 0.60–1.40 (incandescent) of actual lux | Set wide pass bands; a lux meter disagreement inside these bands is not a board fault |
| INT is open-drain, level-style, cleared via COMMAND CLEAR bit; 10–100 kΩ pull-up recommended | R3 = 10 kΩ complies; interrupt is based on CH0 only |
Sensor lux formula (datasheet, high-gain 402 ms-scaled counts):
| CH1/CH0 ratio | Sensor lux |
|---|---|
| 0 < ratio ≤ 0.50 | 0.0304·CH0 − 0.062·CH0·(CH1/CH0)^1.4 |
| 0.50 < ratio ≤ 0.61 | 0.0224·CH0 − 0.031·CH1 |
| 0.61 < ratio ≤ 0.80 | 0.0128·CH0 − 0.0153·CH1 |
| 0.80 < ratio ≤ 1.30 | 0.00146·CH0 − 0.00112·CH1 |
| ratio > 1.30 | 0 |
7. Expected values before bench testing#
All values are targets to verify, not measurements.
| Quantity | Target / calculated | Basis |
|---|---|---|
| Bus idle level, SDA and SCL | 3.3 V (rail) through R1/R2 | Pull-ups via JP1/JP2 |
| SDA→3V3 resistance, unpowered, JP1 fitted | ≈ 4.7 kΩ | R1 |
| SCL→3V3 resistance, unpowered, JP2 fitted | ≈ 4.7 kΩ | R2 |
| SDA/SCL→3V3 after cutting JP1/JP2 | Open (>1 MΩ) on the bus side; SDA_PU/SCL_PU pads still ≈4.7 kΩ | Jumper cut isolates R1/R2 |
| LIGHT_INT (pin 1)→3V3 resistance | ≈ 10.1 kΩ (R4 + R3) | Series path pin1–R4–R3–3V3 |
| ADDR_SEL→GND, JP3 default | ≈ 0 Ω | Factory 1-2 bridge |
| Address-ACK scan | ACK at exactly 0x29 (default); 0x49 after moving JP3 to 2-3; 0x39 with JP3 fully open; NACK everywhere else | Datasheet slave-address table |
| Module supply current, powered down | ≤ ~20 µA (U1: 3.2 µA typ, 15 µA max) | Electrical characteristics |
| Module supply current, powered up | ~0.3 mA typ, ≤0.7 mA (plus bus pull-up current during traffic) | Active IDD 0.24 mA typ / 0.6 mA max |
| CONTROL read-back after writing 0x03 | 0x03 | Datasheet comms-check feature |
| ID register (command 0x8A) | 0x5x (part nibble 0101; revision nibble varies) | ID register definition |
| Dark counts, sensor covered, after ≥1 integration | CH0 ≤ 4, CH1 ≤ 4 → computed lux ≈ 0 | Dark ADC count spec (402 ms) |
| Office fluorescent light ~400 lux, high gain, 402 ms | CH0 ≈ 14,400 (36 counts/lux typ), CH1 ≈ 1,600 (4 counts/lux typ), ratio ≈ 0.11 | Illuminance responsivity, high gain |
| Worked lux example from those counts | 0.0304×14400 − 0.062×14400×(0.111)^1.4 ≈ 438 − 41 ≈ ~397 lux; accept ~260–540 given the 0.65–1.35 accuracy band | Empirical formula, first row |
| Same light at the power-on default (low gain) | CH0 ≈ 900, CH1 ≈ 100; multiply ×16 before applying the formula (low gain is 1/16 of high gain) | Low-gain responsivity 2.3 / 0.25 counts/lux |
| Saturation check, bright light | CH0 pegged at 65535 (402 ms) means switch to low gain or 13.7/101 ms | Full-scale table |
8. Manual schematic and assembly review checklist#
- Confirm U1 orientation against the ChipLED pin-1 marker (pin 1 = VDD, 2 = GND, 3 = ADR_SEL, 4 = SCL, 5 = SDA, 6 = INT). A rotated part swaps supply pins.
- Verify JP3 has exactly one bridge (1-2) as shipped, and that pads 1 and 3 cannot be bridged simultaneously by a solder blob (that is a 3V3–GND short).
- Verify JP1 and JP2 are bridged for standalone use, and record the intended state in the build sheet if this module will sit in a chain.
- Measure R1, R2 (4.7 kΩ), R3 (10 kΩ), R4 (100 Ω) values on the loose reel or in-circuit before power.
- Confirm C1 is present and not cracked; a shorted C1 is a rail short.
- At layout time (still open): keep C1 adjacent to U1 VDD; leave the optical aperture over U1 free of silkscreen and mask artwork; consider adding SDA/SCL/INT/3V3/GND test points.
- Confirm no solder bridges across the fine-pitch J1 header, especially pins 3-4 (SCL-SDA) and 5-6 (GND-3V3).
- Confirm #FLG01/#FLG02 are schematic-only (not in BOM or placement).
9. Ordered bench-test procedure#
Assume a PMOD host (FPGA board) or a current-limited 3.3 V bench supply wired to J1 pins 6/12 (3V3) and 5/11 (GND), plus any I2C master (FPGA soft core, MCU dev board, or USB-I2C adapter) on pins 3/4. Stop at the first abnormal result and record everything.
A. Unpowered inspection and resistance tests#
- Complete the section 8 checklist under magnification.
- Measure 3V3→GND resistance in both meter polarities. Investigate anything under ~10 kΩ before applying power.
- Verify SDA→3V3 ≈ 4.7 kΩ, SCL→3V3 ≈ 4.7 kΩ, pin 1→3V3 ≈ 10.1 kΩ.
- Verify ADDR_SEL→GND ≈ 0 Ω (JP3 default) and ADDR_SEL→3V3 open.
B. First power, no I2C traffic#
- Set the bench supply to 3.3 V with a ~50 mA current limit; power the module.
- Confirm supply current ≤ ~20 µA (device still powered down) and that SDA, SCL, and pin 1 all idle at 3.3 V.
C. Address-ACK scan#
- Scan all 7-bit addresses (e.g.
i2cdetect-style probe or the FPGA I2C master's scan routine). - Expect an ACK only at 0x29. Any other ACK pattern means a JP3 or address-decode problem; no ACK means U1 power, orientation, or bus wiring.
- (Variant check, once per design, on a sacrificial or reworked board: move JP3 to 2-3 and expect 0x49 only; cut JP3 fully open and expect 0x39 only.)
D. First-transaction bring-up (power-up and ID)#
- Write the power-up command: START, address 0x29+W, command byte 0x80, data byte 0x03, STOP.
- Read CONTROL back: write command 0x80, then read one byte — expect 0x03 (the datasheet's designed communication check).
- Read the ID register: write command 0x8A, read one byte — expect 0x5x (part number nibble 0x5; record the revision nibble).
- Confirm supply current stepped up to the ~0.3 mA active range.
E. Raw channel reads and lux math#
- Wait at least one integration period (402 ms at the power-on default) after power-up before the first data read.
- Read CH0 as a word: command 0xAC (0x8C + WORD bit 0x20), read two bytes, low byte first. Read CH1 with command 0xAE. (Byte-at-a-time reads with 0x8C–0x8F work but must read low before high — the low-byte read latches the high byte.)
- Under typical office lighting (~300–500 lux), expect low-gain counts of roughly CH0 700–1200, CH1 60–150; scale ×16 and apply the section 6 formula — the result should land within a factor of ~1.4 of a reference lux meter (datasheet accuracy band).
- Cover the sensor completely (opaque tape or a cap): after the next integration period expect CH0 ≤ 4 and CH1 ≤ 4 counts and computed lux ≈ 0.
- Optionally write TIMING (command 0x81) = 0x12 for high gain and repeat; counts should scale ×16 (until saturation).
- Shine an IR-heavy source (e.g. an IR remote) at the sensor: CH1/CH0 ratio should rise sharply — a good check that the two channels are not swapped in firmware.
F. Threshold interrupt#
- Write low/high thresholds around the current CH0 value (Write Word to commands 0xA2 and 0xA4), then enable the level interrupt: command 0x86, data 0x10 (INTR=01, PERSIST=0).
- Cover then uncover the sensor: pin 1 (LIGHT_INT) should fall to <0.4 V when CH0 leaves the window and stay low until cleared.
- Clear by writing command 0xC0 (CMD|CLEAR); pin 1 should return to 3.3 V.
G. Pull-up chain configuration (JP1/JP2)#
- Power off. Cut JP1 and JP2 with a scalpel; verify SDA→3V3 and SCL→3V3 now read open on this module (unpowered, module alone).
- Connect the module behind another pull-up-fitted module (or add external 4.7 kΩ pull-ups) and repeat the address scan — behavior must be identical.
- To restore standalone use, re-bridge JP1/JP2 with solder and re-verify ≈4.7 kΩ each.
10. Troubleshooting map#
| Symptom | First measurements | Likely areas |
|---|---|---|
| No ACK at any address | 3V3 at U1, SDA/SCL idle levels, JP1/JP2 continuity | U1 unpowered/rotated, cut jumpers with no external pull-ups, J1 solder |
| ACK at 0x39 instead of 0x29 | ADDR_SEL→GND resistance | JP3 bridge lifted or cracked |
| ACK at 0x49 unexpectedly | ADDR_SEL→3V3 | JP3 bridged 2-3 or solder blob to the 3V3 pad |
| CONTROL reads back 0x00 after writing 0x03 | Repeat write, check ACK bits on scope | Write not reaching device (SDA integrity), U1 damaged |
| ID reads wrong / garbage | Scope the read transaction | Bus corruption, wrong command byte (missing CMD bit 0x80) |
| Counts always 0 with light present | Wait time, CONTROL value | Read before first integration completed, device still powered down, optical aperture blocked |
| Counts stuck at 65535 | Light level, TIMING value | Saturation: reduce gain/integration; direct sunlight |
| Lux wildly wrong but counts plausible | Recompute by hand from raw CH0/CH1 | Firmware formula/scaling bug (forgot ×16 low-gain scaling or ratio branch) |
| CH1 > CH0 under an incandescent lamp beyond ratio 1.3 | Ratio math | Expected behavior — formula clamps to 0 for IR-dominated light; not a fault |
| INT never asserts | R3/R4 path, INTERRUPT reg value | Thresholds not bracketing, INTR field 0, R3 open |
| INT stuck low | Read/clear cycle, U1 INT pin solder | Uncleared level interrupt (write 0xC0), shorted R4/pin 1 |
| Supply current mA-range at idle | Thermal check of U1 and C1 | Shorted C1, damaged U1, JP3 double-bridge |
11. Bench record template#
| Field | Record |
|---|---|
| Board revision / serial | |
| JP1/JP2/JP3 state audit | |
| Host / supply and current-limit setting | |
| DMM / scope / lux-meter equipment and calibration | |
| Unpowered resistance results (A) | |
| Idle levels and supply current (B) | |
| Address-scan result (C) | |
| CONTROL read-back and ID value (D) | |
| Raw CH0/CH1 + computed lux vs reference meter (E) | |
| Covered-sensor result (E4) | |
| Interrupt assert/clear result (F) | |
| Chained-bus / jumper-cut result (G) | |
| Deviations, photos, raw-file paths | |
| Reviewer / date / disposition |
12. Review conclusion#
The schematic is a minimal, datasheet-conformant application circuit: the required 0.1 µF bypass, recommended-range pull-ups on both bus lines and the interrupt, a series resistor protecting the interrupt line, and a three-state address jumper that exactly mirrors the ADR_SEL table. The principal open risks are all pre-fabrication: there is no PCB layout yet (so no verified optical aperture, no C1 placement, and no test points), no board has ever been powered, and the lux math lives entirely in unwritten host firmware. The JP3 double-bridge failure mode (3V3–GND short through the jumper) and the sensor's wide ±35–40% lux accuracy band are the two items most worth carrying forward into the layout review and the firmware acceptance criteria.