mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.3.1 AGS02MA
This commit is contained in:
parent
2b00021ae6
commit
a393271f22
@ -2,7 +2,7 @@
|
||||
// FILE: AGS02MA.cpp
|
||||
// AUTHOR: Rob Tillaart, Viktor Balint, Beanow
|
||||
// DATE: 2021-08-12
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// PURPOSE: Arduino library for AGS02MA TVOC
|
||||
// URL: https://github.com/RobTillaart/AGS02MA
|
||||
|
||||
@ -53,12 +53,17 @@ bool AGS02MA::begin()
|
||||
bool AGS02MA::isConnected()
|
||||
{
|
||||
#if defined (__AVR__)
|
||||
TWBR = 255;
|
||||
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
|
||||
TWBR = 78; // == 25.0 KHZ
|
||||
TWSR = 0x01; // prescaler = 4
|
||||
#else
|
||||
_wire->setClock(AGS02MA_I2C_CLOCK);
|
||||
#endif
|
||||
_wire->beginTransmission(_address);
|
||||
bool rv = ( _wire->endTransmission(true) == 0);
|
||||
#if defined (__AVR__)
|
||||
TWSR = 0x00;
|
||||
#endif
|
||||
_wire->setClock(_I2CResetSpeed);
|
||||
return rv;
|
||||
}
|
||||
@ -243,6 +248,7 @@ int AGS02MA::lastError()
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
bool AGS02MA::readRegister(uint8_t address, AGS02MA::RegisterData ®) {
|
||||
if (!_readRegister(address))
|
||||
{
|
||||
@ -293,17 +299,25 @@ bool AGS02MA::_readRegister(uint8_t reg)
|
||||
while (millis() - _lastRegTime < 30) yield();
|
||||
|
||||
#if defined (__AVR__)
|
||||
TWBR = 255;
|
||||
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
|
||||
TWBR = 78; // == 25.0 KHZ
|
||||
TWSR = 0x01; // prescaler = 4
|
||||
#else
|
||||
_wire->setClock(AGS02MA_I2C_CLOCK);
|
||||
#endif
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
_error = _wire->endTransmission(true);
|
||||
|
||||
// TODO investigate async interface
|
||||
delay(30);
|
||||
|
||||
if (_wire->requestFrom(_address, (uint8_t)5) != 5)
|
||||
{
|
||||
_error = AGS02MA_ERROR_READ;
|
||||
#if defined (__AVR__)
|
||||
TWSR = 0x00; // reset prescaler = 1
|
||||
#endif
|
||||
_wire->setClock(_I2CResetSpeed);
|
||||
return false;
|
||||
}
|
||||
@ -311,6 +325,9 @@ bool AGS02MA::_readRegister(uint8_t reg)
|
||||
{
|
||||
_buffer[i] = _wire->read();
|
||||
}
|
||||
#if defined (__AVR__)
|
||||
TWSR = 0x00; // reset prescaler = 1
|
||||
#endif
|
||||
_wire->setClock(_I2CResetSpeed);
|
||||
return true;
|
||||
}
|
||||
@ -322,7 +339,9 @@ bool AGS02MA::_writeRegister(uint8_t reg)
|
||||
_lastRegTime = millis();
|
||||
|
||||
#if defined (__AVR__)
|
||||
TWBR = 255;
|
||||
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
|
||||
TWBR = 78; // == 25.0 KHZ
|
||||
TWSR = 0x01; // prescaler = 4
|
||||
#else
|
||||
_wire->setClock(AGS02MA_I2C_CLOCK);
|
||||
#endif
|
||||
@ -333,6 +352,9 @@ bool AGS02MA::_writeRegister(uint8_t reg)
|
||||
_wire->write(_buffer[i]);
|
||||
}
|
||||
_error = _wire->endTransmission(true);
|
||||
#if defined (__AVR__)
|
||||
TWSR = 0x00;
|
||||
#endif
|
||||
_wire->setClock(_I2CResetSpeed);
|
||||
return (_error == 0);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// FILE: AGS02MA.h
|
||||
// AUTHOR: Rob Tillaart, Viktor Balint, Beanow
|
||||
// DATE: 2021-08-12
|
||||
// VERSION: 0.3.0
|
||||
// VERSION: 0.3.1
|
||||
// PURPOSE: Arduino library for AGS02MA TVOC
|
||||
// URL: https://github.com/RobTillaart/AGS02MA
|
||||
//
|
||||
@ -13,7 +13,7 @@
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#define AGS02MA_LIB_VERSION (F("0.3.0"))
|
||||
#define AGS02MA_LIB_VERSION (F("0.3.1"))
|
||||
|
||||
#define AGS02MA_OK 0
|
||||
#define AGS02MA_ERROR -10
|
||||
@ -22,7 +22,7 @@
|
||||
#define AGS02MA_ERROR_NOT_READY -13
|
||||
|
||||
|
||||
#define AGS02MA_I2C_CLOCK 30000
|
||||
#define AGS02MA_I2C_CLOCK 25000 // max 30000
|
||||
|
||||
|
||||
class AGS02MA
|
||||
|
@ -10,22 +10,45 @@
|
||||
|
||||
Arduino library for AGS02MA TVOC sensor.
|
||||
|
||||
This library is experimental, so please use with care.
|
||||
Note the warning about the I2C speed, the device works at only 30 KHz.
|
||||
This library is still experimental, so please use with care.
|
||||
Note the warning about the I2C low speed, the device works at max 30 KHz.
|
||||
Since 0.3.1 this library uses 25 KHz.
|
||||
|
||||
|
||||
## I2C - warning low speed
|
||||
## I2C
|
||||
|
||||
### PIN layout from left to right
|
||||
|
||||
| Front L->R | Description |
|
||||
|:----------:|:------------|
|
||||
| pin 1 | VDD + |
|
||||
| pin 2 | SDA data |
|
||||
| pin 3 | GND |
|
||||
| pin 4 | SCL clock |
|
||||
|
||||
|
||||
### WARNING - LOW SPEED
|
||||
|
||||
The sensor uses I2C at very low speed <= 30 KHz.
|
||||
For an Arduino UNO the lowest speed possible is about 30.4KHz (TWBR = 255) which works.
|
||||
For an Arduino UNO the lowest speed supported is about 30.4KHz (TWBR = 255) which works.
|
||||
First runs with Arduino UNO indicate 2 failed reads in > 500 Reads, so less than 1%
|
||||
|
||||
Tests with ESP32 / ESP8266 at 30 KHz look good,
|
||||
tests with lower clock speeds are to be done but expected to work.
|
||||
First runs indicate 2 failed reads in > 500 Reads, so less than 1%
|
||||
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 it to 100 KHz after operation.
|
||||
and resets it 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()** e.g. to 200 or 400 KHz.
|
||||
The reset clock speed can be changed with **setI2CResetSpeed(speed)** e.g. to 200 or 400 KHz.
|
||||
|
||||
|
||||
#### 0.3.1 fix.
|
||||
|
||||
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 clock (+ prescaler) is reset again as before.
|
||||
|
||||
|
||||
## Version 118 problems
|
||||
@ -62,7 +85,6 @@ Note: the version 0.2.0 determines the version in the calibration function so
|
||||
it won't calibrate any non 117 version.
|
||||
|
||||
|
||||
|
||||
### Please report your experiences.
|
||||
|
||||
If you have a AGS20MA device, version 117 or 118 or other,
|
||||
@ -111,7 +133,7 @@ Serial.println(dd, HEX); // prints YYYYMMDD e.g. 20210203
|
||||
|
||||
### I2C clock speed
|
||||
|
||||
The library sets the clock speed to 30 KHz during operation
|
||||
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.
|
||||
@ -148,27 +170,27 @@ Simplified formula for 1 atm @ 25°C:
|
||||
|
||||
Some known gasses
|
||||
|
||||
| gas | Common name | ratio | molecular weight M |
|
||||
|:-----|:--------------|:--------------------|:------------------:|
|
||||
| SO2 | | 1 ppb = 2.62 μg/m3 | 64 |
|
||||
| NO2 | | 1 ppb = 1.88 μg/m3 | 46 |
|
||||
| NO | | 1 ppb = 1.25 μg/m3 | 30 |
|
||||
| O3 | | 1 ppb = 2.00 μg/m3 | 48 |
|
||||
| CO | | 1 ppb = 1.145 μg/m3 | 28 |
|
||||
| C6H6 | Benzene | 1 ppb = 3.19 μg/m3 | 78 |
|
||||
| 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 |
|
||||
|
||||
|
||||
### Reading
|
||||
### Read the sensor
|
||||
|
||||
WARNING: The datasheet advises to take 3 seconds between reads.
|
||||
You might be able to squeeze time down to 1.5 second at your own risk.
|
||||
Tests gave stable results at 1.5 second intervals.
|
||||
Use this faster rate at your own risk.
|
||||
|
||||
- **uint32_t readPPB()** reads PPB (parts per billion) from device.
|
||||
Typical value should be between 1 .. 999999.
|
||||
Returns **lastPPB()** value if failed so one does not get sudden jumps in graphs.
|
||||
Check **lastStatus()** and **lastError()** to get more info about success.
|
||||
Time needed is ~35 milliseconds.
|
||||
|
||||
- **uint32_t readUGM3()** reads UGM3 (microgram per cubic meter) current value from device.
|
||||
Typical values depend on the molecular weight of the TVOC.
|
||||
Returns **lastUGM3()** if failed so one does not get sudden jumps in graphs.
|
||||
@ -179,6 +201,8 @@ Typical value should be between 0.01 .. 999.99
|
||||
- **float readUGF3()** returns microgram per cubic feet.
|
||||
|
||||
|
||||
### Error Codes
|
||||
|
||||
| ERROR_CODES | value |
|
||||
|:---------------------------|:-----:|
|
||||
| AGS02MA_OK | 0 |
|
||||
@ -195,16 +219,20 @@ Typical value should be between 0.01 .. 999.99
|
||||
- **uint32_t lastUGM3()** returns last read UGM3 (microgram per cubic meter) value (cached).
|
||||
|
||||
|
||||
### Other
|
||||
### Calibration
|
||||
|
||||
- **bool zeroCalibration()** to be called after at least 5 minutes in fresh air.
|
||||
See example sketch.
|
||||
- **bool manualZeroCalibration(uint16_t value = 0)** Set the zero calibration value manually.
|
||||
To be called after at least 5 minutes in fresh air.
|
||||
For v117: 0-65535 = automatic calibration.
|
||||
For v118: 0 = automatic calibration, 1-65535 manual calibration.
|
||||
- For v117: 0-65535 = automatic calibration.
|
||||
- For v118: 0 = automatic calibration, 1-65535 manual calibration.
|
||||
- **bool getZeroCalibrationData(ZeroCalibrationData &data)** fills a data struct with the current zero calibration status and value.
|
||||
Returns true on success.
|
||||
|
||||
|
||||
### Other
|
||||
|
||||
- **bool readRegister(uint8_t address, RegisterData ®)** fills a data struct with the chip's register data at that address.
|
||||
Primarily intended for troubleshooting and analysis of the sensor. Not recommended to build applications on top of this method's raw data.
|
||||
Returns true when the struct is filled, false when the data could not be read.
|
||||
@ -217,11 +245,11 @@ Read datasheet or table below for details. A new read is needed to update this.
|
||||
|
||||
#### Status bits.
|
||||
|
||||
| bit | description | notes |
|
||||
|:----:|:----------------------------------|:------|
|
||||
| 7-4 | internal use |
|
||||
| 3-1 | 000 = PPB 001 = uG/M3 |
|
||||
| 0 | RDY bit 0 = ready 1 = not ready | 1 == busy
|
||||
| bit | description | notes |
|
||||
|:-----:|:------------------------------------|:--------|
|
||||
| 7-4 | internal use |
|
||||
| 3-1 | 000 = PPB 001 = uG/M3 |
|
||||
| 0 | RDY bit 0 = ready 1 = not ready | 1 == busy
|
||||
|
||||
|
||||
## Future
|
||||
@ -231,4 +259,8 @@ Read datasheet or table below for details. A new read is needed to update this.
|
||||
- add indicative table for PPB health zone
|
||||
- check the mode bits of the status byte with internal \_mode.
|
||||
- elaborate error handling.
|
||||
- create an async interface for **readPPB()** if possible
|
||||
- put the I2C speed code in 2 inline functions
|
||||
- less repeating conditional code places
|
||||
- setLowSpeed() + setNormalSpeed()
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
|
||||
30 KHz
|
||||
|
||||
16:14:33.046 -> ...\AGS02MA_PPB_TIMING.ino
|
||||
16:14:33.046 -> AGS02MA_LIB_VERSION: 0.3.0
|
||||
16:14:33.046 ->
|
||||
16:14:33.046 -> BEGIN: 1
|
||||
16:14:33.046 -> VERS: 117
|
||||
16:14:33.093 ->
|
||||
16:14:33.093 -> Warming up (120 seconds = 24 dots)
|
||||
16:14:38.107 -> ........................
|
||||
16:16:33.243 -> MODE: 1 0
|
||||
16:16:34.790 -> 32 549 10 0
|
||||
16:16:36.325 -> 32 547 10 0
|
||||
16:16:37.872 -> 31 545 10 0
|
||||
16:16:39.418 -> 32 545 10 0
|
||||
16:16:40.922 -> 33 544 10 0
|
||||
16:16:42.469 -> 33 543 10 0
|
||||
16:16:44.015 -> 33 542 10 0
|
||||
16:16:45.562 -> 33 543 10 0
|
||||
16:16:47.062 -> 33 536 10 0
|
||||
16:16:48.608 -> 33 541 10 0
|
||||
16:16:50.155 -> 33 537 10 0
|
||||
16:16:51.701 -> 32 537 10 0
|
||||
16:16:53.201 -> 33 536 10 0
|
||||
16:16:54.747 -> 33 535 10 0
|
||||
16:16:56.294 -> 33 534 10 0
|
||||
16:16:57.810 -> 32 533 10 0
|
||||
16:16:59.357 -> 32 531 10 0
|
@ -0,0 +1,27 @@
|
||||
|
||||
10 KHz (TWBR 198, TWSR 1) just a test
|
||||
|
||||
16:08:08.836 -> ...\AGS02MA_PPB_TIMING.ino
|
||||
16:20:01.824 -> AGS02MA_LIB_VERSION: 0.3.1
|
||||
16:20:01.824 ->
|
||||
16:20:01.824 -> BEGIN: 1
|
||||
16:20:01.824 -> VERS: 117
|
||||
16:20:01.871 ->
|
||||
16:20:01.871 -> Warming up (120 seconds = 24 dots)
|
||||
16:20:06.885 -> ........................
|
||||
16:22:02.077 -> MODE: 1 0
|
||||
16:22:03.624 -> 38 476 10 0
|
||||
16:22:05.165 -> 38 474 10 0
|
||||
16:22:06.712 -> 38 471 10 0
|
||||
16:22:08.247 -> 38 474 10 0
|
||||
16:22:09.794 -> 38 471 10 0
|
||||
16:22:11.325 -> 38 472 10 0
|
||||
16:22:12.871 -> 38 468 10 0
|
||||
16:22:14.418 -> 37 465 10 0
|
||||
16:22:15.917 -> 38 463 10 0
|
||||
16:22:17.464 -> 38 463 10 0
|
||||
16:22:19.016 -> 38 459 10 0
|
||||
16:22:20.547 -> 37 460 10 0
|
||||
16:22:22.094 -> 36 459 10 0
|
||||
16:22:23.640 -> 38 461 10 0
|
||||
|
@ -0,0 +1,32 @@
|
||||
|
||||
25 KHz
|
||||
|
||||
16:08:08.836 -> ...\AGS02MA_PPB_TIMING.ino
|
||||
16:08:08.836 -> AGS02MA_LIB_VERSION: 0.3.1
|
||||
16:08:08.836 ->
|
||||
16:08:08.836 -> BEGIN: 1
|
||||
16:08:08.836 -> VERS: 117
|
||||
16:08:08.929 ->
|
||||
16:08:08.929 -> Warming up (120 seconds = 24 dots)
|
||||
16:08:13.944 -> ........................
|
||||
16:10:09.086 -> MODE: 1 0
|
||||
16:10:10.633 -> 33 845 10 0
|
||||
16:10:12.179 -> 32 846 10 0
|
||||
16:10:13.726 -> 32 847 10 0
|
||||
16:10:15.225 -> 33 847 10 0
|
||||
16:10:16.772 -> 32 847 10 0
|
||||
16:10:18.318 -> 33 841 10 0
|
||||
16:10:19.849 -> 33 835 10 0
|
||||
16:10:21.396 -> 34 829 10 0
|
||||
16:10:22.895 -> 33 825 10 0
|
||||
16:10:24.442 -> 33 828 10 0
|
||||
16:10:25.988 -> 33 823 10 0
|
||||
16:10:27.535 -> 34 824 10 0
|
||||
16:10:29.081 -> 33 821 10 0
|
||||
16:10:30.581 -> 33 821 10 0
|
||||
16:10:32.127 -> 33 816 10 0
|
||||
16:10:33.674 -> 34 826 10 0
|
||||
16:10:35.221 -> 33 839 10 0
|
||||
16:10:36.720 -> 33 855 10 0
|
||||
16:10:38.267 -> 33 857 10 0
|
||||
16:10:39.813 -> 33 857 10 0
|
@ -21,7 +21,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/AGS02MA.git"
|
||||
},
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=AGS02MA
|
||||
version=0.3.0
|
||||
version=0.3.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for AGS02MA - TVOC sensor
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
unittest_setup()
|
||||
{
|
||||
fprintf(stderr, "AGS02MA_LIB_VERSION: %s\n", (char *) AGS02MA_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
@ -41,15 +42,13 @@ unittest_teardown()
|
||||
|
||||
unittest(test_constants)
|
||||
{
|
||||
fprintf(stderr, "AGS02MA_LIB_VERSION: %s\n", (char *) AGS02MA_LIB_VERSION);
|
||||
|
||||
assertEqual( 0, AGS02MA_OK);
|
||||
assertEqual(-10, AGS02MA_ERROR);
|
||||
assertEqual(-11, AGS02MA_ERROR_CRC);
|
||||
assertEqual(-12, AGS02MA_ERROR_READ);
|
||||
assertEqual(-13, AGS02MA_ERROR_NOT_READY);
|
||||
|
||||
assertEqual(30000, AGS02MA_I2C_CLOCK);
|
||||
assertEqual(25000, AGS02MA_I2C_CLOCK);
|
||||
}
|
||||
|
||||
|
||||
@ -58,8 +57,6 @@ unittest(test_base)
|
||||
AGS02MA AGS(26);
|
||||
Wire.begin();
|
||||
|
||||
fprintf(stderr, "AGS02MA_LIB_VERSION: %s\n", (char *) AGS02MA_LIB_VERSION);
|
||||
|
||||
assertTrue(AGS.begin());
|
||||
assertTrue(AGS.isConnected()); // TODO - GODMODE
|
||||
|
||||
@ -84,8 +81,6 @@ unittest(test_mode)
|
||||
AGS02MA AGS(26);
|
||||
Wire.begin();
|
||||
|
||||
fprintf(stderr, "AGS02MA_LIB_VERSION: %s\n", (char *) AGS02MA_LIB_VERSION);
|
||||
|
||||
assertTrue(AGS.begin());
|
||||
assertTrue(AGS.isConnected()); // TODO - GODMODE
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user