Merge pull request #12 from pimoroni/patch-adc
authorPhilip Howard <phil@pimoroni.com>
Wed, 17 Jul 2019 12:21:26 +0000 (13:21 +0100)
committerGitHub <noreply@github.com>
Wed, 17 Jul 2019 12:21:26 +0000 (13:21 +0100)
Add support for breakout ADC channel

examples/adc.py [new file with mode: 0755]
library/enviroplus/gas.py
library/tests/test_setup.py

diff --git a/examples/adc.py b/examples/adc.py
new file mode 100755 (executable)
index 0000000..c4cf45c
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+import time
+from enviroplus import gas
+
+print("""adc.py - Print readings from the MICS6814 Gas sensor.
+
+Press Ctrl+C to exit!
+
+""")
+
+gas.enable_adc()
+gas.set_adc_gain(4.096)
+
+try:
+    while True:
+        readings = gas.read_all()
+        print(readings)
+        time.sleep(1.0)
+except KeyboardInterrupt:
+    pass
index ee1ad80b04da340be013215539c20e373fd1c1dd..584317b6af2dd0ab5d9f2380d69cb3ce37f62bff 100644 (file)
@@ -1,29 +1,41 @@
 """Read the MICS6814 via an ads1015 ADC"""
 
+import time
 import atexit
 import ads1015
 import RPi.GPIO as GPIO
 
 MICS6814_HEATER_PIN = 24
-
+MICS6814_GAIN = 6.144
 
 ads1015.I2C_ADDRESS_DEFAULT = ads1015.I2C_ADDRESS_ALTERNATE
 _is_setup = False
+_adc_enabled = False
+_adc_gain = 6.148
 
 
 class Mics6814Reading(object):
-    __slots__ = 'oxidising', 'reducing', 'nh3'
+    __slots__ = 'oxidising', 'reducing', 'nh3', 'adc'
 
-    def __init__(self, ox, red, nh3):
+    def __init__(self, ox, red, nh3, adc=None):
         self.oxidising = ox
         self.reducing = red
         self.nh3 = nh3
+        self.adc = adc
 
     def __repr__(self):
-        return """Oxidising: {:05.02f} Ohms
-Reducing: {:05.02f} Ohms
-NH3: {:05.02f} Ohms
-""".format(self.oxidising, self.reducing, self.nh3)
+        fmt = """Oxidising: {ox:05.02f} Ohms
+Reducing: {red:05.02f} Ohms
+NH3: {nh3:05.02f} Ohms"""
+        if self.adc is not None:
+            fmt += """
+ADC: {adc:05.02f} Volts
+"""
+        return fmt.format(
+            ox=self.oxidising,
+            red=self.reducing,
+            nh3=self.nh3,
+            adc=self.adc)
 
     __str__ = __repr__
 
@@ -36,7 +48,7 @@ def setup():
 
     adc = ads1015.ADS1015(i2c_addr=0x49)
     adc.set_mode('single')
-    adc.set_programmable_gain(6.148)
+    adc.set_programmable_gain(MICS6814_GAIN)
     adc.set_sample_rate(1600)
 
     GPIO.setwarnings(False)
@@ -46,6 +58,18 @@ def setup():
     atexit.register(cleanup)
 
 
+def enable_adc(value=True):
+    """Enable reading from the additional ADC pin."""
+    global _adc_enabled
+    _adc_enabled = value
+
+
+def set_adc_gain(value):
+    """Set gain value for the additional ADC pin."""
+    global _adc_gain
+    _adc_gain = value
+
+
 def cleanup():
     GPIO.output(MICS6814_HEATER_PIN, 0)
 
@@ -57,11 +81,33 @@ def read_all():
     red = adc.get_voltage('in1/gnd')
     nh3 = adc.get_voltage('in2/gnd')
 
