← AXS-043

Circuit review & bench-test guide

AXS-043 — CCS811 eCO2/TVOC gas-sensor PMOD module

Design-stage — board not yet fabricated

Document purpose#

This document explains the axs-043-eco2 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-043-eco2.kicad_sch), the module README, and the ams CCS811 datasheet (v1-06, 2019-Feb-07).

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 — register values, currents, timings, burn-in behavior — 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 ams (ScioSense) CCS811B-JOPD500, a metal-oxide (MOX) gas sensor with an integrated MCU that converts raw resistance readings into equivalent CO2 (eCO2, 400–29206 ppm) and equivalent total VOC (eTVOC, 0–32768 ppb) estimates. Unlike the SCD40 (AXS-042), this is not a true CO2 measurement — eCO2 is inferred from VOCs, mainly of human origin. The module substitutes the CCS811 for the catalog's original ENS160 (no stock KiCad assets) and teaches the same lessons: boot-to-application state machine (APP_START), measurement-mode selection, data-ready interrupt, baseline save/restore, and the nWAKE handshake.

I2C address is 0x5A (default, JP4 1-2) or 0x5B (JP4 2-3). nWAKE is grounded by default (JP3 1-2, always awake) or handed to the host on PMOD pin 2 (JP3 2-3). nINT reaches PMOD pin 1 through a 10 kΩ pull-up and 100 Ω series resistor. nRESET is pulled up on-module only and is not routed to the PMOD — resets are done through the I2C SW_RESET mailbox.

Functional block diagram#

 PMOD host J1
 3V3 (6,12) ──┬──────┬──────┬──────────────┐
 GND (5,11) ──┼──────┼──────┼───────┐      │
            C1 100n  C2 10µ R3 10k  │      │
              │      │      │       │      │
 SCL (3,9) ───┴──────┴──────┼────> U1 CCS811 (MOX eCO2/TVOC, addr 0x5A/0x5B)
 SDA (4,10) ────────────────┼────>  │
   (pull-ups R1/R2 4.7k     │       │ ADDR <── JP4 (1-2 GND=0x5A / 2-3 3V3=0x5B)
    via JP1/JP2)            │       │ nWAKE <─ JP3 (1-2 GND=awake / 2-3 host pin 2)
                            │       │ nRESET <─ R5 10k to 3V3 (on-module only)
 pin 1 ECO2_INT_N <── R4 100R ── nINT (open-drain, R3 10k pull-up)
 pin 2 ECO2_WAKE_N ──> JP3 pos. 3   │ PWM/Sense/AUX: no-connect per datasheet

2. Safety and scope boundaries#

3. Power and control sequence#

  1. 3V3/GND come from the PMOD host; no local regulator. C1/C2 decouple the pulsed MOX heater supply.
  2. Power-on: with nRESET held high by R5 and nWAKE low (JP3 default), the device boots in 18–20 ms (tSTART) into boot mode (FW_MODE = 0). It is not measuring yet.
  3. Host verifies HW_ID (0x20 = 0x81), checks STATUS (0x00) for APP_VALID = 1, then writes the register address 0xF4 (APP_START) with no data byte. Within 1 ms the device is in application mode (FW_MODE = 1).
  4. Host writes MEAS_MODE (0x01) to select a drive mode; this board's bring-up uses mode 1 (constant power, one measurement per second). DATA_READY in STATUS sets each cycle; nINT (if enabled by INT_DATARDY) pulls PMOD pin 1 low until ALG_RESULT_DATA is read.
  5. If JP3 is moved to 2-3, the host owns nWAKE on PMOD pin 2 and must drive it low before and throughout every I2C transaction; the device is ready within 50 µs of the falling edge (tWAKE) and nWAKE must stay high ≥20 µs (tDWAKE) between wakes.
  6. Reset paths: I2C SW_RESET mailbox 0xFF with the 4-byte key 0x11 0xE5 0x72 0x8A (back to boot mode in 1–2 ms), or a power cycle. nRESET is deliberately not routed off-module.

4. Interfaces#

PMOD pin map (Type 6 extended, J1)#

Pin123456789101112
NetECO2_INT_NECO2_WAKE_NSCLSDAGND3V3NCNCSCLSDAGND3V3

Pin 2 is only driven into the sensor when JP3 is set 2-3; in the default position the net dead-ends at the jumper.

Jumpers#

