Skip to content

Commit 18a1ffe

Browse files
authored
patch for 25 KHz I2C (#19)
* set communication to 25 KHz I2C * update documentation / minor edits.
1 parent 22a1b58 commit 18a1ffe

File tree

9 files changed

+182
-45
lines changed

9 files changed

+182
-45
lines changed

AGS02MA.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// FILE: AGS02MA.cpp
33
// AUTHOR: Rob Tillaart, Viktor Balint, Beanow
44
// DATE: 2021-08-12
5-
// VERSION: 0.3.0
5+
// VERSION: 0.3.1
66
// PURPOSE: Arduino library for AGS02MA TVOC
77
// URL: https://github.com/RobTillaart/AGS02MA
88

@@ -53,12 +53,17 @@ bool AGS02MA::begin()
5353
bool AGS02MA::isConnected()
5454
{
5555
#if defined (__AVR__)
56-
TWBR = 255;
56+
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
57+
TWBR = 78; // == 25.0 KHZ
58+
TWSR = 0x01; // prescaler = 4
5759
#else
5860
_wire->setClock(AGS02MA_I2C_CLOCK);
5961
#endif
6062
_wire->beginTransmission(_address);
6163
bool rv = ( _wire->endTransmission(true) == 0);
64+
#if defined (__AVR__)
65+
TWSR = 0x00;
66+
#endif
6267
_wire->setClock(_I2CResetSpeed);
6368
return rv;
6469
}
@@ -243,6 +248,7 @@ int AGS02MA::lastError()
243248
return e;
244249
}
245250

251+
246252
bool AGS02MA::readRegister(uint8_t address, AGS02MA::RegisterData &reg) {
247253
if (!_readRegister(address))
248254
{
@@ -293,24 +299,35 @@ bool AGS02MA::_readRegister(uint8_t reg)
293299
while (millis() - _lastRegTime < 30) yield();
294300

295301
#if defined (__AVR__)
296-
TWBR = 255;
302+
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
303+
TWBR = 78; // == 25.0 KHZ
304+
TWSR = 0x01; // prescaler = 4
297305
#else
298306
_wire->setClock(AGS02MA_I2C_CLOCK);
299307
#endif
300308
_wire->beginTransmission(_address);
301309
_wire->write(reg);
302310
_error = _wire->endTransmission(true);
311+
312+
// TODO investigate async interface
303313
delay(30);
314+
304315
if (_wire->requestFrom(_address, (uint8_t)5) != 5)
305316
{
306317
_error = AGS02MA_ERROR_READ;
318+
#if defined (__AVR__)
319+
TWSR = 0x00; // reset prescaler = 1
320+
#endif
307321
_wire->setClock(_I2CResetSpeed);
308322
return false;
309323
}
310324
for (uint8_t i = 0; i < 5; i++)
311325
{
312326
_buffer[i] = _wire->read();
313327
}
328+
#if defined (__AVR__)
329+
TWSR = 0x00; // reset prescaler = 1
330+
#endif
314331
_wire->setClock(_I2CResetSpeed);
315332
return true;
316333
}
@@ -322,7 +339,9 @@ bool AGS02MA::_writeRegister(uint8_t reg)
322339
_lastRegTime = millis();
323340

324341
#if defined (__AVR__)
325-
TWBR = 255;
342+
// TWBR = 255; // == 30.4 KHz with TWSR = 0x00
343+
TWBR = 78; // == 25.0 KHZ
344+
TWSR = 0x01; // prescaler = 4
326345
#else
327346
_wire->setClock(AGS02MA_I2C_CLOCK);
328347
#endif
@@ -333,6 +352,9 @@ bool AGS02MA::_writeRegister(uint8_t reg)
333352
_wire->write(_buffer[i]);
334353
}
335354
_error = _wire->endTransmission(true);
355+
#if defined (__AVR__)
356+
TWSR = 0x00;
357+
#endif
336358
_wire->setClock(_I2CResetSpeed);
337359
return (_error == 0);
338360
}

AGS02MA.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// FILE: AGS02MA.h
44
// AUTHOR: Rob Tillaart, Viktor Balint, Beanow
55
// DATE: 2021-08-12
6-
// VERSION: 0.3.0
6+
// VERSION: 0.3.1
77
// PURPOSE: Arduino library for AGS02MA TVOC
88
// URL: https://github.com/RobTillaart/AGS02MA
99
//
@@ -13,7 +13,7 @@
1313
#include "Wire.h"
1414

1515

