drivers.SEN66.adafruit_sen6x.SEN66

class drivers.SEN66.adafruit_sen6x.SEN66(i2c: smbus2.SMBus | int, address: int = SEN6X_I2C_ADDRESS)

Bases: SEN6x

digraph inheritance4de373bce6 { bgcolor=transparent; rankdir=TB; ratio=compress; size="8.0, 6.0"; "SEN66" [URL="SEN66.html#drivers.SEN66.adafruit_sen6x.SEN66",fillcolor="#e8f4f8",fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="filled,rounded",target="_top",tooltip="Driver for the Sensirion SEN66 multi-parameter air-quality sensor."]; "SEN6x" -> "SEN66" [arrowhead=empty,arrowsize=0.8,style="setlinewidth(0.5)"]; "SEN6x" [URL="SEN6x.html#drivers.SEN66.adafruit_sen6x.SEN6x",fillcolor="#e8f4f8",fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="filled,rounded",target="_top",tooltip="Base class for the Sensirion SEN6x environmental-sensor family."]; }

Driver for the Sensirion SEN66 multi-parameter air-quality sensor.

Adds the SEN66-specific measurement, raw-value, particle number-concentration, temperature-compensation, VOC/NOx algorithm tuning, and CO2 (forced recalibration, automatic self-calibration, ambient pressure, and altitude) commands on top of the family base SEN6x. The SEN66 reports PM1.0, PM2.5, PM4.0 and PM10 mass concentrations (microgram per cubic metre), a VOC index, a NOx index, CO2 concentration (ppm), relative humidity (percent), and temperature (degrees Celsius) — all over a single I2C transaction.

Variables:
  • _measurement_data (dict[str, float | None] | None) – Cached result of the most recent all_measurements() call; None until the first successful read. The single-channel convenience properties (temperature, humidity, pm2_5, voc_index, nox_index, co2) re-trigger a measurement and then read from this cache.

  • _measurement_time (float | None) – time.monotonic() timestamp of the first successful measurement; used to detect the CO2/NOx startup phase.

Example

>>> from smbus2 import SMBus
>>> sensor = SEN66(SMBus(1))
>>> sensor.start_measurement()
>>> sensor.all_measurements()
{'pm1_0': ..., 'co2': ..., ...}

See also

SEN6x:

Family base class providing the shared protocol.

drivers.SEN66.SEN66.SEN66:

High-level Oizom wrapper around this class.

Initialise a SEN66-specific driver on top of the SEN6x base.

Forwards i2c and address to SEN6x.__init__() (which opens or wraps the SMBus, waits for sensor startup, and prepares the cached fields) and then sets the SEN66-specific measurement and timestamp caches to None.

Parameters:
  • i2c (smbus2.SMBus | int) – Either an already-open smbus2.SMBus handle or a Linux I2C bus number; in the latter case the SMBus is opened internally.

  • address (int) – 7-bit I2C address of the SEN66. Defaults to SEN6X_I2C_ADDRESS (0x6B); this should normally be left alone for SEN66 hardware.

Returns:

None

Raises:

OSError – Propagated from smbus2.SMBus when opening the bus by index fails.

Example

>>> sensor = SEN66(SMBus(1))

Note

The SEN66 uses Sensirion command 0x0300 for the read measurement call (handled by all_measurements()), distinct from the family-wide commands implemented in SEN6x.

_check_measurements() None

Populate _measurement_data if it is still empty.

Convenience helper used by code paths that need to read a single derived value but do not want to issue all_measurements() themselves. If the cache is already populated this is a no-op; otherwise it pulls a fresh measurement frame and stores it.

Parameters:

None

Returns:

None

Raises:

Example

>>> sensor._check_measurements()

Note

Internally relies on Sensirion command 0x0300 (SEN66 read measurement) via all_measurements().

static _crc8(data: bytes) int

Compute the Sensirion CRC8 checksum for an arbitrary byte string.

Implements the byte-wise CRC8 used by every Sensirion air-quality sensor: polynomial 0x31 (x**8 + x**5 + x**4 + 1), initial value 0xFF, no input or output reflection, no final XOR. Each input byte is XORed into the running CRC, then the CRC is shifted left 8 times with the polynomial XORed in whenever the high bit was set, and finally masked to 8 bits.

