Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,4 @@ on:
jobs:
build_and_deploy:
uses: sensirion/.github/.github/workflows/driver.python.pypi_publish.yml@main
secrets:
PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}

secrets: inherit
6 changes: 4 additions & 2 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ name: Publish Documentation
on:
workflow_dispatch:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"
branches:
- main

jobs:
documentation:
uses: sensirion/.github/.github/workflows/driver.python.documentation.yml@main
with:
use-project-requirements: true
11 changes: 11 additions & 0 deletions .github/workflows/gh_workflow_metadata_update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: Driver Index Metadata Update

on:
push:
branches:
- main

jobs:
driver-index-metadata-update:
uses: sensirion/.github/.github/workflows/driver.common.di_metadata_update.yml@main
secrets: inherit
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.3.0] - 2026-6-5

### Added

- Added get_product_type command.
## [1.2.0] - 2025-3-13

### Added
Expand Down Expand Up @@ -40,7 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add interfaces to start, stop and read measurements.
- Add interfaces to read product name, serial number and version

[Unreleased]: https://github.com/Sensirion/python-i2c-sen66/compare/1.2.0...HEAD
[Unreleased]: https://github.com/Sensirion/python-i2c-sen66/compare/1.3.0...HEAD
[1.3.0]: https://github.com/Sensirion/python-i2c-sen66/compare/1.2.0...1.3.0
[1.2.0]: https://github.com/Sensirion/python-i2c-sen66/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/Sensirion/python-i2c-sen66/compare/1.0.1...1.1.0
[1.0.1]: https://github.com/Sensirion/python-i2c-sen66/compare/1.0.0...1.0.1
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) 2025, Sensirion AG
Copyright (c) 2026, Sensirion AG
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@

This repository contains the Python driver to communicate with a Sensirion SEN66 sensor over I2C.

<img src="https://raw.githubusercontent.com/Sensirion/python-i2c-sen66/master/images/sen6x.png"
<img src="https://raw.githubusercontent.com/Sensirion/python-i2c-sen66/master/images/product-image-sen6x.png"
width="300px" alt="SEN66 picture">


Click [here](https://sensirion.com/sen6x-air-quality-sensor-platform) to learn more about the Sensirion SEN66 sensor.



The default I²C address of [SEN66](https://www.sensirion.com/products/catalog/SEN66) is **0x6B**.
The default I²C address of [SEN66](https://www.sensirion.com/products/catalog/SEN66) is **0x6b**.



## Connect the sensor

You can connect your sensor over a [SEK-SensorBridge](https://developer.sensirion.com/sensirion-products/sek-sensorbridge/).
You can connect your sensor over a [SEK-SensorBridge](https://developer.sensirion.com/product-support/sek-sensorbridge/).
For special setups you find the sensor pinout in the section below.

<details><summary>Sensor pinout</summary>
<p>
<img src="https://raw.githubusercontent.com/Sensirion/python-i2c-sen66/master/images/sen6x-pinout.png"
<img src="https://raw.githubusercontent.com/Sensirion/python-i2c-sen66/master/images/product-pinout-sen6x.png"
width="300px" alt="sensor wiring picture">

| *Pin* | *Cable Color* | *Name* | *Description* | *Comments* |
Expand Down
26 changes: 0 additions & 26 deletions ci/checkin_doc.sh

This file was deleted.

16 changes: 0 additions & 16 deletions ci/set_git_config.sh

This file was deleted.

11 changes: 6 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/execute-measurements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ execute a simple measurement.
python examples/example_usage_sensorbridge_sen66.py --serial-port <your COM 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
Expand Down
71 changes: 71 additions & 0 deletions examples/SEN6x_I2C_FRC_CO2_example_linux_sen66.py
Original file line number Diff line number Diff line change
@@ -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}"
)
80 changes: 80 additions & 0 deletions examples/SEN6x_I2C_FRC_CO2_example_sensorbridge_sen66.py
Original file line number Diff line number Diff line change
@@ -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}"
)
Loading
Loading