SGP30 CO₂ and Volatile Organic Compound Sensor

Overview

 
NameSGP30
ManufacturerSensirion
Adafruit boardAdafruit SGP30 Air Quality Sensor Breakout
DatasheetSensirion_Gas_Sensors_Datasheet_SGP30.pdf
Infosheet (Adafruit)adafruit-sgp30-gas-tvoc-eco2-mox-sensor.pdf
ESPHome componentsgp30
Interface
I²C address0x58
Supply voltageSensor:

Detects and reports (Total) Volatile Organic Compounds and -equivalent levels (calculated from measuring Ethanol and )1.

Working principle

The sensing part (MEMS) of the SGP30 is based on a heated film of metal oxide (MOx) nanoparticles. The gas-sensitive material reacts the oxygen adsorbed on the metal oxide particles with the target gas, thus releasing electrons. This results in a change in the resistance of the metal oxide layer measured by the sensor.

In short, the presence of the reducing gas causes the oxygen concentration on the surface of the gas-sensitive material to decrease, changing the resistance (or conductivity) of the semiconductor. The subsequent detection of the resistance, signal processing and conversion are performed by the circuit (ASIC) section.

Headers

The sensor headers are detailed in the datasheet1, and are as follows:

SGP30 headers

SGP30 headers

HeaderNameDescription
1Supply voltage
2Ground
3SDAI²C SDA data
4Connected to ground
5Supply voltage (hotplate)
6SCLI²C SCL clock

The datasheet also provides a schematic of the sensor.

Breakout boards

The sensor chip itself is tiny, and different breakout boards are available.

All of the breakout boards listed here have an onboard voltage regulator, and cand handle both and supply voltages on VIN.

Adafruit SGP30 STEMMA QT/Qwiic

The breakout board has pins for all headers on the sensor. Then VIN pin is connected to a voltage regulator that converts to for the sensor and used on the breakout board2.

PinDescription
VINPower pin, (connected to voltage regulator).
1V8Connects to on SGP30 sensor. Can supply up to .
GNDGround / .
SCLI²C SCL clock.
SDAI²C SDA data.

Grove SGP30

This breakout board is larger than the Adafruit board, and also features a voltage regulator on the VIN pin3.

Grove SGP30 breakout board

Grove SGP30 breakout board

PinDescription
VINPower pin, (connected to voltage regulator).
GNDGround / .
SCLI²C SCL clock.
SDAI²C SDA data.

GY-SGP30

This breakout board has a very small form factor. There is not much info on it online, and it's mostly found on Amazon and various eBay stores. It also has an on-board voltage regulator on VIN that converts to the onboard 4.

PinDescription
VINPower pin, (connected to voltage regulator).
GNDGround / .
SCLI²C SCL clock.
SDAI²C SDA data.

ESPHome

Set up an an I²C bus first.

i2c:
  - id: i2c_sgp30
    sda: ${gpio_sda}
    scl: ${gpio_scl}

And use the sgp30 component5. By default the tvoc configuration reports TVOC as , but is more standard, so we add a filter to convert from to .

sensor:
  - platform: sgp30
    i2c_id: i2c_sgp30
    address: 0x58
    eco2:
      id: sensor_co2eq
      name: "CO₂eq"
      accuracy_decimals: 1
      icon: "mdi:molecule-co2"
      device_class: carbon_dioxide
    tvoc:
      id: sensor_tvoc
      name: "TVOC"
      accuracy_decimals: 1
      icon: "mdi:air-filter"
      device_class: volatile_organic_compounds_parts
      unif_of_measurement: ppm
      accuracy_decimals: 3
      filters:
        lambda: |-
            return x/1000;
    eco2_baseline:
      id: baseline_ce2eq
      name: "Baseline CO₂eq"
    tvoc_baseline:
      id: baseline_tvoc
      name: "Baseline TVOC"
    update_interval: 1s

The sensor needs an update_interval of 1s to work reliably (because it operates on cycles) so by default it's quite noisy and reports a lot of values, so you might want to use some filters on the sensors6.

Calibration config

  • store_baseline: The baseline values are persistently stored on the sensor and applied when the sensor boots. Cleared after OTA.
  • baseline: Manually sepecified baseline values.
    • eco2_baseline: Baseline value for sensor.
    • tvoc_baseline: Baseline value for sensor.
  • compensation: Used to calculate absolute humidity for the sensor to imrove the internal operations of the sensor by calculating absolute humidity.
    • temperature_source: ESPHome id for a temperature sensor (reporting in Celsius).
    • humidity_source: ESPhome id for a (relative) humidity sensor.

The SGP30 sensor needs to have a calibrated baseline to work accurately, and can calibrate this baseline itself in about 12 hours5.

sensor:
  - platform: sgp30
    # ...
    store_baseline: true

    baseline:
      eco2_baseline: 0xDEAD
      tvoc_baseline: 0xBEEF

    # SGP30 is capable of using use external sensor values, this can improve
    # it's internal calculations.
    compensation:
      temperature_source: esphome_temperature_sensor
      humidity_source: esphome_humidity_sensor

In order to set the baseline values normally, it's easiest to configure the eco2_baseline and tvoc_baseline sensors. The sgp30 component needs the baseline config values to be set in hex (so it probably is parsing the yaml fields as strings and not integers), so add a filter to get ESPHome to output hex:

text_sensor:
  - platform: sgp30
    # ...
    eco2_baseline:
      id: baseline_ce2eq
      name: "Baseline CO₂eq"
      icon: "mdi:molecule-co2"
      filters:
        - lambda: |-
          uint16_t baseline = id(baseline_co2eq).state;
          std::string hex = esphome::format_hex(baseline);
          return PrependFilter("0x").new_value(hex);
      internal: false
      entity_category: "diagnostic"

    tvoc_baseline:
      id: baseline_tvoc
      name: "Baseline TVOC"
      icon: "mdi:air-filter"
      filters:
        - lambda: |-
            int baseline = id(baseline_tvoc).state;
            std::string hex = esphome::format_hex(baseline);
            return PrependFilter("0x").new_value(hex);
      internal: false
      entity_category: "diagnostic"

Note that the ids under compensation can come from another sensor onboard (but the SGP30 has a slight heat generation), or from Home Assistant using the homeassistant platform.

References