Parameters:

data (bytes) – Raw input bytes — typically a single big-endian 16-bit word — whose CRC8 is required.

Returns:

8-bit unsigned CRC value (0..255) suitable for appending after data on the wire, or for comparing to the CRC byte that follows data in a read response.

Return type:

int

Raises:

None

Example

>>> SEN6x._crc8(b"\xBE\xEF")
146

Note

Used directly by _write_command() to protect every argument word and by _read_data() to validate every response word.

_read_data(num_words: int, execution_time: float = _TIME_STANDARD) list[int]

Read and CRC-verify a sequence of 16-bit words from the SEN6x.

Sensirion sensors stream their responses as [MSB, LSB, CRC8] triplets per 16-bit word, so this helper sleeps execution_time first (to let the previous command finish), issues a single num_words * 3 byte smbus2.i2c_msg.read, then validates every word’s CRC8 (polynomial 0x31, init 0xFF) before unpacking each pair into a big-endian unsigned integer.

Parameters:
  • num_words (int) – Number of 16-bit words the device is expected to return after the most recent command; num_words * 3 bytes are read off the wire.

  • execution_time (float) – Seconds to sleep before issuing the read so the device has had time to prepare the response. Defaults to _TIME_STANDARD (20 ms).

Returns:

List of num_words 16-bit unsigned integers decoded from the I2C response in protocol order.

Return type:

list[int]

Raises:
  • RuntimeError – If the CRC8 of any returned word does not match the CRC byte from the device, indicating bus corruption.

  • OSError – Propagated from smbus2.SMBus.i2c_rdwr on an underlying I2C error.

Example

>>> dev._read_data(1)
[...]

Note

CRC is the same Sensirion variant used in _write_command(); one CRC byte follows every word in the response.

_write_command(command: int, data: list[int] | None = None, execution_time: float = _TIME_STANDARD) None

Send a Sensirion 16-bit command, with optional CRC-protected data.

Packs the command big-endian into a bytearray; if a data payload is supplied, each 16-bit word is also packed big-endian and followed by its CRC8 byte (polynomial 0x31, init 0xFF) before being concatenated to the buffer. The whole buffer is then sent in a single smbus2.i2c_msg.write transfer and the call sleeps for execution_time so the sensor has time to act before the host issues the matching read.

Parameters:
  • command (int) – 16-bit Sensirion command ID (the value already encodes the Sensirion command CRC bits; callers pass constants such as _START_MEASUREMENT / 0x0021).

  • data (list[int] | None) – Optional list of 16-bit argument words to append after the command; each word is CRC8-protected on the wire. Defaults to None (command only).

  • execution_time (float) – Seconds to sleep after the write transfer so the device can execute the command. Defaults to _TIME_STANDARD (20 ms).

Returns:

None

Raises:

OSError – Propagated from smbus2.SMBus.i2c_rdwr if the I2C transaction fails (NACK, bus error, etc.).

Example

>>> dev._write_command(0x0021)

Note

All SEN6x command IDs are 16-bit big-endian; per-word CRC8 is mandatory for both writes and reads. The polynomial is 0x31 (x**8 + x**5 + x**4 + 1) with 0xFF initialisation, matching the Sensirion air- quality sensor convention.

all_measurements() dict[str, float | None]

Read every channel of the SEN66 in a single I2C transaction.

Triggers the SEN66 read measurement command and decodes the nine 16-bit words it returns into a dictionary of PM, humidity, temperature, VOC, NOx, and CO2 values, applying the datasheet scale factors (PM /10, RH /100, temperature /200, VOC and NOx /10, CO2 as-is). The result is cached on self._measurement_data so subsequent reads of the per-channel convenience properties do not have to re-pull all nine channels.

Parameters:

None

Returns:

Mapping with keys pm1_0, pm2_5, pm4_0, pm10 (microgram per cubic metre), humidity (percent), temperature (degrees Celsius), voc_index and nox_index (1.0..500.0), and co2 (ppm). Any channel that reports the “unknown” sentinel 0xFFFF/0x7FFF is returned as None.

Return type:

dict[str, float | None]

Raises:

Example

>>> sensor.start_measurement()
>>> sensor.all_measurements()
{'pm1_0': 3.2, 'pm2_5': 4.1, ...}

