Skip to main content

Correction for SGP41(raw) measurement dependent on humidity and temperature

Overview (How I get started with this project)

First I have read the Grove - Smart Air Quality Sensor (SGP41) and the Grove - AHT20 I2C Industrial Grade Temperature&Humidity Sensor documentation.

According to the SGP41 Datasheet (PDF) section 3.2 (Raw Signal Measurement), the SGP41 measurement is dependent on humidity and temperature, so we need to apply a correction to get consistent data: read the relative humidity and temperature from the AHT20 (or another sensor), calculate the ticks and pass them to the sgp41_measure_raw_signals function.

Theory Test

Table 11 (Description of the I2C measurement command) on page 15 describes the formulas to calculate the ticks:

RHticks = RH% × 65535 / 100
Tticks = (T°C + 45) × 65535 / 175

Verify by using the defaults 25°C and 50% relative humidity:

50 × 65535 / 100 = 32767.5 = 0x8000 (hexadecimal, rounded up)
(25 + 45) × 65535 / 175 = 26214 = 0x6666 (hexadecimal)

The results match the constants used in the program used by Grove - Smart Air Quality Sensor (SGP41) and defined in Table 11 of the SGP41 Datasheet (PDF).

The same in c:

        int h_ticks = humi * 0xFFFF;
int t_ticks = (temp + 45) * 0xFFFF / 175;

Note that 'humi' in the program is a value between 0 and 1, so the division by 100 and earlier multiplication were removed.

Hardware Preparation

I am using Seeeduino Nano as the control board and using Grove - Smart Air Quality Sensor (SGP41) and Grove - AHT20 I2C Industrial Grade Temperature&Humidity Sensor to make it happened.

Seeeduino NanoGrove - AHT20 Temperature&Humidity SensorGrove - Smart Air Quality Sensor (SGP41)Grove - Branch Cable

Software Preparation

Arduino IDE

There are multiple libraries that are required and are presented next setp.

Getting Started

note

If this is the first time you work with Arduino, we strongly recommend you to see Getting Started with Arduino before the start.

1. Connect With Arduino Nano

note

Please plug the USB cable gently, otherwise you may damage the port. Please use the USB cable with 4 wires inside, the 2 wires cable can't transfer data. If you are not sure about the wire you have, you can click here to buy

  • Step 1. Connect Grove - Branch Cable to the I2C port of Seeeduino Nano.

  • Step 2. Plug Grove - Branch Cable into the I2C Grove AHT20 sensor module.

  • Step 3. Plug Grove - Branch Cable into the I2C Grove SGP41 sensor module.

  • Step 4. Connect Seeeduino to a PC via a USB cable.

Seeeduino_SGP41_AHT20

2. Downolad the required libraries and add them into Arduino

3. Upload the Code and check the result

  • Step 1. Upload the demo. If you do not know how to upload the code, please check How to upload code.
// ARDUINO DEMO FOR GROVE-AHT20+SGP41
//
#include <Wire.h>
#include "AHT20.h"
#include <Arduino.h>
#include <SensirionI2CSgp41.h>

SensirionI2CSgp41 sgp41;

// time in seconds needed for NOx conditioning
uint16_t conditioning_s = 10;

AHT20 AHT;

void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}

Wire.begin();

uint16_t error;
char errorMessage[256];

sgp41.begin(Wire);

uint16_t serialNumber[3];
uint8_t serialNumberSize = 3;

error = sgp41.getSerialNumber(serialNumber, serialNumberSize);

if (error) {
Serial.print("Error trying to execute getSerialNumber(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("SerialNumber:");
Serial.print("0x");
for (size_t i = 0; i < serialNumberSize; i++) {
uint16_t value = serialNumber[i];
Serial.print(value < 4096 ? "0" : "");
Serial.print(value < 256 ? "0" : "");
Serial.print(value < 16 ? "0" : "");
Serial.print(value, HEX);
}
Serial.println();
}

uint16_t testResult;
error = sgp41.executeSelfTest(testResult);
if (error) {
Serial.print("Error trying to execute executeSelfTest(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else if (testResult != 0xD400) {
Serial.print("executeSelfTest failed with error: ");
Serial.println(testResult);
}
AHT.begin();
}

uint16_t read_sgp41(uint16_t rh, uint16_t t) {
uint16_t error;
char errorMessage[256];
uint16_t srawVoc = 0;
uint16_t srawNox = 0;

delay(1000);

if (conditioning_s > 0) {
// During NOx conditioning (10s) SRAW NOx will remain 0
error = sgp41.executeConditioning(rh, t, srawVoc);
conditioning_s--;
} else {
// Read Measurement
error = sgp41.measureRawSignals(rh, t, srawVoc, srawNox);
}

if (error) {
Serial.print("Error trying to execute measureRawSignals(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("RH ticks: ");
Serial.print(rh);
Serial.print("\t");
Serial.print("T ticks: ");
Serial.print(t);
Serial.print("\t");
Serial.print("SRAW_VOC: ");
Serial.print(srawVoc);
Serial.print("\t");
Serial.print("SRAW_NOx: ");
Serial.println(srawNox);
}
return error;
}

void loop()
{
float humi, temp;

int ret = AHT.getSensor(&humi, &temp);

if(ret) // GET DATA OK
{
Serial.print("humidity: ");
Serial.print(humi*100);
Serial.print("%\t temperature: ");
Serial.print(temp);
Serial.print("\t");
// T-ticks = (T/°C + 45) × 65535 / 175
// H-ticks = RH/% × 65535 / 100
int h_ticks = humi * 0xFFFF;
int t_ticks = (temp + 45) * 0xFFFF / 175;
read_sgp41(h_ticks, t_ticks);
}
else // GET DATA FAIL
{
Serial.println("GET DATA FROM AHT20 FAIL");
}

delay(100);
}

// END FILE
  • Step 2. Open the Serial Monitor of Arduino IDE by click Tool-> Serial Monitor.

Serial Console output

Note that the first ten SRAW_NOx values are zero due to conditioning.

Resources

✨ Contributor Project

Tech Support & Product Discussion

Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs.

Loading Comments...