GO Green with “Envi”: A Qwiic Environmental Combo Sensor for Your Beloved Game Machine

“Gee, it stinks in here,” you might be thinking. While this statement is a little vague, it does indicate that you could be experiencing an air quality issue within your environment. Most odors, toxic or otherwise, are generally termed as derivatives of volatile organic compounds (VOCs). In fact, a key measurement in determining air quality is the quantification of total volatile organic compounds or TVOCs.

One of the premier sensors for measuring VOCs is the ultra low-power CCS811 digital gas sensor by ams AG in Austria. In addition to providing a VOC measurement, the CCS811 is also able to output equivalent CO2 (eCO2) levels. These eCO2 values are typically a form of VOC that is generated by humans.

Figure 1 - Monitor your indoor environment with an ODROID-GO.

These air quality levels are given as parts per billion (PPB) for TVOCs and parts per million (PPM) for eCO2. As a standalone sensor, the output from the CCS811 is unrefined and inaccurate. In order to improve the air quality measurement output, the CCS811 readings can be improved by compensating them with the input of the current air temperature and relative humidity.

A venerable sensor for providing ambient temperature and humidity is the integrated digital environmental sensor BME280 by Bosch Sensortec. Integrating the BME280 output into the calculations for CCS811 air quality could be a cumbersome task. Luckily, SparkFun Electronics (SFE) has thoughtfully combined both the CCS811 and the BME280 sensors together onto a single breakout board that is able to reliably monitor environmental air quality.

Figure 2 - The SFE Environmental Combo Breakout. Image courtesy of SparkFun Electronics.
Figure 2 - The SFE Environmental Combo Breakout. Image courtesy of SparkFun Electronics.

Dubbed the Qwiic Environmental Combo Breakout, SparkFun sweetened the deal further by bundling this air quality monitoring package into their Qwiic I2C ecosystem. Now by utilizing the Qwiic Adapter project that we built in the May 2019 issue of ODROID Magazine, available here, https://magazine.odroid.com/article/go-and-be-qwiic-about-it/?ineedthispage=yes we can easily monitor our indoor air quality with impressive precision via a simple plug-and-GO system. Ah, the sweet smell of success!

Figure 3 - A sample output from the Qwiic Environmental Combo Breakout.
Figure 3 - A sample output from the Qwiic Environmental Combo Breakout.

Parts

SparkFun Environmental Combo Breakout – CSS811/BME280 (Qwiic) – SEN-14348 $35.95 Qwiic Cable – PRT-14427 $1.50

Step-by-Step

1. Plug the Qwiic Adapter into your ODROID-GO GPIO connector.

2. Connect the Qwiic cable to the Qwiic adapter and plug the other end into the Environmental Combo Breakout Board.

3. Input and upload this simple Arduino sketch to your ODROID-GO handheld gaming device:

/******************************************************************************
BME280Compensated.ino
Marshall Taylor @ SparkFun Electronics
April 4, 2017
https://github.com/sparkfun/CCS811_Air_Quality_Breakout
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library
This example uses a BME280 to gather environmental data that is then used
to compensate the CCS811.
Hardware Connections (Breakoutboard to Arduino):
3.3V to 3.3V pin
GND to GND pin
SDA to A4
SCL to A5
Resources:
Uses Wire.h for i2c operation
Hardware Connections:
Attach the Qwiic Environmental Combo to the Qwiic Adapter board mounted on your ODROID-GO
Display on the ODROID-GO @ 320x240
Development environment specifics:
Arduino IDE 1.8.1
This code is released under the [MIT License](http://opensource.org/licenses/MIT).
Please review the LICENSE.md file included with this example. If you have any questions
or concerns with licensing, please contact techsupport@sparkfun.com.
Distributed as-is; no warranty is given.
******************************************************************************/
#include 
#include 
#include 
#include

#define CCS811_ADDR 0x5B //Default I2C Address
//#define CCS811_ADDR 0x5A //Alternate I2C Address

//Global sensor objects
CCS811 myCCS811(CCS811_ADDR);
BME280 myBME280;

ILI9341 lcd = ILI9341();

void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println("Apply BME280 data to CCS811 for compensation.");

Wire.begin();

//This begins the CCS811 sensor and prints error status of .begin()
CCS811Core::status returnCode = myCCS811.begin();
if (returnCode != CCS811Core::SENSOR_SUCCESS)

Serial.println("Problem with CCS811");
printDriverError(returnCode);

else

Serial.println("CCS811 online");

//Initialize BME280
//For I2C, enable the following and disable the SPI section
myBME280.settings.commInterface = I2C_MODE;
myBME280.settings.I2CAddress = 0x77;
myBME280.settings.runMode = 3; //Normal mode
myBME280.settings.tStandby = 0;
myBME280.settings.filter = 4;
myBME280.settings.tempOverSample = 5;
myBME280.settings.pressOverSample = 5;
myBME280.settings.humidOverSample = 5;

