SGP30 doesn't work on Gen3 devices

argon
xenon
boron
Tags: #<Tag:0x00007f1c9e71bb98> #<Tag:0x00007f1c9e71b990> #<Tag:0x00007f1c9e71b850>

#1

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


#2

@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.


#3

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.


#4

@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!!!


#5

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


#6

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.


#7

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.


#8

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
}

#9

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


#10

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