SGP30 doesn't work on Gen3 devices

Has anyone had success with the Adafruit SGP30 sensor on the Gen 3 devices? My sensors work fine on Photons but not on Argons or Xenons. It doesn’t throw an error but it appears the internal heater never kicks in (according to thermal imaging) and all I get back is 0-1 and 400-401. I’ve tried both particle SGP30 libraries though technically they both originate from Adafruit’s code.

To help narrow things down I’ve confirmed all the libraries and code I’ve been trying work on Photons. I’ve then confirmed it doesn’t work on an Argon and a Xenon. I’ve tried different breadboards, different wires. Next I enabled the I2C debugging, within the library code, and see no issues other than the values:
On Startup:

Found SGP30 serial #0A49CAE
                -> 0x20, 0x8,
                <- 0x1, 0x90, 0x4C, 0x0, 0x0, 0x81,
                CRC calced: 0x4C vs. 0x4C
                Read: 0x190
                CRC calced: 0x81 vs. 0x81
                Read: 0x0
TVOC 0 ppb      eCO2 400 ppm
                -> 0x20, 0x8,
                <- 0x1, 0x90, 0x4C, 0x0, 0x0, 0x81,
                CRC calced: 0x4C vs. 0x4C
                Read: 0x190
                CRC calced: 0x81 vs. 0x81
                Read: 0x0
TVOC 0 ppb      eCO2 400 ppm

It’s normal to report 0s for up to 30sec after starting(technically 400ppm is the 0 for eCO2).
Here’s the first baseline output:
****Baseline values: eCO2: 0xFFF8 & TVOC: 0xFFDD
Later on, after it’s been running for awhile, it’s always TVOC 1 and eCO2 of 400 or 401:

                -> 0x20, 0x8,
                <- 0x1, 0x90, 0x4C, 0x0, 0x1, 0xB0,
                CRC calced: 0x4C vs. 0x4C
                Read: 0x190
                CRC calced: 0xB0 vs. 0xB0
                Read: 0x1
TVOC 1 ppb      eCO2 400 ppm
                -> 0x20, 0x8,
                <- 0x1, 0x91, 0x7D, 0x0, 0x1, 0xB0,
                CRC calced: 0x7D vs. 0x7D
                Read: 0x191
                CRC calced: 0xB0 vs. 0xB0
                Read: 0x1
TVOC 1 ppb      eCO2 401 ppm
****Baseline values: eCO2: 0xFFF8 & TVOC: 0xFFF8

A simple way to confirm I don’t have exceptional air is to breathe on it. It’ll spike instantly when run on a Photon, no movement on Gen3 devices. These baseline values are much higher than they should be which may imply even the internal chip isn’t getting good data. So perhaps an initialization issue based on the chip generating no heat (confirmed via thermal imaging) when a heating element is critical to it’s operation. Not sure what else to try. Any ideas?

For those not familiar with this sensor, here’s the product page: https://www.sensirion.com/en/environmental-sensors/gas-sensors/multi-pixel-gas-sensors/
and the datasheet: https://www.mouser.com/ds/2/682/Sensirion_Gas_Sensors_SGP30_Datasheet_EN-1148053.pdf

@Fragma, I have an SGP30 (purchased on AliExpress) running nicely via I2C on a Xenon using the Adafruit_SGP30 library available on the Web IDE.

