Sensirion Environmental Sensor Shield - Review

Table of contents

RoadTest: Sensirion Environmental Sensor Shield - Industrial Sensing

Author: xukangmin

Creation date:

Evaluation Type: Development Boards & Tools

Did you receive all parts the manufacturer stated would be included in the package?: True

What other parts do you consider comparable to this product?: SHT35, MiCS5524, CCS811

What were the biggest problems encountered?: Support on SBC is not good, have to dig around to get proper library.

Detailed Review:

Unboxing

 

First Impression

This development board looks pretty simple to work with, and it is indeed. It designed with Arduino Uno footprint to work directly stack on Arduino like a shield. But if you have other boards such as Raspberry Pi, Tinker board, Onion. It also provides 4 pin connector for easy 3~5V I2C connection.

 

 

It has two environmental sensors, SHTC1 and SGP30. SHTC1 measures temperature and humidity, while SGP30 measures TVOCs and CO2 levels. Temperature and humidity are very common in the maker community. SGP30 is something new to me. It is metal oxide (MOX) gas sensor which measures TVOC and CO2.

 

 

I drew a circuit diagram based on the board. Basically this shield equipped with two level shifter for I2C bus, it can covert the digital signal from 5V/3.3V to 1.8V and vice versa. It can work directly with Arduino Uno or boards with similar footprint. It also has 3 LEDS that can be controlled by Arduino PIN 9, 10, 11. See diagram below. I also attach the schematic at the end. After I drew this, official schematic is available here , but I still want to share my (reverse-engineered) drawing.

 

 

Here is an overview of what this board offers:

SGP30 Sensor, Data Sheet https://www.sensirion.com/file/datasheet_sgp30

 

Key Parameters

Typical Value

VDD

1.8V

Measurement Current

48.2mA

Sleep current

2µA

Communication

I2C

I2C Address

0x58

TVOC Range

0 ppb to 60000 ppb

CO2

400 ppm to 60000 ppm

 

SHTC1, Data Sheet https://www.sensirion.com/file/datasheet_shtc1

 

Key Parameters

Typical Value

VDD

1.8V

Measurement Current

385µA

Sleep current

4.8µA

Communication

I2C

I2C Address

0x70

Temperature Range

-30 to +100°C

Temperature Accuracy

±0.3°C

Humidity Range

0 to 100 %RH

Humidity Accuracy

±3.0 %RH

 

 

TVOC stands for Total Volatile Organic Compound. TVOC is a grouping of wide range of organic chemical compounds including benzene, fossil fuels, methylene chloride, etc. It is a good indicator of indoor air quality. There are several sources of TVOC such as indoor furnishings, new  construction materials, cleaning products. Excessive amount of TVOC may cause health issue for human bodies, such as allergies, asthma, dizziness, nausea and fatigue.

Here is a chart to indicate the effect of different TVOC levels.

