Sensor pinout
-
| *Pin* | *Cable Color* | *Name* | *Description* | *Comments* |
diff --git a/ci/checkin_doc.sh b/ci/checkin_doc.sh
deleted file mode 100644
index 1031751..0000000
--- a/ci/checkin_doc.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-# set shell settings (see https://sipb.mit.edu/doc/safe-shell/)
-set -euv -o pipefail
-
-# clone the repo into a subfolder html, checkout the gh-pages into this folder and commit the freshly generated html
-git clone "git@gitlab:${CI_PROJECT_PATH}.git" html
-cd html
-git checkout gh-pages
-rm -f empty.txt
-rm -f *.html
-rm -f *.js
-rm -rf _*
-cd ..
-# make sure to copy .nojekyll
-cp -rf public/.[!.]* public/* html
-cd html
-git add .
-
-if git diff-index --quiet HEAD --
-then
- exit 0
-fi
-
-git commit -m"Automatic doc update: ${CI_COMMIT_SHORT_SHA}"
-git push
\ No newline at end of file
diff --git a/ci/set_git_config.sh b/ci/set_git_config.sh
deleted file mode 100644
index 860c6aa..0000000
--- a/ci/set_git_config.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-# set shell settings (see https://sipb.mit.edu/doc/safe-shell/)
-set -eufv -o pipefail
-
-# install ssh private key (set as CI variable in GitLab project settings)
-mkdir -p ~/.ssh
-echo "$SSH_DEPLOY_KEY" > ~/.ssh/id_rsa
-chmod 400 ~/.ssh/id_rsa
-
-# change remote URL to SSH to allow pushing with SSH
-git remote set-url --push origin "git@gitlab:${CI_PROJECT_PATH}.git"
-
-# set git author
-git config --global user.name "GitLab-CI"
-git config --global user.email "<>"
diff --git a/docs/conf.py b/docs/conf.py
index 4cbbb71..b7326c4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -4,11 +4,12 @@
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
import os
import sys
from datetime import datetime
-import pkg_resources
+import importlib.metadata as metadata
import sphinx.ext.autodoc
import sensirion_i2c_sen66
@@ -17,16 +18,16 @@
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
# -- Project information -----------------------------------------------------
-distribution = pkg_resources.get_distribution('sensirion_i2c_sen66')
+distribution = metadata.distribution("sensirion_i2c_sen66")
-project = u'sensirion_i2c_sen66'
+project = distribution.name
copyright = u'{} Sensirion AG, Switzerland'.format(datetime.now().year)
author = 'Sensirion AG'
# The short X.Y version
-version = sensirion_i2c_sen66.__version__
+version = distribution.version
# The full version, including alpha/beta/rc tags
-release = sensirion_i2c_sen66.__version__
+release = distribution.version
# -- General configuration ---------------------------------------------------
diff --git a/docs/execute-measurements.rst b/docs/execute-measurements.rst
index 36f0fe7..3028026 100644
--- a/docs/execute-measurements.rst
+++ b/docs/execute-measurements.rst
@@ -26,7 +26,7 @@ execute a simple measurement.
python examples/example_usage_sensorbridge_sen66.py --serial-port
-.. _Sensirion SEK-SensorBridge: https://developer.sensirion.com/sensirion-products/sek-sensorbridge/
+.. _Sensirion SEK-SensorBridge: https://developer.sensirion.com/product-support/sek-sensorbridge/
.. _SensorBridge FTDI Driver Installation: https://sensirion.github.io/python-shdlc-sensorbridge/sensor-bridge-installation.html
Example script
diff --git a/examples/SEN6x_I2C_FRC_CO2_example_linux_sen66.py b/examples/SEN6x_I2C_FRC_CO2_example_linux_sen66.py
new file mode 100644
index 0000000..85045bf
--- /dev/null
+++ b/examples/SEN6x_I2C_FRC_CO2_example_linux_sen66.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Wait at least one second after power on
+ time.sleep(1.0)
+
+ # Perform forced recalibration
+ correction = sensor.perform_forced_co2_recalibration(600)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_FRC_CO2_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_FRC_CO2_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..b70b297
--- /dev/null
+++ b/examples/SEN6x_I2C_FRC_CO2_example_sensorbridge_sen66.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Wait at least one second after power on
+ time.sleep(1.0)
+
+ # Perform forced recalibration
+ correction = sensor.perform_forced_co2_recalibration(600)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_change_NOX_parameters_example_linux_sen66.py b/examples/SEN6x_I2C_change_NOX_parameters_example_linux_sen66.py
new file mode 100644
index 0000000..c25b778
--- /dev/null
+++ b/examples/SEN6x_I2C_change_NOX_parameters_example_linux_sen66.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set nox parameters:
+ # index_offset = 1
+ # learning_time_offset_hours = 12
+ # learning_time_gain_hours = 12
+ # gating_max_duration_minutes = 720
+ # std_initial = 50
+ # gain_factor = 230
+ sensor.set_nox_algorithm_tuning_parameters(1, 12, 12, 720, 50, 230)
+
+ # Start continuous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_change_NOX_parameters_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_change_NOX_parameters_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..35defd8
--- /dev/null
+++ b/examples/SEN6x_I2C_change_NOX_parameters_example_sensorbridge_sen66.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set nox parameters:
+ # index_offset = 1
+ # learning_time_offset_hours = 12
+ # learning_time_gain_hours = 12
+ # gating_max_duration_minutes = 720
+ # std_initial = 50
+ # gain_factor = 230
+ sensor.set_nox_algorithm_tuning_parameters(1, 12, 12, 720, 50, 230)
+
+ # Start continuous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_change_VOC_parameters_example_linux_sen66.py b/examples/SEN6x_I2C_change_VOC_parameters_example_linux_sen66.py
new file mode 100644
index 0000000..668ca57
--- /dev/null
+++ b/examples/SEN6x_I2C_change_VOC_parameters_example_linux_sen66.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set voc paramters:
+ # index_offset = 100
+ # learning_time_offset_hours = 12
+ # learning_time_gain_hours = 12
+ # gating_max_duration_minutes = 180
+ # std_initial = 50
+ # gain_factor = 230
+ sensor.set_voc_algorithm_tuning_parameters(100, 12, 12, 180, 50, 230)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_change_VOC_parameters_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_change_VOC_parameters_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..1e4f11f
--- /dev/null
+++ b/examples/SEN6x_I2C_change_VOC_parameters_example_sensorbridge_sen66.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set voc paramters:
+ # index_offset = 100
+ # learning_time_offset_hours = 12
+ # learning_time_gain_hours = 12
+ # gating_max_duration_minutes = 180
+ # std_initial = 50
+ # gain_factor = 230
+ sensor.set_voc_algorithm_tuning_parameters(100, 12, 12, 180, 50, 230)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_config_STAR_example_linux_sen66.py b/examples/SEN6x_I2C_config_STAR_example_linux_sen66.py
new file mode 100644
index 0000000..107bce0
--- /dev/null
+++ b/examples/SEN6x_I2C_config_STAR_example_linux_sen66.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set the temperature acceleration parameters
+ # k = 1
+ # p = 1
+ # t1 = 1
+ # t2 = 1
+ sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_config_STAR_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_config_STAR_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..ae978f0
--- /dev/null
+++ b/examples/SEN6x_I2C_config_STAR_example_sensorbridge_sen66.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set the temperature acceleration parameters
+ # k = 1
+ # p = 1
+ # t1 = 1
+ # t2 = 1
+ sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
+
+ # Start continous measurement
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_config_coldstart_example_linux_sen66.py b/examples/SEN6x_I2C_config_coldstart_example_linux_sen66.py
new file mode 100644
index 0000000..0ba9d8a
--- /dev/null
+++ b/examples/SEN6x_I2C_config_coldstart_example_linux_sen66.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set the temperature offset parameters:
+ # offset = -400
+ # slope = 0.02 * 1000
+ # time_constant = 800
+ # slot = 0
+ sensor.set_temperature_offset_parameters(-400, 20, 800, 0)
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_config_coldstart_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_config_coldstart_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..f1a1784
--- /dev/null
+++ b/examples/SEN6x_I2C_config_coldstart_example_sensorbridge_sen66.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ # Set the temperature offset parameters:
+ # offset = -400
+ # slope = 0.02 * 1000
+ # time_constant = 800
+ # slot = 0
+ sensor.set_temperature_offset_parameters(-400, 20, 800, 0)
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_heater_example_linux_sen66.py b/examples/SEN6x_I2C_heater_example_linux_sen66.py
new file mode 100644
index 0000000..27facc3
--- /dev/null
+++ b/examples/SEN6x_I2C_heater_example_linux_sen66.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.activate_sht_heater()
+ humi = 0
+ while True:
+ time.sleep(0.05)
+ (humi, t
+ ) = sensor.get_sht_heater_measurements()
+ print(f"current temperature: {t}"
+ )
+ print(f"current humidity: {humi}"
+ )
+ if humi == 32767:
+ break
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_heater_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_heater_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..9d9ccbe
--- /dev/null
+++ b/examples/SEN6x_I2C_heater_example_sensorbridge_sen66.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.activate_sht_heater()
+ humi = 0
+ while True:
+ time.sleep(0.05)
+ (humi, t
+ ) = sensor.get_sht_heater_measurements()
+ print(f"current temperature: {t}"
+ )
+ print(f"current humidity: {humi}"
+ )
+ if humi == 32767:
+ break
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_minimal_example_linux_sen66.py b/examples/SEN6x_I2C_minimal_example_linux_sen66.py
new file mode 100644
index 0000000..35fc3e0
--- /dev/null
+++ b/examples/SEN6x_I2C_minimal_example_linux_sen66.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_minimal_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_minimal_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..2d490e5
--- /dev/null
+++ b/examples/SEN6x_I2C_minimal_example_sensorbridge_sen66.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout data from the sensor
+ (mass_concentration_pm1p0, mass_concentration_pm2p5, mass_concentration_pm4p0, mass_concentration_pm10p0,
+ ambient_humidity, ambient_temperature, voc_index, nox_index, co2
+ ) = sensor.read_measured_values_as_integers()
+ print(f"Mass concentration pm1p0 [µg/m³]: {mass_concentration_pm1p0 / 10.0}"
+ )
+ print(f"Mass concentration pm2p5 [µg/m³]: {mass_concentration_pm2p5 / 10.0}"
+ )
+ print(f"Mass concentration pm4p0 [µg/m³]: {mass_concentration_pm4p0 / 10.0}"
+ )
+ print(f"Mass concentration pm10p0 [µg/m³]: {mass_concentration_pm10p0 / 10.0}"
+ )
+ print(f"Ambient humidity [%]: {ambient_humidity / 100.0}"
+ )
+ print(f"Ambient temperature [°C]: {ambient_temperature / 200.0}"
+ )
+ print(f"VOC index: {voc_index}"
+ )
+ print(f"NOX index: {nox_index}"
+ )
+ print(f"CO₂ [ppm]: {co2}"
+ )
diff --git a/examples/SEN6x_I2C_read_raw_example_linux_sen66.py b/examples/SEN6x_I2C_read_raw_example_linux_sen66.py
new file mode 100644
index 0000000..2f49269
--- /dev/null
+++ b/examples/SEN6x_I2C_read_raw_example_linux_sen66.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import LinuxI2cTransceiver, I2cConnection, CrcCalculator
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--i2c-port', '-p', default='/dev/i2c-1')
+args = parser.parse_args()
+
+with LinuxI2cTransceiver(args.i2c_port) as i2c_transceiver:
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout raw data from the sensor
+ (raw_humidity, raw_temperature, raw_voc, raw_nox, raw_co2
+ ) = sensor.read_measured_raw_values()
+ print(f"Raw humidity: {raw_humidity}"
+ )
+ print(f"Raw temperature: {raw_temperature}"
+ )
+ print(f"Raw VOC index: {raw_voc}"
+ )
+ print(f"Raw NOX index: {raw_nox}"
+ )
+ print(f"Raw CO₂: {raw_co2}"
+ )
diff --git a/examples/SEN6x_I2C_read_raw_example_sensorbridge_sen66.py b/examples/SEN6x_I2C_read_raw_example_sensorbridge_sen66.py
new file mode 100644
index 0000000..4dda647
--- /dev/null
+++ b/examples/SEN6x_I2C_read_raw_example_sensorbridge_sen66.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# (c) Copyright 2026 Sensirion AG, Switzerland
+#
+# THIS FILE IS AUTOMATICALLY GENERATED!
+#
+# Generator: sensirion-driver-generator 1.7.0
+# Product: sen66
+# Model-Version: 1.7.1
+#
+
+import argparse
+import time
+from sensirion_i2c_driver import I2cConnection, CrcCalculator
+from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection
+from sensirion_shdlc_sensorbridge import (SensorBridgePort,
+ SensorBridgeShdlcDevice,
+ SensorBridgeI2cProxy)
+from sensirion_driver_adapters.i2c_adapter.i2c_channel import I2cChannel
+from sensirion_i2c_sen66.device import Sen66Device
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--serial-port', '-p', default='COM1')
+args = parser.parse_args()
+
+with ShdlcSerialPort(port=args.serial_port, baudrate=460800) as port:
+ bridge = SensorBridgeShdlcDevice(ShdlcConnection(port), slave_address=0)
+ bridge.set_i2c_frequency(SensorBridgePort.ONE, frequency=100e3)
+ bridge.set_supply_voltage(SensorBridgePort.ONE, voltage=3.3)
+ bridge.switch_supply_on(SensorBridgePort.ONE)
+ i2c_transceiver = SensorBridgeI2cProxy(bridge, port=SensorBridgePort.ONE)
+ channel = I2cChannel(I2cConnection(i2c_transceiver),
+ slave_address=0x6B,
+ crc=CrcCalculator(8, 0x31, 0xff, 0x0))
+ sensor = Sen66Device(channel)
+ try:
+ sensor.stop_measurement()
+ time.sleep(0.05)
+
+ except: # noqa
+ print("stop measurement not successful"
+ )
+
+ sensor.start_continuous_measurement()
+ time.sleep(1.0)
+ for i in range(100):
+ (padding, data_ready
+ ) = sensor.get_data_ready()
+ if data_ready:
+
+ # Readout raw data from the sensor
+ (raw_humidity, raw_temperature, raw_voc, raw_nox, raw_co2
+ ) = sensor.read_measured_raw_values()
+ print(f"Raw humidity: {raw_humidity}"
+ )
+ print(f"Raw temperature: {raw_temperature}"
+ )
+ print(f"Raw VOC index: {raw_voc}"
+ )
+ print(f"Raw NOX index: {raw_nox}"
+ )
+ print(f"Raw CO₂: {raw_co2}"
+ )
diff --git a/examples/example_usage_linux_sen66.py b/examples/example_usage_linux_sen66.py
index b25b6d5..5327aaa 100644
--- a/examples/example_usage_linux_sen66.py
+++ b/examples/example_usage_linux_sen66.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
import argparse
@@ -31,6 +31,7 @@
print(f"serial_number: {serial_number}; "
)
sensor.start_continuous_measurement()
+ time.sleep(1.1)
for i in range(100):
try:
time.sleep(1.0)
diff --git a/examples/example_usage_sensorbridge_sen66.py b/examples/example_usage_sensorbridge_sen66.py
index 27c21e6..b5f4c2a 100644
--- a/examples/example_usage_sensorbridge_sen66.py
+++ b/examples/example_usage_sensorbridge_sen66.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
import argparse
@@ -40,6 +40,7 @@
print(f"serial_number: {serial_number}; "
)
sensor.start_continuous_measurement()
+ time.sleep(1.1)
for i in range(100):
try:
time.sleep(1.0)
diff --git a/images/product-image-sen6x.png b/images/product-image-sen6x.png
new file mode 100644
index 0000000..b97bde3
Binary files /dev/null and b/images/product-image-sen6x.png differ
diff --git a/images/product-pinout-sen6x.png b/images/product-pinout-sen6x.png
new file mode 100644
index 0000000..a940971
Binary files /dev/null and b/images/product-pinout-sen6x.png differ
diff --git a/metadata.yml b/metadata.yml
index fd42221..cfe9140 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,7 +1,7 @@
# driver generation metadata
-generator_version: 1.1.2
-model_version: 1.6.0
+generator_version: 1.7.0
+model_version: 1.7.1
dg_status: released
is_manually_modified: false
first_generated: '2024-10-30 08:14'
-last_generated: '2025-03-13 10:43'
+last_generated: '2026-06-05 11:22'
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8e0dc33
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,68 @@
+[build-system]
+requires = ["hatchling >= 1.26", "wheel >= 0.45.0"]
+build-backend = "hatchling.build"
+
+[project]
+name = "sensirion_i2c_sen66"
+description = "I2C driver for the Sensirion SEN66 sensor family"
+
+readme = "README.md"
+version = "1.3.0"
+
+requires-python = ">=3.8.4,<4.0"
+
+authors = [
+ { name = "Sensirion", email = "info@sensirion.com" },
+]
+
+license = "BSD-3-Clause"
+license-files = ["LICENSE"]
+
+keywords = [
+ "Sensirion SEN66",
+ "I2C",
+ "SEN66",
+ ]
+
+classifiers = [
+ "Intended Audience :: Developers",
+ "Topic :: System :: Hardware :: Hardware Drivers",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+]
+
+dependencies = [
+ "sensirion-driver-adapters>=2.3.0,<3.0",
+ "sensirion-driver-support-types>=1.2.0,<2.0",
+ "sensirion-i2c-driver>=1.0,<2.0",
+ "sensirion-shdlc-sensorbridge>=0.1.0,<2.0"
+ ]
+
+[project.optional-dependencies]
+
+docs=[
+ "jinja2~=3.1.6",
+ "sphinx-rtd-theme==3.0.2",
+ "sphinx>=7.0,<8.0;python_version < '3.11'",
+ "sphinx==8.2.3;python_version >= '3.11'",
+ "lazy-object-proxy ~=1.7.1",
+ "sphinx-autoapi~=3.0.0",
+]
+
+test= [
+ "flake8>=7.1.0",
+ "mock~=5.2.0",
+ "pytest>=8.3.5",
+ "pytest-cov>=5.0.0",
+ "mypy~=1.13.0",
+ "setuptools>=73.2.0"
+]
+
+[project.urls]
+Changelog = "https://github.com/Sensirion/python-i2c-sen66/blob/master/CHANGELOG.md"
+Repository = "https://github.com/Sensirion/python-i2c-sen66"
+Documentation = "https://sensirion.github.io/python-i2c-sen66"
+
diff --git a/sensirion_i2c_sen66/commands.py b/sensirion_i2c_sen66/commands.py
index 5c0132b..ac19af8 100644
--- a/sensirion_i2c_sen66/commands.py
+++ b/sensirion_i2c_sen66/commands.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
"""
The transfer classes specify the data that is transferred between host and sensor. The generated transfer classes
@@ -27,166 +27,24 @@ class DeviceStatus(BitfieldContainer):
gas_error = BitField(offset=7, width=1)
reserved3 = BitField(offset=8, width=1)
co2_2_error = BitField(offset=9, width=1)
- reserved4 = BitField(offset=10, width=1)
+ hcho_error = BitField(offset=10, width=1)
pm_error = BitField(offset=11, width=1)
- reserved5 = BitField(offset=12, width=1)
- reserved6 = BitField(offset=13, width=8)
+ co2_1_error = BitField(offset=12, width=1)
+ reserved4 = BitField(offset=13, width=8)
fan_speed_warning = BitField(offset=21, width=1)
+ reserved5 = BitField(offset=22, width=10)
-class StartContinuousMeasurement(Transfer):
- """
- Starts a continuous measurement.
- After starting the measurement, it takes some time (~1.1s) until the
- first measurement results are available. You could poll with the command
- "Get Data Ready" to check when the results are ready to read.
- This command is only available in idle mode. If the device is already
- in any measure mode, this command has no effect.
- """
-
- CMD_ID = 0x21
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.05, slave_address=None, ignore_ack=False)
-
-
-class StopMeasurement(Transfer):
- """
- Stops the measurement and returns to idle mode. After sending this
- command, wait at least 1000 ms before starting a new measurement.
- If the device is already in idle mode, this command has no effect.
- """
-
- CMD_ID = 0x104
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=1.0, slave_address=None, ignore_ack=False)
-
-
-class GetDataReady(Transfer):
- """
- This command can be used to check if new measurement results are ready to read. The data ready flag
- is automatically reset after reading the measurement values.
- """
-
- CMD_ID = 0x202
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>B?')
-
-
-class ReadMeasuredValuesAsIntegers(Transfer):
- """
- Returns the measured values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16,
- 0x7FFF for int16).
- """
-
- CMD_ID = 0x300
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>HHHHhhhhH')
-
-
-class ReadNumberConcentrationValuesAsIntegers(Transfer):
- """
- Returns the measured number concentration values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16).
- """
-
- CMD_ID = 0x316
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>HHHHH')
-
-
-class ReadMeasuredRawValues(Transfer):
- """
- Returns the measured raw values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16,
- 0x7FFF for int16).
- """
-
- CMD_ID = 0x405
-
- def pack(self):
- return self.tx_data.pack([])
-
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>hhHHH')
-
-
-class StartFanCleaning(Transfer):
- """
- This command triggers fan cleaning. The fan is set to the maximum
- speed for 10 seconds and then automatically stopped. Wait at least 10s
- after this command before starting a measurement.
- """
+class GetVocAlgorithmTuningParameters(Transfer):
+ """Gets the parameters to customize the VOC algorithm."""
- CMD_ID = 0x5607
+ CMD_ID = 0x60d0
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-
-
-class SetTemperatureOffsetParameters(Transfer):
- """
- This command allows to compensate temperature effects of the
- design-in at customer side by applying custom temperature offsets
- to the ambient temperature. The compensated ambient temperature is
- calculated as follows:
- T_Ambient_Compensated = T_Ambient + (slope * T_Ambient) + offset
- Where slope and offset are the values set with this command,
- smoothed with the specified time constant.
- All temperatures (T_Ambient_Compensated, T_Ambient and offset)
- are represented in °C.
- There are 5 temperature offset slots available that all contribute
- additively to T_Ambient_Compensated. The default values for
- the temperature offset parameters are all zero, meaning that
- T_Ambient_Compensated is equal to T_Ambient by default.
- The parameters can be changed in any state of the device, i.e. both in
- idle mode and in measure mode.
- """
-
- CMD_ID = 0x60b2
-
- def __init__(self, offset, slope, time_constant, slot):
- self._offset = offset
- self._slope = slope
- self._time_constant = time_constant
- self._slot = slot
-
- def pack(self):
- return self.tx_data.pack([self._offset, self._slope, self._time_constant, self._slot])
-
- tx = TxData(CMD_ID, '>HhhHH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>hhhhhh')
class SetVocAlgorithmTuningParameters(Transfer):
@@ -214,41 +72,42 @@ def pack(self):
tx = TxData(CMD_ID, '>Hhhhhhh', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-class GetVocAlgorithmTuningParameters(Transfer):
- """Gets the parameters to customize the VOC algorithm."""
+class GetVocAlgorithmState(Transfer):
+ """
+ Gets the current VOC algorithm state.
+ Allows to backup and restore the VOC algorithm state to resume operation after a power cycle or
+ device reset, skipping initial learning phase. By default, the VOC Engine is reset and the algorithm
+ state is retained if a measurement is stopped and started again. If the VOC algorithm
+ state shall be reset, a device reset or a power cycle can be executed.
+ """
- CMD_ID = 0x60d0
+ CMD_ID = 0x6181
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>hhhhhh')
+ rx = RxData('>8B')
-class SetNoxAlgorithmTuningParameters(Transfer):
+class SetVocAlgorithmState(Transfer):
"""
- Sets the parameters to customize the NOx algorithm.
- This configuration is volatile, i.e. the parameters will be
- reverted to their default values after a device reset.
+ Sets the VOC algorithm state previously received with "Get VOC Algorithm State" command.
+ Allows restoration of the VOC algorithm state to resume operation after a power cycle or device
+ reset, skipping initial learning phase. By default, the VOC Engine is reset, and the algorithm state is retained if
+ a measurement is stopped and started again. If the VOC algorithm state shall be reset, a device reset, or a
+ power cycle can be executed.
"""
- CMD_ID = 0x60e1
+ CMD_ID = 0x6181
- def __init__(self, index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes,
- std_initial, gain_factor):
- self._index_offset = index_offset
- self._learning_time_offset_hours = learning_time_offset_hours
- self._learning_time_gain_hours = learning_time_gain_hours
- self._gating_max_duration_minutes = gating_max_duration_minutes
- self._std_initial = std_initial
- self._gain_factor = gain_factor
+ def __init__(self, state):
+ self._state = state
def pack(self):
- return self.tx_data.pack([self._index_offset, self._learning_time_offset_hours, self._learning_time_gain_hours,
- self._gating_max_duration_minutes, self._std_initial, self._gain_factor])
+ return self.tx_data.pack([self._state])
- tx = TxData(CMD_ID, '>Hhhhhhh', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ tx = TxData(CMD_ID, '>H8B')
class GetNoxAlgorithmTuningParameters(Transfer):
@@ -263,81 +122,83 @@ def pack(self):
rx = RxData('>hhhhhh')
-class SetTemperatureAccelerationParameters(Transfer):
+class SetNoxAlgorithmTuningParameters(Transfer):
"""
- This command allows to set custom temperature acceleration parameters of the RH/T engine.
- It overwrites the default temperature acceleration parameters of the RH/T engine with custom values. This
- configuration is volatile, i.e. the parameters will be reverted to their default values after a device reset.
+ Sets the parameters to customize the NOx algorithm.
+ This configuration is volatile, i.e. the parameters will be
+ reverted to their default values after a device reset.
"""
- CMD_ID = 0x6100
+ CMD_ID = 0x60e1
- def __init__(self, k, p, t1, t2):
- self._k = k
- self._p = p
- self._t1 = t1
- self._t2 = t2
+ def __init__(self, index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes,
+ std_initial, gain_factor):
+ self._index_offset = index_offset
+ self._learning_time_offset_hours = learning_time_offset_hours
+ self._learning_time_gain_hours = learning_time_gain_hours
+ self._gating_max_duration_minutes = gating_max_duration_minutes
+ self._std_initial = std_initial
+ self._gain_factor = gain_factor
def pack(self):
- return self.tx_data.pack([self._k, self._p, self._t1, self._t2])
+ return self.tx_data.pack([self._index_offset, self._learning_time_offset_hours, self._learning_time_gain_hours,
+ self._gating_max_duration_minutes, self._std_initial, self._gain_factor])
- tx = TxData(CMD_ID, '>HHHHH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ tx = TxData(CMD_ID, '>Hhhhhhh', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-class SetVocAlgorithmState(Transfer):
+class PerformForcedCo2Recalibration(Transfer):
"""
- Sets the VOC algorithm state previously received with "Get VOC Algorithm State" command.
- Allows restoration of the VOC algorithm state to resume operation after a power cycle or device
- reset, skipping initial learning phase. By default, the VOC Engine is reset, and the algorithm state is retained if
- a measurement is stopped and started again. If the VOC algorithm state shall be reset, a device reset, or a
- power cycle can be executed.
+ Execute the forced recalibration (FRC) of the CO₂. See the datasheet of the
+ SCD4x sensor for details how the forced recalibration shall be used.
"""
- CMD_ID = 0x6181
+ CMD_ID = 0x6707
- def __init__(self, state):
- self._state = state
+ def __init__(self, target_co2_concentration):
+ self._target_co2_concentration = target_co2_concentration
def pack(self):
- return self.tx_data.pack([self._state])
+ return self.tx_data.pack([self._target_co2_concentration])
- tx = TxData(CMD_ID, '>H8B')
+ tx = TxData(CMD_ID, '>HH', device_busy_delay=0.5, slave_address=None, ignore_ack=False)
+ rx = RxData('>H')
-class GetVocAlgorithmState(Transfer):
+class PerformCo2SensorFactoryReset(Transfer):
"""
- Gets the current VOC algorithm state.
- Allows to backup and restore the VOC algorithm state to resume operation after a power cycle or
- device reset, skipping initial learning phase. By default, the VOC Engine is reset and the algorithm
- state is retained if a measurement is stopped and started again. If the VOC algorithm
- state shall be reset, a device reset or a power cycle can be executed.
+ This command resets all CO₂ sensor configuration settings
+ stored in the EEPROM and erases the FRC and ASC algorithm
+ history of the CO₂ sensor.
+ The configuration settings are CO₂ sensor temperature offset (cannot be
+ modified over I2C interface), sensor altitude and the ASC
+ enabled/disabled parameters which are by default stored
+ in the volatile memory (RAM).
+ This command is only available in idle mode.
"""
- CMD_ID = 0x6181
+ CMD_ID = 0x6754
def pack(self):
return self.tx_data.pack([])
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>8B')
+ tx = TxData(CMD_ID, '>H', device_busy_delay=1.4, slave_address=None, ignore_ack=False)
-class PerformForcedCo2Recalibration(Transfer):
+class GetCo2SensorAutomaticSelfCalibration(Transfer):
"""
- Execute the forced recalibration (FRC) of the CO₂. See the datasheet of the
- SCD4x sensor for details how the forced recalibration shall be used.
+ The CO₂ sensor supports automatic self calibration (ASC) for long-term
+ stability of the CO₂ output. This feature can be enabled or disabled.
+ By default it is enabled.
"""
- CMD_ID = 0x6707
-
- def __init__(self, target_co2_concentration):
- self._target_co2_concentration = target_co2_concentration
+ CMD_ID = 0x6711
def pack(self):
- return self.tx_data.pack([self._target_co2_concentration])
+ return self.tx_data.pack([])
- tx = TxData(CMD_ID, '>HH', device_busy_delay=0.5, slave_address=None, ignore_ack=False)
- rx = RxData('>H')
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>B?')
class SetCo2SensorAutomaticSelfCalibration(Transfer):
@@ -346,8 +207,6 @@ class SetCo2SensorAutomaticSelfCalibration(Transfer):
The CO₂ sensor supports automatic self calibration (ASC) for long-term
stability of the CO₂ output. This feature can be enabled or disabled.
By default it is enabled.
- This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device restart.
"""
CMD_ID = 0x6711
@@ -361,22 +220,20 @@ def pack(self):
tx = TxData(CMD_ID, '>HH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-class GetCo2SensorAutomaticSelfCalibration(Transfer):
+class GetAmbientPressure(Transfer):
"""
- The CO₂ sensor supports automatic self calibration (ASC) for long-term
- stability of the CO₂ output. This feature can be enabled or disabled.
- By default it is enabled.
- This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device restart.
+ Gets the ambient pressure value.
+ The ambient pressure can be used for pressure compensation in the CO₂
+ sensor.
"""
- CMD_ID = 0x6711
+ CMD_ID = 0x6720
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>B?')
+ rx = RxData('>H')
class SetAmbientPressure(Transfer):
@@ -402,14 +259,14 @@ def pack(self):
tx = TxData(CMD_ID, '>HH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-class GetAmbientPressure(Transfer):
+class GetSensorAltitude(Transfer):
"""
- Gets the ambient pressure value.
- The ambient pressure can be used for pressure compensation in the CO₂
+ Gets the current sensor altitude.
+ The sensor altitude can be used for pressure compensation in the CO₂
sensor.
"""
- CMD_ID = 0x6720
+ CMD_ID = 0x6736
def pack(self):
return self.tx_data.pack([])
@@ -438,62 +295,144 @@ def pack(self):
tx = TxData(CMD_ID, '>HH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
-class GetSensorAltitude(Transfer):
+class StartContinuousMeasurement(Transfer):
"""
- Gets the current sensor altitude.
- The sensor altitude can be used for pressure compensation in the CO₂
- sensor.
+ Starts a continuous measurement.
+ After starting the measurement, it takes some time (~1.1s) until the
+ first measurement results are available. You could poll with the command
+ "Get Data Ready" to check when the results are ready to read.
+ This command is only available in idle mode. If the device is already
+ in any measure mode, this command has no effect.
"""
- CMD_ID = 0x6736
+ CMD_ID = 0x21
def pack(self):
return self.tx_data.pack([])
- tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>H')
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.05, slave_address=None, ignore_ack=False)
-class ActivateShtHeater(Transfer):
+class StopMeasurement(Transfer):
"""
- This command allows to use the inbuilt heater in SHT sensor
- to reverse creep at high humidity.
- This command activates the SHT sensor heater with 200mW for 1s.
- The heater is then automatically deactivated again.
- The "get_sht_heater_measurements" command can be used to check if the
- heater has finished (firmware version >= 4.0).
- Wait at least 20s after this command before starting a measurement to get
- coherent temperature values (heating consequence to disappear).
+ Stops the measurement and returns to idle mode. After sending this
+ command, wait at least 1000 ms before starting a new measurement.
+ If the device is already in idle mode, this command has no effect.
"""
- CMD_ID = 0x6765
+ CMD_ID = 0x104
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=1.4, slave_address=None, ignore_ack=False)
+
+
+class GetDataReady(Transfer):
+ """
+ This command can be used to check if new measurement results are ready to read. The data ready flag
+ is automatically reset after reading the measurement values.
+ """
+
+ CMD_ID = 0x202
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>B?')
-class GetShtHeaterMeasurements(Transfer):
+class ReadNumberConcentrationValuesAsIntegers(Transfer):
"""
- Get the measured values when the SHT sensor heating is triggerd. If the
- heating is not finished, the returned humidity and temperature values
- are 0x7FFF.
+ Returns the measured number concentration values.
+ The command 0x0202 "Get Data Ready" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16).
"""
- CMD_ID = 0x6790
+ CMD_ID = 0x316
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>hh')
+ rx = RxData('>HHHHH')
-class GetProductName(Transfer):
- """Gets the product name from the device."""
+class SetTemperatureOffsetParameters(Transfer):
+ """
+ This command allows to compensate temperature effects of the
+ design-in at customer side by applying custom temperature offsets
+ to the ambient temperature.
- CMD_ID = 0xd014
+ The compensated ambient temperature is calculated as follows:
+
+ * T_Ambient_Compensated = T_Ambient + (slope * T_Ambient) + offset
+
+ Where \"slope\" and \"offset\" are the values set with this command,
+ smoothed with the specified time constant.
+ All temperatures (\"T_Ambient_Compensated\", \"T_Ambient\" and \"offset\")
+ are represented in °C.
+ There are 5 temperature offset slots available that all contribute
+ additively to \"T_Ambient_Compensated\". The default values for
+ the temperature offset parameters are all zero, meaning that
+ \"T_Ambient_Compensated\" is equal to \"T_Ambient\" by default.
+ The parameters can be changed in any state of the device, i.e. both in
+ idle mode and in measure mode.
+ """
+
+ CMD_ID = 0x60b2
+
+ def __init__(self, offset, slope, time_constant, slot):
+ self._offset = offset
+ self._slope = slope
+ self._time_constant = time_constant
+ self._slot = slot
+
+ def pack(self):
+ return self.tx_data.pack([self._offset, self._slope, self._time_constant, self._slot])
+
+ tx = TxData(CMD_ID, '>HhhHH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+
+
+class SetTemperatureAccelerationParameters(Transfer):
+ """
+ This command allows to set custom temperature acceleration parameters of the RH/T engine.
+ It overwrites the default temperature acceleration parameters of the RH/T engine with custom values. This
+ configuration is volatile, i.e. the parameters will be reverted to their default values after a device reset.
+ """
+
+ CMD_ID = 0x6100
+
+ def __init__(self, k, p, t1, t2):
+ self._k = k
+ self._p = p
+ self._t1 = t1
+ self._t2 = t2
+
+ def pack(self):
+ return self.tx_data.pack([self._k, self._p, self._t1, self._t2])
+
+ tx = TxData(CMD_ID, '>HHHHH', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+
+
+class GetProductType(Transfer):
+ """
+ Gets the product type from the device.
+
+ The following product types are expected:
+ - SEN62: '00085800'
+ - SEN63C: '00085700'
+ - SEN65: '00085200'
+ - SEN66: '00085300'
+ - SEN68: '00085400'
+ - SEN69C: '00085900'
+ """
+
+ CMD_ID = 0xd002
def pack(self):
return self.tx_data.pack([])
@@ -502,10 +441,10 @@ def pack(self):
rx = RxData('>32s')
-class GetSerialNumber(Transfer):
- """Gets the serial number from the device."""
+class GetProductName(Transfer):
+ """Gets the product name from the device."""
- CMD_ID = 0xd033
+ CMD_ID = 0xd014
def pack(self):
return self.tx_data.pack([])
@@ -514,16 +453,16 @@ def pack(self):
rx = RxData('>32s')
-class GetVersion(Transfer):
- """Gets the version information for the hardware, firmware and communication protocol."""
+class GetSerialNumber(Transfer):
+ """Gets the serial number from the device."""
- CMD_ID = 0xd100
+ CMD_ID = 0xd033
def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
- rx = RxData('>BB')
+ rx = RxData('>32s')
class ReadDeviceStatus(Transfer):
@@ -561,6 +500,18 @@ def pack(self):
rx = RxData('>I')
+class GetVersion(Transfer):
+ """Gets the version information for the firmware."""
+
+ CMD_ID = 0xd100
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>BB')
+
+
class DeviceReset(Transfer):
"""Executes a reset on the device. This has the same effect as a power cycle."""
@@ -570,3 +521,95 @@ def pack(self):
return self.tx_data.pack([])
tx = TxData(CMD_ID, '>H', device_busy_delay=1.2, slave_address=None, ignore_ack=False)
+
+
+class StartFanCleaning(Transfer):
+ """
+ This command triggers fan cleaning. The fan is set to the maximum
+ speed for 10 seconds and then automatically stopped. Wait at least 10s
+ after this command before starting a measurement.
+ """
+
+ CMD_ID = 0x5607
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+
+
+class ActivateShtHeater(Transfer):
+ """
+ Activate the heater feature of the SHT4x sensor.
+ This command allows to use the inbuilt heater in SHT sensor
+ to decontaminate and reverse creep at high humidity.
+ This command activates the SHT sensor heater with 200mW for 1s.
+ The SHT heater measurement done just before deactivation can be
+ read using the command \"Get SHT Heater Measurements\" after
+ the duration of the heating feature as specified in the SHT4x
+ datasheet.
+ Wait at least 20s after this command before starting a measurement
+ to get coherent temperature values (heating consequence to disappear).
+ """
+
+ CMD_ID = 0x6765
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+
+
+class GetShtHeaterMeasurements(Transfer):
+ """
+ Get the measurement values when the SHT sensor heating
+ is finished.
+ """
+
+ CMD_ID = 0x6790
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>hh')
+
+
+class ReadMeasuredValuesAsIntegers(Transfer):
+ """
+ Returns the measured values.
+ The command \"Get Data Ready\" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16,
+ 0x7FFF for int16).
+ """
+
+ CMD_ID = 0x414
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>HHHHhhhhH')
+
+
+class ReadMeasuredRawValues(Transfer):
+ """
+ Returns the measured raw values.
+ The command "Get Data Ready" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16,
+ 0x7FFF for int16).
+ """
+
+ CMD_ID = 0x405
+
+ def pack(self):
+ return self.tx_data.pack([])
+
+ tx = TxData(CMD_ID, '>H', device_busy_delay=0.02, slave_address=None, ignore_ack=False)
+ rx = RxData('>hhHHH')
diff --git a/sensirion_i2c_sen66/device.py b/sensirion_i2c_sen66/device.py
index 39ba589..a70d8bf 100644
--- a/sensirion_i2c_sen66/device.py
+++ b/sensirion_i2c_sen66/device.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
"""
The class Sen66DeviceBase implements the low level interface of the sensor.
@@ -19,9 +19,10 @@
from sensirion_driver_support_types.mixin_access import MixinAccess
from sensirion_i2c_sen66.commands import (ActivateShtHeater, DeviceReset, DeviceStatus, GetAmbientPressure,
GetCo2SensorAutomaticSelfCalibration, GetDataReady,
- GetNoxAlgorithmTuningParameters, GetProductName, GetSensorAltitude,
- GetSerialNumber, GetShtHeaterMeasurements, GetVersion, GetVocAlgorithmState,
- GetVocAlgorithmTuningParameters, PerformForcedCo2Recalibration,
+ GetNoxAlgorithmTuningParameters, GetProductName, GetProductType,
+ GetSensorAltitude, GetSerialNumber, GetShtHeaterMeasurements, GetVersion,
+ GetVocAlgorithmState, GetVocAlgorithmTuningParameters,
+ PerformCo2SensorFactoryReset, PerformForcedCo2Recalibration,
ReadAndClearDeviceStatus, ReadDeviceStatus, ReadMeasuredRawValues,
ReadMeasuredValuesAsIntegers, ReadNumberConcentrationValuesAsIntegers,
SetAmbientPressure, SetCo2SensorAutomaticSelfCalibration,
@@ -30,12 +31,8 @@
SetVocAlgorithmState, SetVocAlgorithmTuningParameters,
StartContinuousMeasurement, StartFanCleaning, StopMeasurement)
-from sensirion_i2c_sen66.result_types import (SignalCo2, SignalHumidity, SignalMassConcentrationPm10p0,
- SignalMassConcentrationPm1p0, SignalMassConcentrationPm2p5,
- SignalMassConcentrationPm4p0, SignalNoxIndex,
- SignalNumberConcentrationPm0p5, SignalNumberConcentrationPm10p0,
- SignalNumberConcentrationPm1p0, SignalNumberConcentrationPm2p5,
- SignalNumberConcentrationPm4p0, SignalTemperature, SignalVocIndex)
+from sensirion_i2c_sen66.result_types import (SignalDividedBy10Int16, SignalDividedBy10Uint16, SignalHumidity,
+ SignalTemperature)
class Sen66DeviceBase:
@@ -48,203 +45,31 @@ def __init__(self, channel):
def channel(self):
return self._channel
- def start_continuous_measurement(self):
- """
- Starts a continuous measurement.
- After starting the measurement, it takes some time (~1.1s) until the
- first measurement results are available. You could poll with the command
- "Get Data Ready" to check when the results are ready to read.
- This command is only available in idle mode. If the device is already
- in any measure mode, this command has no effect.
- """
- transfer = StartContinuousMeasurement()
- return execute_transfer(self._channel, transfer)
-
- def stop_measurement(self):
- """
- Stops the measurement and returns to idle mode. After sending this
- command, wait at least 1000 ms before starting a new measurement.
- If the device is already in idle mode, this command has no effect.
- """
- transfer = StopMeasurement()
- return execute_transfer(self._channel, transfer)
-
- def get_data_ready(self):
- """
- This command can be used to check if new measurement results are ready to read. The data ready flag
- is automatically reset after reading the measurement values.
-
- :return padding:
- Padding byte, always 0x00.
- :return data_ready:
- True (0x01) if data is ready, False (0x00) if not. When no measurement is running, False will be
- returned.
- """
- transfer = GetDataReady()
- return execute_transfer(self._channel, transfer)
-
- def read_measured_values_as_integers(self):
- """
- Returns the measured values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16,
- 0x7FFF for int16).
-
- :return mass_concentration_pm1p0:
- Value is scaled with factor 10: PM1.0 [µg/m³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return mass_concentration_pm2p5:
- Value is scaled with factor 10: PM2.5 [µg/m³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return mass_concentration_pm4p0:
- Value is scaled with factor 10: PM4.0 [µg/m³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return mass_concentration_pm10p0:
- Value is scaled with factor 10: PM10.0 [µg/m³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return ambient_humidity:
- Value is scaled with factor 100: RH [%] = value / 100
- *Note: If this value is unknown, 0x7FFF is returned.*
- :return ambient_temperature:
- Value is scaled with factor 200: T [°C] = value / 200
- *Note: If this value is unknown, 0x7FFF is returned.*
- :return voc_index:
- Value is scaled with factor 10: VOC Index = value / 10
- *Note: If this value is unknown, 0x7FFF is returned.*
- :return nox_index:
- Value is scaled with factor 10: NOx Index = value / 10
- *Note: If this value is unknown, 0x7FFF is returned. During
- the first 10..11 seconds after power-on or device reset, this
- value will be 0x7FFF as well.*
- :return co2:
- CO₂ concentration [ppm]
- *Note: If this value is unknown, 0xFFFF is returned. During the
- first 5..6 seconds after power-on or device reset, this value
- will be 0xFFFF as well.*
- """
- transfer = ReadMeasuredValuesAsIntegers()
- return execute_transfer(self._channel, transfer)
-
- def read_number_concentration_values_as_integers(self):
- """
- Returns the measured number concentration values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16).
-
- :return number_concentration_pm0p5:
- Value is scaled with factor 10: PM0.5 [particles/cm³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return number_concentration_pm1p0:
- Value is scaled with factor 10: PM1.0 [particles/cm³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return number_concentration_pm2p5:
- Value is scaled with factor 10: PM2.5 [particles/cm³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return number_concentration_pm4p0:
- Value is scaled with factor 10: PM4.0 [particles/cm³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return number_concentration_pm10p0:
- Value is scaled with factor 10: PM10.0 [particles/cm³] = value / 10
- *Note: If this value is unknown, 0xFFFF is returned.*
- """
- transfer = ReadNumberConcentrationValuesAsIntegers()
- return execute_transfer(self._channel, transfer)
-
- def read_measured_raw_values(self):
- """
- Returns the measured raw values.
- The command "Get Data Ready" can be used to check if new
- data is available since the last read operation. If no new data is
- available, the previous values will be returned again. If no data
- is available at all (e.g. measurement not running for at least one
- second), all values will be at their upper limit (0xFFFF for uint16,
- 0x7FFF for int16).
-
- :return raw_humidity:
- Value is scaled with factor 100: RH [%] = value / 100
- *Note: If this value is unknown, 0x7FFF is returned.*
- :return raw_temperature:
- Value is scaled with factor 200: T [°C] = value / 200
- *Note: If this value is unknown, 0x7FFF is returned.*
- :return raw_voc:
- Raw measured VOC ticks without scale factor.
- *Note: If this value is unknown, 0xFFFF is returned.*
- :return raw_nox:
- Raw measured NOx ticks without scale factor.
- *Note: If this value is unknown, 0xFFFF is returned. During
- the first 10..11 seconds after power-on or device reset, this
- value will be 0xFFFF as well.*
- :return raw_co2:
- Not interpolated CO₂ concentration [ppm] updated every five
- seconds.
- *Note: If this value is unknown, 0xFFFF is returned. During the
- first 5..6 seconds after power-on or device reset, this value
- will be 0xFFFF as well.*
+ def get_voc_algorithm_tuning_parameters(self):
"""
- transfer = ReadMeasuredRawValues()
- return execute_transfer(self._channel, transfer)
+ Gets the parameters to customize the VOC algorithm.
- def start_fan_cleaning(self):
- """
- This command triggers fan cleaning. The fan is set to the maximum
- speed for 10 seconds and then automatically stopped. Wait at least 10s
- after this command before starting a measurement.
+ :return index_offset:
+ VOC index representing typical (average) conditions.
+ :return learning_time_offset_hours:
+ Time constant to estimate the VOC algorithm offset from the history in hours. Past events will be
+ forgotten after about twice the learning time.
+ :return learning_time_gain_hours:
+ Time constant to estimate the VOC algorithm gain from the history in hours. Past events will be
+ forgotten after about twice the learning time.
+ :return gating_max_duration_minutes:
+ Maximum duration of gating in minutes (freeze of estimator during high VOC index signal). Zero
+ disables the gating.
+ :return std_initial:
+ Initial estimate for standard deviation. Lower value boosts events during initial learning period,
+ but may result in larger device-to-device variations.
+ :return gain_factor:
+ Gain factor to amplify or to attenuate the VOC index output.
.. note::
This command is only available in idle mode.
"""
- transfer = StartFanCleaning()
- return execute_transfer(self._channel, transfer)
-
- def set_temperature_offset_parameters(self, offset, slope, time_constant, slot):
- """
- This command allows to compensate temperature effects of the
- design-in at customer side by applying custom temperature offsets
- to the ambient temperature. The compensated ambient temperature is
- calculated as follows:
- T_Ambient_Compensated = T_Ambient + (slope * T_Ambient) + offset
- Where slope and offset are the values set with this command,
- smoothed with the specified time constant.
- All temperatures (T_Ambient_Compensated, T_Ambient and offset)
- are represented in °C.
- There are 5 temperature offset slots available that all contribute
- additively to T_Ambient_Compensated. The default values for
- the temperature offset parameters are all zero, meaning that
- T_Ambient_Compensated is equal to T_Ambient by default.
- The parameters can be changed in any state of the device, i.e. both in
- idle mode and in measure mode.
-
- :param offset:
- Constant temperature offset scaled with factor 200 (T [°C] = value / 200).
- :param slope:
- Normalized temperature offset slope scaled with factor 10000 (applied factor = value / 10000).
- :param time_constant:
- The time constant determines how fast the new slope and offset will be applied.
- After the specified value in seconds, 63% of the new slope and offset are applied.
- A time constant of zero means the new values will be applied immediately
- (within the next measure interval of 1 second).
- :param slot:
- The temperature offset slot to be modified.
- Valid values are 0 .. 4. If the value is outside this range,
- the parameters will not be applied.
-
- .. note::
- This configuration is volatile, i.e. the parameters will be reverted to their default value of zero
- after a device reset.
-
- :Example:
- .. code-block:: python
-
- sensor.set_temperature_offset_parameters(1, 10, 1, 0)
-
- """
- transfer = SetTemperatureOffsetParameters(offset, slope, time_constant, slot)
+ transfer = GetVocAlgorithmTuningParameters()
return execute_transfer(self._channel, transfer)
def set_voc_algorithm_tuning_parameters(self, index_offset, learning_time_offset_hours, learning_time_gain_hours,
@@ -290,31 +115,68 @@ def set_voc_algorithm_tuning_parameters(self, index_offset, learning_time_offset
gating_max_duration_minutes, std_initial, gain_factor)
return execute_transfer(self._channel, transfer)
- def get_voc_algorithm_tuning_parameters(self):
+ def get_voc_algorithm_state(self):
"""
- Gets the parameters to customize the VOC algorithm.
+ Gets the current VOC algorithm state.
+ Allows to backup and restore the VOC algorithm state to resume operation after a power cycle or
+ device reset, skipping initial learning phase. By default, the VOC Engine is reset and the algorithm
+ state is retained if a measurement is stopped and started again. If the VOC algorithm
+ state shall be reset, a device reset or a power cycle can be executed.
+
+ :return state:
+ Current VOC algorithm state.
+
+ .. note::
+ This command can be used either in measure mode or in idle mode (which will then return the state at the
+ time when the measurement was stopped). In measure mode, the state can be read each measure interval to
+ always have the latest state available, even in case of a sudden power loss.
+ """
+ transfer = GetVocAlgorithmState()
+ return execute_transfer(self._channel, transfer)[0]
+
+ def set_voc_algorithm_state(self, state):
+ """
+ Sets the VOC algorithm state previously received with "Get VOC Algorithm State" command.
+ Allows restoration of the VOC algorithm state to resume operation after a power cycle or device
+ reset, skipping initial learning phase. By default, the VOC Engine is reset, and the algorithm state is retained if
+ a measurement is stopped and started again. If the VOC algorithm state shall be reset, a device reset, or a
+ power cycle can be executed.
+
+ :param state:
+ VOC algorithm state to restore.
+
+ .. note::
+ This command is only available in idle mode and the state will be applied only once when starting
+ the next measurement. In measure mode, this command has no effect.
+ """
+ transfer = SetVocAlgorithmState(state)
+ return execute_transfer(self._channel, transfer)
+
+ def get_nox_algorithm_tuning_parameters(self):
+ """
+ Gets the parameters to customize the NOx algorithm.
:return index_offset:
- VOC index representing typical (average) conditions.
+ NOx index representing typical (average) conditions.
:return learning_time_offset_hours:
- Time constant to estimate the VOC algorithm offset from the history in hours. Past events will be
+ Time constant to estimate the NOx algorithm offset from the history in hours. Past events will be
forgotten after about twice the learning time.
:return learning_time_gain_hours:
- Time constant to estimate the VOC algorithm gain from the history in hours. Past events will be
- forgotten after about twice the learning time.
+ The time constant to estimate the NOx algorithm gain from the history has no impact for NOx. This
+ parameter is still in place for consistency reasons with the VOC tuning parameters command.
:return gating_max_duration_minutes:
- Maximum duration of gating in minutes (freeze of estimator during high VOC index signal). Zero
+ Maximum duration of gating in minutes (freeze of estimator during high NOx index signal). Zero
disables the gating.
:return std_initial:
- Initial estimate for standard deviation. Lower value boosts events during initial learning period,
- but may result in larger device-to-device variations.
+ The initial estimate for standard deviation has no impact for NOx. This parameter is still in place
+ for consistency reasons with the VOC tuning parameters command.
:return gain_factor:
- Gain factor to amplify or to attenuate the VOC index output.
+ Gain factor to amplify or to attenuate the NOx index output.
.. note::
- This command is only available in idle mode.
+ This command is available only in idle mode.
"""
- transfer = GetVocAlgorithmTuningParameters()
+ transfer = GetNoxAlgorithmTuningParameters()
return execute_transfer(self._channel, transfer)
def set_nox_algorithm_tuning_parameters(self, index_offset, learning_time_offset_hours, learning_time_gain_hours,
@@ -360,285 +222,322 @@ def set_nox_algorithm_tuning_parameters(self, index_offset, learning_time_offset
gating_max_duration_minutes, std_initial, gain_factor)
return execute_transfer(self._channel, transfer)
- def get_nox_algorithm_tuning_parameters(self):
+ def perform_forced_co2_recalibration(self, target_co2_concentration):
"""
- Gets the parameters to customize the NOx algorithm.
+ Execute the forced recalibration (FRC) of the CO₂. See the datasheet of the
+ SCD4x sensor for details how the forced recalibration shall be used.
- :return index_offset:
- NOx index representing typical (average) conditions.
- :return learning_time_offset_hours:
- Time constant to estimate the NOx algorithm offset from the history in hours. Past events will be
- forgotten after about twice the learning time.
- :return learning_time_gain_hours:
- The time constant to estimate the NOx algorithm gain from the history has no impact for NOx. This
- parameter is still in place for consistency reasons with the VOC tuning parameters command.
- :return gating_max_duration_minutes:
- Maximum duration of gating in minutes (freeze of estimator during high NOx index signal). Zero
- disables the gating.
- :return std_initial:
- The initial estimate for standard deviation has no impact for NOx. This parameter is still in place
- for consistency reasons with the VOC tuning parameters command.
- :return gain_factor:
- Gain factor to amplify or to attenuate the NOx index output.
+ :param target_co2_concentration:
+ Target CO₂ concentration [ppm] of the test setup.
+
+ :return correction:
+ Correction value as received from the SCD [ppm CO₂].
+ FRC correction [ppm CO₂] is calculated as follows:
+ FRC = return_value - 0x8000
+ If the recalibration has failed this returned value
+ is 0xFFFF.
.. note::
- This command is available only in idle mode.
+ After power-on wait at least 1000 ms and after stopping a measurement 600 ms before sending this
+ command. This command is not available in measure mode. The recalibration procedure will take about
+ 500 ms to complete, during which time no other functions can be executed.
+ This configuration is persistent, i.e. the parameters will be retained during a device reset or power cycle.
"""
- transfer = GetNoxAlgorithmTuningParameters()
+ transfer = PerformForcedCo2Recalibration(target_co2_concentration)
+ return execute_transfer(self._channel, transfer)[0]
+
+ def perform_co2_sensor_factory_reset(self):
+ """
+ This command resets all CO₂ sensor configuration settings
+ stored in the EEPROM and erases the FRC and ASC algorithm
+ history of the CO₂ sensor.
+ The configuration settings are CO₂ sensor temperature offset (cannot be
+ modified over I2C interface), sensor altitude and the ASC
+ enabled/disabled parameters which are by default stored
+ in the volatile memory (RAM).
+ This command is only available in idle mode.
+ """
+ transfer = PerformCo2SensorFactoryReset()
return execute_transfer(self._channel, transfer)
- def set_temperature_acceleration_parameters(self, k, p, t1, t2):
+ def get_co2_sensor_automatic_self_calibration(self):
"""
- This command allows to set custom temperature acceleration parameters of the RH/T engine.
- It overwrites the default temperature acceleration parameters of the RH/T engine with custom values. This
- configuration is volatile, i.e. the parameters will be reverted to their default values after a device reset.
+ The CO₂ sensor supports automatic self calibration (ASC) for long-term
+ stability of the CO₂ output. This feature can be enabled or disabled.
+ By default it is enabled.
- :param k:
- Filter constant K scaled with factor 10 (K = value / 10).
- :param p:
- Filter constant P scaled with factor 10 (P = value / 10).
- :param t1:
- Time constant T1 scaled with factor 10 (T1 [s] = value / 10).
- :param t2:
- Time constant T2 scaled with factor 10 (T2 [s] = value / 10).
+ :return padding:
+ Padding byte, always 0x00.
+ :return status:
+ Is set true (0x01) if the automatic self calibration is enabled or false (0x00) if the automatic
+ self calibration is disabled.
.. note::
- The command is only available in idle mode.
+ This command is only available in idle mode.
+ This configuration is persistent, i.e. the status will be retained during a device reset or power cycle.
+ """
+ transfer = GetCo2SensorAutomaticSelfCalibration()
+ return execute_transfer(self._channel, transfer)
+
+ def set_co2_sensor_automatic_self_calibration(self, status):
+ """
+ Sets the status of the CO₂ sensor automatic self-calibration (ASC).
+ The CO₂ sensor supports automatic self calibration (ASC) for long-term
+ stability of the CO₂ output. This feature can be enabled or disabled.
+ By default it is enabled.
+
+ :param status:
+ Set to true (0x0001) to enable or false (0x0000) to disable the automatic CO₂ measurement self
+ calibration feature. High byte of uint16 is padding and always 0x00.
+
+ .. note::
+ This command is only available in idle mode.
+ This configuration is persistent, i.e. the status will be retained during a device reset or power cycle.
:Example:
.. code-block:: python
- sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
+ sensor.set_co2_sensor_automatic_self_calibration(0)
"""
- transfer = SetTemperatureAccelerationParameters(k, p, t1, t2)
+ transfer = SetCo2SensorAutomaticSelfCalibration(status)
return execute_transfer(self._channel, transfer)
- def set_voc_algorithm_state(self, state):
+ def get_ambient_pressure(self):
"""
- Sets the VOC algorithm state previously received with "Get VOC Algorithm State" command.
- Allows restoration of the VOC algorithm state to resume operation after a power cycle or device
- reset, skipping initial learning phase. By default, the VOC Engine is reset, and the algorithm state is retained if
- a measurement is stopped and started again. If the VOC algorithm state shall be reset, a device reset, or a
- power cycle can be executed.
+ Gets the ambient pressure value.
+ The ambient pressure can be used for pressure compensation in the CO₂
+ sensor.
- :param state:
- VOC algorithm state to restore.
+ :return ambient_pressure:
+ Currently used ambient pressure [hPa] for pressure compensation.
.. note::
- This command is only available in idle mode and the state will be applied only once when starting
- the next measurement. In measure mode, this command has no effect.
+ This command can be used in any state of the device, i.e. both in idle
+ mode and in measure mode.
"""
- transfer = SetVocAlgorithmState(state)
- return execute_transfer(self._channel, transfer)
+ transfer = GetAmbientPressure()
+ return execute_transfer(self._channel, transfer)[0]
- def get_voc_algorithm_state(self):
+ def set_ambient_pressure(self, ambient_pressure):
"""
- Gets the current VOC algorithm state.
- Allows to backup and restore the VOC algorithm state to resume operation after a power cycle or
- device reset, skipping initial learning phase. By default, the VOC Engine is reset and the algorithm
- state is retained if a measurement is stopped and started again. If the VOC algorithm
- state shall be reset, a device reset or a power cycle can be executed.
+ The ambient pressure can be used for pressure compensation in the CO₂
+ sensor. Setting an ambient pressure overrides any pressure compensation
+ based on a previously set sensor altitude. Use of this command is
+ recommended for applications experiencing significant ambient pressure
+ changes to ensure CO₂ sensor accuracy. Valid input values are between
+ 700 to 1'200 hPa. The default value is 1013 hPa.
+ This configuration is volatile, i.e. the parameter will be
+ reverted to its default value after a device restart.
- :return state:
- Current VOC algorithm state.
+ :param ambient_pressure:
+ Ambient pressure [hPa] to be used for pressure compensation.
.. note::
- This command can be used either in measure mode or in idle mode (which will then return the state at the
- time when the measurement was stopped). In measure mode, the state can be read each measure interval to
- always have the latest state available, even in case of a sudden power loss.
- """
- transfer = GetVocAlgorithmState()
- return execute_transfer(self._channel, transfer)[0]
+ This command can be used in any state of the device, i.e. both in idle
+ mode and in measure mode.
+
+ :Example:
+ .. code-block:: python
+
+ sensor.set_ambient_pressure(1013)
- def perform_forced_co2_recalibration(self, target_co2_concentration):
"""
- Execute the forced recalibration (FRC) of the CO₂. See the datasheet of the
- SCD4x sensor for details how the forced recalibration shall be used.
+ transfer = SetAmbientPressure(ambient_pressure)
+ return execute_transfer(self._channel, transfer)
- :param target_co2_concentration:
- Target CO₂ concentration [ppm] of the test setup.
+ def get_sensor_altitude(self):
+ """
+ Gets the current sensor altitude.
+ The sensor altitude can be used for pressure compensation in the CO₂
+ sensor.
- :return correction:
- Correction value as received from the SCD [ppm CO₂].
- FRC correction [ppm CO₂] is calculated as follows:
- FRC = return_value - 0x8000
- If the recalibration has failed this returned value
- is 0xFFFF.
+ :return altitude:
+ Current sensor altitude [m].
.. note::
- After power-on wait at least 1000 ms and after stopping a measurement 600 ms before sending this
- command. This command is not available in measure mode. The recalibration procedure will take about
- 500 ms to complete, during which time no other functions can be executed.
+ This command is only available in idle mode.
"""
- transfer = PerformForcedCo2Recalibration(target_co2_concentration)
+ transfer = GetSensorAltitude()
return execute_transfer(self._channel, transfer)[0]
- def set_co2_sensor_automatic_self_calibration(self, status):
+ def set_sensor_altitude(self, altitude):
"""
- Sets the status of the CO₂ sensor automatic self-calibration (ASC).
- The CO₂ sensor supports automatic self calibration (ASC) for long-term
- stability of the CO₂ output. This feature can be enabled or disabled.
- By default it is enabled.
+ The sensor altitude can be used for pressure compensation in the CO₂
+ sensor. The default sensor altitude value is set to 0 meters above sea
+ level. Valid input values are between 0 and 3000m.
This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device restart.
-
- :param status:
- Set to true (0x0001) to enable or false (0x0000) to disable the automatic CO₂ measurement self
- calibration feature. High byte of uint16 is padding and always 0x00.
+ reverted to its default value after a device reset.
- .. note::
- This command is only available in idle mode.
+ :param altitude:
+ Sensor altitude [m], valid input between 0 and 3000m.
:Example:
.. code-block:: python
- sensor.set_co2_sensor_automatic_self_calibration(0)
+ sensor.set_sensor_altitude(0)
"""
- transfer = SetCo2SensorAutomaticSelfCalibration(status)
+ transfer = SetSensorAltitude(altitude)
return execute_transfer(self._channel, transfer)
- def get_co2_sensor_automatic_self_calibration(self):
+ def start_continuous_measurement(self):
"""
- The CO₂ sensor supports automatic self calibration (ASC) for long-term
- stability of the CO₂ output. This feature can be enabled or disabled.
- By default it is enabled.
- This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device restart.
+ Starts a continuous measurement.
+ After starting the measurement, it takes some time (~1.1s) until the
+ first measurement results are available. You could poll with the command
+ "Get Data Ready" to check when the results are ready to read.
+ This command is only available in idle mode. If the device is already
+ in any measure mode, this command has no effect.
+ """
+ transfer = StartContinuousMeasurement()
+ return execute_transfer(self._channel, transfer)
+
+ def stop_measurement(self):
+ """
+ Stops the measurement and returns to idle mode. After sending this
+ command, wait at least 1000 ms before starting a new measurement.
+ If the device is already in idle mode, this command has no effect.
+ """
+ transfer = StopMeasurement()
+ return execute_transfer(self._channel, transfer)
+
+ def get_data_ready(self):
+ """
+ This command can be used to check if new measurement results are ready to read. The data ready flag
+ is automatically reset after reading the measurement values.
:return padding:
Padding byte, always 0x00.
- :return status:
- Is set true (0x01) if the automatic self calibration is enabled or false (0x00) if the automatic
- self calibration is disabled.
+ :return data_ready:
+ True (0x01) if data is ready, False (0x00) if not. When no measurement is running, False will be
+ returned.
+ """
+ transfer = GetDataReady()
+ return execute_transfer(self._channel, transfer)
- .. note::
- This command is only available in idle mode.
+ def read_number_concentration_values_as_integers(self):
+ """
+ Returns the measured number concentration values.
+ The command 0x0202 "Get Data Ready" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16).
+
+ :return number_concentration_pm0p5:
+ Value is scaled with factor 10: PM0.5 [particles/cm³] = value / 10.
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return number_concentration_pm1p0:
+ Value is scaled with factor 10: PM1.0 [particles/cm³] = value / 10.
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return number_concentration_pm2p5:
+ Value is scaled with factor 10: PM2.5 [particles/cm³] = value / 10.
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return number_concentration_pm4p0:
+ Value is scaled with factor 10: PM4.0 [particles/cm³] = value / 10.
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return number_concentration_pm10p0:
+ Value is scaled with factor 10: PM10.0 [particles/cm³] = value / 10.
+ *Note: If this value is unknown, 0xFFFF is returned.*
"""
- transfer = GetCo2SensorAutomaticSelfCalibration()
+ transfer = ReadNumberConcentrationValuesAsIntegers()
return execute_transfer(self._channel, transfer)
- def set_ambient_pressure(self, ambient_pressure):
+ def set_temperature_offset_parameters(self, offset, slope, time_constant, slot):
"""
- The ambient pressure can be used for pressure compensation in the CO₂
- sensor. Setting an ambient pressure overrides any pressure compensation
- based on a previously set sensor altitude. Use of this command is
- recommended for applications experiencing significant ambient pressure
- changes to ensure CO₂ sensor accuracy. Valid input values are between
- 700 to 1'200 hPa. The default value is 1013 hPa.
- This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device restart.
+ This command allows to compensate temperature effects of the
+ design-in at customer side by applying custom temperature offsets
+ to the ambient temperature.
- :param ambient_pressure:
- Ambient pressure [hPa] to be used for pressure compensation.
+ The compensated ambient temperature is calculated as follows:
+
+ * T_Ambient_Compensated = T_Ambient + (slope * T_Ambient) + offset
+
+ Where \"slope\" and \"offset\" are the values set with this command,
+ smoothed with the specified time constant.
+ All temperatures (\"T_Ambient_Compensated\", \"T_Ambient\" and \"offset\")
+ are represented in °C.
+ There are 5 temperature offset slots available that all contribute
+ additively to \"T_Ambient_Compensated\". The default values for
+ the temperature offset parameters are all zero, meaning that
+ \"T_Ambient_Compensated\" is equal to \"T_Ambient\" by default.
+ The parameters can be changed in any state of the device, i.e. both in
+ idle mode and in measure mode.
+
+ :param offset:
+ Constant temperature offset scaled with factor 200 (T [°C] = value / 200).
+ :param slope:
+ Normalized temperature offset slope scaled with factor 10000 (applied factor = value / 10000).
+ :param time_constant:
+ The time constant determines how fast the new slope and offset will be applied.
+ After the specified value in seconds, 63% of the new slope and offset are applied.
+ A time constant of zero means the new values will be applied immediately
+ (within the next measure interval of 1 second).
+ :param slot:
+ The temperature offset slot to be modified.
+ Valid values are 0 .. 4. If the value is outside this range,
+ the parameters will not be applied.
.. note::
- This command can be used in any state of the device, i.e. both in idle
- mode and in measure mode.
+ This configuration is volatile, i.e. the parameters will be reverted to their default value of zero
+ after a device reset.
:Example:
.. code-block:: python
- sensor.set_ambient_pressure(1013)
+ sensor.set_temperature_offset_parameters(1, 10, 1, 0)
"""
- transfer = SetAmbientPressure(ambient_pressure)
+ transfer = SetTemperatureOffsetParameters(offset, slope, time_constant, slot)
return execute_transfer(self._channel, transfer)
- def get_ambient_pressure(self):
+ def set_temperature_acceleration_parameters(self, k, p, t1, t2):
"""
- Gets the ambient pressure value.
- The ambient pressure can be used for pressure compensation in the CO₂
- sensor.
+ This command allows to set custom temperature acceleration parameters of the RH/T engine.
+ It overwrites the default temperature acceleration parameters of the RH/T engine with custom values. This
+ configuration is volatile, i.e. the parameters will be reverted to their default values after a device reset.
- :return ambient_pressure:
- Currently used ambient pressure [hPa] for pressure compensation.
+ :param k:
+ Filter constant K scaled with factor 10 (K = value / 10).
+ :param p:
+ Filter constant P scaled with factor 10 (P = value / 10).
+ :param t1:
+ Time constant T1 scaled with factor 10 (T1 [s] = value / 10).
+ :param t2:
+ Time constant T2 scaled with factor 10 (T2 [s] = value / 10).
.. note::
- This command can be used in any state of the device, i.e. both in idle
- mode and in measure mode.
- """
- transfer = GetAmbientPressure()
- return execute_transfer(self._channel, transfer)[0]
-
- def set_sensor_altitude(self, altitude):
- """
- The sensor altitude can be used for pressure compensation in the CO₂
- sensor. The default sensor altitude value is set to 0 meters above sea
- level. Valid input values are between 0 and 3000m.
- This configuration is volatile, i.e. the parameter will be
- reverted to its default value after a device reset.
-
- :param altitude:
- Sensor altitude [m], valid input between 0 and 3000m.
+ The command is only available in idle mode.
:Example:
.. code-block:: python
- sensor.set_sensor_altitude(0)
+ sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
"""
- transfer = SetSensorAltitude(altitude)
+ transfer = SetTemperatureAccelerationParameters(k, p, t1, t2)
return execute_transfer(self._channel, transfer)
- def get_sensor_altitude(self):
+ def get_product_type(self):
"""
- Gets the current sensor altitude.
- The sensor altitude can be used for pressure compensation in the CO₂
- sensor.
+ Gets the product type from the device.
- :return altitude:
- Current sensor altitude [m].
+ The following product types are expected:
+ - SEN62: '00085800'
+ - SEN63C: '00085700'
+ - SEN65: '00085200'
+ - SEN66: '00085300'
+ - SEN68: '00085400'
+ - SEN69C: '00085900'
- .. note::
- This command is only available in idle mode.
+ :return product_type:
+ Null-terminated ASCII string containing the product type.
+ Up to 32 characters can be read from the device.
"""
- transfer = GetSensorAltitude()
+ transfer = GetProductType()
return execute_transfer(self._channel, transfer)[0]
- def activate_sht_heater(self):
- """
- This command allows to use the inbuilt heater in SHT sensor
- to reverse creep at high humidity.
- This command activates the SHT sensor heater with 200mW for 1s.
- The heater is then automatically deactivated again.
- The "get_sht_heater_measurements" command can be used to check if the
- heater has finished (firmware version >= 4.0).
- Wait at least 20s after this command before starting a measurement to get
- coherent temperature values (heating consequence to disappear).
-
- .. note::
- This command is only available in idle mode.
- For firmware version < 4.0, wait for at least 1300ms before sending another
- command, to ensure heating is finsihed.
- """
- transfer = ActivateShtHeater()
- return execute_transfer(self._channel, transfer)
-
- def get_sht_heater_measurements(self):
- """
- Get the measured values when the SHT sensor heating is triggerd. If the
- heating is not finished, the returned humidity and temperature values
- are 0x7FFF.
-
- :return humidity:
- Value is scaled with factor 100: RH [%] = value / 100
- *Note: If this value is not available, 0x7FFF is returned.*
- :return temperature:
- Value is scaled with factor 200: T [°C] = value / 200
- *Note: If this value is not available, 0x7FFF is returned.*
-
- .. note::
- This command is only availble in idle mode.
- This command is only available for firmware version >= 4.0.
- This command must be used after the "activate_sht_heater" command.
- The get_sht_heater_measurements command can be queried every 0.05s to get
- the measurements.
- """
- transfer = GetShtHeaterMeasurements()
- return execute_transfer(self._channel, transfer)
-
def get_product_name(self):
"""
Gets the product name from the device.
@@ -661,18 +560,6 @@ def get_serial_number(self):
transfer = GetSerialNumber()
return execute_transfer(self._channel, transfer)[0]
- def get_version(self):
- """
- Gets the version information for the hardware, firmware and communication protocol.
-
- :return firmware_major:
- Firmware major version number.
- :return firmware_minor:
- Firmware minor version number.
- """
- transfer = GetVersion()
- return execute_transfer(self._channel, transfer)
-
def read_device_status(self):
"""
Reads the current device status.
@@ -710,11 +597,157 @@ def read_and_clear_device_status(self):
res_0 = execute_transfer(self._channel, transfer)[0]
return DeviceStatus(res_0)
+ def get_version(self):
+ """
+ Gets the version information for the firmware.
+
+ :return firmware_major:
+ Firmware major version number.
+ :return firmware_minor:
+ Firmware minor version number.
+ """
+ transfer = GetVersion()
+ return execute_transfer(self._channel, transfer)
+
def device_reset(self):
"""Executes a reset on the device. This has the same effect as a power cycle."""
transfer = DeviceReset()
return execute_transfer(self._channel, transfer)
+ def start_fan_cleaning(self):
+ """
+ This command triggers fan cleaning. The fan is set to the maximum
+ speed for 10 seconds and then automatically stopped. Wait at least 10s
+ after this command before starting a measurement.
+
+ .. note::
+ This command is only available in idle mode.
+ """
+ transfer = StartFanCleaning()
+ return execute_transfer(self._channel, transfer)
+
+ def activate_sht_heater(self):
+ """
+ Activate the heater feature of the SHT4x sensor.
+ This command allows to use the inbuilt heater in SHT sensor
+ to decontaminate and reverse creep at high humidity.
+ This command activates the SHT sensor heater with 200mW for 1s.
+ The SHT heater measurement done just before deactivation can be
+ read using the command \"Get SHT Heater Measurements\" after
+ the duration of the heating feature as specified in the SHT4x
+ datasheet.
+ Wait at least 20s after this command before starting a measurement
+ to get coherent temperature values (heating consequence to disappear).
+
+ .. note::
+ This command is only available in idle mode.
+ """
+ transfer = ActivateShtHeater()
+ return execute_transfer(self._channel, transfer)
+
+ def get_sht_heater_measurements(self):
+ """
+ Get the measurement values when the SHT sensor heating
+ is finished.
+
+ :return sht_relative_humidity:
+ If the sht heating is completed, this value indicates
+ the scaled relative humidity of the SHT4x sensor.
+ Value is scaled with factor 100: RH [%] = value / 100
+ *Note: If this value is not available, 0x7FFF is returned.*
+ :return sht_temperature:
+ If the sht heating is completed, this value indicates
+ the scaled temperature of the SHT4x sensor.
+ Value is scaled with factor 200: T [°C] = value / 200
+ *Note: If this value is not available, 0x7FFF is returned.*
+
+ .. note::
+ This command must be used after the \"Activate SHT Heater\" command. The get sht heater measurements
+ command can be queried every 0.05s to get the measurements. This command is only available in idle
+ mode.
+ """
+ transfer = GetShtHeaterMeasurements()
+ return execute_transfer(self._channel, transfer)
+
+ def read_measured_values_as_integers(self):
+ """
+ Returns the measured values.
+ The command \"Get Data Ready\" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16,
+ 0x7FFF for int16).
+
+ :return mass_concentration_pm1p0:
+ Value is scaled with factor 10: PM1.0 [µg/m³] = value / 10
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return mass_concentration_pm2p5:
+ Value is scaled with factor 10: PM2.5 [µg/m³] = value / 10
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return mass_concentration_pm4p0:
+ Value is scaled with factor 10: PM4.0 [µg/m³] = value / 10
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return mass_concentration_pm10p0:
+ Value is scaled with factor 10: PM10.0 [µg/m³] = value / 10
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return ambient_humidity:
+ Value is scaled with factor 100: RH [%] = value / 100
+ *Note: If this value is unknown, 0x7FFF is returned.*
+ :return ambient_temperature:
+ Value is scaled with factor 200: T [°C] = value / 200
+ *Note: If this value is unknown, 0x7FFF is returned.*
+ :return voc_index:
+ Value is scaled with factor 10: VOC Index = value / 10
+ *Note: If this value is unknown, 0x7FFF is returned.*
+ :return nox_index:
+ Value is scaled with factor 10: NOx Index = value / 10
+ *Note: If this value is unknown, 0x7FFF is returned. During
+ the first 10..11 seconds after power-on or device reset, this
+ value will be 0x7FFF as well.*
+ :return co2:
+ CO₂ concentration [ppm]
+ *Note: If this value is unknown, 0xFFFF is returned. During the
+ first 5..6 seconds after power-on or device reset, this value
+ will be 0xFFFF as well.*
+ """
+ transfer = ReadMeasuredValuesAsIntegers()
+ return execute_transfer(self._channel, transfer)
+
+ def read_measured_raw_values(self):
+ """
+ Returns the measured raw values.
+ The command "Get Data Ready" can be used to check if new
+ data is available since the last read operation. If no new data is
+ available, the previous values will be returned again. If no data
+ is available at all (e.g. measurement not running for at least one
+ second), all values will be at their upper limit (0xFFFF for uint16,
+ 0x7FFF for int16).
+
+ :return raw_humidity:
+ Value is scaled with factor 100: RH [%] = value / 100
+ *Note: If this value is unknown, 0x7FFF is returned.*
+ :return raw_temperature:
+ Value is scaled with factor 200: T [°C] = value / 200
+ *Note: If this value is unknown, 0x7FFF is returned.*
+ :return raw_voc:
+ Raw measured VOC ticks without scale factor.
+ *Note: If this value is unknown, 0xFFFF is returned.*
+ :return raw_nox:
+ Raw measured NOx ticks without scale factor.
+ *Note: If this value is unknown, 0xFFFF is returned. During
+ the first 10..11 seconds after power-on or device reset, this
+ value will be 0xFFFF as well.*
+ :return raw_co2:
+ Not interpolated CO₂ concentration [ppm] updated every five
+ seconds.
+ *Note: If this value is unknown, 0xFFFF is returned. During the
+ first 5..6 seconds after power-on or device reset, this value
+ will be 0xFFFF as well.*
+ """
+ transfer = ReadMeasuredRawValues()
+ return execute_transfer(self._channel, transfer)
+
class Sen66Device(Sen66DeviceBase):
"""Driver class implementation of SEN66"""
@@ -740,24 +773,24 @@ def read_measured_values(self):
:return humidity:
Measured humidity in %RH.
:return temperature:
- Measured temperature in degrees celsius.
+ Measured temperature in degrees Celsius.
:return voc_index:
- Measured VOC Index between 0 and 500.
+ VOC Index
:return nox_index:
- Measured NOx Index between 0 and 500.
+ NOx Index
:return co2:
- Measured CO2 concentration in ppm.
+ CO2 concentration in ppm.
"""
(mass_concentration_pm1p0_raw, mass_concentration_pm2p5_raw, mass_concentration_pm4p0_raw,
mass_concentration_pm10p0_raw, humidity_raw, temperature_raw, voc_index_raw, nox_index_raw,
co2_raw
) = self.read_measured_values_as_integers()
- return (SignalMassConcentrationPm1p0(mass_concentration_pm1p0_raw),
- SignalMassConcentrationPm2p5(mass_concentration_pm2p5_raw),
- SignalMassConcentrationPm4p0(mass_concentration_pm4p0_raw),
- SignalMassConcentrationPm10p0(mass_concentration_pm10p0_raw), SignalHumidity(humidity_raw),
- SignalTemperature(temperature_raw), SignalVocIndex(voc_index_raw), SignalNoxIndex(nox_index_raw),
- SignalCo2(co2_raw))
+ return (SignalDividedBy10Uint16(mass_concentration_pm1p0_raw),
+ SignalDividedBy10Uint16(mass_concentration_pm2p5_raw),
+ SignalDividedBy10Uint16(mass_concentration_pm4p0_raw),
+ SignalDividedBy10Uint16(mass_concentration_pm10p0_raw), SignalHumidity(humidity_raw),
+ SignalTemperature(temperature_raw), SignalDividedBy10Int16(voc_index_raw),
+ SignalDividedBy10Int16(nox_index_raw), co2_raw)
def read_number_concentration_values(self):
"""
@@ -777,8 +810,8 @@ def read_number_concentration_values(self):
(number_concentration_pm0p5_raw, number_concentration_pm1p0_raw, number_concentration_pm2p5_raw,
number_concentration_pm4p0_raw, number_concentration_pm10p0_raw
) = self.read_number_concentration_values_as_integers()
- return (SignalNumberConcentrationPm0p5(number_concentration_pm0p5_raw),
- SignalNumberConcentrationPm1p0(number_concentration_pm1p0_raw),
- SignalNumberConcentrationPm2p5(number_concentration_pm2p5_raw),
- SignalNumberConcentrationPm4p0(number_concentration_pm4p0_raw),
- SignalNumberConcentrationPm10p0(number_concentration_pm10p0_raw))
+ return (SignalDividedBy10Uint16(number_concentration_pm0p5_raw),
+ SignalDividedBy10Uint16(number_concentration_pm1p0_raw),
+ SignalDividedBy10Uint16(number_concentration_pm2p5_raw),
+ SignalDividedBy10Uint16(number_concentration_pm4p0_raw),
+ SignalDividedBy10Uint16(number_concentration_pm10p0_raw))
diff --git a/sensirion_i2c_sen66/response_provider.py b/sensirion_i2c_sen66/response_provider.py
index 95ac2e4..cd20a2a 100644
--- a/sensirion_i2c_sen66/response_provider.py
+++ b/sensirion_i2c_sen66/response_provider.py
@@ -4,7 +4,8 @@
class Sen66ResponseProvider(rp.ResponseProvider):
- RESPONSE_MAP = {0xd014: struct.pack('>32s', rp.random_ascii_string(32)),
+ RESPONSE_MAP = {0xd002: struct.pack('>32s', rp.random_ascii_string(32)),
+ 0xd014: struct.pack('>32s', rp.random_ascii_string(32)),
0xd033: struct.pack('>32s', rp.random_ascii_string(32))}
def get_id(self) -> str:
diff --git a/sensirion_i2c_sen66/result_types.py b/sensirion_i2c_sen66/result_types.py
index 19a8288..ef580f9 100644
--- a/sensirion_i2c_sen66/result_types.py
+++ b/sensirion_i2c_sen66/result_types.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
"""
The signal classes specify transformations of the raw sensor signals into a meaningful units.
@@ -17,134 +17,42 @@
from sensirion_driver_support_types.signals import AbstractSignal
-class SignalMassConcentrationPm1p0(AbstractSignal):
- """Mass concentration in μg/m³ for particles smaller than 1.0 μm"""
+class SignalDividedBy10Uint16(AbstractSignal):
+ """
+ All mass and number concentrations are scaled by a factor 10 to avoid
+ floating point operations on the communication interface.
+ """
- def __init__(self, mass_concentration_pm1p0_raw):
- self._mass_concentration_pm1p0 = mass_concentration_pm1p0_raw / 10.0
+ def __init__(self, scaled_integer_value):
+ self._divided_by_10_uint16 = scaled_integer_value / 10.0
@property
def value(self):
- return self._mass_concentration_pm1p0
+ return self._divided_by_10_uint16
def __str__(self):
return '{0:.2f}'.format(self.value)
-class SignalMassConcentrationPm2p5(AbstractSignal):
- """Mass concentration in μg/m³ for particles smaller than 2.5 μm"""
+class SignalDividedBy10Int16(AbstractSignal):
+ """
+ The VOC and NOx indices are scaled by a factor 10 to avoid
+ floating point operations on the communication interface.
+ """
- def __init__(self, mass_concentration_pm2p5_raw):
- self._mass_concentration_pm2p5 = mass_concentration_pm2p5_raw / 10.0
+ def __init__(self, scaled_integer_value):
+ self._divided_by_10_int16 = scaled_integer_value / 10.0
@property
def value(self):
- return self._mass_concentration_pm2p5
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalMassConcentrationPm4p0(AbstractSignal):
- """Mass concentration in μg/m³ for particles smaller than 4.0 μm"""
-
- def __init__(self, mass_concentration_pm4p0_raw):
- self._mass_concentration_pm4p0 = mass_concentration_pm4p0_raw / 10.0
-
- @property
- def value(self):
- return self._mass_concentration_pm4p0
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalMassConcentrationPm10p0(AbstractSignal):
- """Mass concentration in μg/m³ for particles smaller than 10.0 μm"""
-
- def __init__(self, mass_concentration_pm10p0_raw):
- self._mass_concentration_pm10p0 = mass_concentration_pm10p0_raw / 10.0
-
- @property
- def value(self):
- return self._mass_concentration_pm10p0
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNumberConcentrationPm0p5(AbstractSignal):
- """Number concentration in particles/cm³ for particles smaller than 0.5 μm"""
-
- def __init__(self, number_concentration_pm0p5_raw):
- self._number_concentration_pm0p5 = number_concentration_pm0p5_raw / 10.0
-
- @property
- def value(self):
- return self._number_concentration_pm0p5
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNumberConcentrationPm1p0(AbstractSignal):
- """Number concentration in particles/cm³ for particles smaller than 1.0 μm"""
-
- def __init__(self, number_concentration_pm1p0_raw):
- self._number_concentration_pm1p0 = number_concentration_pm1p0_raw / 10.0
-
- @property
- def value(self):
- return self._number_concentration_pm1p0
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNumberConcentrationPm2p5(AbstractSignal):
- """Number concentration in particles/cm³ for particles smaller than 2.5 μm"""
-
- def __init__(self, number_concentration_pm2p5_raw):
- self._number_concentration_pm2p5 = number_concentration_pm2p5_raw / 10.0
-
- @property
- def value(self):
- return self._number_concentration_pm2p5
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNumberConcentrationPm4p0(AbstractSignal):
- """Number concentration in particles/cm³ for particles smaller than 4.0 μm"""
-
- def __init__(self, number_concentration_pm4p0_raw):
- self._number_concentration_pm4p0 = number_concentration_pm4p0_raw / 10.0
-
- @property
- def value(self):
- return self._number_concentration_pm4p0
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNumberConcentrationPm10p0(AbstractSignal):
- """Number concentration in particles/cm³ for particles smaller than 10.0 μm"""
-
- def __init__(self, number_concentration_pm10p0_raw):
- self._number_concentration_pm10p0 = number_concentration_pm10p0_raw / 10.0
-
- @property
- def value(self):
- return self._number_concentration_pm10p0
+ return self._divided_by_10_int16
def __str__(self):
return '{0:.2f}'.format(self.value)
class SignalTemperature(AbstractSignal):
- """Measured temperature in degrees celsius. The raw value is scaled appropriately."""
+ """Measured temperature in degrees Celsius. The raw value is scaled appropriately."""
def __init__(self, temperature_raw):
self._temperature = temperature_raw / 200.0
@@ -170,45 +78,3 @@ def value(self):
def __str__(self):
return '{0:.2f}'.format(self.value)
-
-class SignalVocIndex(AbstractSignal):
- """Measured VOC Index ticks."""
-
- def __init__(self, voc_index_raw):
- self._voc_index = voc_index_raw / 10.0
-
- @property
- def value(self):
- return self._voc_index
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalNoxIndex(AbstractSignal):
- """Measured NOx Index ticks."""
-
- def __init__(self, nox_index_raw):
- self._nox_index = nox_index_raw / 10.0
-
- @property
- def value(self):
- return self._nox_index
-
- def __str__(self):
- return '{0:.2f}'.format(self.value)
-
-
-class SignalCo2(AbstractSignal):
- """Measured CO2 in ppm."""
-
- def __init__(self, co2_raw):
- self._co2 = co2_raw
-
- @property
- def value(self):
- return self._co2
-
- def __str__(self):
- return '{0}'.format(self.value)
-
diff --git a/sensirion_i2c_sen66/version.py b/sensirion_i2c_sen66/version.py
index 8fd97df..2c6391c 100644
--- a/sensirion_i2c_sen66/version.py
+++ b/sensirion_i2c_sen66/version.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
+import importlib.metadata as metadata
+from typing import Final
-version = "1.2.0"
+version: Final[str] = metadata.version("sensirion_i2c_sen66")
diff --git a/setup.py b/setup.py
index 86951ec..bfae448 100644
--- a/setup.py
+++ b/setup.py
@@ -1,70 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+from setuptools import setup
-import os
-import re
-
-from setuptools import setup, find_packages
-
-# Python versions this package is compatible with
-python_requires = '>=3.6, <4'
-
-# Packages that this package imports. List everything apart from standard lib packages.
-install_requires = [
- 'sensirion-i2c-driver>=1.0.0,<2.0',
- 'sensirion-driver-adapters>=2.1.9,<3.0',
- 'sensirion-driver-support-types>=1.1.0,<2.0',
- 'sensirion-shdlc-sensorbridge>=0.1.0,<0.3.0'
-]
-
-# Packages required for tests and docs
-extras_require = {
- 'test': [
- 'flake8~=3.7.8',
- 'pytest~=6.2.5',
- 'pytest-cov~=3.0.0',
- ]
-}
-
-# Read version number from version.py
-version_line = open("sensirion_i2c_sen66/version.py", "rt").read()
-result = re.search(r"^version = ['\"]([^'\"]*)['\"]", version_line, re.M)
-if result:
- version_string = result.group(1)
-else:
- raise RuntimeError("Unable to find version string")
-
-# Use README.rst and CHANGELOG.md as package description
-root_path = os.path.dirname(__file__)
-long_description = open(os.path.join(root_path, 'README.md')).read()
-
-setup(
- name='sensirion_i2c_sen66',
- version=version_string,
- author='Sensirion',
- author_email='info@sensirion.com',
- description='I2C driver for the Sensirion SEN66 sensor family',
- license='BSD',
- keywords="""Sensirion SEN66
- I2C
- SEN66""",
- project_urls={
- "Documentation": "https://sensirion.github.io/python-i2c-sen66",
- "Repository": "https://github.com/Sensirion/python-i2c-sen66",
- "Changelog": "https://github.com/Sensirion/python-i2c-sen66/blob/master/CHANGELOG.md",
- },
- packages=find_packages(exclude=['tests', 'tests.*']),
- long_description=long_description,
- long_description_content_type='text/markdown',
- python_requires=python_requires,
- install_requires=install_requires,
- extras_require=extras_require,
- classifiers=[
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.11',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ]
-)
+setup()
\ No newline at end of file
diff --git a/tests/test_sen66.py b/tests/test_sen66.py
index 7a55cae..82894eb 100644
--- a/tests/test_sen66.py
+++ b/tests/test_sen66.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# (c) Copyright 2025 Sensirion AG, Switzerland
+# (c) Copyright 2026 Sensirion AG, Switzerland
#
# THIS FILE IS AUTOMATICALLY GENERATED!
#
-# Generator: sensirion-driver-generator 1.1.2
+# Generator: sensirion-driver-generator 1.7.0
# Product: sen66
-# Model-Version: 1.6.0
+# Model-Version: 1.7.1
#
import pytest
@@ -24,9 +24,9 @@ def sensor(channel_provider):
yield Sen66Device(channel)
-def test_perform_forced_co2_recalibration1(sensor):
- correction = sensor.perform_forced_co2_recalibration(600)
- print(f"correction: {correction}; "
+def test_get_product_type1(sensor):
+ product_type = sensor.get_product_type()
+ print(f"product_type: {product_type}; "
)
@@ -54,52 +54,34 @@ def test_set_temperature_offset_parameters1(sensor):
sensor.set_temperature_offset_parameters(1, 10, 1, 0)
-def test_set_voc_algorithm_tuning_parameters1(sensor):
- sensor.set_voc_algorithm_tuning_parameters(100, 12, 12, 180, 50, 230)
-
-
-def test_get_voc_algorithm_tuning_parameters1(sensor):
- (index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial,
- gain_factor
- ) = sensor.get_voc_algorithm_tuning_parameters()
- print(f"index_offset: {index_offset}; "
- f"learning_time_offset_hours: {learning_time_offset_hours}; "
- f"learning_time_gain_hours: {learning_time_gain_hours}; "
- f"gating_max_duration_minutes: {gating_max_duration_minutes}; "
- f"std_initial: {std_initial}; "
- f"gain_factor: {gain_factor}; "
- )
+def test_set_temperature_acceleration_parameters1(sensor):
+ sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
-def test_set_nox_algorithm_tuning_parameters1(sensor):
- sensor.set_nox_algorithm_tuning_parameters(1, 12, 12, 720, 50, 230)
+def test_activate_sht_heater1(sensor):
+ sensor.activate_sht_heater()
-def test_get_nox_algorithm_tuning_parameters1(sensor):
- (index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial,
- gain_factor
- ) = sensor.get_nox_algorithm_tuning_parameters()
- print(f"index_offset: {index_offset}; "
- f"learning_time_offset_hours: {learning_time_offset_hours}; "
- f"learning_time_gain_hours: {learning_time_gain_hours}; "
- f"gating_max_duration_minutes: {gating_max_duration_minutes}; "
- f"std_initial: {std_initial}; "
- f"gain_factor: {gain_factor}; "
+def test_read_device_status1(sensor):
+ device_status = sensor.read_device_status()
+ print(f"device_status: {device_status}; "
)
-def test_set_temperature_acceleration_parameters1(sensor):
- sensor.set_temperature_acceleration_parameters(1, 1, 1, 1)
+def test_read_and_clear_device_status1(sensor):
+ device_status = sensor.read_and_clear_device_status()
+ print(f"device_status: {device_status}; "
+ )
-def test_get_voc_algorithm_state1(sensor):
- state = sensor.get_voc_algorithm_state()
- print(f"state: {state}; "
+def test_perform_forced_co2_recalibration1(sensor):
+ correction = sensor.perform_forced_co2_recalibration(600)
+ print(f"correction: {correction}; "
)
-def test_set_co2_sensor_automatic_self_calibration1(sensor):
- sensor.set_co2_sensor_automatic_self_calibration(0)
+def test_perform_co2_sensor_factory_reset1(sensor):
+ sensor.perform_co2_sensor_factory_reset()
def test_get_co2_sensor_automatic_self_calibration1(sensor):
@@ -110,8 +92,18 @@ def test_get_co2_sensor_automatic_self_calibration1(sensor):
)
-def test_set_ambient_pressure1(sensor):
- sensor.set_ambient_pressure(1013)
+def test_set_co2_sensor_automatic_self_calibration1(sensor):
+ sensor.set_co2_sensor_automatic_self_calibration(0)
+
+
+def test_get_sensor_altitude1(sensor):
+ altitude = sensor.get_sensor_altitude()
+ print(f"altitude: {altitude}; "
+ )
+
+
+def test_set_sensor_altitude1(sensor):
+ sensor.set_sensor_altitude(0)
def test_get_ambient_pressure1(sensor):
@@ -120,29 +112,47 @@ def test_get_ambient_pressure1(sensor):
)
-def test_set_sensor_altitude1(sensor):
- sensor.set_sensor_altitude(0)
+def test_set_ambient_pressure1(sensor):
+ sensor.set_ambient_pressure(1013)
-def test_get_sensor_altitude1(sensor):
- altitude = sensor.get_sensor_altitude()
- print(f"altitude: {altitude}; "
+def test_get_voc_algorithm_tuning_parameters1(sensor):
+ (index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial,
+ gain_factor
+ ) = sensor.get_voc_algorithm_tuning_parameters()
+ print(f"index_offset: {index_offset}; "
+ f"learning_time_offset_hours: {learning_time_offset_hours}; "
+ f"learning_time_gain_hours: {learning_time_gain_hours}; "
+ f"gating_max_duration_minutes: {gating_max_duration_minutes}; "
+ f"std_initial: {std_initial}; "
+ f"gain_factor: {gain_factor}; "
)
-def test_activate_sht_heater1(sensor):
- sensor.activate_sht_heater()
+def test_set_voc_algorithm_tuning_parameters1(sensor):
+ sensor.set_voc_algorithm_tuning_parameters(100, 12, 12, 180, 50, 230)
-def test_read_device_status1(sensor):
- device_status = sensor.read_device_status()
- print(f"device_status: {device_status}; "
+def test_get_nox_algorithm_tuning_parameters1(sensor):
+ (index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial,
+ gain_factor
+ ) = sensor.get_nox_algorithm_tuning_parameters()
+ print(f"index_offset: {index_offset}; "
+ f"learning_time_offset_hours: {learning_time_offset_hours}; "
+ f"learning_time_gain_hours: {learning_time_gain_hours}; "
+ f"gating_max_duration_minutes: {gating_max_duration_minutes}; "
+ f"std_initial: {std_initial}; "
+ f"gain_factor: {gain_factor}; "
)
-def test_read_and_clear_device_status1(sensor):
- device_status = sensor.read_and_clear_device_status()
- print(f"device_status: {device_status}; "
+def test_set_nox_algorithm_tuning_parameters1(sensor):
+ sensor.set_nox_algorithm_tuning_parameters(1, 12, 12, 720, 50, 230)
+
+
+def test_get_voc_algorithm_state1(sensor):
+ state = sensor.get_voc_algorithm_state()
+ print(f"state: {state}; "
)
@@ -206,8 +216,6 @@ def test_start_continuous_measurement1(sensor):
f"raw_co2: {raw_co2}; "
)
sensor.set_temperature_offset_parameters(1, 10, 1, 0)
- state = sensor.get_voc_algorithm_state()
- print(f"state: {state}; "
- )
+ sensor.set_ambient_pressure(1013)
sensor.stop_measurement()