Sgp30 with sleep mode


I am trying to use an sgp30 sensor. I am using the provided example code, except with two additions:

  1. I am using a load switch (connected to pin D6 on the Particle Electron) to control when the sensor gets 3.3 volts power provided to it.
  2. I am having the sensor go to sleep mode after each loop. The load switch will turn on, power the sensor, sensor gathers data, load switch will cut off power, the electron will go to sleep, then repeat.

The output is fine the first time, but every time after, the serial shows “Measurement failed”. Does anyone have any ideas on how to fix this issue?

Here is my code:

// This #include statement was automatically added by the Particle IDE.
#include <SensirionSGP30.h>

#include <Wire.h>

SensirionSGP30 sgp;

/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
    // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
    const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
    const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
    return absoluteHumidityScaled;

void setup() {
  Serial.println("SGP30 test");
    pinMode(D6, OUTPUT);
    digitalWrite(D6, HIGH);

  if (! sgp.begin()){
    Serial.println("Sensor not found :(");
    while (1);
  Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);

  // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
  //sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!

int counter = 0;
void loop() {
  // If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
  //float temperature = 22.1; // [°C]
  //float humidity = 45.2; // [%RH]
  //sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
  digitalWrite(D6, HIGH);
  for (int i = 0; i < 30; i++) {
  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

  if (counter == 30) {
    counter = 0;

    uint16_t TVOC_base, eCO2_base;
    if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
      Serial.println("Failed to get baseline readings");
    Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
    Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
  digitalWrite(D6, LOW);



Here is a optimized library for the SGP30 sensor that will get the most accurate readings from the sensor. I’ve been using this sensor for a year now and it works perfectly along with the SHT31 temp Humidity sensor and their new particulate sensor.

My dashboard below:


Hello! I think the hackster page is expired


Fixed it.


If my understanding is correct, during your 10,000 delay line, the SGP30 stays powered on correct? I included a switch that will cut it’s access to power before putting it into sleep mode to save battery life. My issue is somewhere in the code in that the sensor works fine the first run through, but after waking up the 2nd time and every time after, will fail the IAQmeasure test. Do you have any idea as to why?


If you power down the sensor you will need to run .begin() just after the device wakes and re-applies power to the sensor.


Not sure on the specific issue but this sensor needs to run 12hrs to establish a baseline. So even if you do fix it to report data it may not be accurate. I found mine wasn’t and had to implement the baseline calculation, then saving it to eeprom and validating it on startup and periodically saving a new baseline. It’s also a picky sensor, it needs to see fresh air every so often or it’ll drift; only an issue if running indoors. Perhaps baseline isn’t needed if it’s outside 24x7?

Here’s a discussion on baselines :

If no stored baseline is available after initializing the baseline algorithm, the sensor has to run for 12 hours until the baseline can be stored. This will ensure an optimal behavior for preceding startups. Reading out the baseline prior should be avoided unless a valid baseline is restored first. Once the baseline is properly initialized or restored, the current baseline value should be stored approximately once per hour. While the sensor is off, baseline values are valid for a maximum of seven days.

I have code I can share if you want to fully implement the baseline tracking. I’m not sure this sensor is a good choice for non-continuous operation but I am curious to hear how it works out.


I’ve been using the sensor for abou 6 months an it is very accurate and the baseline holds steady, I have noticed no drifting which is a key advertised benefit of the sensors design.

I’m not sure sleeping the sensor is acceptable if you want accurate long term data considering how it wants constant updates.


Indoors or outdoors? The simple test I do is to take my indoor sensor outside for an hour and bring it back in. If it had been drifting then I’ll very different values (assuming no real change in indoor air quality during that hour). ie it’ll be reporting 1000-2000 eCO2 before and 700 after.

I had a PMS7003 sensor that would also drift and I finally found it was due to my USB power source and after fixing that it hasn’t drifted since. The same device runs my SGP30 so it could have been the same issue; I haven’t re-tested it since.

My understanding was that for example if my indoor air is always around 1,000 eCo2 then the sensor over time will report lower values until what was 1,000 will now show as 400. Move the sensor where it can see actual 400 CO2 levels for a bit and it’ll go back to reporting 1,000 as 1,000.


I’ve used the sensor indoors and in a shop environment that has a garage door.

When I first setup the sensor I place it outside for a few hours so it can get an ambient outside Voc levels set. Then I bring it in and start using it and have never noticed any drifts happening.

To get the stable performance you have to do all recommended stuff like is emplemented in the library here.

In use the sensor in the shop all the time and would notice any drifting or odd behavior and somfar I have not seen any of that, I’m very happy with the sensor.


Just created a Hackster account to view that project. It’s very impressive . It already has all the enhancements I had added and then some extras like the humidity compensation and Udibots. I didn’t realize we could create webhooks via Web UI now. I think I’m going to get another SGP30 and some legos and duplicate that project :grin:


I modified that code to send data to Losant instead.

I also added the new particulate sensor SPG30

My Losant dashboard is here for these sensors.


I found a recent Adafruit post was looking at battery powering a SGP30. They said it was using 48ma which wasn’t going to work in their use case, but they found a new IDT sensor that only needs 7ma. I couldn’t find any breakout boards for available for it.

Adafruit Thread:
IDT Sensor page:


Have you run the SGP30 on an Argon or Xenon? Not sure why but neither my original nor new sensor returns any real data on them. The baseline and data values stay the same forever:
TVOC = 1.00 ppb
CO2 = 400.00 ppm
eco2_base = 65535
tvoc_base = 65535

Yet both sensors work fine on 2 of my Photons. I tried both my code and the Hackster code, same behavior from both. Using a thermal imaging camera I can the SGP on the Argon is cold/ambient temp whereas it’s hot (>120F) when connected to a photon. The argon reports no issues and will happily get/set baseline, humidity compensation, etc. The SHT sensor is plugged into the exact same Argon pins and has no issue. I’m stumped, not sure what else to try.


I have not tried them on the Gen3 devices yet.


Hello @RWB - What does it mean to “call the setBaseline function from the Particle console.” ? From the instructions of the project you linked to.

Aslo what happens if you dont have the option to place the sensor outside during the initial calibration period? Mine is powered by ethernet poe. thx.


Set baseline will basically reset the VOC baseline to default again.

After some time I see the Sgp30 VOC spike to max levels and then I click that reset baseline and it resets and is back to normal again.

You just need to place the sensor outside for 10-15 mins for the sensor to see basically zero VOC levels to properly calibrate it.


You just click the “call” button? No values entered?

I guess i can open the window to the room for awhile - if that will work?


You can try entering 1 to trigger the function to run.

I would put it outside for 5-10 mins, not just open the window since that will not be as clean as outside air from my testing.


Got it. Unfortunately, I can’t put it outside without powering it with a battery - or extending the network cable through the window!

But a noob question - Isn’t there default values for what a “clean” environment should be , and thus default co2 and voc values? Why the need to set the baseline outside for every install environment?