Details can be found here. (https://www.wikiwand.com/en/Volatile_organic_compound)

 

                                                                                              TVOC Level Reference

TVOC [ppb]

Level

Recommendation

Exposure Limit

2200 – 5500

5

Unhealthy

Use only if unavoidable /

Intense ventilation necessary

hours

660 – 2200

4

Poor

Intensified ventilation / airing necessary

Search for sources

< 1 month

220 – 660

3

Moderate

Intensified ventilation / airing necessary

Search for sources

< 12 months

65 – 220

2

Good

Ventilation / airing recommended

no limit

0 – 65

1

Excellent

Target value

no limit

Source: TVOC guidelines issued by the German Federal Environmental Agency

 

Carbon dioxide is a non-toxic and non-flammable gas, but excessive amount of CO2 still may do harm to people’s health, here is a chart for reference.

                                                       CO2 Level Reference

CO2 [ppm]

Level

Effects

>20%

8

Rapid unconsciousness, death

>10%

7

Nausea, vomiting, unconsciousness

3-8%

6

Increased respiration rate, headache

6,000 – 30,000 ppm

5

Concern, short exposure only

5,000 ppm

4

Average exposure limit over 8-hour period

1,000 ppm

3

Tolerable indoor air quality

600 – 800 ppm

2

Acceptable indoor air quality

350 – 450 ppm

1

Typical atmospheric concentration

 

 

Interfacing

 

  • Arduino

     Setup is pretty easy, basically plug and play.

     Here is my setup.

         

     Currently there are two libraries we can directly use.

         

          1. Official library https://github.com/Sensirion/arduino-ess

            

          Test Results: (Temperature (C), Humidity (%), TVOC (ppb), CO2 (ppm) )

          Note: TVOC and CO2 values are constant 0 and 400 in the first 15 seconds, that's SGP30's internal initialization state for measurement.

SGP30 detected, running feature set version 32

26.13 42.86 0.00 400.00

26.16 42.83 0.00 400.00

26.16 42.84 0.00 400.00

26.18 42.83 0.00 400.00

26.16 42.82 0.00 400.00

26.17 42.86 0.00 400.00

26.16 42.88 0.00 400.00

26.16 42.90 0.00 400.00

26.18 42.86 0.00 400.00

26.13 42.82 0.00 400.00

26.16 42.81 0.00 400.00

26.16 42.81 0.00 400.00

26.15 42.84 0.00 400.00

26.19 42.91 0.00 400.00

26.18 42.94 0.00 400.00

26.16 42.99 0.00 400.00

26.19 42.99 2.00 400.00

26.18 43.04 5.00 400.00

26.19 43.08 1.00 403.00

26.18 43.08 0.00 406.00

26.19 43.09 0.00 400.00

       2. Adafruit Library for SGP30 https://github.com/adafruit/Adafruit_SGP30

Test Results: (Temperature (C), Humidity (%), TVOC (ppb), CO2 (ppm) )

SGP30 test

Found SGP30 serial #07AE4F3

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 400 ppm

TVOC 3 ppb        eCO2 404 ppm

TVOC 6 ppb        eCO2 407 ppm

TVOC 3 ppb        eCO2 404 ppm

TVOC 3 ppb        eCO2 400 ppm

TVOC 5 ppb        eCO2 400 ppm

TVOC 0 ppb        eCO2 405 ppm

 

  • Raspberry Pi (Circuit Python)

Setup:

         Directly connect to the 3.3V, GND, SCL, SDA PINS on Raspberry Pi

    

Use i2cdetect to check connection of the board, if you see 0x58, 0x70, the board is connected.

 

 

Follow this guide to install circuit python on Raspberry Pi, https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi

 

By using the Adafruit Circuit Python SGP30 library, you can get this output, Notice first 15 seconds' data are constant 0 and 400 because of chip initialization.

 

There is no available python library for SHTC1, I wrote a simple one for testing. You can expand to a full library easily using circuit python.

import board
import busio
import time
from adafruit_bus_device.i2c_device import I2CDevice

i2c = busio.I2C(board.SCL, board.SDA)
device = I2CDevice(i2c,0x70)



def _get_data():
    with device:
        device.write(bytes([0x7C,0xA2]), stop=False)
        time.sleep(0.015)
        result = bytearray(6)
        device.readinto(result)
        temp_arr = [result[0],result[1]]
        val = int.from_bytes(temp_arr, byteorder='big', signed=False)
        temp = -45 + 175 * (val / 65535.0);
        hum_arr = [result[3], result[4]]
        val = int.from_bytes(hum_arr, byteorder='big', signed=False)
        hum = 100 * (val / 65535.0)
        return [temp, hum]

while True:
    time.sleep(1)
    [t,h] = _get_data()
    print('temp={0:.3f}, humidity={1:.3f}'.format(t,h))

 

Here is the ouput:

 

Environmental Testing

     Setup:

Sparkfun ESP8266 Thing board + 2000mAh Li-Ion battery + Sensirion ESS + Adafruit IO

I use the box come with the sensor to create a mobile testing box, and cut two holes for two sensors to expose to the atmosphere. (ignore my bad cutting skill XD)

 

 

Here is the code for remote monitoring / testing, it's based on Adafruit.io library publish example

#include "config.h"
#include <sensirion_ess.h>
#include <Wire.h>


SensirionESS ess;


AdafruitIO_Feed *temp = io.feed("sensirion-ess-test.temp");
AdafruitIO_Feed *hum = io.feed("sensirion-ess-test.hum");
AdafruitIO_Feed *co2 = io.feed("sensirion-ess-test.co2");
AdafruitIO_Feed *tvoc = io.feed("sensirion-ess-test.tvoc");


int count = 0;


void setup() {


  // start the serial connection
  Serial.begin(115200);
  delay(10000); // let console settle
  // wait for serial monitor to open
  while(! Serial);


  Serial.print("Connecting to Adafruit IO");
  // connect to io.adafruit.com
  io.connect();


  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }


  // we are connected
  Serial.println();
  Serial.println(io.statusText());


    if (ess.initSensors() != 0) {
      Serial.print("Error while initializing sensors: ");
      Serial.print(ess.getError());
      Serial.print("\n");
      while (1) { // loop forever
        delay(1000);
        Serial.println("error");
      }
  }


  int type = ess.getProductType();
  int fsVersion = ess.getFeatureSetVersion();


  Serial.print((type == SensirionESS::PRODUCT_TYPE_SGP30) ? "SGP30" : "SGPC3");
  Serial.print(" detected, running feature set version ");
  Serial.println(fsVersion);


}


