diff --git a/__init__.py b/__init__.py index 76ecb48..3570da1 100644 --- a/__init__.py +++ b/__init__.py @@ -1,44 +1,5 @@ -try: - from config import dht_gpio -except ImportError: - dht_gpio = None - -try: - import Adafruit_DHT as dht -except ImportError: - dht = None - -try: - import Adafruit_BMP.BMP085 as bmp -except ImportError: - bmp = None - -#TODO: background process for value sensing (every x seconds) - -KEY_TEMPERATURE = 't' -KEY_HUMIDITY = 'h' -KEY_PRESSURE = 'p' +import logging -class EnvSens(object): - def __init__(self): - if bmp is not None: - self.bmp = bmp.BMP085() - - def get_env_data(self): - # - # DHT22 - # - if dht is None or dht_gpio is None: - h = -17.3 - t = -125.7 - else: - h, t = dht.read_retry(dht.DHT22, dht_gpio) - # - # BMP180 - # - if bmp is None: - p = -1024.17 - else: - p = self.bmp.read_pressure()/100. - return {KEY_TEMPERATURE: t, KEY_HUMIDITY: h, KEY_PRESSURE: p} +logger_name = 'RPI_ENVSENS' +logger = logging.getLogger(logger_name) diff --git a/bmp.py b/bmp.py new file mode 100644 index 0000000..23d2e79 --- /dev/null +++ b/bmp.py @@ -0,0 +1,141 @@ +# Distributed with a free-will license. +# Use it any way you want, profit or free, provided it fits in the licenses of its associated works. +# BMP180 +# This code is designed to work with the BMP180_I2CS I2C Mini Module available from ControlEverything.com. +# https://www.controleverything.com/content/Pressure?sku=BMP180_I2CS#tabs-0-product_tabset-2 + +import smbus +import threading +import time + +from . import logger + + +class bmp_180(object): + KEY_TEMPERATURE = 'temperature' + KEY_PRESSURE = 'pressure' + KEY_TIME = 'time' + + def __init__(self, data_callback=None): + self.__data_callback__ = data_callback + # Initial the dht device, with data pin connected to: + self.__active__ = True + self.__thread__ = threading.Thread(target=self.run, args=()) + self.__thread__.daemon = True # Daemonize thread + self.__thread__.start() # Start the execution + + def run(self): + while self.__active__: + data = self.__bmp_data_transmission__() + if data is not None: + logger.debug('BMP-Communication: Successfully: %s', repr(data)) + if self.__data_callback__ is not None: + self.__data_callback__(**data) + time.sleep(0.5) + + def close(self): + self.__active__ = False + self.__thread__.join() + + def __del__(self): + self.close() + + def __bmp_data_transmission__(self): + rv = {} + # Get I2C bus + bus = smbus.SMBus(1) + + # BMP180 address, 0x77(119) + # Read data back from 0xAA(170), 22 bytes + data = bus.read_i2c_block_data(0x77, 0xAA, 22) + + # Convert the data + AC1 = data[0] * 256 + data[1] + if AC1 > 32767 : + AC1 -= 65535 + AC2 = data[2] * 256 + data[3] + if AC2 > 32767 : + AC2 -= 65535 + AC3 = data[4] * 256 + data[5] + if AC3 > 32767 : + AC3 -= 65535 + AC4 = data[6] * 256 + data[7] + AC5 = data[8] * 256 + data[9] + AC6 = data[10] * 256 + data[11] + B1 = data[12] * 256 + data[13] + if B1 > 32767 : + B1 -= 65535 + B2 = data[14] * 256 + data[15] + if B2 > 32767 : + B2 -= 65535 + MB = data[16] * 256 + data[17] + if MB > 32767 : + MB -= 65535 + MC = data[18] * 256 + data[19] + if MC > 32767 : + MC -= 65535 + MD = data[20] * 256 + data[21] + if MD > 32767 : + MD -= 65535 + + time.sleep(0.5) + + # BMP180 address, 0x77(119) + # Select measurement control register, 0xF4(244) + # 0x2E(46) Enable temperature measurement + bus.write_byte_data(0x77, 0xF4, 0x2E) + + time.sleep(0.5) + + # BMP180 address, 0x77(119) + # Read data back from 0xF6(246), 2 bytes + # temp MSB, temp LSB + data = bus.read_i2c_block_data(0x77, 0xF6, 2) + + # Convert the data + temp = data[0] * 256 + data[1] + + # BMP180 address, 0x77(119) + # Select measurement control register, 0xF4(244) + # 0x74(116) Enable pressure measurement, OSS = 1 + bus.write_byte_data(0x77, 0xF4, 0x74) + + time.sleep(0.5) + + # BMP180 address, 0x77(119) + # Read data back from 0xF6(246), 3 bytes + # pres MSB1, pres MSB, pres LSB + data = bus.read_i2c_block_data(0x77, 0xF6, 3) + + rv[self.KEY_TIME] = time.time() + + # Convert the data + pres = ((data[0] * 65536) + (data[1] * 256) + data[2]) / 128 + # Callibration for Temperature + X1 = (temp - AC6) * AC5 / 32768.0 + X2 = (MC * 2048.0) / (X1 + MD) + B5 = X1 + X2 + rv[self.KEY_TEMPERATURE] = ((B5 + 8.0) / 16.0) / 10.0 + + # Calibration for Pressure + B6 = B5 - 4000 + X1 = (B2 * (B6 * B6 / 4096.0)) / 2048.0 + X2 = AC2 * B6 / 2048.0 + X3 = X1 + X2 + B3 = (((AC1 * 4 + X3) * 2) + 2) / 4.0 + X1 = AC3 * B6 / 8192.0 + X2 = (B1 * (B6 * B6 / 2048.0)) / 65536.0 + X3 = ((X1 + X2) + 2) / 4.0 + B4 = AC4 * (X3 + 32768) / 32768.0 + B7 = ((pres - B3) * (25000.0)) + pressure = 0.0 + if B7 < 2147483648: + pressure = (B7 * 2) / B4 + else : + pressure = (B7 / B4) * 2 + X1 = (pressure / 256.0) * (pressure / 256.0) + X1 = (X1 * 3038.0) / 65536.0 + X2 = ((-7357) * pressure) / 65536.0 + rv[self.KEY_PRESSURE] = (pressure + (X1 + X2 + 3791) / 16.0) / 100 + + return rv diff --git a/dht.py b/dht.py new file mode 100644 index 0000000..0407b5e --- /dev/null +++ b/dht.py @@ -0,0 +1,55 @@ +import adafruit_dht +import threading +import time + +from . import logger + + +class dht_22(object): + KEY_TEMPERATURE = 'temperature' + KEY_HUMIDITY = 'humidity' + KEY_TIME = 'time' + + def __init__(self, gpio, data_callback=None): + self.__data_callback__ = data_callback + # Initial the dht device, with data pin connected to: + self.__dht_device__ = adafruit_dht.DHT22(gpio) + self.__active__ = True + self.__thread__ = threading.Thread(target=self.run, args=()) + self.__thread__.daemon = True # Daemonize thread + self.__thread__.start() # Start the execution + + def run(self): + while self.__active__: + data = self.__dht_data_transmission__() + if data is not None: + logger.debug('DHT-Communication: Successfully: %s', repr(data)) + if self.__data_callback__ is not None: + self.__data_callback__(**data) + time.sleep(2.0) + + def close(self): + self.__active__ = False + self.__thread__.join() + + def __del__(self): + self.close() + + def __dht_data_transmission__(self): + while self.__active__: + try: + # Store the values + data = {} + data[self.KEY_TEMPERATURE] = self.__dht_device__.temperature + data[self.KEY_HUMIDITY] = self.__dht_device__.humidity + data[self.KEY_TIME] = time.time() + if data[self.KEY_TEMPERATURE] is not None and data[self.KEY_HUMIDITY] is not None: + return data + time.sleep(2.0) + except RuntimeError as error: + # Errors happen fairly often, DHT's are hard to read, just keep going + logger.debug('DHT-Communication: ' + error.args[0]) + time.sleep(0.1) + except Exception as error: + self.__dht_device__.exit() + raise error