Ref.TypeDefaultFunction
JP12-pad solder jumper, bridgedfittedSDA pull-up R1 in circuit; cut when a chained module provides pull-ups
JP22-pad solder jumper, bridgedfittedSCL pull-up R2 in circuit; cut likewise
JP33-pad solder jumper, 1-2 bridgednWAKE = GND (always awake)2-3 hands nWAKE to the host as ECO2_WAKE_N on PMOD pin 2
JP43-pad solder jumper, 1-2 bridgedADDR = GND → 0x5A2-3 sets ADDR = 3V3 → 0x5B

Test points#

None are defined in the schematic. Probe at J1 pins and jumper pads. Layout should add TPs for nINT, nWAKE, nRESET, SDA, SCL, and 3V3.

5. Component-by-component review#

Every reference designator in generate_design.py is covered.

5.1 Active device and connector#

Ref.Part / datasheet summaryFunction and why neededIf absent/openIf shorted, wrong, or misassembled
U1ams CCS811B-JOPD500, LGA-10 2.7×4.0 mm, MOX eCO2/TVOC with integrated MCU, VDD 1.8–3.3 VThe sensor and its algorithm engineNo ACK; module inertRotated LGA misconnects the heater pins; PWM (4) and Sense (5) must be tied together inside this design's no-NTC option they float per datasheet note — see review note below; solder voids under the EP break the ground return
J112-pin PMOD plugHost power, I2C, interrupt, optional wakeNo power/busReversed insertion puts 3V3/GND on signal pins

PWM/Sense review note: the datasheet's recommended circuit connects pins 4 and 5 together (heater loop). This schematic leaves PWM, Sense, and AUX as no-connects, citing the datasheet's external-NTC-unused guidance. This is a deliberate deviation to re-verify against the datasheet and ScioSense application note before layout — if pins 4-5 must be commoned even without the NTC network, the schematic needs a one-wire fix. Flagged OPEN.

5.2 Pull-ups, series parts, and decoupling#

Refs.ValueFunctionIf omitted or wrong
R14.7 kΩ (Yageo RC0603FR-074K7L)SDA pull-up to 3V3 through JP1Bus floats without another pull-up source
R24.7 kΩ (Yageo RC0603FR-074K7L)SCL pull-up to 3V3 through JP2Same, on the clock
R310 kΩ (Yageo RC0603FR-0710KL)Pull-up for the open-drain nINT outputnINT never returns high reliably; host sees a stuck interrupt
R4100 Ω (Yageo RC0603FR-07100RL)Series protection between sensor nINT and host pin (fault-current limiting on a sensor-driven line)Direct pin-to-pin coupling; a host driving against the sensor sources unlimited current
R510 kΩ (Yageo RC0603FR-0710KL)nRESET pull-up, on-module only (datasheet: 4.7 kΩ pull-up and/or decoupling "may be necessary to avoid erroneous noise-induced resets")nRESET has a weak internal pull-up, but noise-induced resets become plausible; with R5 open the reset behavior is unverified
C1100 nF 16 V X7R (Murata GRM188R71C104KA01D)VDD high-frequency decoupling (datasheet requires a decoupling cap close to VDD)Heater-pulse noise on VDD; risk of boot-sampling errors since VDD is sampled at boot
C210 µF 10 V X5R 0805 (Murata GRM21BR61A106KE19L)Bulk reservoir for the pulsed MOX heater (datasheet circuit shows 4.7 µF; 10 µF is a superset)Supply droop during heater pulses; marginal operation on soft supplies
JP1/JP2/JP3/JP4solder jumpersSee section 4A 3-pad jumper with no side bridged floats ADDR or nWAKE: ADDR must be tied per datasheet, and a floating nWAKE can park the device in sleep — always bridge exactly one side

5.3 ERC-only artifacts#

Refs.What they areReview note
#FLG01 (3V3), #FLG02 (GND)KiCad PWR_FLAG symbolsERC markers only; no physical part, no test action

6. Datasheet summary and design interpretation#