Note

Sensirion command 0x0300 (SEN66 read measurement); CO2 values stay 0xFFFF (decoded as None) for the first ~5-6 s after start_measurement() and NOx values stay 0x7FFF (also None) for the first ~10-11 s after power-on or reset.

check_sensor_errors() None

Raise if any critical sensor-error flags are currently set.

Reads device_status once and raises a RuntimeError if either the fan-error bit is set (which invalidates every channel) or any of the PM, gas, or RH+T error bits are set. Intended to be called immediately before a measurement read so callers can fail fast rather than persisting bogus values.

Parameters:

None

Returns:

Returns silently when no critical error bits are set.

Return type:

None

Raises:
  • RuntimeError – When the fan-error bit is set (“Fan error detected - measurements unreliable”), or when any of the PM, gas, or RH+T error bits are set (“Sensor errors detected: …”).

  • OSError – Propagated from the underlying SMBus transfer used by device_status.

Example

>>> dev.check_sensor_errors()

Note

Internally triggers Sensirion command 0xD206 (device_status) via device_status; does not clear any flags.

clear_device_status() None

Clear all sticky error and warning flags in the status register.

Sensirion error flags are “sticky” — once set they persist across the underlying condition disappearing, until the host explicitly clears them or the sensor is reset. This call issues the clear command; flags whose underlying condition is still active will be re-asserted on the next status read.

Parameters:

None

Returns:

None

Raises:

OSError – Propagated from the underlying SMBus transfer.

Example

>>> dev.clear_device_status()

Note

Sensirion command 0xD210 (clear_device_status) with an execution delay of _TIME_STANDARD (20 ms).

force_co2_recalibration(target_co2_ppm: int) int | None

Perform forced CO2 recalibration (FRC) against a known reference.

Forces the SEN66’s CO2 channel to recalibrate to target_co2_ppm; the sensor must already be at a known steady-state CO2 concentration (for example outdoor air at ~420 ppm) for the result to be meaningful. The device returns the applied correction so callers can sanity-check the adjustment.

Parameters:

target_co2_ppm (int) – Known CO2 concentration in ppm at the sensor’s current location.

Returns:

Correction applied in ppm (response_word - 0x8000), or None when the sensor signals that recalibration failed by returning 0xFFFF.

Return type:

int | None

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.force_co2_recalibration(420)
12

Note

Sensirion command 0x6707 (perform_forced_co2_recalibration); the host must wait at least 1000 ms after power-on or 600 ms after stop_measurement() before issuing it. The 500 ms execution delay _TIME_CO2_RECALIBRATION is built into the write, so the subsequent read uses 0 ms.

nox_algorithm_tuning(index_offset: int = 1, learning_time_offset_hours: int = 12, gating_max_duration_minutes: int = 720, gain_factor: int = 230) None

Overwrite the SEN66 NOx algorithm tuning parameters.

Updates the four configurable NOx-algorithm tuning values. The two NOx-fixed fields (learning_time_gain_hours = 12 and std_initial = 50) are filled in automatically so the host need only supply the meaningful inputs. Each argument is range-checked against the bounds documented by Sensirion before the values are written.

Parameters:
  • index_offset (int) – NOx index for average conditions; range 1..``250``. Defaults to 1.

  • learning_time_offset_hours (int) – Time constant for offset learning; range 1..``1000``. Defaults to 12.

  • gating_max_duration_minutes (int) – Maximum gating duration; range 0..``3000`` (0 disables gating). Defaults to 720.

  • gain_factor (int) – Output gain factor; range 1..``1000``. Defaults to 230.

Returns:

None

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.nox_algorithm_tuning(
...     gating_max_duration_minutes=600
... )

Note

Sensirion command 0x60E1 (set_nox_algorithm_tuning_parameters); configuration is volatile and reverts to defaults on power cycle. learning_time_gain_hours is forced to 12 and std_initial to 50 because the NOx channel ignores other values.

number_concentration() dict[str, float | None]

Read particle number-concentration values from the SEN66.

Pulls the five-channel number-concentration response from the sensor and decodes each 16-bit word through the /10 scale factor that the SEN66 uses for these values.

Parameters:

None

Returns:

