Skip to content

Commit f08f559

Browse files
authored
Merge pull request #3 from jposada202020/docs
Documentation and type hinting. Removing some print debugging comments
2 parents d77e625 + 7d2eb7a commit f08f559

File tree

1 file changed

+66
-14
lines changed

1 file changed

+66
-14
lines changed

adafruit_ags02ma.py

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
2828
"""
2929

30+
try:
31+
from busio import I2C
32+
except ImportError:
33+
pass
34+
3035
import time
3136
import struct
3237
from micropython import const
@@ -44,10 +49,10 @@
4449
_AGS02MA_CRC8_POLYNOMIAL = const(0x31)
4550

4651

47-
def _generate_crc(data):
52+
def _generate_crc(data: int) -> int:
4853
"""8-bit CRC algorithm for checking data
4954
50-
:param bytearray data: The data to generate a CRC for
55+
:param int data: The data to generate a CRC for
5156
"""
5257

5358
crc = _AGS02MA_CRC8_INIT
@@ -64,13 +69,47 @@ def _generate_crc(data):
6469

6570

6671
class AGS02MA:
67-
"""Driver for the AGS02MA air quality sensor
72+
"""Driver for the AGS02MA air quality sensor.
73+
74+
.. warning::
75+
I2C communication rate cannot be higher than 30KHZ. Refer to
76+
https://cdn-shop.adafruit.com/product-files/5593/datasheet+ags02ma.pdf
77+
Section 3.
6878
6979
:param ~busio.I2C i2c_bus: The I2C bus the AGS02MA is connected to.
7080
:param int address: The I2C device address. Defaults to :const:`0x1A`
81+
82+
:raises RunTimeError: When the sensor could not be found
83+
84+
85+
**Quickstart: Importing and using the device**
86+
87+
Here is an example of using the :class:`AGS02MA` class.
88+
First you will need to import the libraries to use the sensor
89+
90+
.. code-block:: python
91+
92+
import board
93+
import busio
94+
from adafruit_ags02ma import AGS02MA
95+
96+
Once this is done you can define your `busio.I2C` object and define your sensor object
97+
98+
.. code-block:: python
99+
100+
i2c = busio.I2C(board.SCL, board.SDA, frequency=20_000)
101+
ags = AGS02MA(i2c, address=0x1A)
102+
103+
Now you have access to the :attr:`gas_resistance` and :attr:`TVOC` attributes
104+
105+
.. code-block:: python
106+
107+
res = ags.gas_resistance
108+
tvoc = ags.TVOC
109+
71110
"""
72111

73-
def __init__(self, i2c_bus, address=AGS02MA_I2CADDR_DEFAULT):
112+
def __init__(self, i2c_bus: I2C, address: int = AGS02MA_I2CADDR_DEFAULT) -> None:
74113
self.i2c_device = i2c_device.I2CDevice(i2c_bus, address)
75114

76115
self._buf = bytearray(5)
@@ -80,30 +119,40 @@ def __init__(self, i2c_bus, address=AGS02MA_I2CADDR_DEFAULT):
80119
except RuntimeError as exc: # a CRC error or something!
81120
raise RuntimeError("Failed to find AGS02MA - check your wiring!") from exc
82121

83-
def firmware_version(self):
122+
def firmware_version(self) -> int:
84123
"""Return 24-bit value which contains the firmware version"""
85124
return self._read_reg(_AGS02MA_VERSION_REG, 30)
86125

87126
@property
88-
def gas_resistance(self):
127+
def gas_resistance(self) -> int:
89128
"""The resistance of the MEMS gas sensor"""
90129
return self._read_reg(_AGS02MA_GASRES_REG, 1500) * 100 # in 0.1Kohm
91130

92131
@property
93-
def TVOC(self): # pylint: disable=invalid-name
94-
"""The calculated Total Volatile Organic Compound measurement, in ppb"""
132+
def TVOC(self) -> int: # pylint: disable=invalid-name
133+
"""The calculated Total Volatile Organic Compound measurement, in ppb
134+
135+
:raises RunTimeError: When the sensor still preheating
136+
"""
95137
val = self._read_reg(_AGS02MA_TVOCSTAT_REG, 1500)
96138
status = val >> 24
97-
# print(hex(status))
139+
98140
if status & 0x1:
99141
raise RuntimeError("Sensor still preheating")
100142
return val & 0xFFFFFF
101143

102-
def set_address(self, new_addr):
144+
def set_address(self, new_addr: int) -> None:
103145
"""Set the address for the I2C interface, from 0x0 to 0x7F
146+
The sensor supports modifying the I2C address. After sending
147+
this command, the new address will take effect immediately,
148+
New address will remain after powering the sensor off.
104149
105-
:param int new_addr: THe new address
150+
:param int new_addr: The new address
151+
152+
:raises: ValueError: When selected address is not in the range 0x00-0x7F
106153
"""
154+
if new_addr not in range(1, 128):
155+
raise ValueError("Selected address must be between 0x00 and 0x7F")
107156

108157
_buf = bytearray(
109158
[
@@ -119,21 +168,24 @@ def set_address(self, new_addr):
119168
with self.i2c_device as i2c:
120169
i2c.write(_buf)
121170

122-
def _read_reg(self, addr, delayms):
171+
def _read_reg(self, addr: int, delayms: int) -> int:
123172
"""Read a register
124173
125174
:param int addr: The address to read
126175
:param int delayms: The delay between writes and reads, in milliseconds
176+
177+
:raises RunTimeError: When CRC check have failed.
178+
127179
"""
128180

129181
with self.i2c_device as i2c:
130182
self._addr[0] = addr
131183
i2c.write(self._addr)
132184
time.sleep(delayms / 1000)
133185
i2c.readinto(self._buf)
134-
# print([hex(x) for x in self._buf])
186+
135187
if _generate_crc(self._buf) != 0:
136188
raise RuntimeError("CRC check failed")
137189
val, crc = struct.unpack(">IB", self._buf) # pylint: disable=unused-variable
138-
# print(hex(val), hex(crc))
190+
139191
return val

0 commit comments

Comments
 (0)