DeviceKey manufacturer facts used hereBoard-specific interpretation
CCS811 (v1-06)VDD 1.8–3.3 V operating, 1.8–3.6 V abs max; IDD ≈26 mA typ while measuring, 30 mA abs-max average (mode 1), 54 mA abs-max peak (modes 2/3), 19 µA sleep; I2C 10–400 kHz, addresses 0x5A/0x5B via ADDR; clock stretching 0–100 ms max — the host I2C master must support clock stretching; tSTART 18–20 ms after power-on, 1–2 ms after reset; tAPP_START ≤1 ms; tWAKE ≤50 µs after falling nWAKE; tDWAKE ≥20 µs; nRESET low ≥15 µs; HW_ID (0x20) = 0x81; HW_Version (0x21) = 0x1X; STATUS (0x00) bits FW_MODE(7)/APP_VALID(4)/DATA_READY(3)/ERROR(0); MEAS_MODE (0x01) DRIVE_MODE bits 6:4, INT_DATARDY bit 3; ALG_RESULT_DATA (0x02) 8 bytes; BASELINE (0x11) 2-byte save/restore; ERROR_ID (0xE0); SW_RESET (0xFF) key 0x11 0xE5 0x72 0x8A; eCO2 400–29206 ppm, eTVOC 0–32768 ppb; burn-in 48 h (usable after 60 min), run-in 20 min after each MEAS_MODE write; mode changes to a slower mode require 10 min in mode 0 firstThe 3.3 V rail is at the top of the operating range — verify no overshoot. The 100 ms clock-stretch ceiling is the notorious CCS811 erratum territory: many MCU/FPGA masters (and bit-banged masters with fixed timeouts) fail here; the AruviX HDL I2C master must implement SCL-released detection with a ≥100 ms timeout, or run SCL slow (10–100 kHz) during bring-up. nWAKE grounded via JP3 default removes the tWAKE burden for first bring-up; the 2-3 position exists to teach the handshake later
Baseline managementBASELINE (0x11) holds an encoded baseline; automatic baseline correction runs over ≥24 h windows; manual save/restore per ams AN000370; conditioning (run-in) must be observed before writing BASELINESave the baseline after long clean-air operation, restore after power cycles for faster useful readings; never write a baseline into an un-conditioned sensor
PassivesYageo RC series; Murata capacitorsStandard parts, no special constraints at 3.3 V