Mapping with keys nc_pm0_5, nc_pm1_0, nc_pm2_5, nc_pm4_0, and nc_pm10, all expressed as particles per cubic centimetre. None is used for any channel that returns the unknown sentinel 0xFFFF.

Return type:

dict[str, float | None]

Raises:

Example

>>> sensor.number_concentration()
{'nc_pm0_5': 12.1, 'nc_pm1_0': 18.4, ...}

Note

Sensirion command 0x0316 (read number concentration); execution time _TIME_READ_MEASUREMENT (20 ms).

raw_values() dict[str, float | None]

Read the SEN66 raw signal channels (pre-algorithm values).

Returns the raw outputs from the on-board RH+T, VOC, NOx, and CO2 sensors before the Sensirion VOC/NOx index algorithms run, useful for diagnostics or off-device signal processing.

Parameters:

None

Returns:

Mapping with keys raw_humidity (percent), raw_temperature (degrees Celsius), raw_voc (raw ticks), raw_nox (raw ticks), and raw_co2 (ppm, updated only every ~5 s internally). Any channel returning the unknown sentinel is decoded as None.

Return type:

dict[str, float | None]

Raises:

Example

>>> sensor.raw_values()
{'raw_humidity': 35.4, 'raw_temperature': 24.8, ...}

Note

Sensirion command 0x0405 (read raw values); RH+T use scale factors 100/200, VOC and NOx are returned as integer ticks, CO2 is in ppm.

reset() None

Reset the SEN6x sensor and wait for it to come back up.

Issues the Sensirion reset command, clears the local _measurement_started flag and the cached serial number and product name, then sleeps _SENSOR_STARTUP_TIME so the sensor has time to reboot before further commands are sent. All on-device configuration values (temperature offset, VOC/NOx tuning, ambient pressure/altitude, CO2 ASC state, etc.) are restored to their factory defaults.

Parameters:

None

Returns:

None

Raises:

OSError – Propagated from the underlying SMBus transfer.

Example

>>> dev.reset()

Note

Sensirion command 0xD304 (reset) with an execution time of _TIME_RESET (1.2 s); a further 1 s startup sleep is applied here, matching the constructor.

start_fan_cleaning() None

Spin the fan up to maximum for 10 s to blow out accumulated dust.

Spins the SEN6x fan up to its maximum speed for ten seconds so any dust that has settled in the PM channel is blown clear. The command is only valid when the sensor is in idle mode; callers are expected to wait at least 10 seconds after invoking this before calling start_measurement() again.

Parameters:

None

Returns:

None

Raises:
  • RuntimeError – If the sensor is currently in measurement mode (self._measurement_started is True); callers must stop_measurement() first.

  • OSError – Propagated from the underlying SMBus transfer.

Example

>>> dev.stop_measurement()
>>> dev.start_fan_cleaning()

Note

Sensirion command 0x5607 (start_fan_cleaning) with an execution delay of _TIME_STANDARD (20 ms); the actual cleaning runs for ~10 s on the device side.

start_measurement() None

Switch the sensor into continuous measurement mode.

Sends the Sensirion start measurement command and sets the _measurement_started flag so subsequent calls become no-ops; the sensor then continuously updates its internal result registers and raises the data_ready flag once per measurement cycle.

Parameters:

None

Returns:

None

Raises:

OSError – Propagated from the underlying SMBus transfer.

Example

>>> dev.start_measurement()

Note

Sensirion command 0x0021 (start_measurement) with an execution delay of _TIME_START_MEASUREMENT (50 ms); first valid measurement frame is available about _FIRST_MEASUREMENT_DELAY (1.1 s) later.

stop_measurement() None

Return the sensor to idle mode so configuration can be changed.

Sends the Sensirion stop measurement command and clears the _measurement_started flag. Many configuration commands (CO2 FRC/ASC, temperature acceleration, VOC/NOx tuning, altitude, fan cleaning, …) require the device to be in idle mode and must be preceded by this call.

Parameters:

None

Returns:

None

Raises:

OSError – Propagated from the underlying SMBus transfer.

Example

>>> dev.stop_measurement()

Note

Sensirion command 0x0104 (stop_measurement) with an execution time of _TIME_STOP_MEASUREMENT (1 s).

temperature_acceleration(k: float = 10.0, p: float = 10.0, t1: float = 10.0, t2: float = 10.0) None