-    ox = (ox * 56000) / (3.3 - ox)
-    red = (red * 56000) / (3.3 - red)
-    nh3 = (nh3 * 56000) / (3.3 - nh3)
+    try:
+        ox = (ox * 56000) / (3.3 - ox)
+    except ZeroDivisionError:
+        ox = 0
+
+    try:
+        red = (red * 56000) / (3.3 - red)
+    except ZeroDivisionError:
+        red = 0
 
-    return Mics6814Reading(ox, red, nh3)
+    try:
+        nh3 = (nh3 * 56000) / (3.3 - nh3)
+    except ZeroDivisionError:
+        nh3 = 0
+
+    analog = None
+
+    if _adc_enabled:
+        if _adc_gain == MICS6814_GAIN:
+            analog = adc.get_voltage('ref/gnd')
+        else:
+            adc.set_programmable_gain(_adc_gain)
+            time.sleep(0.05)
+            analog = adc.get_voltage('ref/gnd')
+            adc.set_programmable_gain(MICS6814_GAIN)
+
+    return Mics6814Reading(ox, red, nh3, analog)
 
 
 def read_oxidising():
@@ -86,3 +132,9 @@ def read_nh3():
     """Return gas resistance for nh3/ammonia"""
     setup()
     return read_all().nh3
+
+
+def read_adc():
+    """Return spare ADC channel value"""
+    setup()
+    return read_all().adc
index b912a3764ee7bcf414c3856aded295ce719af1e0..7c25d9465bb372038e6b0b5ef0a85f8e606f004b 100644 (file)
@@ -16,6 +16,7 @@ def test_gas_setup():
     smbus.SMBus = SMBusFakeDevice
     sys.modules['smbus'] = smbus
     from enviroplus import gas
+    gas._is_setup = False
     gas.setup()
     gas.setup()
 
@@ -27,6 +28,7 @@ def test_gas_read_all():
     smbus.SMBus = SMBusFakeDevice
     sys.modules['smbus'] = smbus
     from enviroplus import gas
+    gas._is_setup = False
     result = gas.read_all()
 
     assert type(result.oxidising) == float
@@ -48,7 +50,49 @@ def test_gas_read_each():
     smbus.SMBus = SMBusFakeDevice
     sys.modules['smbus'] = smbus
     from enviroplus import gas
+    gas._is_setup = False
 
     assert int(gas.read_oxidising()) == 16641
     assert int(gas.read_reducing()) == 16727
     assert int(gas.read_nh3()) == 16813
+
+
+def test_gas_read_adc():
+    sys.modules['RPi'] = mock.Mock()
+    sys.modules['RPi.GPIO'] = mock.Mock()
+    smbus = mock.Mock()
+    smbus.SMBus = SMBusFakeDevice
+    sys.modules['smbus'] = smbus
+    from enviroplus import gas
+    gas._is_setup = False
+
+    gas.enable_adc(True)
+    gas.set_adc_gain(2.048)
+    assert gas.read_adc() == 0.255
+
+
+def test_gas_read_adc_default_gain():
+    sys.modules['RPi'] = mock.Mock()
+    sys.modules['RPi.GPIO'] = mock.Mock()
+    smbus = mock.Mock()
+    smbus.SMBus = SMBusFakeDevice
+    sys.modules['smbus'] = smbus
+    from enviroplus import gas
+    gas._is_setup = False
+
+    gas.enable_adc(True)
+    assert gas.read_adc() == 0.255
+
+
+def test_gas_read_adc_str():
+    sys.modules['RPi'] = mock.Mock()
+    sys.modules['RPi.GPIO'] = mock.Mock()
+    smbus = mock.Mock()
+    smbus.SMBus = SMBusFakeDevice
+    sys.modules['smbus'] = smbus
+    from enviroplus import gas
+    gas._is_setup = False
+
+    gas.enable_adc(True)
+    gas.set_adc_gain(2.048)
+    assert 'ADC' in str(gas.read_all())