Skip to main content

SCD30 CO₂ sensor I²C driver in Python 3

Status: initial release

The SCD30 is a high-precision CO2 sensor based on NDIR spectroscopy. The sensor module also includes an SHT31 temperature and humidity sensor onboard (see description of the PCB layout).

Overview

This library provides a Python interface to the main I²C-level commands supported by the SCD30 as listed in the interface description.

The primary intended use case is driving the sensor directly from a Raspberry Pi using hardware I²C. However, the code may be adapted for use with other devices supporting the protocol and/or software I²C.

Installation

The library is available for download from the Python Package Index (tested with Python 3.7.3):

python3 -m pip install scd30_i2c

System setup

The library was developed using a Raspberry Pi 4B (8GB RAM) running Raspberry Pi OS Buster. For more details about the chip, see the BCM2711 datasheet.

Wiring

The Raspberry Pi can drive the SCD30 module via its hardware I²C interface directly without any additional components:

SCD30 Raspberry Pi
VDD 3V3 Power
GND Ground
TX/SCL BCM 3 (SCL)
RX/SDA BCM 2 (SDA)
SEL Ground¹

¹ To select I²C mode, the SEL pin should be left floating or connected to ground. This forum post suggests grounding the pin may be the more reliable option.

Note the sequential order of the power, ground, and I²C pins on the SCD30 may be different from other popular sensor breakouts. For instance, the Pimoroni breakouts use (3V3, SDA, SCL, INT, GND).

For more details, see the Raspberry Pi I2C pinout.

Software configuration and I²C clock stretching

The SCD30 supports a maximal I²C speed of 100kHz (the default of the Pi 4B).

It also requires the I²C bus to support clock stretching of up to 150ms. By default, the bcm2835-i2c driver which is still used by the 4B (BCM2711) hard-codes the timeout to 35ms regardless of the speed. This does not seem to matter for one-off readings, however may interfere with the long-term stability and particularly the automatic self-calibration feature.

As a workaround, the rpi-i2c binary utility provides means to manipulate the relevant I2C controller registers directly.

Usage

Contrary to other sensors that provide one-off readings, the SCD30 is designed to run continuously. Upon activation, periodic measurements are stored in a buffer. A "data ready status" command is provided to check whether a reading is available.

Sample code

The following example code will begin periodic measurements at a two-second interval and print the readings:

from scd30_i2c import SCD30

scd30 = SCD30()

scd30.set_measurement_interval(2)
scd30.start_periodic_measurement()

time.sleep(2)

while True:
    if scd30.get_data_ready():
        m = scd30.read_measurement()
        if m is not None:
            print(f"CO2: {m[0]:.2f}ppm, temp: {m[1]:.2f}'C, rh: {m[2]:.2f}%")
        time.sleep(2)
    else:
        time.sleep(0.2)

Note that this minimal example script will NOT issue a stop command upon termination and the sensor will continue taking periodic measurements unless powered off. This may or may not be appropriate depending on the use case.

For a more complete example, see here.

Temperature calibration

The SCD30 module contains a temperature and humidity sensor, which allows for temperature compensation of the CO₂ sensor signal. Therefore, the correctness of the temperature measurements is critical to achieving highly accurate CO₂ readings.

Due to the small size of the module, the inherent self-heating of the various electrical components on and around the PCB are likely to cause values above ambient temperature to be reported. To counteract this, a temperature offset can be configured via the I²C interface. The correct value will depend on the placement and configuration of the sensor and should be updated if any changes are made. For instance, setting a different measurement interval can change the average power draw of the sensor, and in turn, the heat produced by its components. Changing its position relative to other components, altering the airflow or installing additional sensors nearby may similarly change the offset required.

By default, the temperature offset is disabled, i.e. set to 0'C. However, the following calculations apply in the general case, even with non-zero temperature offsets already set.

To determine the correct temperature offset, consider the following values:

  • T_ambient: the "reference" ambient temperature, measured through means other than the SCD30.
  • T_measured: the raw temperature reading obtained internally onboard the SCD30; we assume T_measured >= T_ambient.
  • T_reported: the temperature reported by the SCD30 after applying the configured offset, i.e. T_reported = T_measured - T_offset.

Clearly, the end goal is to minimize the error:

Δ = |T_reported - T_ambient|
  = |T_measured - T_offset - T_ambient|
  = |T_measured - T_ambient - T_offset|

Consequently:

T_offset = T_measured - T_ambient

Note that the SCD30 does not expose T_measured directly; the value returned by read_measurement() already has the current offset applied, i.e. T_reported is returned instead. Recall that:

T_reported = T_measured - T_offset

Therefore, the raw value T_measured can be computed by factoring in the current offset T_offset_old (obtained using get_temperature_offset()):

T_measured = T_reported + T_offset_old

Having obtained T_measured and a "true" reference temperature T_ambient (e.g. using a different thermometer) a new offset can be calculated:

T_offset_new = T_measured - T_ambient = (T_reported + T_offset_old) - T_ambient.

Metadata

Release files for scd30-i2c 0.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scd30-i2c 0.0.6
File Size Uploaded
scd30_i2c-0.0.6.tar.gz 7.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for scd30-i2c 0.0.6
File Interpreter ABI Platform
scd30_i2c-0.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 16.5 kB

Release files / scd30_i2c-0.0.6.tar.gz

Download URL scd30_i2c-0.0.6.tar.gz
Size 7.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a19bb9dee183e35aa0d77ad73f75733ed0c243faa24bff7efe5f48d360979efa
BLAKE2b-256 checksum
How to use checksums
29e1cf2973a621b94d0a748edf03bb30a1b844d3a3e23697e08e9e8b0c45d5aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/47.3.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.7.3

Release files / scd30_i2c-0.0.6-py3-none-any.whl

Download URL scd30_i2c-0.0.6-py3-none-any.whl
Size 8.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bf326ae20faad9c58deb85a79cafd9ec7d417eccc374a2855d36faa433d9222b
BLAKE2b-256 checksum
How to use checksums
65515b5a4d8c1655f2e8be2538a27591902044b7e0d23f458c03e2483932aa4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/47.3.1 requests-toolbelt/0.9.1 tqdm/4.46.1 CPython/3.7.3

Release history Release notifications | RSS feed

This release

0.0.6 This release

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page