Configure temperature-acceleration filter parameters of the RH+T engine.

Overwrites the four temperature-acceleration constants used by the SEN66’s RH+T compensation engine. The supplied values are scaled by 10 on the wire (i.e. a Python value of 10.0 is transmitted as 100 and represents on-device 10.0).

Parameters:
  • k (float) – Filter constant K. Defaults to 10.0.

  • p (float) – Filter constant P. Defaults to 10.0.

  • t1 (float) – Time constant T1 in seconds. Defaults to 10.0.

  • t2 (float) – Time constant T2 in seconds. Defaults to 10.0.

Returns:

None

Raises:
  • RuntimeError – If called while measurement mode is active; the sensor requires idle mode for this command. Call stop_measurement() first.

  • OSError – Propagated from the underlying SMBus transfer.

Example

>>> sensor.stop_measurement()
>>> sensor.temperature_acceleration()

Note

Sensirion command 0x6100 (set temperature acceleration parameters); configuration is volatile and is reset to defaults on power cycle.

temperature_offset(offset: float = 0.0, slope: float = 0.0, time_constant: int = 0, slot: int = 0) None

Configure a temperature-offset slot for design-in compensation.

Configures one of the SEN66’s five temperature-offset slots so the reported temperature is corrected for the thermal environment of the host PCB. The on-device formula is compensated_temp = ambient_temp + (slope * ambient_temp) + offset; a non-zero time_constant causes the change to be applied gradually over that many seconds rather than instantaneously.

Parameters:
  • offset (float) – Constant temperature offset in degrees Celsius added to the raw reading; defaults to 0.0. Scaled by 200 on the wire.

  • slope (float) – Temperature-dependent offset factor; defaults to 0.0. Scaled by 10000 on the wire.

  • time_constant (int) – Time constant in seconds for fading the new offset in. 0 (default) applies the change immediately.

  • slot (int) – Offset slot to write (0..``4``); the SEN66 maintains five independent slots that are summed at runtime. Defaults to 0.

Returns:

None

Raises:
  • ValueError – If slot is outside 0..4.

  • OSError – Propagated from the underlying SMBus transfer.

Example

>>> sensor.temperature_offset(offset=-1.5)

Note

Sensirion command 0x60B2 (set temperature offset parameters); configuration is volatile and is reset to defaults on power cycle.

voc_algorithm_tuning(index_offset: int = 100, learning_time_offset_hours: int = 12, learning_time_gain_hours: int = 12, gating_max_duration_minutes: int = 180, std_initial: int = 50, gain_factor: int = 230) None

Overwrite the SEN66 VOC algorithm tuning parameters.

Updates the six VOC-algorithm tuning values used by the on-device VOC index calculation. Each input is range-checked against the bounds documented by Sensirion before the values are written.

Parameters:
  • index_offset (int) – VOC index value for average conditions; range 1..``250``. Defaults to 100.

  • learning_time_offset_hours (int) – Time constant for offset learning; range 1..``1000``. Defaults to 12.

  • learning_time_gain_hours (int) – Time constant for gain learning; range 1..``1000``. Defaults to 12.

  • gating_max_duration_minutes (int) – Maximum gating duration; range 0..``3000`` (0 disables gating). Defaults to 180.

  • std_initial (int) – Initial standard deviation; range 10..``5000``. Defaults to 50.

  • gain_factor (int) – Output gain factor; range 1..``1000``. Defaults to 230.

Returns:

None

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.voc_algorithm_tuning(index_offset=120)

Note

Sensirion command 0x60D0 (set_voc_algorithm_tuning_parameters); configuration is volatile and reverts to defaults on power cycle.

_address: int = 107
_measurement_data: dict[str, float | None] | None = None
_measurement_started: bool = False
_measurement_time: float | None = None
_product_name: str | None = None
_serial_number: str | None = None
property ambient_pressure: int

Ambient pressure currently used for SEN66 CO2 compensation.

Parameters:

None

Returns:

Currently configured ambient pressure in hPa (hectopascals).

Return type:

int

Raises:

Example

>>> sensor.ambient_pressure
1013

Note

Sensirion command 0x6720 (get_ambient_pressure); the SEN66 stores the value as a single 16-bit hPa integer.

property co2: float | None

