#!/usr/bin/python import time from Adafruit_I2C import Adafruit_I2C # =========================================================================== # BMP085 Class # =========================================================================== class BMP085 : i2c = None # Operating Modes __BMP085_ULTRALOWPOWER = 0 __BMP085_STANDARD = 1 __BMP085_HIGHRES = 2 __BMP085_ULTRAHIGHRES = 3 # BMP085 Registers __BMP085_CAL_AC1 = 0xAA # R Calibration data (16 bits) __BMP085_CAL_AC2 = 0xAC # R Calibration data (16 bits) __BMP085_CAL_AC3 = 0xAE # R Calibration data (16 bits) __BMP085_CAL_AC4 = 0xB0 # R Calibration data (16 bits) __BMP085_CAL_AC5 = 0xB2 # R Calibration data (16 bits) __BMP085_CAL_AC6 = 0xB4 # R Calibration data (16 bits) __BMP085_CAL_B1 = 0xB6 # R Calibration data (16 bits) __BMP085_CAL_B2 = 0xB8 # R Calibration data (16 bits) __BMP085_CAL_MB = 0xBA # R Calibration data (16 bits) __BMP085_CAL_MC = 0xBC # R Calibration data (16 bits) __BMP085_CAL_MD = 0xBE # R Calibration data (16 bits) __BMP085_CONTROL = 0xF4 __BMP085_TEMPDATA = 0xF6 __BMP085_PRESSUREDATA = 0xF6 __BMP085_READTEMPCMD = 0x2E __BMP085_READPRESSURECMD = 0x34 # Private Fields _cal_AC1 = 0 _cal_AC2 = 0 _cal_AC3 = 0 _cal_AC4 = 0 _cal_AC5 = 0 _cal_AC6 = 0 _cal_B1 = 0 _cal_B2 = 0 _cal_MB = 0 _cal_MC = 0 _cal_MD = 0 # Constructor def __init__(self, address=0x77, mode=1, debug=False): self.i2c = Adafruit_I2C(address) self.address = address self.debug = debug # Make sure the specified mode is in the appropriate range if ((mode < 0) | (mode > 3)): if (self.debug): print "Invalid Mode: Using STANDARD by default" self.mode = self.__BMP085_STANDARD else: self.mode = mode # Read the calibration data self.readCalibrationData() def readS16(self, register): "Reads a signed 16-bit value" hi = self.i2c.readS8(register) lo = self.i2c.readU8(register+1) return (hi << 8) + lo def readU16(self, register): "Reads an unsigned 16-bit value" hi = self.i2c.readU8(register) lo = self.i2c.readU8(register+1) return (hi << 8) + lo def readCalibrationData(self): "Reads the calibration data from the IC" self._cal_AC1 = self.readS16(self.__BMP085_CAL_AC1) # INT16 self._cal_AC2 = self.readS16(self.__BMP085_CAL_AC2) # INT16 self._cal_AC3 = self.readS16(self.__BMP085_CAL_AC3) # INT16 self._cal_AC4 = self.readU16(self.__BMP085_CAL_AC4) # UINT16 self._cal_AC5 = self.readU16(self.__BMP085_CAL_AC5) # UINT16 self._cal_AC6 = self.readU16(self.__BMP085_CAL_AC6) # UINT16 self._cal_B1 = self.readS16(self.__BMP085_CAL_B1) # INT16 self._cal_B2 = self.readS16(self.__BMP085_CAL_B2) # INT16 self._cal_MB = self.readS16(self.__BMP085_CAL_MB) # INT16 self._cal_MC = self.readS16(self.__BMP085_CAL_MC) # INT16 self._cal_MD = self.readS16(self.__BMP085_CAL_MD) # INT16 if (self.debug): self.showCalibrationData() def showCalibrationData(self): "Displays the calibration values for debugging purposes" print "DBG: AC1 = %6d" % (self._cal_AC1) print "DBG: AC2 = %6d" % (self._cal_AC2) print "DBG: AC3 = %6d" % (self._cal_AC3) print "DBG: AC4 = %6d" % (self._cal_AC4) print "DBG: AC5 = %6d" % (self._cal_AC5) print "DBG: AC6 = %6d" % (self._cal_AC6) print "DBG: B1 = %6d" % (self._cal_B1) print "DBG: B2 = %6d" % (self._cal_B2) print "DBG: MB = %6d" % (self._cal_MB) print "DBG: MC = %6d" % (self._cal_MC) print "DBG: MD = %6d" % (self._cal_MD) def readRawTemp(self): "Reads the raw (uncompensated) temperature from the sensor" self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READTEMPCMD) time.sleep(0.005) # Wait 5ms raw = self.readU16(self.__BMP085_TEMPDATA) if (self.debug): print "DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw) return raw def readRawPressure(self): "Reads the raw (uncompensated) pressure level from the sensor" self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READPRESSURECMD + (self.mode << 6)) if (self.mode == self.__BMP085_ULTRALOWPOWER): time.sleep(0.005) elif (self.mode == self.__BMP085_HIGHRES): time.sleep(0.014) elif (self.mode == self.__BMP085_ULTRAHIGHRES): time.sleep(0.026) else: time.sleep(0.008) msb = self.i2c.readU8(self.__BMP085_PRESSUREDATA) lsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+1) xlsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+2) raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode) if (self.debug): print "DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw) return raw def readTemperature(self): "Gets the compensated temperature in degrees celcius" UT = 0 X1 = 0 X2 = 0 B5 = 0 temp = 0.0 # Read raw temp before aligning it with the calibration values UT = self.readRawTemp() X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15 X2 = (self._cal_MC << 11) / (X1 + self._cal_MD) B5 = X1 + X2 temp = ((B5 + 8) >> 4) / 10.0 if (self.debug): print "DBG: Calibrated temperature = %f C" % temp return temp def readPressure(self): "Gets the compensated pressure in pascal" UT = 0 UP = 0 B3 = 0 B5 = 0 B6 = 0 X1 = 0 X2 = 0 X3 = 0 p = 0 B4 = 0 B7 = 0 UT = self.readRawTemp() UP = self.readRawPressure() # You can use the datasheet values to test the conversion results # dsValues = True dsValues = False if (dsValues): UT = 27898 UP = 23843 self._cal_AC6 = 23153 self._cal_AC5 = 32757 self._cal_MB = -32768; self._cal_MC = -8711 self._cal_MD = 2868 self._cal_B1 = 6190 self._cal_B2 = 4 self._cal_AC3 = -14383 self._cal_AC2 = -72 self._cal_AC1 = 408 self._cal_AC4 = 32741 self.mode = self.__BMP085_ULTRALOWPOWER if (self.debug): self.showCalibrationData() # True Temperature Calculations X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15 X2 = (self._cal_MC << 11) / (X1 + self._cal_MD) B5 = X1 + X2 if (self.debug): print "DBG: X1 = %d" % (X1) print "DBG: X2 = %d" % (X2) print "DBG: B5 = %d" % (B5) print "DBG: True Temperature = %.2f C" % (((B5 + 8) >> 4) / 10.0) # Pressure Calculations B6 = B5 - 4000 X1 = (self._cal_B2 * (B6 * B6) >> 12) >> 11 X2 = (self._cal_AC2 * B6) >> 11 X3 = X1 + X2 B3 = (((self._cal_AC1 * 4 + X3) << self.mode) + 2) / 4 if (self.debug): print "DBG: B6 = %d" % (B6) print "DBG: X1 = %d" % (X1) print "DBG: X2 = %d" % (X2) print "DBG: X3 = %d" % (X3) print "DBG: B3 = %d" % (B3) X1 = (self._cal_AC3 * B6) >> 13 X2 = (self._cal_B1 * ((B6 * B6) >> 12)) >> 16 X3 = ((X1 + X2) + 2) >> 2 B4 = (self._cal_AC4 * (X3 + 32768)) >> 15 B7 = (UP - B3) * (50000 >> self.mode) if (self.debug): print "DBG: X1 = %d" % (X1) print "DBG: X2 = %d" % (X2) print "DBG: X3 = %d" % (X3) print "DBG: B4 = %d" % (B4) print "DBG: B7 = %d" % (B7) if (B7 < 0x80000000): p = (B7 * 2) / B4 else: p = (B7 / B4) * 2 if (self.debug): print "DBG: X1 = %d" % (X1) X1 = (p >> 8) * (p >> 8) X1 = (X1 * 3038) >> 16 X2 = (-7357 * p) >> 16 if (self.debug): print "DBG: p = %d" % (p) print "DBG: X1 = %d" % (X1) print "DBG: X2 = %d" % (X2) p = p + ((X1 + X2 + 3791) >> 4) if (self.debug): print "DBG: Pressure = %d Pa" % (p) return p def readAltitude(self, seaLevelPressure=101325): "Calculates the altitude in meters" altitude = 0.0 pressure = float(self.readPressure()) altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903)) if (self.debug): print "DBG: Altitude = %d" % (altitude) return altitude return 0