void loop() {


  // io.run(); is required for all sketches.
  // it should always be present at the top of your loop
  // function. it keeps the client connected to
  // io.adafruit.com, and processes any incoming data.
  io.run();


   float temp_val, rh_val, tvoc_val, eco2_val = -1;


  // we'll start by triggering a measurement of the VOC/CO2 sensor;
  // it's important to do this first to make sure sleep timing is
  // correct. If the command succeeds, the local variables will
  // be set to the values we just read; if it fails, they'll be -1
  if (ess.measureIAQ() != 0) {
    Serial.print("Error while measuring IAQ: ");
    Serial.print(ess.getError());
    Serial.print("\n");
  } else {
    tvoc_val = ess.getTVOC();
    eco2_val = ess.getECO2(); // SGP30 only
  }


  // next, we'll trigger the humidity and temperature measurement
  if (ess.measureRHT() != 0) {
    Serial.print("Error while measuring RHT: ");
    Serial.print(ess.getError());
    Serial.print("\n");
  } else {
    temp_val = ess.getTemperature();
    rh_val = ess.getHumidity();
  }


  // finally, let's print those to the serial console
  Serial.print(temp_val);
  Serial.print(" ");
  Serial.print(rh_val);
  Serial.print(" ");
  Serial.print(tvoc_val);
  Serial.print(" ");
  if (ess.getProductType() == SensirionESS::PRODUCT_TYPE_SGP30) {
    Serial.print(eco2_val);
  }


  Serial.println();
  // and then, we'll use remainingWaitTimeMS() to ensure the correct
  // Measurement rate
  delay(ess.remainingWaitTimeMS());


  count++;


  if (count >= 60) {
    count = 0;  
    temp->save(temp_val);
    hum->save(rh_val);
    co2->save(eco2_val);
    tvoc->save(tvoc_val);
  }
  
}

 

I collect one full day of data for each environment. It's kind of surprise to see how bad our indoor air quality is.

 

     Bedroom

     Generally the sensor is sensitive enough to capture any changes in a enclosed environment. Whenever an event happens that can increase air circulation, the sensor is able to capture that, such as Opening window, close windows, AC running. So increasing indoor air circulation is the key to maintain a healthy indoor environment.

 

    Baby room

    

     The trend seems similar to the bedroom.

 

    Outdoor

     Outdoor data seems pretty smooth as expected, TVOC is less than 20 ppb most of the time and CO2 is around 400 ppm. A weried thing is that spike in the middle of the day. I guess it's a fly or bug stick on the sensor since it's not a single value that is way over range, it's a series of out-of-range values.

   The out-of-range data sets are like below. It seems like an actual bug than sensor firmware bugs.

11:18 AM53426
11:19 AM42406
11:20 AM81477
11:21 AM80456
11:22 AM55412
11:23 AM79457
11:25 AM174934
11:26 AM6175201
11:27 AM313711169
11:28 AM17723811
11:29 AM10132031
11:30 AM6801502
11:31 AM4821011
11:32 AM371856
11:33 AM3861061
11:35 AM333739
11:36 AM233533
11:37 AM284726
11:38 AM219506

Basement

    Our basement is not finished, it is a more or less enclosed environment. The data seems pretty smooth. It is more like a human indicator. When we are at home, the CO2 and TVOC level begin to climb slowly, when we left home, they began to drop.

Mobile Environmental Testing Box

   I use a OLED from Amazon and this shield to build a simple environmental testing box, it can display current envriomental data readings and push the data to the cloud. (adafruit.io)

  Components:

     NodeMCU 1.0

     LiPo 1000mAh

     0.96" OLED Display

     Sensirion ESS

    

  Diagram:

        

 

Code:

 

 

#include "config.h"
#include <sensirion_ess.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define OLED_RESET LED_BUILTIN //4
Adafruit_SSD1306 display(OLED_RESET);


#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2




#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };


#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
//  Create an instance of SensirionESS
SensirionESS ess;
/************************ Example Starts Here *******************************/


// this int will hold the current count for our sketch


