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 Nano | Grove - AHT20 Temperature&Humidity Sensor | Grove - 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
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
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.
2. Downolad the required libraries and add them into Arduino
Step 1. Download the dependency libraries from Github.
arduino-core Library:
arduino-i2c-sgp41 Library:
Seeed_Arduino_AHT20 Library:
Step 2. Refer to How to install library to install library for Arduino.
Step 3. After downloading and installing the libraries correctly, you can upload the code below, which is a combination of the SGP41 and the AHT20 software with the formulas described in the introduction added.
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.
Note that the first ten SRAW_NOx values are zero due to conditioning.
Resources
✨ Contributor Project
- This project is supported by the Seeed Studio Contributor Project.
- Thanks Hans's efforts and your work will be exhibited.
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.