Python: add dht11 sensor python code.
authorFabien Reboia <srounet@gmail.com>
Mon, 9 Feb 2015 09:36:47 +0000 (09:36 +0000)
committerFabien Reboia <srounet@gmail.com>
Mon, 9 Feb 2015 09:36:47 +0000 (09:36 +0000)
It consists of a stripped rewrite of the DHT22 code.
As an addition it implements the iterable protocol.

EXAMPLES/Python/DHT11_SENSOR/README [new file with mode: 0644]
EXAMPLES/Python/DHT11_SENSOR/dht11.py [new file with mode: 0644]

diff --git a/EXAMPLES/Python/DHT11_SENSOR/README b/EXAMPLES/Python/DHT11_SENSOR/README
new file mode 100644 (file)
index 0000000..6e3259c
--- /dev/null
@@ -0,0 +1,2 @@
+Class to read the relative humidity and temperature from a DHT11 sensor.
+It implements the iterator python protocol.
diff --git a/EXAMPLES/Python/DHT11_SENSOR/dht11.py b/EXAMPLES/Python/DHT11_SENSOR/dht11.py
new file mode 100644 (file)
index 0000000..455ad2a
--- /dev/null
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+import time
+import pigpio
+
+
+class DHT11(object):
+    """
+    The DHT11 class is a stripped version of the DHT22 sensor code by joan2937.
+    You can find the initial implementation here:
+    - https://github.com/srounet/pigpio/tree/master/EXAMPLES/Python/DHT22_AM2302_SENSOR
+
+    example code:
+    >>> pi = pigpio.pi()
+    >>> sensor = DHT11(pi, 4) # 4 is the data GPIO pin connected to your sensor
+    >>> for response in sensor:
+    ....    print("Temperature: {}".format(response['temperature']))
+    ....    print("Humidity: {}".format(response['humidity']))
+    """
+
+    def __init__(self, pi, gpio):
+        """
+        pi (pigpio): an instance of pigpio
+        gpio (int): gpio pin number
+        """
+        self.pi = pi
+        self.gpio = gpio
+        self.high_tick = 0
+        self.bit = 40
+        self.temperature = 0
+        self.humidity = 0
+        self.either_edge_cb = None
+        self.setup()
+
+    def setup(self):
+        """
+        Clears the internal gpio pull-up/down resistor.
+        Kills any watchdogs.
+        """
+        self.pi.set_pull_up_down(self.gpio, pigpio.PUD_OFF)
+        self.pi.set_watchdog(self.gpio, 0)
+        self.register_callbacks()
+
+    def register_callbacks(self):
+        """
+        Monitors RISING_EDGE changes using callback.
+        """
+        self.either_edge_cb = self.pi.callback(
+            self.gpio,
+            pigpio.EITHER_EDGE,
+            self.either_edge_callback
+        )
+
+    def either_edge_callback(self, gpio, level, tick):
+        """
+        Either Edge callbacks, called each time the gpio edge changes.
+        Accumulate the 40 data bits from the dht11 sensor.
+        """
+        level_handlers = {
+            pigpio.FALLING_EDGE: self._edge_FALL,
+            pigpio.RISING_EDGE: self._edge_RISE,
+            pigpio.EITHER_EDGE: self._edge_EITHER
+        }
+        handler = level_handlers[level]
+        diff = pigpio.tickDiff(self.high_tick, tick)
+        handler(tick, diff)
+
+    def _edge_RISE(self, tick, diff):
+        """
+        Handle Rise signal.
+        """
+        val = 0
+        if diff >= 50:
+            val = 1
+        if diff >= 200: # Bad bit?
+            self.checksum = 256 # Force bad checksum
+
+        if self.bit >= 40: # Message complete
+            self.bit = 40
+        elif self.bit >= 32: # In checksum byte
+            self.checksum = (self.checksum << 1) + val
+            if self.bit == 39:
+                # 40th bit received
+                self.pi.set_watchdog(self.gpio, 0)
+                total = self.humidity + self.temperature
+                # is checksum ok ?
+                if not (total & 255) == self.checksum:
+                    raise
+        elif 16 <= self.bit < 24: # in temperature byte
+            self.temperature = (self.temperature << 1) + val
+        elif 0 <= self.bit < 8: # in humidity byte
+            self.humidity = (self.humidity << 1) + val
+        else: # skip header bits
+            pass
+        self.bit += 1
+
+    def _edge_FALL(self, tick, diff):
+        """
+        Handle Fall signal.
+        """
+        self.high_tick = tick
+        if diff <= 250000:
+            return
+        self.bit = -2
+        self.checksum = 0
+        self.temperature = 0
+        self.humidity = 0
+
+    def _edge_EITHER(self, tick, diff):
+        """
+        Handle Either signal.
+        """
+        self.pi.set_watchdog(self.gpio, 0)
+
+    def read(self):
+        """
+        Start reading over DHT11 sensor.
+        """
+        self.pi.write(self.gpio, pigpio.LOW)
+        time.sleep(0.017) # 17 ms
+        self.pi.set_mode(self.gpio, pigpio.INPUT)
+        self.pi.set_watchdog(self.gpio, 200)
+        time.sleep(0.2)
+
+    def close(self):
+        """
+        Stop reading sensor, remove callbacks.
+        """
+        self.pi.set_watchdog(self.gpio, 0)
+        if self.either_edge_cb:
+            self.either_edge_cb.cancel()
+            self.either_edge_cb = None
+
+    def __iter__(self):
+        """
+        Support the iterator protocol.
+        """
+        return self
+
+    def next(self):
+        """
+        Call the read method and return temperature and humidity informations.
+        """
+        self.read()
+        response =  {
+            'humidity': self.humidity,
+            'temperature': self.temperature
+        }
+        return response
+
+
+if __name__ == '__main__':
+    pi = pigpio.pi()
+    sensor = DHT11(pi, 4)
+    for d in sensor:
+        print("temperature: {}".format(d['temperature']))
+        print("humidity: {}".format(d['humidity']))
+        time.sleep(1)
+    sensor.close()
+