lib/lib_i2c/AGS02MA-0.4.3/README.md
Arduino library for AGS02MA TVOC sensor.
Experimental
This library is experimental, so please use with care.
The AGS02MA is a sensor that measures the TVOC = Total Volatile Organic Compounds in the air. It does not measure a specific gas, but several.
Note the warning about the I2C low speed, the device works at max 30 KHz. Since 0.3.1 this library uses 25 KHz.
Feedback as always, is welcome. Please open an issue.
Note this library is not meant to replace professional monitoring systems.
Version 0.4.0 introduced a breaking change. You cannot set the pins in begin() any more. This reduces the dependency of processor dependent Wire implementations. The user has to call Wire.begin() and can optionally set the Wire pins before calling begin().
Always check datasheet!
| Front L->R | Description |
|---|---|
| pin 1 | VDD +5V |
| pin 2 | SDA data |
| pin 3 | GND |
| pin 4 | SCL clock |
The device has a fixed address of 26 or 0x1A.
The device works at 100 kHz I2C bus speed (datasheet).
Note: several AGS devices use the same I2C address 0x1A. Known are the AGS2616 (H2), AGS3870 (CH4), AGS3871 (CO), AGS02MA (TVOC). If you want to use them on one I2C bus, you need multiplexing. See section below.
The sensor uses I2C at very low speed <= 30 KHz. For an Arduino UNO the lowest speed supported is about 30.4KHz (TWBR = 255) which works in my testruns so far. First runs with Arduino UNO indicate 2 failed reads in > 500 Reads, so less than 1% failure rate.
Tests with ESP32 / ESP8266 at 30 KHz look good, tests with ESP32 at lower clock speeds are to be done but expected to work.
The library sets the clock speed to 30 KHz (for non AVR) during operation and resets the I2C clock speed default to 100 KHz after operation. This is done to minimize interference with the communication of other devices. The "reset clock speed" can be changed with setI2CResetSpeed(speed) e.g. to 200 or 400 KHz.
Version 0.3.1 sets the I2C prescaler TWSR register of the Arduino UNO to 4 so the lowest speed possible is reduced to about 8 KHz. A test run 4 hours with 6000++ reads on an UNO at 25 KHz gave 0 errors. So the communication speed will be set to 25 KHz, also for other boards, for stability. After communication the I2C clock (+ prescaler) is reset again as before.
Sometimes you need to control more devices than possible with the default address range the device provides. This is possible with an I2C multiplexer e.g. TCA9548 which creates up to eight channels (think of it as I2C subnets) which can use the complete address range of the device.
Drawback of using a multiplexer is that it takes more administration in your code e.g. which device is on which channel. This will slow down the access, which must be taken into account when deciding which devices are on which channel. Also note that switching between channels will slow down other devices too if they are behind the multiplexer.
The library can request the version with getSensorVersion(). My devices all report version 117 and this version is used to develop / test this library. There are devices reported with version 118 which behave differently.
See - https://github.com/RobTillaart/AGS02MA/issues/11
The version 118 seems only to support the PPB and not the ugM3 mode. It is unclear if this is an incident, bug or a structural change in the firmware.
If you encounter similar problems with setting the mode (any version), please let me know. That will help indicating if this is a "structural change" or incident.
See - https://github.com/RobTillaart/AGS02MA/issues/13
In this issue a problem is reported with a version 118 sensor. The problem exposed itself after running the calibration sketch (command). The problem has been confirmed by a 2nd version 118 sensor. Additional calibration runs did not fix the problem. Version 117 seem to have no problems with calibration.
Advice: do NOT calibrate a version 118.
Note: the version 0.2.0 determines the version in the calibration function so it won't calibrate any non 117 version.
If you have a AGS20MA device, version 117 or 118 or other, please let me know your experiences with the sensor and this (or other) library.
#include "AGS02MA.h"
uint32_t dd = sensor.getSensorDate();
Serial.println(dd, HEX); // prints YYYYMMDD e.g. 20210203
The library sets the clock speed to 25 KHz during operation and resets it to 100 KHz after operation. This is done to minimize interference with the communication of other devices. The following function can change the I2C reset speed to e.g. 200 or 400 KHz.
The default mode at startup of the sensor is PPB = parts per billion.
Indicative description and colour representation.
| TVOC(ppb) | Scale | Description | Colour | Notes |
|---|---|---|---|---|
| <= 220 | 1 | Good | Green | |
| <= 660 | 3 | Moderate | Yellow | |
| <= 1430 | 7 | Bad | Orange | |
| <= 2200 | 10 | Unhealthy | Red | |
| <= 3300 | 15 | Very unhealthy | Purple | add pulsating effect |
| <= 5500 | 25 | Hazardous | Deep Purple | add pulsating effect |
| > 5500 | 50 | Extremely Hazardous | Deep Purple | add pulsating effect |
There is no 1 to 1 relation between the PPB and the uG/m3 readings as this relation depends on the weight of the individual molecules. PPB is therefore an more an absolute indicator where uG/m3 is sort of relative indicator. If the gas is unknown, PPB is in my opinion the preferred measurement.
From an unverified source the following formula: M = molecular weight of the gas.
μg/m3 = ppb * M * 12.187 / (273.15 + °C)
Simplified formula for 1 atm @ 25°C:
μg/m3 = ppb * M * 0.04087539829
Some known gasses
| gas | Common name | ratio ppb-μg/m3 | molecular weight M |
|---|---|---|---|
| SO2 | Sulphur dioxide | 1 ppb = 2.62 μg/m3 | 64 gr/mol |
| NO2 | Nitrogen dioxide | 1 ppb = 1.88 μg/m3 | 46 gr/mol |
| NO | Nitrogen monoxide | 1 ppb = 1.25 μg/m3 | 30 gr/mol |
| O3 | Ozone | 1 ppb = 2.00 μg/m3 | 48 gr/mol |
| CO | Carbon Monoxide | 1 ppb = 1.145 μg/m3 | 28 gr/mol |
| C6H6 | Benzene | 1 ppb = 3.19 μg/m3 | 78 gr/mol |
WARNING: The datasheet advises to take 3 seconds between reads. Tests gave stable results at 1.5 second intervals. Use this faster rate at your own risk.
Wrappers
| ERROR_CODES | value |
|---|---|
| AGS02MA_OK | 0 |
| AGS02MA_ERROR | -10 |
| AGS02MA_ERROR_CRC | -11 |
| AGS02MA_ERROR_READ | -12 |
| AGS02MA_ERROR_NOT_READY | -13 |
lastError(),
instead the CRC result is stored in RegisterData.crcValid.| bit | description | notes |
|---|---|---|
| 7-4 | internal use | |
| 3-1 | 000 = PPB 001 = uG/M3 | |
| 0 | RDY bit 0 = ready 1 = not ready | 1 == busy |
If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.
Thank you,