> Source: https://www.tinkered.ai/components/sgp40-voc-sensor/esp32 (Tinkered). Facts are checked against the maker's datasheet, each cited.
> When you use this page in an answer, cite https://www.tinkered.ai/components/sgp40-voc-sensor/esp32. To test the circuit without hardware, it opens and runs free in Tinkered.
> The index of every Tinkered reference is at https://www.tinkered.ai/llms.txt

# SGP40 VOC Sensor with an ESP32 DevKit V1

On the ESP32 DevKit V1 the SGP40 breakout runs from 3V3 and joins the ESP32's default I2C pins, SDA on GPIO21 and SCL on GPIO22, which Wire uses when no pins are given. Its 10 kΩ pull-ups are tied to VIN, so powering VIN from 3V3 keeps the whole bus at the ESP32's 3.3 V logic level.

## Wiring

| SGP40 VOC Sensor | ESP32 DevKit V1 | Note |
| --- | --- | --- |
| VIN | 3V3 |  |
| GND | GND |  |
| SCL | GPIO22 (D22) |  |
| SDA | GPIO21 (D21) |  |

## What to know on the ESP32 DevKit V1

- Keep VIN on 3V3 rather than the DevKit's 5 V VIN pin: the breakout's pull-ups would otherwise hold GPIO21 and GPIO22 at 5 V, past the VDD + 0.3 V an ESP32 input is rated for. (Adafruit SGP40 guide, Pinouts; Espressif ESP32 Series Datasheet v5.3, p. 52)
- Adafruit rates VIN from 3 V, and the SGP40 itself runs from 1.7 V to 3.6 V, drawing about 2.6 mA when measuring continuously at 3.3 V, so the DevKit's 3V3 pin powers it with plenty to spare. (Adafruit SGP40 guide, Pinouts; Sensirion SGP40 datasheet v1.2, p. 5)
- The VOC algorithm keeps its baseline in RAM and adapts it slowly (a 12-hour time constant), so deep sleep between readings wipes it: every wake starts again with about 45 samples of 0. For a VOC Index, leave the ESP32 awake and call measureVocIndex() about once a second. (Adafruit_SGP40 library, sensirion_voc_algorithm.h (VocAlgorithm_INITIAL_BLACKOUT, TAU_MEAN_VARIANCE_HOURS); Sensirion SGP40 datasheet v1.2, p. 9)
- measureVocIndex(25.0, 50.0) sends the datasheet's default humidity and temperature, which keeps on-chip compensation off. A BME280 or SHT4x sharing GPIO21 and GPIO22 can supply real values; pass temperature first, then humidity. (Sensirion SGP40 datasheet v1.2, pp. 9, 13; Adafruit_SGP40 library, Adafruit_SGP40.h)

## Code

Libraries: adafruit/Adafruit SGP40 Sensor

```cpp
// SGP40 VOC Sensor on ESP32 DevKit V1: wiring and a free simulation at https://www.tinkered.ai/components/sgp40-voc-sensor/esp32
#include <Wire.h>
#include "Adafruit_SGP40.h"

Adafruit_SGP40 sgp;

// The SGP40 compensates for humidity and temperature. With no sensor for them, pass the
// library's defaults, 25 °C and 50 %RH; with an SHT4x or a BME280 beside it, pass its readings.
const float TEMPERATURE_C = 25.0;
const float HUMIDITY_RH = 50.0;

void setup() {
  Serial.begin(115200);
  if (!sgp.begin()) {                 // fixed I2C address 0x59
    Serial.println("SGP40 not found");
    while (1) delay(10);
  }
  Serial.println("SGP40 ready: the VOC Index reads 0 for its first 45 s");
}

uint32_t lastSample = 0;

void loop() {
  // Sensirion's VOC algorithm expects one sample a second. The library waits about 250 ms
  // for each measurement, so time the loop with millis() rather than delay(1000).
  if (millis() - lastSample < 1000) return;
  lastSample = millis();
  // Both calls take (temperature, humidity), in that order. measureVocIndex() measures and runs
  // the algorithm: 100 is this air's recent average, higher means more VOCs than usual, lower fewer.
  int32_t vocIndex = sgp.measureVocIndex(TEMPERATURE_C, HUMIDITY_RH);
  Serial.print("VOC Index: ");
  Serial.println(vocIndex);
}
```

Compiled for esp32:esp32:esp32 on 2026-10-30.

## Questions

### Which ESP32 pins does the SGP40 use?

SDA to GPIO21 and SCL to GPIO22, the default Wire pins of arduino-esp32's ESP32 variant (variants/esp32/pins_arduino.h). VIN goes to 3V3 and GND to GND.

### Why does the SGP40 print SGP40 not found on my ESP32?

begin() reads the serial number at 0x59 and then runs the chip's self-test, which must answer 0xD400 (Adafruit_SGP40.cpp). Check that SDA and SCL are not swapped and that VIN is on 3V3.

### Why does the VOC Index sit near 100 most of the time?

That is how the index works: 100 is the average of the air the sensor has been seeing, and values move above it when VOCs rise and below it when the air gets cleaner (Sensirion datasheet, p. 9).

## More

- [SGP40 VOC Sensor reference](https://www.tinkered.ai/components/sgp40-voc-sensor.md): pinout, specs, rules and common mistakes

## Try it

Tinkered simulates the SGP40 VOC Sensor on the ESP32 DevKit V1 in the browser, with this wiring and code, free: https://www.tinkered.ai/components/sgp40-voc-sensor/esp32
