SGP30 air quality sensor
The Sensirion SGP30 air quality sensor on I2C at 0x58: CO2 equivalent in ppm and
TVOC in ppb. Aliases: Adafruit SGP30, eCO2 sensor.
It is the sensor in most home-built air quality monitors. A metal-oxide hot plate reacts to the gases people and paint give off, and the chip turns that into two numbers. The CO2 figure is an estimate from those gases, not a measurement of CO2 itself, which is why the datasheet calls it CO2eq.
Pins
| Pin | What it does |
|---|---|
VIN |
Supply, 3.3 V or 5 V. The board regulates it down to the chip's 1.8 V. |
GND |
Ground. |
SCL |
I2C clock. The board carries the pull-ups. |
SDA |
I2C data. |
Properties
eco2 (ppm, 400 to 60000) and tvoc (ppb, 0 to 60000) are the air. The two sliders
on the part change them while the circuit runs; they cover indoor air, 400 to 5000
ppm and 0 to 3000 ppb, and the properties take the sensor's whole range.
How it talks
Sixteen-bit commands, high byte first, and replies of two-byte words, each followed by
the same CRC-8 as the SHT31 (polynomial 0x31, starting at 0xFF). While a command
runs the sensor does not answer its address at all.
| Command | Code | Time | Reply |
|---|---|---|---|
| Init_air_quality | 0x2003 |
10 ms | none |
| Measure_air_quality | 0x2008 |
12 ms | CO2eq, TVOC |
| Get_baseline | 0x2015 |
10 ms | CO2eq and TVOC baselines |
| Set_baseline | 0x201E |
10 ms | none; TVOC first, then CO2eq |
| Set_humidity | 0x2061 |
10 ms | none; absolute humidity in 8.8 g/m³ |
| Measure_test | 0x2032 |
220 ms | 0xD400 |
| Get_feature_set_version | 0x202F |
10 ms | 0x0020 |
| Measure_raw_signals | 0x2050 |
25 ms | H2 and ethanol raw signals |
| Get_serial_id | 0x3682 |
0.5 ms | three words |
The warm-up. For 15 s after Init_air_quality every measurement reads 400 ppm and 0 ppb, the datasheet's fixed start values. The datasheet then asks for a measurement every second, which is what feeds the sensor's baseline algorithm.
The library
Adafruit_SGP30.h works as its tutorial uses it:
#include <Wire.h>
#include "Adafruit_SGP30.h"
Adafruit_SGP30 sgp;
void setup() {
Serial.begin(115200);
if (!sgp.begin()) {
Serial.println("Sensor not found :(");
while (1);
}
}
void loop() {
if (!sgp.IAQmeasure()) {
Serial.println("Measurement failed");
return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
delay(1000);
}
IAQmeasureRaw(), getIAQBaseline(), setIAQBaseline(), setHumidity() and
serialnumber[] are there too. setHumidity() takes mg/m³. Upstream's example works
that out from a temperature and relative humidity with exp(), which does not link on
the boards here; the Air quality monitor template does it with a table and integers.
What the model gets right
The command set and each command's execution time, the silence while a command runs, the 15 s warm-up at 400 ppm and 0 ppb, the CRC on every word in both directions (a parameter with a bad CRC is refused), the baseline's reversed write order, and the feature set and self-test replies, all from the SGP30 datasheet (version 1.0).
What it does not model
The baseline algorithm itself: a baseline you set reads back, and a new sensor's baseline is an assumed pair. The humidity compensation is taken and stored but does not change the readings. The raw signals follow the TVOC slider by the datasheet's logarithmic relation, from reference values assumed for clean air. The general call reset, drift and the sensor's slow response are not modeled.
Common mistakes
Believing the first readings. For 15 s they are 400 ppm and 0 ppb whatever the air is doing.
Measuring less often than once a second. The sensor still answers, but on the bench its baseline algorithm needs the regular rhythm.
See it in action
Air quality monitor reads an SGP30 and an SHT31 on the same two wires and shows them on a 16x2 LCD. Open it at /templates.