Circuit review & bench-test guide
AXS-042 — SCD40 true-NDIR CO2 sensor PMOD module
Document purpose#
This document explains the axs-042-scd40 prototype at component level and turns the design evidence into a practical manual-review and bench-test plan. It is based on the implemented schematic (generate_design.py, axs-042-scd40.kicad_sch), the module README, and the Sensirion SCD4x datasheet (version 1.5, July 2023).
The board is schematic-only. ERC is clean (0/0) and the netlist has been reviewed, but no PCB layout exists, no board has been fabricated, and there is no recorded bench result. Every numeric value below — currents, command timings, CRC bytes, expected CO2 readings — is a verification target taken from the schematic and the datasheet, not a measured result.
1. What the board does#
The board is an I2C PMOD module around the Sensirion SCD40-D-R2, a true photoacoustic-NDIR CO2 sensor (not a metal-oxide eCO2 estimator) with an integrated SHT4x-class temperature/humidity sensor for on-chip compensation. It reports CO2 in ppm (specified range 400–2000 ppm for the SCD40; output range 0–40000 ppm), temperature, and relative humidity over I2C at fixed address 0x62.
The interface is Sensirion's command protocol: 16-bit commands, 16-bit data words each followed by a CRC-8 byte, and millisecond-to-second command latencies. The IR-emitter pulses draw large supply-current peaks (up to 205 mA maximum at 3.3 V), which is why the schematic fits two 10 µF bulk reservoirs plus a 100 nF decoupler at the sensor.
Functional block diagram#
PMOD host J1
3V3 (6,12) ────┬────────┬────────┬──────────┐
GND (5,11) ────┼────────┼────────┼──────┐ │
│ │ │ │ │
C1 100n C2 10µ C3 10µ │ │ emitter-pulse reservoirs
│ │ │ │ │
SCL (3,9) ──┬──┴────────┴────────┴──> U1 SCD40 (addr 0x62)
SDA (4,10) ─┼─┬ VDD+VDDH = 3V3, GND
│ │ photoacoustic NDIR CO2 + T/RH
R2 4.7k ───┘ │ (via JP2, SCL)
R1 4.7k ─────┘ (via JP1, SDA)
2. Safety and scope boundaries#
- Electrically this is a benign 3.3 V board, but the peak supply current is up to 205 mA at 3.3 V during emitter pulses. A bench current limit set below ≈250 mA will brown out the sensor mid-measurement and produce confusing resets — set the limit accordingly and note it in the record.
- Sensirion specifies the unloaded supply ripple below 30 mV peak-to-peak; a long, thin bench lead defeats the on-board reservoirs. Keep leads short.
- The white protection membrane on the sensor top must not be removed or touched; the sensor opening must stay unobstructed. Handling damage is invisible and permanent.
- Do not blow breath directly at the sensor as a "CO2 test" and then trust the absolute number; exhaled air saturates it (>>5000 ppm). Use it only as a gross respond/no-respond check.
- The automatic self-calibration (ASC) algorithm, enabled by default, assumes weekly exposure to ~400 ppm fresh air. Long sealed-box storage of a running sensor will corrupt its baseline; that is an algorithm property, not a board fault.
- MSL 3 package: after the vacuum bag is opened, floor life and any reflow must follow Sensirion's soldering instructions. Hand-rework of the LGA-21 with a hot-air pencil is high-risk to the membrane.
- This prototype has no layout, no fab, and no bench history. All numbers below are targets to verify, not achieved results.
3. Power and control sequence#
- 3V3 and GND come directly from the PMOD host (J1 pins 6/12 and 5/11); the board has no regulator. VDD and VDDH of the SCD40 are the same 3V3 net, as the datasheet requires (they must be kept at the same voltage).
- Power-up: the sensor is ready for commands at most 30 ms after VDD passes the power-up threshold (idle state). It powers up in idle: no measurement runs and supply current stays low until commanded.
start_periodic_measurement(0x21B1) begins the 5-second measurement cycle. From then on, average current is ≈15 mA (18 mA max) at 3.3 V, with pulse peaks up to 205 mA drawn from C2/C3 and the supply.- First data become available ≈5 s after start (one signal-update interval). Data readiness is polled with
get_data_ready_status(0xE4B8). stop_periodic_measurement(0x3F86) returns to idle; the sensor accepts no other command for 500 ms afterwards. Most configuration commands are legal only in idle mode.- There is no reset pin; recovery paths are the
reinitcommand (0x3646, 30 ms, only in idle) or a power cycle.
4. Interfaces#
PMOD pin map (Type 6 extended, J1)#
| 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 |
Pins 9/10 repeat the bus for module chaining.
Jumpers#
| Ref. | Type | Default | Function |
|---|---|---|---|
| JP1 | 2-pad solder jumper, bridged | fitted | SDA pull-up R1 in circuit; cut when another chained module provides the pull-ups |
| JP2 | 2-pad solder jumper, bridged | fitted | SCL pull-up R2 in circuit; cut likewise |
There are no address jumpers: the SCD40 address is fixed at 0x62. Two SCD40 modules cannot share one bus.
Test points#
None are defined in the schematic. Probe at J1 pins and jumper pads. Adding TPs for 3V3 (at the sensor), SDA, and SCL is a recommended layout task, especially for observing supply droop during emitter pulses.
5. Component-by-component review#
Every reference designator in generate_design.py is covered.
5.1 Active device and connector#
| Ref. | Part / datasheet summary | Function and why needed | If absent/open | If shorted, wrong, or misassembled |
|---|---|---|---|---|
| U1 | Sensirion SCD40-D-R2, LGA-21 10.1×10.1×6.5 mm, photoacoustic NDIR CO2 + T/RH, VDD 2.4–5.5 V, I2C 0x62, ≤400 kHz | The sensor; everything else on the board supports it | No ACK at 0x62; module inert | VDD/VDDH not commoned (layout error) violates the datasheet supply rule; solder paste on the exposed-pad opening (contrary to Sensirion guidance, echoed in the schematic note) can wick and damage acoustics; membrane contamination degrades accuracy invisibly |
| J1 | 12-pin PMOD plug | Host power and I2C; duplicated bus on 9/10 | No power/bus | Reversed insertion puts 3V3/GND on signal pins; verify keying before power |
5.2 Pull-ups, decoupling, and jumpers#
| Refs. | Value | Function | If omitted or wrong |
|---|---|---|---|
| R1 | 4.7 kΩ (Yageo RC0603FR-074K7L) | SDA pull-up to 3V3 through JP1 | Bus floats (no other pull-up source): no ACKs |
| R2 | 4.7 kΩ (Yageo RC0603FR-074K7L) | SCL pull-up to 3V3 through JP2 | Same, on the clock |
| C1 | 100 nF 16 V X7R (Murata GRM188R71C104KA01D) | High-frequency VDD decoupling at the sensor | HF noise on VDD; marginal behavior near pulse edges |
| C2 | 10 µF 10 V X5R 0805 (Murata GRM21BR61A106KE19L) | Emitter-pulse bulk reservoir (datasheet-recommended local reservoir) | Supply droop during 175–205 mA pulses; possible sensor resets/ripple beyond the 30 mV budget |
| C3 | 10 µF 10 V X5R 0805 (Murata GRM21BR61A106KE19L) | Second reservoir; schematic note targets droop < 0.1 V during pulses | Reduced margin; may still work on a stiff supply — verify droop on the bench before deleting it |
| JP1 / JP2 | solder jumpers, bridged | Chain configuration for the bus pull-ups | Both cut with no external pull-ups = dead bus; verify with ohmmeter after any rework |
5.3 ERC-only artifacts#
| Refs. | What they are | Review note |
|---|---|---|
| #FLG01 (3V3), #FLG02 (GND) | KiCad PWR_FLAG symbols | ERC markers only; no physical part, no assembly or test action |
6. Datasheet summary and design interpretation#
| Device | Key manufacturer facts used here | Board-specific interpretation |
|---|---|---|
| SCD40 (SCD4x datasheet v1.5) | VDD 2.4–5.5 V; peak current 175 mA typ / 205 mA max at 3.3 V; periodic-mode average 15 mA typ / 18 mA max at 3.3 V; supply ripple ≤30 mV; abs max supply −0.3–6.0 V; SDA/SCL abs max VDD + 0.3 V; power-up ≤30 ms; SCL ≤400 kHz; fixed address 0x62; commands are 16-bit, data words 16-bit + CRC-8; CO2 accuracy (SCD40) ±(50 ppm + 5 %) in 400–2000 ppm; T = −45 + 175·raw/(2^16 − 1); RH = 100·raw/(2^16 − 1); signal update interval 5 s | 3.3 V PMOD rail is comfortably in range. The 205 mA peak dominates bench planning: current limit ≥250 mA and short leads. No reset pin exists, so the driver needs the reinit/power-cycle recovery path. The read protocol has no clock stretching: if data is not ready or a command is executing, the sensor simply NACKs the read header — the master must tolerate NACK-and-retry |
| CRC-8 (datasheet §3.11) | Polynomial 0x31 (x⁸+x⁵+x⁴+1), init 0xFF, no input/output reflection, final XOR 0x00, computed over each 2-byte word; documented check value CRC(0xBE 0xEF) = 0x92 | Implement exactly this in the HDL/driver and unit-test against 0xBEEF→0x92 before touching hardware; write direction requires the CRC, read direction should verify it |
| Passives | Yageo RC series; Murata capacitors | Standard parts; the 10 V X5R rating on 3.3 V leaves ample DC-bias margin |
Key commands used in this guide (datasheet Table 9):
| Command | Code | Max execution time | Allowed during measurement |
|---|---|---|---|
| start_periodic_measurement | 0x21B1 | — | no |
| read_measurement | 0xEC05 | 1 ms | yes |
| stop_periodic_measurement | 0x3F86 | 500 ms | yes |
| get_data_ready_status | 0xE4B8 | 1 ms | yes |
| get_serial_number | 0x3682 | 1 ms | no |
| perform_self_test | 0x3639 | 10000 ms | no |
| reinit | 0x3646 | 30 ms | no |
| persist_settings | 0x3615 | 800 ms | no |
Official references: Sensirion SCD4x datasheet v1.5, Sensirion SCD40 product page, Yageo RC thick-film resistors, Murata capacitor search. Check the latest datasheet revision before procurement.
7. Expected values before bench testing#
All values are calculated/datasheet targets, not measurements.
| Quantity | Design target | What to measure |
|---|---|---|
| SDA/SCL idle level | 3.3 V high through R1/R2 | DMM at J1 pins 3/4 |
| SDA/SCL to 3V3 resistance, unpowered | ≈4.7 kΩ each (JP1/JP2 fitted); open if cut | Ohmmeter |
| Idle supply current (powered, no measurement) | low single-digit mA or less (datasheet gives averages per mode, idle is below all of them — record the actual value; "verify against datasheet" for an exact idle figure, which v1.5 does not tabulate) | Bench supply |
| Average current, periodic mode | 15 mA typ / 18 mA max at 3.3 V | Bench supply, averaged |
| Peak current pulses | 175 mA typ / 205 mA max at 3.3 V | Current probe or shunt + scope |
| 3V3 droop during pulses | < 0.1 V (schematic design target with C2+C3) | Scope at the sensor pads |
| Address ACK | 0x62 only | I2C scan |
| Serial-number read | 3 words + 3 valid CRCs, nonzero serial | First transaction (section 9.C) |
| Time to first data | ≈5 s after 0x21B1 | Poll 0xE4B8 |
| Indoor CO2 plausibility | 400–2000 ppm typical indoor air; accuracy ±(50 ppm + 5 %) | read_measurement |
| Temperature plausibility | room ambient ±1.5 °C (before offset tuning; default offset 4 °C applies inside enclosures) | read_measurement word[1] |
| RH plausibility | room RH ±9 % | read_measurement word[2] |
| Self test | word[0] = 0x0000 (no malfunction), takes 10 s | perform_self_test |
8. Manual schematic and assembly review checklist#
- Verify U1 pin-1 orientation via the notched corner of the protection membrane; LGA-21 is not visually reversible after reflow without X-ray.
- Confirm VDD (pin 7) and VDDH (pin 19) are both on 3V3 and GND pads (6, 20, center pads) are grounded; DNC pads soldered to floating pads only.
- Confirm no solder paste on the exposed thermal-pad opening per the schematic note and Sensirion handling guidance.
- Membrane clean, no flux residue, no paste splatter; opening unobstructed by neighboring tall parts (layout review item).
- JP1/JP2 bridged (default) or deliberately cut per chain plan.
- C1 placed nearest the sensor supply pads, C2/C3 adjacent (layout task).
- Buzz J1 pin 3 → U1 SCL, pin 4 → U1 SDA, and the 9/10 duplicates.
- 3V3-to-GND: no hard short (ohmmeter rises as 20 µF charges).
- Confirm the CRC-8 implementation in the host/HDL passes 0xBEEF → 0x92 before first attach.
9. Ordered bench-test procedure#
Stop at the first abnormal result. Assumed bench: PMOD host (3.3 V) or current-limited 3.3 V bench supply, limit ≥250 mA, short leads.
A. Unpowered inspection and resistance tests#
- Complete the checklist in section 8 under magnification.
- Ohmmeter: 3V3-to-GND no hard short; SDA-to-3V3 ≈4.7 kΩ; SCL-to-3V3 ≈4.7 kΩ (JP1/JP2 fitted verification — cut jumpers must read open).
- SDA-to-SCL: open (no bridge across the jumper bank).
B. First power-up, bus idle#
- Apply 3.3 V, current limit 250 mA. Wait ≥30 ms (power-up time).
- Supply current: expect a low idle value well under the 15 mA periodic average; record it. Sustained tens of mA before any command suggests a sensor stuck mid-measurement from a previous run or a fault.
- DMM: SDA and SCL both ≈3.3 V (bus idle high through the pull-ups).
C. Address ACK and first transaction: serial number with CRC check#
- I2C scan at 100 kHz: expect ACK at 0x62 only.
- Defensive start: because the sensor may still be in a periodic mode from a previous session, first send
stop_periodic_measurement:S 0x62+W ACK 0x3F ACK 0x86 ACK P, then wait 500 ms. - Serial-number read (bring-up transaction):
- Write command 0x3682:
S 0x62+W 0x36 0x82 P - Wait ≥1 ms (command execution time).
- Read 9 bytes:
S 0x62+R b0 b1 crc0 b2 b3 crc1 b4 b5 crc2 NACK P - Verify each CRC-8 (poly 0x31, init 0xFF) over its preceding word pair. Datasheet example: a serial of 273'325'796'834'238 returns
0xF8 0x96 0x31 0x9F 0x07 0xC2 0x3B 0xBE 0x89— your serial differs, but all three CRCs must verify and the 48-bit serial must be nonzero.
- A NACK on the read header here means the 1 ms wait was skipped or the sensor is still busy (e.g. inside the 500 ms stop window).
D. First CO2 measurement#
- Send
start_periodic_measurement:S 0x62+W 0x21 0xB1 P. - Poll
get_data_ready_statusno faster than ~every 500 ms: write 0xE4B8, wait ≥1 ms, read 3 bytes (word + CRC). Data not ready while the least-significant 11 bits are all 0 (e.g. response0x80 0x00 0xA2); ready otherwise. Expect readiness after ≈5 s. - Send
read_measurement0xEC05, wait ≥1 ms, read 9 bytes:
- word[0] = CO2 in ppm (direct); word[1] = raw temperature, T = −45 + 175 × raw / (2^16 − 1); word[2] = raw RH, RH = 100 × raw / (2^16 − 1); each word followed by its CRC.
- Datasheet worked example:
0x01 0xF4 0x7B 0x66 0x67 0xA2 0x5E 0xB9 0x3C= 500 ppm, 25 °C, 37 % RH.
- Plausibility: indoor CO2 400–2000 ppm (a just-ventilated room sits near 400–600 ppm; an occupied closed room drifts up). Temperature within a few °C of ambient (the default 4 °C offset is tuned for enclosed products; on an open board expect a warm-reading bias to verify and tune later). RH within ±9 % of a reference.
- Gross response check: exhale near (not onto) the sensor; CO2 must rise by hundreds-to-thousands of ppm within a few update intervals and decay afterwards. Treat direction of change, not the absolute number, as the result.
- Observe supply behavior during measurement: pulses on the 3V3 rail with droop < 0.1 V at the sensor. If the bench limit trips, raise it — peaks up to 205 mA are specified behavior.
E. Stop discipline and idle-mode commands#
- Send
stop_periodic_measurement0x3F86 and wait 500 ms. Confirm the sensor NACKs/ignores idle-only commands sent inside that window (expected protocol behavior, useful driver test). - In idle, run
perform_self_test0x3639: wait 10 s, read 3 bytes; expect word 0x0000 + valid CRC (no malfunction detected). - Optional:
reinit0x3646, wait 30 ms, then repeat the serial-number read to confirm recovery paths work.
F. Chaining and endurance (deferred)#
- Chain test with another AXS module: cut JP1/JP2 on one board, verify ohms (cut = open, fitted = 4.7 kΩ), confirm both devices ACK.
- Multi-hour soak logging CO2/T/RH; watch ASC behavior across days and verify against a reference meter before trusting absolute calibration.
- Do not run FRC (forced recalibration) or persist_settings casually: they write sensor EEPROM/calibration state.
10. Troubleshooting map#
| Symptom | First measurements | Likely areas |
|---|---|---|
| No ACK at 0x62 | SDA/SCL idle levels, 3V3 at sensor | JP1/JP2 cut with no external pull-ups, sensor orientation/solder, <30 ms wait after power |
| ACK on address, NACK on read header | Delay between command and read | Execution-time wait skipped (1 ms / 400 ms / 500 ms / 10 s per command); command sent during measurement that is not allowed |
| CRC failures on received data | Recompute with poly 0x31/init 0xFF; scope SDA | Wrong CRC algorithm (reflection/final-XOR bugs), bus noise, missing pull-up |
| Sensor ignores config commands | Mode state | Still in periodic mode: stop (0x3F86) + 500 ms first |
| Random resets / gibberish mid-measurement | Scope 3V3 at sensor during pulses | Supply droop >30 mV/0.1 V: bench limit too low, long leads, missing C2/C3 |
| CO2 pinned near 0 or wildly high | Serial read OK? membrane intact? | Damaged/contaminated membrane, sensor abuse, reading during first 5 s |
| Temperature reads several °C high | Offset setting, airflow | Default 4 °C offset plus self-heating; tune set_temperature_offset later, not a hardware fault by itself |
| Two SCD40 modules conflict | — | Fixed 0x62 address; not chainable with each other |
11. Bench record template#
| Field | Record |
|---|---|
| Board revision / serial (board and sensor 48-bit serial) | |
| JP1/JP2 state and measured pull-up resistance | |
| Host/supply, current limit, lead length, equipment IDs | |
| Idle supply current | |
| Address-scan result | |
| Serial-number bytes and CRC verification result | |
| Time from 0x21B1 to first data-ready | |
| First measurement raw bytes and converted CO2/T/RH | |
| Reference CO2/T/RH instrument and readings | |
| Peak current / droop capture during pulses | |
| Self-test result | |
| Deviations, captures, raw-file paths | |
| Reviewer / date / disposition |
12. Review conclusion#
The schematic follows the Sensirion application circuit: commoned VDD/VDDH, pull-ups behind cut jumpers, and a deliberate 20 µF + 100 nF local reservoir sized for the documented 205 mA emitter peaks — the single most likely bench failure source if ignored. The protocol burden (16-bit commands, per-word CRC-8, execution-time waits, NACK-not-stretch semantics, the 500 ms stop window) lives in the host/HDL, and this guide pins the exact bytes to send and expect. Principal open risks: no layout (sensor-opening keep-out, paste keep-out on the exposed pad, and reservoir placement are unproven), no fabricated first article, no bench data, and no reference CO2 instrument yet identified for absolute-accuracy verification. Nothing above should be read as evidence the board works — it is the plan for finding out.