drivers.SEN66.adafruit_sen6x.SEN66¶
- class drivers.SEN66.adafruit_sen6x.SEN66(i2c: smbus2.SMBus | int, address: int = SEN6X_I2C_ADDRESS)¶
Bases:
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."]; }SEN6xDriver 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 recentall_measurements()call;Noneuntil 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 toNone.- Parameters:
i2c (
smbus2.SMBus | int) – Either an already-opensmbus2.SMBushandle 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 toSEN6X_I2C_ADDRESS(0x6B); this should normally be left alone for SEN66 hardware.
- Returns:
None
- Raises:
OSError – Propagated from
smbus2.SMBuswhen opening the bus by index fails.
Example
>>> sensor = SEN66(SMBus(1))
Note
The SEN66 uses Sensirion command
0x0300for the read measurement call (handled byall_measurements()), distinct from the family-wide commands implemented inSEN6x.- _check_measurements() None¶
Populate
_measurement_dataif 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:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor._check_measurements()
Note
Internally relies on Sensirion command
0x0300(SEN66 read measurement) viaall_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 value0xFF, 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:
- 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 singlenum_words * 3bytesmbus2.i2c_msg.read, then validates every word’s CRC8 (polynomial0x31, init0xFF) 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 * 3bytes 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:
- 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_rdwron 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 (polynomial0x31, init0xFF) before being concatenated to the buffer. The whole buffer is then sent in a singlesmbus2.i2c_msg.writetransfer 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 toNone(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_rdwrif 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) with0xFFinitialisation, 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_dataso 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_indexandnox_index(1.0..500.0), andco2(ppm). Any channel that reports the “unknown” sentinel0xFFFF/0x7FFFis returned asNone.- Return type:
- Raises:
RuntimeError – If
start_measurement()has not been called yet, or from_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.start_measurement() >>> sensor.all_measurements() {'pm1_0': 3.2, 'pm2_5': 4.1, ...}
Note
Sensirion command
0x0300(SEN66 read measurement); CO2 values stay0xFFFF(decoded asNone) for the first ~5-6 s afterstart_measurement()and NOx values stay0x7FFF(alsoNone) 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_statusonce and raises aRuntimeErrorif 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) viadevice_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), orNonewhen the sensor signals that recalibration failed by returning0xFFFF.- Return type:
int | None
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.OSError – Propagated from the underlying SMBus transfer.
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 afterstop_measurement()before issuing it. The 500 ms execution delay_TIME_CO2_RECALIBRATIONis 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 = 12andstd_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; range1..``250``. Defaults to1.learning_time_offset_hours (
int) – Time constant for offset learning; range1..``1000``. Defaults to12.gating_max_duration_minutes (
int) – Maximum gating duration; range0..``3000`` (0disables gating). Defaults to720.gain_factor (
int) – Output gain factor; range1..``1000``. Defaults to230.
- Returns:
None
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.ValueError – If any argument is outside its documented range.
OSError – Propagated from the underlying SMBus transfer.
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_hoursis forced to12andstd_initialto50because 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, andnc_pm10, all expressed as particles per cubic centimetre.Noneis used for any channel that returns the unknown sentinel0xFFFF.- Return type:
- Raises:
RuntimeError – If
start_measurement()has not been called yet, or from_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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), andraw_co2(ppm, updated only every ~5 s internally). Any channel returning the unknown sentinel is decoded asNone.- Return type:
- Raises:
RuntimeError – If
start_measurement()has not been called yet, or from_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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_startedflag and the cached serial number and product name, then sleeps_SENSOR_STARTUP_TIMEso 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_startedisTrue); callers muststop_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_startedflag so subsequent calls become no-ops; the sensor then continuously updates its internal result registers and raises thedata_readyflag 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_startedflag. 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.0is transmitted as100and represents on-device10.0).- Parameters:
- 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 to0.0. Scaled by 200 on the wire.slope (
float) – Temperature-dependent offset factor; defaults to0.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 to0.
- 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; range1..``250``. Defaults to100.learning_time_offset_hours (
int) – Time constant for offset learning; range1..``1000``. Defaults to12.learning_time_gain_hours (
int) – Time constant for gain learning; range1..``1000``. Defaults to12.gating_max_duration_minutes (
int) – Maximum gating duration; range0..``3000`` (0disables gating). Defaults to180.std_initial (
int) – Initial standard deviation; range10..``5000``. Defaults to50.gain_factor (
int) – Output gain factor; range1..``1000``. Defaults to230.
- Returns:
None
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.ValueError – If any argument is outside its documented range.
OSError – Propagated from the underlying SMBus transfer.
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.
- property ambient_pressure: int¶
Ambient pressure currently used for SEN66 CO2 compensation.
- Parameters:
None
- Returns:
Currently configured ambient pressure in hPa (hectopascals).
- Return type:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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
Nonewhen the channel currently reports “unknown” (normal during the first ~5-6 s afterstart_measurement()).- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.co2 420.0
Note
Calls
all_measurements()every access (Sensirion command0x0300); CO2 compensation is also affected byambient_pressureandsensor_altitude.
- property co2_automatic_self_calibration: bool¶
Whether the SEN66 CO2 automatic self-calibration (ASC) is enabled.
- Parameters:
None
- Returns:
Trueif ASC is enabled,Falseif disabled.- Return type:
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.OSError – Propagated from the underlying SMBus transfer.
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:
Truewhen the sensor has produced a new measurement that has not yet been read;Falseif the sensor is in idle mode or the previous frame has already been consumed.- Return type:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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
DeviceStatuswrapping the two 16-bit words just read from the device, exposing individual fan/PM/gas/RH+T/CO2 flags and theDeviceStatus.errorsandDeviceStatus.warningsaggregates.- Return type:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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 toDeviceStatus.
- 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:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch while reading the status register.OSError – Propagated from the underlying SMBus transfer.
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
Nonewhen the channel currently reports “unknown”.- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.humidity 35.4
Note
Calls
all_measurements()every access (Sensirion command0x0300).
- 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), andgain_factoras currently programmed in the device.- Return type:
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.OSError – Propagated from the underlying SMBus transfer.
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
Noneif the channel currently reports “unknown” (which is normal for the first ~10-11 s after power-on).- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.nox_index 1.0
Note
Calls
all_measurements()every access (Sensirion command0x0300).
- 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
Noneif the channel currently reports “unknown”.- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.pm2_5 4.1
Note
Calls
all_measurements()every access (Sensirion command0x0300).
- 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:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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:
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.OSError – Propagated from the underlying SMBus transfer.
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:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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 isNonewhen heating has not yet finished.- Return type:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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
Nonewhen the channel currently reports “unknown”.- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.temperature 24.8
Note
Calls
all_measurements()every access (Sensirion command0x0300); 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:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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_initialandgain_factoras currently programmed in the device.- Return type:
- Raises:
RuntimeError – If the sensor is currently measuring;
stop_measurement()must be called first.OSError – Propagated from the underlying SMBus transfer.
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:
- Raises:
RuntimeError – From
_read_data()on a CRC mismatch.OSError – Propagated from the underlying SMBus transfer.
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
Noneif the channel currently reports “unknown”.- Return type:
float | None
- Raises:
RuntimeError – From
all_measurements()if the sensor is not in measurement mode or a CRC check fails.OSError – Propagated from the underlying SMBus transfer.
Example
>>> sensor.voc_index 102.3
Note
Calls
all_measurements()every access (Sensirion command0x0300).