Yet Another WebIOPi+
 All Classes Namespaces Files Functions Variables Macros Pages
bme280.py
Go to the documentation of this file.
1 from webiopi.utils.types import toint, signInteger
2 from webiopi.devices.i2c import I2C
3 from webiopi.devices.sensor import Temperature, Pressure, Humidity
4 #from webiopi.utils import logger
5 from webiopi.utils.logger import info, exception
6 
8  def __init__(self, altitude=0, external=None, oversampling=0, filter=0, standby=0.5, slave=0x76):
9  I2C.__init__(self, toint(slave))
10  Pressure.__init__(self, altitude, external)
11 
12  self.t1 = self.readUnsigned(0x88, 2)
13  self.t2 = self.readSigned(0x8A, 2)
14  self.t3 = self.readSigned(0x8C, 2)
15 
16  self.p1 = self.readUnsigned(0x8E, 2)
17  self.p2 = self.readSigned(0x90, 2)
18  self.p3 = self.readSigned(0x92, 2)
19  self.p4 = self.readSigned(0x94, 2)
20  self.p5 = self.readSigned(0x96, 2)
21  self.p6 = self.readSigned(0x98, 2)
22  self.p7 = self.readSigned(0x9A, 2)
23  self.p8 = self.readSigned(0x9C, 2)
24  self.p9 = self.readSigned(0x9E, 2)
25 
26  self.h1 = self.readUnsigned(0xA1, 1)
27  self.h2 = self.readSigned(0xE1, 2)
28  self.h3 = self.readUnsigned(0xE3, 1)
29  self.h4 = (self.readUnsigned(0xE4, 1) << 4) | (self.readUnsigned(0xE5, 1) & 0x0F)
30  self.h5 = (self.readSigned(0xE6, 1) << 4) | (self.readSigned(0xE5, 1) >> 4)
31  self.h6 = self.readSigned(0xE7, 1)
32 
33  oversamplingBits = toint(oversampling).bit_length()
34  self.writeRegister(0xF2, oversamplingBits) # Humidity oversampling. Must be set before temp/press oversampling (see datasheet 5.4.3).
35  self.writeRegister(0xF4, (oversamplingBits << 5) | (oversamplingBits << 2) | 0x03) # Pressure, temperature oversampling, sensor normal mode.
36 
37  standbyValues = {'0.5':0, '10':6, '20':7, '62.5':1, '125':2, '250':3, '500':4, '1000':5}
38  if standby in standbyValues:
39  tStandbyBits = standbyValues[standby]
40  else:
41  tStandbyBits = 0 # Default to 0.5ms t_standby
42  # logger.warn('Invalid value for standby: %s' % standby)
43  spiBits = 0 # No SPI of course.
44  filterBits = toint(filter) >> 1
45  self.writeRegister(0xF5, (tStandbyBits << 5) | (filterBits << 2) | spiBits)
46 
47  def __str__(self):
48  return "BME280"
49 
50  def __family__(self):
51  return [Temperature.__family__(self), Pressure.__family__(self), Humidity.__family__(self)]
52 
53  def readUnsigned(self, address, numBytes, byteOrder='little'):
54  d = self.readRegisters(address, numBytes)
55  x = 0
56  if byteOrder == 'big':
57  for i in range(0, numBytes):
58  x |= d[i] << (8 * (numBytes - (i + 1)))
59  else:
60  for i in range(0, numBytes):
61  x |= d[i] << (8 * i)
62  return x
63 
64  def readSigned(self, address, numBytes, byteOrder = 'little'):
65  d = self.readUnsigned(address, numBytes, byteOrder)
66  return signInteger(d, numBytes * 8)
67 
68  # Reading all ADC registers at once ensures consistency (see datasheet section 4).
69  def readAdc(self):
70  raw = self.readUnsigned(0xF7, 8, 'big')
71  adc_P = raw >> 44
72  adc_T = ((raw >> 16) & 0xFFFFFF) >> 4
73  adc_H = raw & 0xFFFF
74  return (adc_T, adc_P, adc_H)
75 
76  def compensateTfine(self, adc_T):
77  #Taken straight out of the datasheet. Could be rewritten to be clearer.
78  var1 = (((adc_T >> 3) - (self.t1 << 1)) * self.t2) >> 11
79  var2 = (((((adc_T >> 4) - self.t1) * ((adc_T >> 4) - self.t1)) >> 12) * self.t3) >> 14
80 
81  return var1 + var2
82 
83  def compensateT(self, t_fine):
84  #Taken straight out of the datasheet. Could be rewritten to be clearer.
85  return float((t_fine * 5 + 128) >> 8) / 100.0
86 
87  def compensateP(self, t_fine, adc_P):
88  #Taken straight out of the datasheet. Could be rewritten to be clearer.
89  var1 = t_fine - 128000
90  var2 = var1 * var1 * self.p6
91  var2 = var2 + ((var1 * self.p5) << 17)
92  var2 = var2 + (self.p4 << 35)
93  var1 = ((var1 * var1 * self.p3) >> 8) + ((var1 * self.p2) << 12)
94  var1 = ((1 << 47) + var1) * self.p1 >> 33
95 
96  if var1 == 0:
97  return 0
98 
99  p = 1048576 - adc_P
100  p = (((p << 31) - var2) * 3125) // var1
101  var1 = (self.p9 * (p >> 13) * (p >> 13)) >> 25
102  var2 = (self.p8 * p) >> 19
103  p = ((p + var1 + var2) >> 8) + (self.p7 << 4)
104 
105  return float(p) / 256.0
106 
107  def compensateH(self, t_fine, adc_H):
108  #Taken straight out of the datasheet. Could be rewritten to be clearer.
109  v_x1_u32r = t_fine - 76800
110  v_x1_u32r = ((((adc_H << 14) - (self.h4 << 20) - (self.h5 * v_x1_u32r)) + 16384) >> 15) * (((((((v_x1_u32r * self.h6) >> 10) * (((v_x1_u32r * self.h3) >> 11) + 32768)) >> 10) + 2097152) * self.h2 + 8192) >> 14)
111  v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * self.h1) >> 4)
112  v_x1_u32r = max(v_x1_u32r, 0)
113  v_x1_u32r = min(v_x1_u32r, 419430400)
114 
115  return float(v_x1_u32r >> 12) / 1024.0
116 
117  def __getAll__(self):
118  raw = self.readUnsigned(0xF7, 8, 'big')
119  adc_P = raw >> 44
120  adc_T = ((raw >> 16) & 0xFFFFFF) >> 4
121  adc_H = raw & 0xFFFF
122  t_fine = self.compensateTfine(adc_T)
123  T = self.compensateT(t_fine)
124  P = self.compensateP(t_fine, adc_P)
125  H = self.compensateH(t_fine, adc_H)
126  return (T, P, H)
127 
128  def __getCelsius__(self):
129  adc = self.readAdc()
130  #t_fine = self.compensateTfine(adc.T)
131  t_fine = self.compensateTfine(adc[0])
132  return self.compensateT(t_fine)
133 
134  def __getKelvin__(self):
135  return self.Celsius2Kelvin()
136 
137  def __getFahrenheit__(self):
138  return self.Celsius2Fahrenheit()
139 
140  def __getPascal__(self):
141  adc = self.readAdc()
142  #t_fine = self.compensateTfine(adc.T)
143  #return self.compensateP(t_fine, adc.P)
144  t_fine = self.compensateTfine(adc[0])
145  return self.compensateP(t_fine, adc[1])
146 
147  def __getHumidity__(self):
148  adc = self.readAdc()
149 # t_fine = self.compensateTfine(adc.T)
150 # return self.compensateH(t_fine, adc.H) / 100.0
151  t_fine = self.compensateTfine(adc[0])
152  return self.compensateH(t_fine, adc[2]) / 100.0