16-
#define AGS02MA_LIB_VERSION (F("0.3.0"))
16+
#define AGS02MA_LIB_VERSION (F("0.3.1"))
1717

1818
#define AGS02MA_OK 0
1919
#define AGS02MA_ERROR -10
@@ -22,7 +22,7 @@
2222
#define AGS02MA_ERROR_NOT_READY -13
2323

2424

25-
#define AGS02MA_I2C_CLOCK 30000
25+
#define AGS02MA_I2C_CLOCK 25000 // max 30000
2626

2727

2828
class AGS02MA

README.md

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,45 @@
1010

1111
Arduino library for AGS02MA TVOC sensor.
1212

13-
This library is experimental, so please use with care.
14-
Note the warning about the I2C speed, the device works at only 30 KHz.
13+
This library is still experimental, so please use with care.
14+
Note the warning about the I2C low speed, the device works at max 30 KHz.
15+
Since 0.3.1 this library uses 25 KHz.
1516

1617

17-
## I2C - warning low speed
18+
## I2C
19+
20+
### PIN layout from left to right
21+
22+
| Front L->R | Description |
23+
|:----------:|:------------|
24+
| pin 1 | VDD + |
25+
| pin 2 | SDA data |
26+
| pin 3 | GND |
27+
| pin 4 | SCL clock |
28+
29+
30+
### WARNING - LOW SPEED
1831

1932
The sensor uses I2C at very low speed <= 30 KHz.
20-
For an Arduino UNO the lowest speed possible is about 30.4KHz (TWBR = 255) which works.
33+
For an Arduino UNO the lowest speed supported is about 30.4KHz (TWBR = 255) which works.
34+
First runs with Arduino UNO indicate 2 failed reads in > 500 Reads, so less than 1%
35+
2136
Tests with ESP32 / ESP8266 at 30 KHz look good,
22-
tests with lower clock speeds are to be done but expected to work.
23-
First runs indicate 2 failed reads in > 500 Reads, so less than 1%
37+
tests with ESP32 at lower clock speeds are to be done but expected to work.
2438

2539
The library sets the clock speed to 30 KHz (for non AVR) during operation
26-
and resets it to 100 KHz after operation.
40+
and resets it default to 100 KHz after operation.
2741
This is done to minimize interference with the communication of other devices.
28-
The reset clock speed can be changed with **setI2CResetSpeed()** e.g. to 200 or 400 KHz.
42+
The reset clock speed can be changed with **setI2CResetSpeed(speed)** e.g. to 200 or 400 KHz.
43+
44+
45+
#### 0.3.1 fix.
46+
47+
Version 0.3.1 sets the **I2C prescaler TWSR** register of the Arduino UNO to 4 so the lowest
48+
speed possible is reduced to about 8 KHz.
49+
A test run 4 hours with 6000++ reads on an UNO at 25 KHz gave 0 errors.
50+
So the communication speed will be set to 25 KHz, also for other boards, for stability.
51+
After communication the clock (+ prescaler) is reset again as before.
2952

3053

3154
## Version 118 problems
@@ -62,7 +85,6 @@ Note: the version 0.2.0 determines the version in the calibration function so
6285
it won't calibrate any non 117 version.
6386

6487

65-
6688
### Please report your experiences.
6789

6890
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
111133

112134
### I2C clock speed
113135

114-
The library sets the clock speed to 30 KHz during operation
136+
The library sets the clock speed to 25 KHz during operation
115137
and resets it to 100 KHz after operation.
116138
This is done to minimize interference with the communication of other devices.
117139
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:
148170

149171
Some known gasses
150172

151-
| gas | Common name | ratio | molecular weight M |
152-
|:-----|:--------------|:--------------------|:------------------:|
153-
| SO2 | | 1 ppb = 2.62 μg/m3 | 64 |
154-
| NO2 | | 1 ppb = 1.88 μg/m3 | 46 |
155-
| NO | | 1 ppb = 1.25 μg/m3 | 30 |
156-
| O3 | | 1 ppb = 2.00 μg/m3 | 48 |
157-
| CO | | 1 ppb = 1.145 μg/m3 | 28 |
158-
| C6H6 | Benzene | 1 ppb = 3.19 μg/m3 | 78 |
173+
| gas | Common name | ratio ppb-μg/m3 | molecular weight M |
174+
|:-----|:------------------|:--------------------|:------------------:|
175+
| SO2 | Sulphur dioxide | 1 ppb = 2.62 μg/m3 | 64 gr/mol |
176+
| NO2 | Nitrogen dioxide | 1 ppb = 1.88 μg/m3 | 46 gr/mol |
177+
| NO | Nitrogen monoxide | 1 ppb = 1.25 μg/m3 | 30 gr/mol |
178+
| O3 | Ozone | 1 ppb = 2.00 μg/m3 | 48 gr/mol |
179+
| CO | Carbon Monoxide | 1 ppb = 1.145 μg/m3 | 28 gr/mol |
180+
| C6H6 | Benzene | 1 ppb = 3.19 μg/m3 | 78 gr/mol |
159181