//Calling .begin() causes the settings to be loaded
delay(10); //Make sure sensor had enough time to turn on. BME280 requires 2ms to start up.
byte id = myBME280.begin(); //Returns ID of 0x60 if successful
if (id != 0x60)

Serial.println("Problem with BME280");

else

Serial.println("BME280 online");

// Setup LCD
lcd.begin();
lcd.setRotation(1);
lcd.fillScreen(BLACK);
lcd.setBrightness(255);
lcd.setTextFont(1);
lcd.setTextSize(2);
lcd.setCharCursor(10, 2);
lcd.setTextColor(LIGHTGREY);
lcd.println("ODROID-GO");
lcd.setCharCursor(5, 4);
lcd.println("Environmental Data");
lcd.setTextSize(2);

}
//---------------------------------------------------------------
void loop()
{
// Initiate the text cursor position
lcd.setCharCursor(1, 6);

//Check to see if data is available
if (myCCS811.dataAvailable())

//Calling this function updates the global tVOC and eCO2 variables
myCCS811.readAlgorithmResults();
//printData fetches the values of tVOC and eCO2
printData();

float BMEtempC = myBME280.readTempC();
float BMEhumid = myBME280.readFloatHumidity();

Serial.print("Applying new values (deg C, %): ");
Serial.print(BMEtempC);
Serial.print(",");
Serial.println(BMEhumid);
Serial.println();

//This sends the temperature data to the CCS811
myCCS811.setEnvironmentalData(BMEhumid, BMEtempC);

else if (myCCS811.checkForStatusError())

Serial.println(myCCS811.getErrorRegister()); //Prints whatever CSS811 error flags are detected

delay(2000); //Wait for next reading
}

//---------------------------------------------------------------
void printData()
{
lcd.setTextColor(BLUE, BLACK);
Serial.print(" CO2[");
lcd.print ("CO2: [");
Serial.print(myCCS811.getCO2());
lcd.print (myCCS811.getCO2());
Serial.print("]ppm");
lcd.println ("] ppm");

Serial.print(" TVOC[");
lcd.print (" TVOC: [");
Serial.print(myCCS811.getTVOC());
lcd.print (myCCS811.getTVOC());
Serial.print("]ppb");
lcd.println ("] ppb");
lcd.println (" ");

lcd.setTextColor(RED, BLACK);
Serial.print(" temp[");
lcd.print (" Temp: ");
Serial.print(myBME280.readTempC(), 1);
lcd.print (myBME280.readTempC(), 1);
Serial.print("]C");
lcd.println ("C");

Serial.print(" pressure[");
lcd.print (" Press: ");
Serial.print(myBME280.readFloatPressure(), 2);
lcd.print (myBME280.readFloatPressure(), 2);
Serial.print("]Pa");
lcd.println ("Pa");
lcd.println (" ");

lcd.setTextColor(ORANGE, BLACK);
Serial.print(" humidity[");
lcd.print (" Humidity: ");
Serial.print(myBME280.readFloatHumidity(), 0);
lcd.print (myBME280.readFloatHumidity(), 0);
Serial.print("]%");
lcd.println ("%");

Serial.println();
}

//printDriverError decodes the CCS811Core::status type and prints the
//type of error to the serial terminal.
//
//Save the return value of any function of type CCS811Core::status, then pass
//to this function to see what the output was.
void printDriverError( CCS811Core::status errorCode )
{
switch ( errorCode )

case CCS811Core::SENSOR_SUCCESS:
Serial.print("SUCCESS");
break;
case CCS811Core::SENSOR_ID_ERROR:
Serial.print("ID_ERROR");
break;
case CCS811Core::SENSOR_I2C_ERROR:
Serial.print("I2C_ERROR");
break;
case CCS811Core::SENSOR_INTERNAL_ERROR:
Serial.print("INTERNAL_ERROR");
break;
case CCS811Core::SENSOR_GENERIC_ERROR:
Serial.print("GENERIC_ERROR");
break;
default:
Serial.print("Unspecified error.");

}
4. Use your newly built air quality sensor to discover who’s been using the formaldehyde without your permission.

Figure 4 - Compare the results between two similar environmental sensor boards. Does something smell fishy here?
Figure 4 - Compare the results between two similar environmental sensor boards. Does something smell fishy here?

NOTE: In order to obtain valid air quality output from the Environmental Combo board, you must do a single “burn-in”cycle of the CSS811 sensor for 48 hours AND you must perform a warm-up wait of 20 minutes before each use.

Be the first to comment

Leave a Reply