Skip to main content

Python driver for Senseair Sunrise, Sunlight and S12 CO2 sensors (I2C and Modbus RTU)

Project description

senseair-sunrise

Python driver for Senseair Sunrise / Sunlight and S12 CO2 sensors over I2C and Modbus RTU (UART), on Linux (incl. Raspberry Pi), Windows and macOS.

A Pythonic port of the Senseair Arduino library.

Sensor I2C class Modbus class
Sunrise / Sunlight SunriseI2C SunriseModbus
S12 S12I2C S12Modbus

All four share the measurement / configuration / calibration API inherited from SunriseBase. Methods raise a SunriseError subclass on failure and return dataclasses. A successful read_measurement() still requires checking Measurement.error_status against the ErrorStatus flags to confirm the reading is valid.

Installation

pip install senseair-sunrise              # core (Modbus RTU works everywhere)
pip install "senseair-sunrise[rpi]"       # + smbus2/gpiozero for Raspberry Pi native I2C/GPIO
pip install "senseair-sunrise[ftdi]"      # + pyftdi for an FT232H/FT2232H USB-I2C bridge

To install from a local checkout of this repository (e.g. before it is published), use a path instead of the package name — the same extras apply:

pip install -e .                          # editable install from a clone of this repo
pip install -e ".[rpi]"                   # editable + Raspberry Pi I2C/GPIO extras
pip install /path/to/python-sunrise       # non-editable, from a local path

Modbus RTU needs only pyserial. I2C and the EN/nRDY pins go through pluggable backends, so the same sensor classes run on a Raspberry Pi or, via an FTDI USB bridge, on Windows/macOS.

On a Raspberry Pi, the EN/nRDY pins can be driven through two interchangeable backends (both implement the Pin protocol):

  • GpiodPin (libgpiod) — the install-friendly default for examples/rpi_pins.py. It talks to the kernel's GPIO character device directly, with no separate pin factory to install:

    sudo apt install python3-libgpiod    # prebuilt, no compiler
    python examples/rpi_pins.py --gpio-backend gpiod --en-pin 17 --nrdy-pin 27
    

    GpiodPin works with both libgpiod v1 (Raspberry Pi OS Bookworm's apt package) and v2. Pins are integer BCM line offsets on a gpiochip; on a Raspberry Pi 5 the 40-pin header may live on a chip other than /dev/gpiochip0, so pass --gpiochip if line requests fail.

  • GpiozeroPin (gpiozero) — also needs a separate pin-factory backend. Install lgpio from apt, which ships a prebuilt module:

    sudo apt install python3-lgpio
    

    Prefer apt over pip install lgpio: the PyPI source build needs swig and a C toolchain, and prebuilt wheels are not always available for newer Python versions. Without any backend, gpiozero falls back to its experimental sysfs pin factory, which fails on current kernels. (To see an apt-installed module from a virtualenv, create it with --system-site-packages.)

Usage

Continuous mode over Modbus RTU:

import time
from senseair_sunrise import SunriseModbus, describe_error_status

sensor = SunriseModbus("/dev/ttyUSB0")   # default address 0x68
sensor.enable()

while True:
    meas = sensor.read_measurement()
    print(f"{meas.co2_ppm} ppm  {meas.temperature_c:.2f} C")
    for flag in describe_error_status(meas.error_status):
        print("  -", flag)
    time.sleep(16)

Over I2C on a Raspberry Pi (or an FTDI USB bridge on Windows/macOS):

from senseair_sunrise import SunriseI2C, SMBus2Bus      # FtdiI2CBus for an FTDI bridge

sensor = SunriseI2C(SMBus2Bus(1))                        # /dev/i2c-1
sensor.enable()
print(sensor.read_measurement().co2_ppm)

Driving the enable / nRDY pins (recommended for single mode) uses the pluggable Pin backends (GpiozeroPin, FtdiPin), passed as enable_pin= / nrdy_pin=. Over an FTDI bridge, get the GPIO controller from the bus with FtdiI2CBus.get_gpio() and wrap individual bits in FtdiPin.

I2C bus speed and latency

The sensors support an I2C clock of up to 100 kHz (constants.I2C_CLOCK_HZ; the S12 also supports 400 kHz Fast Mode, but this library targets 100 kHz). The two backends configure the bus differently:

  • FtdiI2CBus(url, frequency=...) defaults to a conservative 20 kHz due to the FTDI MPSSE engine limitations, the actual bitrate for write operations over I2C is very slow (see pyftdi for details). The FTDI latency timer is set to SUNRISE_I2C_IDLE_TIMEOUT_MS // 3 (~5 ms) so the host services the bus before the sensor sleeps after 15 ms of idle.
  • SMBus2Bus runs at whatever clock the kernel/OS configures (e.g. dtparam=i2c_arm_baudrate= in /boot/config.txt on a Raspberry Pi). It cannot be set or read from Python, so make sure the OS configures it at or below 100 kHz.

Examples

Runnable scripts live in examples/sunrise_continuous.py, sunrise_single.py, sunrise_change_address.py, sunrise_scale_factor.py, s12_continuous.py, s12_single.py, and calibrate.py. Each takes --protocol modbus|i2c plus --port / --bus / --ftdi; the continuous/single scripts also expose --set-continuous / --set-single, --samples and --period for measurement settings. Two more cover I2C wiring setups: multi_sensor.py reads several sensors sharing one bus (distinct addresses), ftdi_pins.py drives the EN/nRDY pins through an FTDI bridge's GPIO, and rpi_pins.py does the same from a Raspberry Pi's native GPIO and I2C port (--gpio-backend gpiozero or gpiod). Run any script with --help for details.

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest          # hardware-free unit tests
ruff check .
mypy src

License

BSD-3-Clause. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

senseair_sunrise-0.1.0.tar.gz (36.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

senseair_sunrise-0.1.0-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

File details

Details for the file senseair_sunrise-0.1.0.tar.gz.

File metadata

  • Download URL: senseair_sunrise-0.1.0.tar.gz
  • Upload date:
  • Size: 36.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for senseair_sunrise-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ce82ded014e8b1b35315f113d7beb38c4270cf7315929157394983f9c0254808
MD5 ef5ed7157199f3810e37f9f116bca2c2
BLAKE2b-256 0fe1517c2647a34700185b86dbf2584a92d6484496ae2e809cd647069cbf5103

See more details on using hashes here.

File details

Details for the file senseair_sunrise-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for senseair_sunrise-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 77878b765d2e98e0510c40225c88382df5a6e8dd0cbfdb81d7c914a50712a750
MD5 e7ec160e84a9455516f96473e1ac275a
BLAKE2b-256 84308af632c3fcc0d15983a4e1385f6c8a59b29d47355701788c79d63344ca9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page