160182

161-
### Reading
183+
### Read the sensor
162184

163185
WARNING: The datasheet advises to take 3 seconds between reads.
164-
You might be able to squeeze time down to 1.5 second at your own risk.
186+
Tests gave stable results at 1.5 second intervals.
187+
Use this faster rate at your own risk.
165188

166189
- **uint32_t readPPB()** reads PPB (parts per billion) from device.
167190
Typical value should be between 1 .. 999999.
168191
Returns **lastPPB()** value if failed so one does not get sudden jumps in graphs.
169192
Check **lastStatus()** and **lastError()** to get more info about success.
170193
Time needed is ~35 milliseconds.
171-
172194
- **uint32_t readUGM3()** reads UGM3 (microgram per cubic meter) current value from device.
173195
Typical values depend on the molecular weight of the TVOC.
174196
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
179201
- **float readUGF3()** returns microgram per cubic feet.
180202

181203

204+
### Error Codes
205+
182206
| ERROR_CODES | value |
183207
|:---------------------------|:-----:|
184208
| AGS02MA_OK | 0 |
@@ -195,16 +219,20 @@ Typical value should be between 0.01 .. 999.99
195219
- **uint32_t lastUGM3()** returns last read UGM3 (microgram per cubic meter) value (cached).
196220

197221

198-
### Other
222+
### Calibration
199223

200224
- **bool zeroCalibration()** to be called after at least 5 minutes in fresh air.
201225
See example sketch.
202226
- **bool manualZeroCalibration(uint16_t value = 0)** Set the zero calibration value manually.
203227
To be called after at least 5 minutes in fresh air.
204-
For v117: 0-65535 = automatic calibration.
205-
For v118: 0 = automatic calibration, 1-65535 manual calibration.
228+
- For v117: 0-65535 = automatic calibration.
229+
- For v118: 0 = automatic calibration, 1-65535 manual calibration.
206230
- **bool getZeroCalibrationData(ZeroCalibrationData &data)** fills a data struct with the current zero calibration status and value.
207231
Returns true on success.
232+
233+
234+
### Other
235+
208236
- **bool readRegister(uint8_t address, RegisterData &reg)** fills a data struct with the chip's register data at that address.
209237
Primarily intended for troubleshooting and analysis of the sensor. Not recommended to build applications on top of this method's raw data.
210238
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.
217245

218246
#### Status bits.
219247

220-
| bit | description | notes |
221-
|:----:|:----------------------------------|:------|
222-
| 7-4 | internal use |
223-
| 3-1 | 000 = PPB 001 = uG/M3 |
224-
| 0 | RDY bit 0 = ready 1 = not ready | 1 == busy
248+
| bit | description | notes |
249+
|:-----:|:------------------------------------|:--------|
250+
| 7-4 | internal use |
251+
| 3-1 | 000 = PPB 001 = uG/M3 |
252+
| 0 | RDY bit 0 = ready 1 = not ready | 1 == busy
225253

226254