Official references: CCS811 datasheet v1-06 (SparkFun-hosted ams PDF), ScioSense CCS811 product page (ams gas sensing was transferred to ScioSense; check there for current documentation and application notes AN000369/AN000370/AN000371), Yageo RC thick-film resistors, Murata capacitor search. Note the CCS811 is end-of-life at ScioSense (successor ENS160 — the catalog's original choice); confirm stock before committing the BOM.

7. Expected values before bench testing#

All values are datasheet/design targets, not measurements.

QuantityDesign targetWhat to measure
SDA/SCL idle level3.3 V high through R1/R2DMM at J1 pins 3/4
SDA/SCL to 3V3, unpowered≈4.7 kΩ each (JP1/JP2 fitted); open if cutOhmmeter
nINT idle≈3.3 V through R3 (via R4 at pin 1)DMM at J1 pin 1
nWAKE at sensor0 V (JP3 1-2 default)DMM at JP3 common pad
ADDR at sensor0 V (JP4 1-2) → address 0x5ADMM at JP4 common pad
Boot timeready for I2C 18–20 ms after powerDelay before first transaction
Idle/boot supply currentwell under measuring levels; sleep spec 19 µA (nWAKE high) — "verify against datasheet" for a boot-idle figure, which v1-06 does not tabulate separatelyBench supply
Supply current, mode 1 measuring≈26 mA typ pulses; ≤30 mA average (abs max); ≤54 mA peaks if modes 2/3 triedBench supply / scope
HW_ID (0x20)0x81First transaction
HW_Version (0x21)0x1X (top nibble 1)Read
STATUS after bootFW_MODE = 0, APP_VALID = 1, ERROR = 0 (e.g. 0x10)Read 0x00
STATUS after APP_STARTFW_MODE = 1 (e.g. 0x90; 0x98 once data ready)Read 0x00
First readings (new sensor)eCO2 pinned 400 ppm, eTVOC 0 ppb — normal during early burn-in/run-inALG_RESULT_DATA
Readings after 20 min run-ineCO2 400–29206 ppm range; responds to VOC stimulus (alcohol swab, breath) within secondsALG_RESULT_DATA trend
Clock stretch eventsup to 100 ms SCL held lowScope/analyzer on SCL

8. Manual schematic and assembly review checklist#

9. Ordered bench-test procedure#

Stop at the first abnormal result. Assumed bench: PMOD host (3.3 V, verified ≤3.3 V no-overshoot) or current-limited 3.3 V supply, limit ≈100 mA. Run SCL at 100 kHz or slower until clock-stretch handling is proven.

A. Unpowered inspection and resistance tests#

  1. Complete the checklist in section 8 under magnification.
  2. Ohmmeter: SDA-to-3V3 ≈4.7 kΩ, SCL-to-3V3 ≈4.7 kΩ (JP1/JP2 fitted verification; cut = open). nINT-node-to-3V3 ≈10 kΩ (R3); J1 pin 1 to the sensor nINT pad ≈100 Ω (R4).
  3. JP3 common to GND: ≈0 Ω (default). JP4 common to GND: ≈0 Ω (default).
  4. 3V3-to-GND: no hard short (rises as C2 charges).

B. First power-up, bus idle#

  1. Apply 3.3 V, limit 100 mA. Wait ≥20 ms (tSTART).
  2. Supply current: expect a small boot-mode value, far below measuring levels; record it. Tens of mA before MEAS_MODE is set is suspicious.
  3. DMM: SDA, SCL ≈3.3 V; nINT (J1 pin 1) ≈3.3 V.

C. Address ACK and first transaction: HW_ID#

  1. I2C scan at ≤100 kHz: expect ACK at 0x5A only (JP4 default). With JP4 re-bridged 2-3, expect 0x5B only. Both ACKing, or neither, means a strap/solder problem.
  2. First transaction — HW_ID readback:
  1. Read HW_Version 0x21: expect 0x1X. Read STATUS 0x00: expect FW_MODE = 0 (boot), APP_VALID = 1, ERROR = 0 — typically 0x10.
  2. If ERROR = 1: read ERROR_ID 0xE0 (this also clears the error) and decode bits 0–5 (WRITE_REG_INVALID, READ_REG_INVALID, MEASMODE_INVALID, MAX_RESISTANCE, HEATER_FAULT, HEATER_SUPPLY).

D. App-start sequence and measurement mode#

  1. Confirm STATUS shows APP_VALID = 1 and FW_MODE = 0.
  2. APP_START: write the register address alone, no data byte: S 0x5A+W ACK 0xF4 ACK P. Wait ≥1 ms (tAPP_START).
  3. Re-read STATUS: expect FW_MODE = 1 (e.g. 0x90). FW_MODE still 0 means the app did not start — check APP_VALID and ERROR_ID.
  4. MEAS_MODE: write drive mode 1 with data-ready interrupt enabled: S 0x5A+W ACK 0x01 ACK 0x18 ACK P (DRIVE_MODE = 001, INT_DATARDY = 1; use 0x10 if polling STATUS instead of using nINT).
  5. Within ~1 s: STATUS DATA_READY (bit 3) sets each second; with 0x18, nINT (J1 pin 1) pulses low each cycle and releases when ALG_RESULT_DATA is read. Scope it: this is the interrupt-wiring test for R3/R4.

E. First data read and burn-in honesty#

  1. Read ALG_RESULT_DATA (0x02), 8 bytes: byte 0/1 = eCO2 ppm (MSB first), byte 2/3 = eTVOC ppb, byte 4 = STATUS, byte 5 = ERROR_ID, bytes 6/7 = RAW_DATA (current source 6 bits + 10-bit raw ADC).
  2. Expected early behavior — do not mislabel it a failure: a new sensor in burn-in, or any sensor in its first 20-minute run-in after MEAS_MODE, legitimately reports eCO2 = 400 ppm, eTVOC = 0 ppb flat. Datasheet conditions: 48-hour early-life burn-in (readings usable after 60 min in modes 1–3) and 20-minute conditioning after each mode write; conditioning must also pass before writing BASELINE.
  3. Stimulus test (direction, not magnitude): an alcohol swab waved near the sensor must spike eTVOC (and eCO2 upward) within seconds, decaying after removal. This proves the MOX element and heater work long before absolute accuracy is meaningful.
  4. Log STATUS/ERROR_ID with every sample; any ERROR bit fails the run until decoded.

F. Baseline, wake handshake, and reset paths (second session)#

  1. After ≥20 min run-in in clean air (ideally after 48 h burn-in), read BASELINE (0x11, 2 bytes) and store it with the board record. Restore it after a power cycle and confirm readings converge faster. Follow ams AN000370 semantics; never restore a stale baseline across mode changes.
  2. JP3 2-3 wake handshake test: move JP3 to 2-3; host must drive ECO2_WAKE_N (pin 2) low ≥ tWAKE-settled (device ready ≤50 µs after the falling edge) before each transaction, hold it low throughout, and keep it high ≥20 µs (tDWAKE) between transactions. Verify: with pin 2 held high, the device must NACK (asleep, ~19 µA); with pin 2 low, HW_ID reads 0x81 again.
  3. SW_RESET: write 0xFF 0x11 0xE5 0x72 0x8A in one transaction; wait 2 ms; STATUS must show FW_MODE = 0 again; repeat APP_START to recover.
  4. Mode-change discipline check: switching to a slower mode (e.g. 1 → 3) requires 10 minutes in mode 0 first; verify the driver enforces it.

G. Clock-stretch stress (before HDL sign-off)#

  1. With a scope on SCL, capture stretch events during ALG_RESULT_DATA reads and around APP_START; the datasheet allows up to 100 ms.
  2. Sweep SCL 10 → 100 → 400 kHz; the AruviX I2C master must complete transfers at each speed or degrade gracefully. Any master timeout shorter than 100 ms is a design bug on this bus, not a sensor fault.

10. Troubleshooting map#

SymptomFirst measurementsLikely areas
No ACK at 0x5A/0x5BSDA/SCL idle, ADDR pad voltage, nWAKE pad voltageJP4 unbridged/floating, JP3 unbridged (device asleep), JP1/JP2 cut without external pull-ups, U1 solder
ACK at 0x5B when 0x5A expectedJP4 bridge sideStrap bridged 2-3, or 3V3 solder whisker to ADDR
HW_ID not 0x81Repeat at 10 kHz; scope SCL for stretchingMaster clock-stretch mishandling (classic CCS811 failure), bus corruption
APP_START does not set FW_MODESTATUS APP_VALID bit; ERROR_IDNo valid app firmware (APP_VALID = 0), data byte wrongly appended to the 0xF4 write
MEAS_MODE write errorsERROR_ID bit 2 (MEASMODE_INVALID)Reserved bits set, unsupported mode code
DATA_READY never setsSTATUS each second; supply currentMEAS_MODE still 0 (idle), heater fault (ERROR_ID bits 4/5), VDD droop during heater pulses (C1/C2)
nINT never asserts but DATA_READY setsINT_DATARDY bit; R3/R4 continuityMEAS_MODE written 0x10 not 0x18, open R3/R4, pin-1 wiring
nINT stuck lowRead ALG_RESULT_DATA (releases it)Data never read; solder short on the nINT net
Readings stuck 400 ppm / 0 ppbTime since power-on and mode writeNormal burn-in/run-in behavior — wait 20 min (and up to 48 h for spec accuracy) before judging
Wild/pinned-high readingsERROR_ID MAX_RESISTANCE; environmentSensor poisoning (siloxanes), end-of-life element, contaminated assembly
Random resets to boot modeVDD at U1 during heater pulses; R5Supply droop/noise on nRESET (datasheet warns of noise-induced resets), boot-time VDD variation

11. Bench record template#

FieldRecord
Board revision / serial
JP1–JP4 positions; measured pull-up/strap resistances
Host/supply, current limit, measured rail (incl. overshoot check)
Address-scan result
HW_ID / HW_Version / FW_Boot_Version (0x23) / FW_App_Version (0x24)
STATUS before and after APP_START
MEAS_MODE value written; time of write
Supply current in mode 1 (average and pulse capture)
Time-stamped eCO2/eTVOC log incl. stimulus response
Clock-stretch capture (max duration observed, SCL speed)
BASELINE value saved / restore result
Wake-handshake test result (if JP3 2-3 exercised)
SW_RESET recovery result
Deviations, captures, raw-file paths
Reviewer / date / disposition

12. Review conclusion#

The schematic is a reasonable CCS811 application: strap-selectable address, default-grounded nWAKE for painless bring-up with a jumpered path to the real handshake, an on-module-only nRESET (forcing the more instructive SW_RESET path), protected open-drain interrupt routing, and heater-aware decoupling. Three open items dominate: (1) the PWM/Sense pins are floated where the datasheet's application circuit ties pins 4 and 5 together — resolve before layout; (2) the 100 ms clock-stretch requirement must be designed into the AruviX I2C master, since this is the CCS811's best-known integration failure; (3) the part is end-of-life at ScioSense, so BOM availability (or a pivot back to the ENS160 once symbols exist) needs a decision. Beyond those: no layout, no fabricated first article, and no bench data exist — the burn-in/run-in expectations above are written precisely so that a fresh board's boring 400 ppm/0 ppb output is not misread as either success or failure.