Latest SEN66 CO2 concentration in parts per million.

Parameters:

None

Returns:

Most recent CO2 reading in ppm, or None when the channel currently reports “unknown” (normal during the first ~5-6 s after start_measurement()).

Return type:

float | None

Raises:

Example

>>> sensor.co2
420.0

Note

Calls all_measurements() every access (Sensirion command 0x0300); CO2 compensation is also affected by ambient_pressure and sensor_altitude.

property co2_automatic_self_calibration: bool

Whether the SEN66 CO2 automatic self-calibration (ASC) is enabled.

Parameters:

None

Returns:

True if ASC is enabled, False if disabled.

Return type:

bool

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.co2_automatic_self_calibration
True

Note

Sensirion command 0x6711 (get_co2_automatic_self_calibration); only the low-order byte of the returned word carries the status.

property data_ready: bool

Whether a fresh measurement frame is waiting on the SEN6x.

Parameters:

None

Returns:

True when the sensor has produced a new measurement that has not yet been read; False if the sensor is in idle mode or the previous frame has already been consumed.

Return type:

bool

Raises:

Example

>>> dev.start_measurement()
>>> dev.data_ready
True

Note

Sensirion command 0x0202 (data_ready); only the least-significant bit of the returned word carries the ready flag.

property device_status: DeviceStatus

Current 32-bit device status register, parsed into a typed object.

Parameters:

None

Returns:

A fresh DeviceStatus wrapping the two 16-bit words just read from the device, exposing individual fan/PM/gas/RH+T/CO2 flags and the DeviceStatus.errors and DeviceStatus.warnings aggregates.

Return type:

DeviceStatus

Raises:

Example

>>> dev.device_status.errors
False

Note

Sensirion command 0xD206 (device_status); the two response words are concatenated MSB-first into a 32-bit value before being handed to DeviceStatus.

property error_status_description: dict[str, str]

Human-readable summary of which error flags are set and why it matters.

Parameters:

None

Returns:

Mapping from short error tag ("fan", "pm", "gas", "rht", "co2") to a short English sentence explaining what the flag means for the measurement results; entries for flags that are not set are omitted, so an empty dict means the sensor is healthy.

Return type:

dict[str, str]

Raises:

Example

>>> dev.error_status_description
{}

Note

Backed by Sensirion command 0xD206 (device_status); the descriptions exposed here match the wording in the SEN66 datasheet.

property humidity: float | None

Latest SEN66 relative humidity reading, in percent.

Parameters:

None

Returns:

Most recent relative humidity in percent, or None when the channel currently reports “unknown”.

Return type:

float | None

Raises:

Example

>>> sensor.humidity
35.4

Note

Calls all_measurements() every access (Sensirion command 0x0300).

property nox_algorithm: dict[str, int]

Read the SEN66 NOx algorithm tuning parameters currently in effect.

Parameters:

None

Returns:

Mapping with keys index_offset, learning_time_offset_hours, learning_time_gain_hours (has no effect for NOx), gating_max_duration_minutes, std_initial (has no effect for NOx), and gain_factor as currently programmed in the device.

Return type:

dict[str, int]

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.nox_algorithm
{'index_offset': 1, ...}

Note

Sensirion command 0x60E1 (get_nox_algorithm_tuning_parameters); response is six 16-bit words but two fields are inert on the NOx channel (see Sensirion datasheet).

property nox_index: float | None

Latest SEN66 NOx index value (1.0..500.0).

Parameters:

None

Returns:

Most recent NOx index (Sensirion NOx algorithm output, 1.0..500.0), or None if the channel currently reports “unknown” (which is normal for the first ~10-11 s after power-on).

Return type:

float | None

Raises:

Example

>>> sensor.nox_index
1.0

Note

Calls all_measurements() every access (Sensirion command 0x0300).

property pm2_5: float | None

Latest SEN66 PM2.5 mass concentration in microgram per cubic metre.

Parameters:

None

Returns:

Most recent PM2.5 reading (microgram per cubic metre), or None if the channel currently reports “unknown”.

Return type:

float | None

Raises:

Example

>>> sensor.pm2_5
4.1

Note

Calls all_measurements() every access (Sensirion command 0x0300).

property product_name: str

The SEN6x product name string as reported by the device.