227255
## Future
@@ -231,4 +259,8 @@ Read datasheet or table below for details. A new read is needed to update this.
231259
- add indicative table for PPB health zone
232260
- check the mode bits of the status byte with internal \_mode.
233261
- elaborate error handling.
262+
- create an async interface for **readPPB()** if possible
263+
- put the I2C speed code in 2 inline functions
264+
- less repeating conditional code places
265+
- setLowSpeed() + setNormalSpeed()
234266

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
30 KHz
3+
4+
16:14:33.046 -> ...\AGS02MA_PPB_TIMING.ino
5+
16:14:33.046 -> AGS02MA_LIB_VERSION: 0.3.0
6+
16:14:33.046 ->
7+
16:14:33.046 -> BEGIN: 1
8+
16:14:33.046 -> VERS: 117
9+
16:14:33.093 ->
10+
16:14:33.093 -> Warming up (120 seconds = 24 dots)
11+
16:14:38.107 -> ........................
12+
16:16:33.243 -> MODE: 1 0
13+
16:16:34.790 -> 32 549 10 0
14+
16:16:36.325 -> 32 547 10 0
15+
16:16:37.872 -> 31 545 10 0
16+
16:16:39.418 -> 32 545 10 0
17+
16:16:40.922 -> 33 544 10 0
18+
16:16:42.469 -> 33 543 10 0
19+
16:16:44.015 -> 33 542 10 0
20+
16:16:45.562 -> 33 543 10 0
21+
16:16:47.062 -> 33 536 10 0
22+
16:16:48.608 -> 33 541 10 0
23+
16:16:50.155 -> 33 537 10 0
24+
16:16:51.701 -> 32 537 10 0
25+
16:16:53.201 -> 33 536 10 0
26+
16:16:54.747 -> 33 535 10 0
27+
16:16:56.294 -> 33 534 10 0
28+
16:16:57.810 -> 32 533 10 0
29+
16:16:59.357 -> 32 531 10 0
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
10 KHz (TWBR 198, TWSR 1) just a test
3+
4+
16:08:08.836 -> ...\AGS02MA_PPB_TIMING.ino
5+
16:20:01.824 -> AGS02MA_LIB_VERSION: 0.3.1
6+
16:20:01.824 ->
7+
16:20:01.824 -> BEGIN: 1
8+
16:20:01.824 -> VERS: 117
9+
16:20:01.871 ->
10+
16:20:01.871 -> Warming up (120 seconds = 24 dots)
11+
16:20:06.885 -> ........................
12+
16:22:02.077 -> MODE: 1 0
13+
16:22:03.624 -> 38 476 10 0
14+
16:22:05.165 -> 38 474 10 0
15+
16:22:06.712 -> 38 471 10 0
16+
16:22:08.247 -> 38 474 10 0
17+
16:22:09.794 -> 38 471 10 0
18+
16:22:11.325 -> 38 472 10 0
19+
16:22:12.871 -> 38 468 10 0
20+
16:22:14.418 -> 37 465 10 0
21+
16:22:15.917 -> 38 463 10 0
22+
16:22:17.464 -> 38 463 10 0
23+
16:22:19.016 -> 38 459 10 0
24+
16:22:20.547 -> 37 460 10 0
25+
16:22:22.094 -> 36 459 10 0
26+
16:22:23.640 -> 38 461 10 0
27+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
25 KHz
3+
4+
16:08:08.836 -> ...\AGS02MA_PPB_TIMING.ino
5+
16:08:08.836 -> AGS02MA_LIB_VERSION: 0.3.1
6+
16:08:08.836 ->
7+
16:08:08.836 -> BEGIN: 1
8+
16:08:08.836 -> VERS: 117
9+
16:08:08.929 ->
10+
16:08:08.929 -> Warming up (120 seconds = 24 dots)
11+
16:08:13.944 -> ........................
12+
16:10:09.086 -> MODE: 1 0
13+
16:10:10.633 -> 33 845 10 0
14+
16:10:12.179 -> 32 846 10 0
15+
16:10:13.726 -> 32 847 10 0
16+
16:10:15.225 -> 33 847 10 0
17+
16:10:16.772 -> 32 847 10 0
18+
16:10:18.318 -> 33 841 10 0
19+
16:10:19.849 -> 33 835 10 0
20+
16:10:21.396 -> 34 829 10 0
21+
16:10:22.895 -> 33 825 10 0
22+
16:10:24.442 -> 33 828 10 0
23+
16:10:25.988 -> 33 823 10 0
24+
16:10:27.535 -> 34 824 10 0
25+
16:10:29.081 -> 33 821 10 0
26+
16:10:30.581 -> 33 821 10 0
27+
16:10:32.127 -> 33 816 10 0
28+
16:10:33.674 -> 34 826 10 0
29+
16:10:35.221 -> 33 839 10 0
30+
16:10:36.720 -> 33 855 10 0
31+
16:10:38.267 -> 33 857 10 0
32+
16:10:39.813 -> 33 857 10 0

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"type": "git",
2222
"url": "https://github.com/RobTillaart/AGS02MA.git"
2323
},
24-
"version": "0.3.0",
24+
"version": "0.3.1",
2525
"license": "MIT",
2626
"frameworks": "arduino",
2727
"platforms": "*",

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=AGS02MA
2-
version=0.3.0
2+
version=0.3.1
33
author=Rob Tillaart <[email protected]>
44
maintainer=Rob Tillaart <[email protected]>
55
sentence=Arduino library for AGS02MA - TVOC sensor

0 commit comments

Comments
 (0)