← AXS-012

Circuit review & bench-test guide

AXS-012 — APDS-9301 ambient-light PMOD module

Design-stage — board not yet fabricated

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#

3. Power and control sequence#

  1. 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.
  2. 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).
  3. 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.
  4. 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.
  5. 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).
  6. 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 pin123456789101112
NetLIGHT_INTNCSCLSDAGND3V3NCNCSCLSDAGND3V3

Pins 9/10 duplicate SCL/SDA so a second I2C module can be chained.

Jumpers#

Ref.TypeFactory stateFunction
JP12-pad solder jumper, bridgedBridgedConnects R1 (4.7 kΩ) to SDA. Cut when another module in the chain provides the bus pull-ups.
JP22-pad solder jumper, bridgedBridgedConnects R2 (4.7 kΩ) to SCL. Cut together with JP1.
JP33-pad solder jumper, 1-2 bridged1-2 bridgedI2C 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 / valueFunction and why neededIf absent / openIf shorted, wrong, or misassembledKey datasheet parameters
J12x6 right-angle PMOD male header (Conn_02x06_Odd_Even)Host connection: power, ground, I2C, INT, and the chained-bus pinsNo 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 powerPMOD Type 6 extended assignment; 3.3 V rail defined by host
U1Broadcom APDS-9301-020 ambient-light sensor, ChipLED-6The measurement device: dual photodiodes, dual 16-bit ADCs, I2C interface, threshold interruptBoard is inert; bus scans show no ACK at any addressWrong orientation swaps VDD/GND and can destroy the part; solder on the optical face degrades response; a VDD–GND short pulls down the railVDD 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
C1100 nF 16 V X7R 0603 (Murata GRM188R71C104KA01D)U1 VDD high-frequency decoupling, the datasheet's required 0.1 µF bypassSupply bounce during ADC/logic switching; possible flaky I2C or noisy countsA shorted C1 is a 3V3–GND short: rail collapses, supply current limit tripsDatasheet application circuit calls for 0.1 µF close to the package, low-ESR ceramic
R14.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 possibleToo-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
R24.7 kΩ 0603 (Yageo RC0603FR-074K7L)SCL bus pull-up (via JP2)Same as R1 but for SCL: clock floats, no transactionsSame failure modes as R1Same as R1
R310 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_INTShort to 3V3 masks all interrupts (line can never go low); wrong low value exceeds INT sink specDatasheet recommends 10–100 kΩ on INT; VOL ≤ 0.4 V at 3 mA sink
R4100 Ω 0603 (Yageo RC0603FR-07100RL)Series protection between the sensor-driven ALS_INT and PMOD pin 1Interrupt 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
JP12-pad solder jumper, factory bridgedMakes the SDA pull-up removable for chained busesCut: module relies on external pull-ups — correct only in a chainRe-bridged with solder blob including nearby copper could short SDA to 3V3 or GNDSee section 4
JP22-pad solder jumper, factory bridgedMakes the SCL pull-up removableAs JP1, for SCLAs JP1See section 4
JP33-pad solder jumper, factory 1-2 bridgedSets ADR_SEL: GND / VDD / float → I2C address 0x29 / 0x49 / 0x39Fully open is a valid state (0x39), so "absent" is not a fault — but an unintentionally lifted bridge silently moves the device to 0x39Bridging 1-2 and 2-3 shorts 3V3 to GND through the jumper — rail collapse; wrong side bridged = wrong addressSlave address table: GND 0x29, float 0x39, VDD 0x49
#FLG01PWR_FLAG on 3V3ERC-only artifact: tells KiCad the 3V3 net is power-drivenNot a physical part; absence only causes ERC "no driver" warningsNot applicable — never fitted, not in BOM/POS
#FLG02PWR_FLAG on GNDERC-only artifact for GNDAs #FLG01Not 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 maximum3.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-downWhole-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 0x49JP3 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 addressID 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 checkThis read-back is the designed first-transaction bring-up test
TIMING (1h) resets to 0x02: low gain (1×), 402 ms integrationFirst 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 revisionExpect 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 ≤ 4Saturation 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 luxSet 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 recommendedR3 = 10 kΩ complies; interrupt is based on CH0 only

Sensor lux formula (datasheet, high-gain 402 ms-scaled counts):

CH1/CH0 ratioSensor lux
0 < ratio ≤ 0.500.0304·CH0 − 0.062·CH0·(CH1/CH0)^1.4
0.50 < ratio ≤ 0.610.0224·CH0 − 0.031·CH1
0.61 < ratio ≤ 0.800.0128·CH0 − 0.0153·CH1
0.80 < ratio ≤ 1.300.00146·CH0 − 0.00112·CH1
ratio > 1.300

7. Expected values before bench testing#

All values are targets to verify, not measurements.

