|
@@ -0,0 +1,141 @@
|
|
1
|
+# Distributed with a free-will license.
|
|
2
|
+# Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
|
|
3
|
+# BMP180
|
|
4
|
+# This code is designed to work with the BMP180_I2CS I2C Mini Module available from ControlEverything.com.
|
|
5
|
+# https://www.controleverything.com/content/Pressure?sku=BMP180_I2CS#tabs-0-product_tabset-2
|
|
6
|
+
|
|
7
|
+import smbus
|
|
8
|
+import threading
|
|
9
|
+import time
|
|
10
|
+
|
|
11
|
+from . import logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+class bmp_180(object):
|
|
15
|
+ KEY_TEMPERATURE = 'temperature'
|
|
16
|
+ KEY_PRESSURE = 'pressure'
|
|
17
|
+ KEY_TIME = 'time'
|
|
18
|
+
|
|
19
|
+ def __init__(self, data_callback=None):
|
|
20
|
+ self.__data_callback__ = data_callback
|
|
21
|
+ # Initial the dht device, with data pin connected to:
|
|
22
|
+ self.__active__ = True
|
|
23
|
+ self.__thread__ = threading.Thread(target=self.run, args=())
|
|
24
|
+ self.__thread__.daemon = True # Daemonize thread
|
|
25
|
+ self.__thread__.start() # Start the execution
|
|
26
|
+
|
|
27
|
+ def run(self):
|
|
28
|
+ while self.__active__:
|
|
29
|
+ data = self.__bmp_data_transmission__()
|
|
30
|
+ if data is not None:
|
|
31
|
+ logger.debug('BMP-Communication: Successfully: %s', repr(data))
|
|
32
|
+ if self.__data_callback__ is not None:
|
|
33
|
+ self.__data_callback__(**data)
|
|
34
|
+ time.sleep(0.5)
|
|
35
|
+
|
|
36
|
+ def close(self):
|
|
37
|
+ self.__active__ = False
|
|
38
|
+ self.__thread__.join()
|
|
39
|
+
|
|
40
|
+ def __del__(self):
|
|
41
|
+ self.close()
|
|
42
|
+
|
|
43
|
+ def __bmp_data_transmission__(self):
|
|
44
|
+ rv = {}
|
|
45
|
+ # Get I2C bus
|
|
46
|
+ bus = smbus.SMBus(1)
|
|
47
|
+
|
|
48
|
+ # BMP180 address, 0x77(119)
|
|
49
|
+ # Read data back from 0xAA(170), 22 bytes
|
|
50
|
+ data = bus.read_i2c_block_data(0x77, 0xAA, 22)
|
|
51
|
+
|
|
52
|
+ # Convert the data
|
|
53
|
+ AC1 = data[0] * 256 + data[1]
|
|
54
|
+ if AC1 > 32767 :
|
|
55
|
+ AC1 -= 65535
|
|
56
|
+ AC2 = data[2] * 256 + data[3]
|
|
57
|
+ if AC2 > 32767 :
|
|
58
|
+ AC2 -= 65535
|
|
59
|
+ AC3 = data[4] * 256 + data[5]
|
|
60
|
+ if AC3 > 32767 :
|
|
61
|
+ AC3 -= 65535
|
|
62
|
+ AC4 = data[6] * 256 + data[7]
|
|
63
|
+ AC5 = data[8] * 256 + data[9]
|
|
64
|
+ AC6 = data[10] * 256 + data[11]
|
|
65
|
+ B1 = data[12] * 256 + data[13]
|
|
66
|
+ if B1 > 32767 :
|
|
67
|
+ B1 -= 65535
|
|
68
|
+ B2 = data[14] * 256 + data[15]
|
|
69
|
+ if B2 > 32767 :
|
|
70
|
+ B2 -= 65535
|
|
71
|
+ MB = data[16] * 256 + data[17]
|
|
72
|
+ if MB > 32767 :
|
|
73
|
+ MB -= 65535
|
|
74
|
+ MC = data[18] * 256 + data[19]
|
|
75
|
+ if MC > 32767 :
|
|
76
|
+ MC -= 65535
|
|
77
|
+ MD = data[20] * 256 + data[21]
|
|
78
|
+ if MD > 32767 :
|
|
79
|
+ MD -= 65535
|
|
80
|
+
|
|
81
|
+ time.sleep(0.5)
|
|
82
|
+
|
|
83
|
+ # BMP180 address, 0x77(119)
|
|
84
|
+ # Select measurement control register, 0xF4(244)
|
|
85
|
+ # 0x2E(46) Enable temperature measurement
|
|
86
|
+ bus.write_byte_data(0x77, 0xF4, 0x2E)
|
|
87
|
+
|
|
88
|
+ time.sleep(0.5)
|
|
89
|
+
|
|
90
|
+ # BMP180 address, 0x77(119)
|
|
91
|
+ # Read data back from 0xF6(246), 2 bytes
|
|
92
|
+ # temp MSB, temp LSB
|
|
93
|
+ data = bus.read_i2c_block_data(0x77, 0xF6, 2)
|
|
94
|
+
|
|
95
|
+ # Convert the data
|
|
96
|
+ temp = data[0] * 256 + data[1]
|
|
97
|
+
|
|
98
|
+ # BMP180 address, 0x77(119)
|
|
99
|
+ # Select measurement control register, 0xF4(244)
|
|
100
|
+ # 0x74(116) Enable pressure measurement, OSS = 1
|
|
101
|
+ bus.write_byte_data(0x77, 0xF4, 0x74)
|
|
102
|
+
|
|
103
|
+ time.sleep(0.5)
|
|
104
|
+
|
|
105
|
+ # BMP180 address, 0x77(119)
|
|
106
|
+ # Read data back from 0xF6(246), 3 bytes
|
|
107
|
+ # pres MSB1, pres MSB, pres LSB
|
|
108
|
+ data = bus.read_i2c_block_data(0x77, 0xF6, 3)
|
|
109
|
+
|
|
110
|
+ rv[self.KEY_TIME] = time.time()
|
|
111
|
+
|
|
112
|
+ # Convert the data
|
|
113
|
+ pres = ((data[0] * 65536) + (data[1] * 256) + data[2]) / 128
|
|
114
|
+ # Callibration for Temperature
|
|
115
|
+ X1 = (temp - AC6) * AC5 / 32768.0
|
|
116
|
+ X2 = (MC * 2048.0) / (X1 + MD)
|
|
117
|
+ B5 = X1 + X2
|
|
118
|
+ rv[self.KEY_TEMPERATURE] = ((B5 + 8.0) / 16.0) / 10.0
|
|
119
|
+
|
|
120
|
+ # Calibration for Pressure
|
|
121
|
+ B6 = B5 - 4000
|
|
122
|
+ X1 = (B2 * (B6 * B6 / 4096.0)) / 2048.0
|
|
123
|
+ X2 = AC2 * B6 / 2048.0
|
|
124
|
+ X3 = X1 + X2
|
|
125
|
+ B3 = (((AC1 * 4 + X3) * 2) + 2) / 4.0
|
|
126
|
+ X1 = AC3 * B6 / 8192.0
|
|
127
|
+ X2 = (B1 * (B6 * B6 / 2048.0)) / 65536.0
|
|
128
|
+ X3 = ((X1 + X2) + 2) / 4.0
|
|
129
|
+ B4 = AC4 * (X3 + 32768) / 32768.0
|
|
130
|
+ B7 = ((pres - B3) * (25000.0))
|
|
131
|
+ pressure = 0.0
|
|
132
|
+ if B7 < 2147483648:
|
|
133
|
+ pressure = (B7 * 2) / B4
|
|
134
|
+ else :
|
|
135
|
+ pressure = (B7 / B4) * 2
|
|
136
|
+ X1 = (pressure / 256.0) * (pressure / 256.0)
|
|
137
|
+ X1 = (X1 * 3038.0) / 65536.0
|
|
138
|
+ X2 = ((-7357) * pressure) / 65536.0
|
|
139
|
+ rv[self.KEY_PRESSURE] = (pressure + (X1 + X2 + 3791) / 16.0) / 100
|
|
140
|
+
|
|
141
|
+ return rv
|