from ustruct importunpack as unpfrom machine importI2C, Pinimportmathimporttime#BMP180 class
classBMP180():'''Module for the BMP180 pressure sensor.'''_bmp_addr= 119 #adress of BMP180 is hardcoded on the sensor
#init
def __init__(self, i2c_bus):#create i2c obect
_bmp_addr =self._bmp_addr
self._bmp_i2c=i2c_bus
self._bmp_i2c.start()
self.chip_id= self._bmp_i2c.readfrom_mem(_bmp_addr, 0xD0, 2)#read calibration data from EEPROM
self._AC1 = unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xAA, 2))[0]
self._AC2= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xAC, 2))[0]
self._AC3= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xAE, 2))[0]
self._AC4= unp('>H', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xB0, 2))[0]
self._AC5= unp('>H', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xB2, 2))[0]
self._AC6= unp('>H', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xB4, 2))[0]
self._B1= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xB6, 2))[0]
self._B2= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xB8, 2))[0]
self._MB= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xBA, 2))[0]
self._MC= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xBC, 2))[0]
self._MD= unp('>h', self._bmp_i2c.readfrom_mem(_bmp_addr, 0xBE, 2))[0]#settings to be adjusted by user
self.oversample_setting = 3self.baseline= 101325.0
#output raw
self.UT_raw =None
self.B5_raw=None
self.MSB_raw=None
self.LSB_raw=None
self.XLSB_raw=None
self.gauge= self.makegauge() #Generator instance
for _ in range(128):
next(self.gauge)
time.sleep_ms(1)defcompvaldump(self):'''Returns a list of all compensation values'''
return[self._AC1, self._AC2, self._AC3, self._AC4, self._AC5, self._AC6,
self._B1, self._B2, self._MB, self._MC, self._MD, self.oversample_setting]#gauge raw
defmakegauge(self):'''Generator refreshing the raw measurments.'''delays= (5, 8, 14, 25)whileTrue:
self._bmp_i2c.writeto_mem(self._bmp_addr,0xF4, bytearray([0x2E]))
t_start=time.ticks_ms()while (time.ticks_ms() - t_start) <= 5: #5mS delay
yieldNonetry:
self.UT_raw= self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF6, 2)except:yieldNone
self._bmp_i2c.writeto_mem(self._bmp_addr,0xF4, bytearray([0x34+(self.oversample_setting << 6)]))
t_pressure_ready=delays[self.oversample_setting]
t_start=time.ticks_ms()while (time.ticks_ms() - t_start) <=t_pressure_ready:yieldNonetry:
self.MSB_raw= self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF6, 1)
self.LSB_raw= self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF7, 1)
self.XLSB_raw= self._bmp_i2c.readfrom_mem(self._bmp_addr, 0xF8, 1)except:yieldNoneyieldTruedefblocking_read(self):if next(self.gauge) is not None: #Discard old data
pass
while next(self.gauge) isNone:pass@propertydefoversample_sett(self):returnself.oversample_setting
@oversample_sett.setterdefoversample_sett(self, value):if value in range(4):
self.oversample_setting=valueelse:print('oversample_sett can only be 0, 1, 2 or 3, using 3 instead')
self.oversample_setting= 3@propertydeftemperature(self):'''Temperature in degree C.'''next(self.gauge)try:
UT= unp('>H', self.UT_raw)[0]except:return 0.0X1= (UT-self._AC6)*self._AC5/2**15X2= self._MC*2**11/(X1+self._MD)
self.B5_raw= X1+X2return (((X1+X2)+8)/2**4)/10@propertydefpressure(self):'''Pressure in mbar.'''next(self.gauge)
self.temperature#Populate self.B5_raw
try:
MSB= unp('B', self.MSB_raw)[0]
LSB= unp('B', self.LSB_raw)[0]
XLSB= unp('B', self.XLSB_raw)[0]except:return 0.0UP= ((MSB << 16)+(LSB << 8)+XLSB) >> (8-self.oversample_setting)
B6= self.B5_raw-4000X1= (self._B2*(B6**2/2**12))/2**11X2= self._AC2*B6/2**11X3= X1+X2
B3= ((int((self._AC1*4+X3)) << self.oversample_setting)+2)/4X1= self._AC3*B6/2**13X2= (self._B1*(B6**2/2**12))/2**16X3= ((X1+X2)+2)/2**2B4= abs(self._AC4)*(X3+32768)/2**15B7= (abs(UP)-B3) * (50000 >>self.oversample_setting)if B7 < 0x80000000:
pressure= (B7*2)/B4else:
pressure= (B7/B4)*2X1= (pressure/2**8)**2X1= (X1*3038)/2**16X2= (-7357*pressure)/2**16
return pressure+(X1+X2+3791)/2**4@propertydefaltitude(self):'''Altitude in m.'''
try:
p= -7990.0*math.log(self.pressure/self.baseline)except:
p= 0.0
return p