QuantityTarget / calculatedBasis
Bus idle level, SDA and SCL3.3 V (rail) through R1/R2Pull-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/JP2Open (>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 scanACK at exactly 0x29 (default); 0x49 after moving JP3 to 2-3; 0x39 with JP3 fully open; NACK everywhere elseDatasheet 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 0x030x03Datasheet comms-check feature
ID register (command 0x8A)0x5x (part nibble 0101; revision nibble varies)ID register definition
Dark counts, sensor covered, after ≥1 integrationCH0 ≤ 4, CH1 ≤ 4 → computed lux ≈ 0Dark ADC count spec (402 ms)
Office fluorescent light ~400 lux, high gain, 402 msCH0 ≈ 14,400 (36 counts/lux typ), CH1 ≈ 1,600 (4 counts/lux typ), ratio ≈ 0.11Illuminance responsivity, high gain
Worked lux example from those counts0.0304×14400 − 0.062×14400×(0.111)^1.4 ≈ 438 − 41 ≈ ~397 lux; accept ~260–540 given the 0.65–1.35 accuracy bandEmpirical 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 lightCH0 pegged at 65535 (402 ms) means switch to low gain or 13.7/101 msFull-scale table

8. Manual schematic and assembly review checklist#

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#

  1. Complete the section 8 checklist under magnification.
  2. Measure 3V3→GND resistance in both meter polarities. Investigate anything under ~10 kΩ before applying power.
  3. Verify SDA→3V3 ≈ 4.7 kΩ, SCL→3V3 ≈ 4.7 kΩ, pin 1→3V3 ≈ 10.1 kΩ.
  4. Verify ADDR_SEL→GND ≈ 0 Ω (JP3 default) and ADDR_SEL→3V3 open.

B. First power, no I2C traffic#

  1. Set the bench supply to 3.3 V with a ~50 mA current limit; power the module.
  2. 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#

  1. Scan all 7-bit addresses (e.g. i2cdetect-style probe or the FPGA I2C master's scan routine).
  2. 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.
  3. (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)#

  1. Write the power-up command: START, address 0x29+W, command byte 0x80, data byte 0x03, STOP.
  2. Read CONTROL back: write command 0x80, then read one byte — expect 0x03 (the datasheet's designed communication check).
  3. Read the ID register: write command 0x8A, read one byte — expect 0x5x (part number nibble 0x5; record the revision nibble).
  4. Confirm supply current stepped up to the ~0.3 mA active range.

E. Raw channel reads and lux math#

  1. Wait at least one integration period (402 ms at the power-on default) after power-up before the first data read.
  2. 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.)
  3. 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).
  4. 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.
  5. Optionally write TIMING (command 0x81) = 0x12 for high gain and repeat; counts should scale ×16 (until saturation).
  6. 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#

  1. 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).
  2. 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.
  3. Clear by writing command 0xC0 (CMD|CLEAR); pin 1 should return to 3.3 V.

G. Pull-up chain configuration (JP1/JP2)#

  1. Power off. Cut JP1 and JP2 with a scalpel; verify SDA→3V3 and SCL→3V3 now read open on this module (unpowered, module alone).
  2. 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.
  3. To restore standalone use, re-bridge JP1/JP2 with solder and re-verify ≈4.7 kΩ each.

10. Troubleshooting map#

SymptomFirst measurementsLikely areas
No ACK at any address3V3 at U1, SDA/SCL idle levels, JP1/JP2 continuityU1 unpowered/rotated, cut jumpers with no external pull-ups, J1 solder
ACK at 0x39 instead of 0x29ADDR_SEL→GND resistanceJP3 bridge lifted or cracked
ACK at 0x49 unexpectedlyADDR_SEL→3V3JP3 bridged 2-3 or solder blob to the 3V3 pad
CONTROL reads back 0x00 after writing 0x03Repeat write, check ACK bits on scopeWrite not reaching device (SDA integrity), U1 damaged
ID reads wrong / garbageScope the read transactionBus corruption, wrong command byte (missing CMD bit 0x80)
Counts always 0 with light presentWait time, CONTROL valueRead before first integration completed, device still powered down, optical aperture blocked
Counts stuck at 65535Light level, TIMING valueSaturation: reduce gain/integration; direct sunlight
Lux wildly wrong but counts plausibleRecompute by hand from raw CH0/CH1Firmware formula/scaling bug (forgot ×16 low-gain scaling or ratio branch)
CH1 > CH0 under an incandescent lamp beyond ratio 1.3Ratio mathExpected behavior — formula clamps to 0 for IR-dominated light; not a fault
INT never assertsR3/R4 path, INTERRUPT reg valueThresholds not bracketing, INTR field 0, R3 open
INT stuck lowRead/clear cycle, U1 INT pin solderUncleared level interrupt (write 0xC0), shorted R4/pin 1
Supply current mA-range at idleThermal check of U1 and C1Shorted C1, damaged U1, JP3 double-bridge

11. Bench record template#

FieldRecord
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.