Parameters:

None

Returns:

ASCII product name (for example "SEN66") with trailing null bytes stripped. Cached after the first read.

Return type:

str

Raises:

Example

>>> dev.product_name
'SEN66'

Note

Sensirion command 0xD014 (get_product_name); the response is 32 bytes (16 words) of null-padded ASCII.

property sensor_altitude: int

Sensor altitude currently used for SEN66 CO2 compensation.

Parameters:

None

Returns:

Configured sensor altitude in metres above sea level.

Return type:

int

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.sensor_altitude
0

Note

Sensirion command 0x6736 (get_sensor_altitude); the SEN66 stores the value as a single 16-bit metres integer.

property serial_number: str

The SEN6x serial number as an ASCII string (up to 32 characters).

Parameters:

None

Returns:

ASCII serial number read from the sensor, with any trailing null bytes stripped. The value is cached after the first successful read so subsequent accesses are free.

Return type:

str

Raises:

Example

>>> dev.serial_number
'...'

Note

Sensirion command 0xD033 (get_serial_number); the response is 32 bytes (16 words) of null-padded ASCII.

property sht_heater_measurements: dict[str, float | None]

RH+T values produced while the SHT internal heater is active.

Available on firmware >= 4.0 only; intended to monitor the progress of an SHT heater cycle (used to drive moisture out of the RH+T sensor). While heating is still in progress the sensor returns the unknown sentinel value for one or both channels, which is surfaced here as None.

Parameters:

None

Returns:

Mapping with keys "humidity" (relative humidity, percent) and "temperature" (degrees Celsius); either value is None when heating has not yet finished.

Return type:

dict[str, float | None]

Raises:

Example

>>> dev.sht_heater_measurements
{'humidity': 35.4, 'temperature': 24.8}

Note

Sensirion command 0x6790 (activate_sht_heater); response uses scale factors 100 for humidity and 200 for temperature.

property temperature: float | None

Latest SEN66 temperature reading in degrees Celsius.

Parameters:

None

Returns:

Most recent temperature in degrees Celsius, or None when the channel currently reports “unknown”.

Return type:

float | None

Raises:

Example

>>> sensor.temperature
24.8

Note

Calls all_measurements() every access (Sensirion command 0x0300); cache the dict if you need multiple channels at the same instant.

property version: tuple[int, int]

The on-device firmware version as a (major, minor) tuple.

Parameters:

None

Returns:

(major_version, minor_version) pair decoded from the high and low bytes of the single 16-bit response word.

Return type:

tuple[int, int]

Raises:

Example

>>> dev.version
(4, 0)

Note

Sensirion command 0xD100 (read_version); the response packs major in the high byte and minor in the low byte of one word.

property voc_algorithm: dict[str, int]

Read the SEN66 VOC algorithm tuning parameters currently in effect.

Parameters:

None

Returns:

Mapping with keys index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial and gain_factor as currently programmed in the device.

Return type:

dict[str, int]

Raises:

Example

>>> sensor.stop_measurement()
>>> sensor.voc_algorithm
{'index_offset': 100, ...}

Note

Sensirion command 0x60D0 (get_voc_algorithm_tuning_parameters); response is six 16-bit words.

property voc_algorithm_state: bytes

Snapshot of the current VOC algorithm state for backup/restore.

Can be called either in idle or in measurement mode. In measurement mode it returns the live algorithm state; in idle mode it returns the state from when measurement was last stopped. The returned blob can later be written back through the setter to skip the VOC learning phase after a power cycle.

Parameters:

None

Returns:

Exactly 8 bytes (four 16-bit words concatenated big-endian) representing the VOC algorithm state.

Return type:

bytes

Raises:

Example

>>> blob = sensor.voc_algorithm_state
>>> len(blob)
8

Note

Sensirion command 0x6181 (get_voc_algorithm_state); response is 4 words = 8 bytes.

property voc_index: float | None

Latest SEN66 VOC index value (1.0..500.0).

Parameters:

None

Returns:

Most recent VOC index (Sensirion VOC algorithm output, 1.0..500.0), or None if the channel currently reports “unknown”.

Return type:

float | None

Raises:

Example

>>> sensor.voc_index
102.3

Note

Calls all_measurements() every access (Sensirion command 0x0300).