That’s good to hear. Is it the Adafruit breakout or some other configuration?
I just tried that library again [https://build.particle.io/libs/Adafruit_SGP30/1.0.0/tab/example/sgp30test.ino] to confirm it doesn’t work for me. I’m on 0.9.0, the Web IDE wouldn’t let me flash any prior versions.

@Fragma, I’m using THIS board from AliExpress. I now realize as I write this post that I didn’t check the power requirements and I’m using 3.3v instead of 1.8v!!! Oddly, it is working as expected :thinking: So it is working but it shouldn’t!

UPDATE: Yup, the SGP30 went to that big recycling yard in the sky. Morale… RTFM!!!

1 Like

So that’s why my Adafruit Breakout has a 1.8v regulator on it :grinning:

1 Like

Haven’t figured out why but mine just started working. I left the Adafruit example running the last few days and now I see valid data. I tried all the other code variations that weren’t working before and they all work after the 15-30sec startup process, even without a saved baseline. It’s quite odd.

1 Like

I’ve duplicated the same results Fragma reports with the SGP30 working well when connected to a Photon, but not at all with a Xenon. I purchased a second SGP30 board from Adafruit thinking I damaged the first, but see the same results. I’ve used the Adafruit library. There is a note at the top that specifically notes modification for the Photon & Core: // Example usage for Adafruit_SGP30 library.
// This library was modified/wrapped by SJB (https://github.com/dyadica)
// in order to work with Particle Photon & Core.

1 Like

I have had no problems running the SGP30 on an Argon and Xenon using the Adafruit example.

Initially it worked fine using code modified from the example provided with the library for the sensor, but that only read and stored the CO2 and VOC readings. Now I would like to be warned of rapidly increasing levels and it won’t work. The code below is meant to take samples of 5 readings 1 sec apart and average them. If the averages increase for 3 consecutive samples, then I want an alarm published to the cloud. I have mostly copied the SGP code from the example and placed it into a boiler plate that builds and rotates the samples. This code keeps reading 400 CO2 and 0 VOC, which means 0. This is still the case even after running it over night. I assume that I am mishandling the baselines somehow.

I have tried to organize and comment my amateurish code. Any help is appreciated.

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

int sampleSize = 5; //# of readings included in a sample
int sample[5];

const char room = 'B200';    //Location of sensor

void setup() {
    Serial.begin();
    RGB.control(true);  
    RGB.brightness(0);  //Turn off the RGB LED
    
    if (! sgp.begin()){
        Serial.println("Sensor not found :(");
        while (1);
    }
    
   Serial.print("Found SGP30 serial #");    //Retrieve the serial number of the sensor 
   Serial.print(sgp.serialnumber[0], HEX);
   Serial.print(sgp.serialnumber[1], HEX);
   Serial.println(sgp.serialnumber[2], HEX);

}

void loop() {
    Time.zone(-5);
    int defcon = 0; //The number of consecutive increases before triggering alert.
    int newAvg = 0;
    int oldAvg = 0;
    int sampling = 1;
    int sum = 0;
    
    if (! sgp.IAQmeasure()) {
        Serial.println("Measurement failed");
        return;
    }
    
    Particle.publish("Sampling Beginning");
    while (sampling < 7) {  

        for (int reading = 0;reading < sampleSize ;reading++) { //Build sample of 5 readings, 1 second apart.
            sample[reading] = sgp.TVOC;
            sum = sum + sample[reading];
            delay(1000);
        }
        newAvg = sum / sampleSize;
        Mesh.publish("sgp reading", Time.format("%H:%M:%S") + "," + String(newAvg));
        sum = 0;

        if (newAvg > oldAvg) {  //Raise alert level if new avg is greater than previous
            defcon++;
            Serial.print("Defcon: " + String(defcon));
        }

        else {
            defcon = 0; // Reset alert level if new avg not greater than previous
        }
        
        oldAvg = newAvg;    
        
        if (defcon > 3){    // Publish alert after enough consecutive increases
            Mesh.publish("sgp reading", "Alert: " + String(room) + "," + String(newAvg));
            Particle.publish("alert", room + "," + String(newAvg));
            defcon = 0;    
        }
        
        if (sampling == 6) {    //Reset the baseline every 6 samples (30 readings). I think my issue may lie here!
            uint16_t TVOC_base, eCO2_base;
            if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
                Serial.println("Failed to get baseline readings");
                return;
            }
            
            sampling = 1; //Resart the loop
        }

    } //end while
}

I guess you should call sgp.IAQmeasure() each time you want to get a new reading :wink:

That worked. Thanks, I thought that step was just a preliminary check.

How did you go with this? I am having the exact same issue.

edit: to elaborate further. I am using Particle Boron and Argon and getting either ‘sensor not found’ or flat TVOC and eCO2 values of 0 & 400 respectively.

Have tried with/without any other sensors on the I2C and also have confirmed the I2C works as a number of other sensors on the same line are working fine (incl a BME280).

Killing me.

Just a note that mine stopped working on the Argon, not sure when exactly, it was long ago. It detects the sensor but I get 0-1 and 400-401 forever. I was actually thinking it was broken and was going to get another until I saw your reply that reminded me of this issue.

Sounds like it must be the library… I’ll see if adafruit are aware of the issue perhaps?

I’ve been assuming that since it works on the Photon it’s up to us to figure out what changes are needed for the Argon. I doubt they’ll assist us with that.

With my multimeter on my Photon, I can see the SGP30 starts drawing about 45ma right after the sgp.begin() until the next power cycle, presumably this is for the onboard heater. If you hit the reset button or flash new firmware the heater stays powered up. On the Argon the heater never powers up and the SGP30 only uses 0.01ma the entire time it’s on. I tried using the latest Adafruit code from git but it didn’t make a difference, works on Photon, not on Argon. I tried adding delays to no effect. I also tried running that .begin() command multiple times but it didn’t help. Finally I enabled i2c debug and compared the input/output of each but there were no differences. I’m out of ideas :slightly_frowning_face:

1 Like

Have you tried this library?

Yes, couldnt get it to work either. I’m at my witts end.

Didn’t work for my Argon either, it’s fine on the Photon though.

I don’t have the Adafruit breakout on hand right now to test, but it worked for me last year with both an argon and a boron running DeviceOS 1.2.1 and Adafruit_SGP30. Does it work if you downgrade the firmware?

That’s a tricky downgrade, wouldn’t take 1.2.1 directly, SOS10, I was able to go to 1.1.1 but only briefly before an OTA update kicks in and ends up back with an SOS10 after a multistep update process. Safe mode is either broken or what’s doing the SOS. 1.3.1 was the oldest I was able to go w/o SOS and it had the same SGP issue as the newer firmware versions.

The issues I encountered and steps I took can be seen here: How to downgrade firmware