// set up the 'counter' feed
AdafruitIO_Feed *temp = io.feed("sensirion-ess-test.temp");
AdafruitIO_Feed *hum = io.feed("sensirion-ess-test.hum");
AdafruitIO_Feed *co2 = io.feed("sensirion-ess-test.co2");
AdafruitIO_Feed *tvoc = io.feed("sensirion-ess-test.tvoc");


int count = 0;


void setup() {


  // start the serial connection
  Serial.begin(115200);
  delay(10000); // let console settle
  // wait for serial monitor to open
  while(! Serial);


  Serial.print("Connecting to Adafruit IO");


  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)


  // connect to io.adafruit.com
  io.connect();


  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }


  // we are connected
  Serial.println();
  Serial.println(io.statusText());


    if (ess.initSensors() != 0) {
      Serial.print("Error while initializing sensors: ");
      Serial.print(ess.getError());
      Serial.print("\n");
      while (1) { // loop forever
        delay(1000);
        Serial.println("error");
      }
  }


  int type = ess.getProductType();
  int fsVersion = ess.getFeatureSetVersion();


  Serial.print((type == SensirionESS::PRODUCT_TYPE_SGP30) ? "SGP30" : "SGPC3");
  Serial.print(" detected, running feature set version ");
  Serial.println(fsVersion);


}


void display_on_oled(float t, float rh, float tvoc, float co2) {
  // Clear the buffer.
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print("Temp:"); 
  display.println(t,2);
  display.print("Hum:");
  display.println(rh,2);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print("TVOC:"); 
  display.println(tvoc,2);
  display.print("CO2:");
  display.println(co2,2);
  display.display();
}


void loop() {


  // io.run(); is required for all sketches.
  // it should always be present at the top of your loop
  // function. it keeps the client connected to
  // io.adafruit.com, and processes any incoming data.
  io.run();


   float temp_val, rh_val, tvoc_val, eco2_val = -1;


  // we'll start by triggering a measurement of the VOC/CO2 sensor;
  // it's important to do this first to make sure sleep timing is
  // correct. If the command succeeds, the local variables will
  // be set to the values we just read; if it fails, they'll be -1
  if (ess.measureIAQ() != 0) {
    Serial.print("Error while measuring IAQ: ");
    Serial.print(ess.getError());
    Serial.print("\n");
  } else {
    tvoc_val = ess.getTVOC();
    eco2_val = ess.getECO2(); // SGP30 only
  }


  // next, we'll trigger the humidity and temperature measurement
  if (ess.measureRHT() != 0) {
    Serial.print("Error while measuring RHT: ");
    Serial.print(ess.getError());
    Serial.print("\n");
  } else {
    temp_val = ess.getTemperature();
    rh_val = ess.getHumidity();
  }


  // finally, let's print those to the serial console
  Serial.print(temp_val);
  Serial.print(" ");
  Serial.print(rh_val);
  Serial.print(" ");
  Serial.print(tvoc_val);
  Serial.print(" ");
  if (ess.getProductType() == SensirionESS::PRODUCT_TYPE_SGP30) {
    Serial.print(eco2_val);
  }


  display_on_oled(temp_val, rh_val, tvoc_val, eco2_val);
  
  Serial.println();
  // and then, we'll use remainingWaitTimeMS() to ensure the correct
  // Measurement rate
  delay(ess.remainingWaitTimeMS());


  count++;


  if (count >= 60) {
    count = 0;  
    temp->save(temp_val);
    hum->save(rh_val);
    co2->save(eco2_val);
    tvoc->save(tvoc_val);
  }
  
}

 

   Build & Results:

    

Summary

I have tested Sensirion Environmental Sensor Shield on both MCUs (Arduino Uno and ESP8266) and SBC (Raspberry Pi). It is basically plug-and-play in Arduino Eco System, the library is capable of providing accurate results. When using ESP8266, make sure you remove LED controlling codes in the official library because they are not compatible as of now.

 

While working on Linux, I need a bit of tinkering to get the board working correctly with the help of CircuitPython, but not too much pain. Thank you winkj for the Arduino ESS library and Adafruit IO for providing CircuitPython and SGP30 python library.

 

I like the hardware design of the board because it provides on-board level shifter so everyone from the 3.3V / 5V world can talk to 1.8V sensors easily.

 

For the sensors data testing, since I don't have other sensors for comparison, I test multiple locations around my house to see if the results make sense. It turns out it met my expectation. While there is a human activity, the TVOC and CO2 level will increase slightly. Air circulation will greatly help improving indoor air quality. I may perform a lab test for SHTC1 if I have a chance later. I will keep the results posted.

 

Thanks for your time.

 

Let me know if you have any questions or suggestions.

Anonymous