ENS160
ScioSense ENS160 digital metal-oxide multi-gas sensor (TVOC, eCO2, AQI-UBA).
Live catalog
Prefer labwired_describe with the catalog id over guessing pins or addresses.
Status at a glance
| Aspect | Status |
|---|---|
| Catalog id | ens160 |
| Bus | I²C |
| Address | 0x52 (0x53 with MISO/ADDR high) |
| Source | configs/devices/ens160.yaml (declarative, no Rust model) |
| Datasheet | ScioSense ENS160 datasheet v1.3 (SC-001224-DS-9), §16 Registers |
| Tier | smoke-proven (register-level tests: crates/core/tests/everyday_sensor_set.rs) |
Pins / attachment
| Pin / net | Role |
|---|---|
| SDA | I²C SDA |
| SCL | I²C SCL |
| VDD/GND | Power (digital twin) |
Support matrix
| Behavior | Status | Notes |
|---|---|---|
| PART_ID 0x0160 (little-endian) | ✅ | Reads 0x60, 0x01 |
| OPMODE (IDLE at power-on, STANDARD 0x02, RESET 0xF0) | ✅ | RESET returns OPMODE to IDLE only |
| DATA_AQI 0x21 / DATA_TVOC 0x22 / DATA_ECO2 0x24 | ✅ | Live in STANDARD only; defaults until then, last value held after |
| DEVICE_STATUS STATAS / NEWDAT | ⚠️ | NEWDAT has no published cadence; ready at every poll |
| DEVICE_STATUS VALIDITY | ⚠️ | Host-driven validity channel (warm-up / start-up) |
| TEMP_IN / RH_IN → DATA_T / DATA_RH | ✅ | Copied; compensation itself not modelled |
| MOx algorithm, COMMAND / GPR, DATA_MISR, INTn | ❌ | Not modelled |
Stimulus
Host inputs: tvoc (ppb), eco2 (ppm), aqi (1..5), validity (0..3).
How to run
- Place the part and an MCU in Playground, or add it to a system YAML:
- Agent:
labwired_list→labwired_describe id=ens160→ wire →labwired_validate→labwired_run/labwired_verify. - Register-level smoke:
cargo test -p labwired-core --test everyday_sensor_set— PART_ID, OPMODE = IDLE, then STANDARD with AQI 2 / 100 ppb / 600 ppm. The same file's negative control proves the check fails against a part that answers only 0x00 or only 0xFF.
Limitations
- The three outputs are independent host channels; ScioSense's TrueVOC algorithm that relates them is not modelled.
- DATA_TVOC is at 0x22 (datasheet Table 16); 0x26 is reserved.
- Warm-up (3 min) and initial start-up (1 h) are posed by the host through
validity, not timed.
See the YAML header for the full datasheet trace and every named approximation.