通过上一章,相信各位对树莓派I2C编程有一定的了解了,今天我们继续使用I2C来控制BMP180压强传感器。BMP180压强传感器操作原理比较简单,开机先通过I2C读取出AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD等寄存器的值,这些寄存器的值作为校准时使用。如何读取温度寄存器,压强寄存器的值,根据下图公式算出测得的当前温度和压强。
本章主要讲解python程序,使大家熟悉python编程。关于bcm2835,wiringpi程序具体可参看Pioneer600示例程序。
驱动文件bmp180.py
004 | # BMP085 default address. |
008 | BMP180_ULTRALOWPOWER = 0 |
011 | BMP180_ULTRAHIGHRES = 3 |
014 | BMP180_CAL_AC1 = 0xAA # R Calibration data (16 bits) |
015 | BMP180_CAL_AC2 = 0xAC # R Calibration data (16 bits) |
016 | BMP180_CAL_AC3 = 0xAE # R Calibration data (16 bits) |
017 | BMP180_CAL_AC4 = 0xB0 # R Calibration data (16 bits) |
018 | BMP180_CAL_AC5 = 0xB2 # R Calibration data (16 bits) |
019 | BMP180_CAL_AC6 = 0xB4 # R Calibration data (16 bits) |
020 | BMP180_CAL_B1 = 0xB6 # R Calibration data (16 bits) |
021 | BMP180_CAL_B2 = 0xB8 # R Calibration data (16 bits) |
022 | BMP180_CAL_MB = 0xBA # R Calibration data (16 bits) |
023 | BMP180_CAL_MC = 0xBC # R Calibration data (16 bits) |
024 | BMP180_CAL_MD = 0xBE # R Calibration data (16 bits) |
026 | BMP180_TEMPDATA = 0xF6 |
027 | BMP180_PRESSUREDATA = 0xF6 |
030 | BMP180_READTEMPCMD = 0x2E |
031 | BMP180_READPRESSURECMD = 0x34 |
035 | def __init__(self, address=BMP180_I2CADDR, mode=BMP180_STANDARD): |
037 | self._address = address |
038 | self._bus = smbus.SMBus(1) |
039 | # Load calibration values. |
040 | self._load_calibration() |
041 | def _read_byte(self,cmd): |
042 | return self._bus.read_byte_data(self._address,cmd) |
044 | def _read_u16(self,cmd): |
045 | MSB = self._bus.read_byte_data(self._address,cmd) |
046 | LSB = self._bus.read_byte_data(self._address,cmd+1) |
047 | return (MSB << 8) + LSB |
049 | def _read_s16(self,cmd): |
050 | result = self._read_u16(cmd) |
051 | if result > 32767:result -= 65536 |
054 | def _write_byte(self,cmd,val): |
055 | self._bus.write_byte_data(self._address,cmd,val) |
057 | def _load_calibration(self): |
059 | self.cal_AC1 = self._read_s16(BMP180_CAL_AC1) # INT16 |
060 | self.cal_AC2 = self._read_s16(BMP180_CAL_AC2) # INT16 |
061 | self.cal_AC3 = self._read_s16(BMP180_CAL_AC3) # INT16 |
062 | self.cal_AC4 = self._read_u16(BMP180_CAL_AC4) # UINT16 |
063 | self.cal_AC5 = self._read_u16(BMP180_CAL_AC5) # UINT16 |
064 | self.cal_AC6 = self._read_u16(BMP180_CAL_AC6) # UINT16 |
065 | self.cal_B1 = self._read_s16(BMP180_CAL_B1) # INT16 |
066 | self.cal_B2 = self._read_s16(BMP180_CAL_B2) # INT16 |
067 | self.cal_MB = self._read_s16(BMP180_CAL_MB) # INT16 |
068 | self.cal_MC = self._read_s16(BMP180_CAL_MC) # INT16 |
069 | self.cal_MD = self._read_s16(BMP180_CAL_MD) # INT16 |
071 | def read_raw_temp(self): |
072 | "" "Reads the raw (uncompensated) temperature from the sensor." "" |
073 | self._write_byte(BMP180_CONTROL, BMP180_READTEMPCMD) |
074 | time.sleep(0.005) # Wait 5ms |
075 | MSB = self._read_byte(BMP180_TEMPDATA) |
076 | LSB = self._read_byte(BMP180_TEMPDATA+1) |
077 | raw = (MSB << 8) + LSB |
080 | def read_raw_pressure(self): |
081 | "" "Reads the raw (uncompensated) pressure level from the sensor." "" |
082 | self._write_byte(BMP180_CONTROL, BMP180_READPRESSURECMD + (self._mode << 6)) |
083 | if self._mode == BMP180_ULTRALOWPOWER: |
085 | elif self._mode == BMP180_HIGHRES: |
087 | elif self._mode == BMP180_ULTRAHIGHRES: |
091 | MSB = self._read_byte(BMP180_PRESSUREDATA) |
092 | LSB = self._read_byte(BMP180_PRESSUREDATA+1) |
093 | XLSB = self._read_byte(BMP180_PRESSUREDATA+2) |
094 | raw = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - self._mode) |
097 | def read_temperature(self): |
098 | "" "Gets the compensated temperature in degrees celsius." "" |
099 | UT = self.read_raw_temp() |
101 | X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15 |
102 | X2 = (self.cal_MC << 11) / (X1 + self.cal_MD) |
104 | temp = ((B5 + 8) >> 4) / 10.0 |
107 | def read_pressure(self): |
108 | "" "Gets the compensated pressure in Pascals." "" |
109 | UT = self.read_raw_temp() |
110 | UP = self.read_raw_pressure() |
113 | X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15 |
114 | X2 = (self.cal_MC << 11) / (X1 + self.cal_MD) |
117 | # Pressure Calculations |
119 | X1 = (self.cal_B2 * (B6 * B6) >> 12) >> 11 |
120 | X2 = (self.cal_AC2 * B6) >> 11 |
122 | B3 = (((self.cal_AC1 * 4 + X3) << self._mode) + 2) / 4 |
124 | X1 = (self.cal_AC3 * B6) >> 13 |
125 | X2 = (self.cal_B1 * ((B6 * B6) >> 12)) >> 16 |
126 | X3 = ((X1 + X2) + 2) >> 2 |
127 | B4 = (self.cal_AC4 * (X3 + 32768)) >> 15 |
128 | B7 = (UP - B3) * (50000 >> self._mode) |
134 | X1 = (p >> 8) * (p >> 8) |
135 | X1 = (X1 * 3038) >> 16 |
136 | X2 = (-7357 * p) >> 16 |
138 | p = p + ((X1 + X2 + 3791) >> 4) |
141 | def read_altitude(self, sealevel_pa=101325.0): |
142 | "" "Calculates the altitude in meters." "" |
143 | # Calculation taken straight from section 3.6 of the datasheet. |
144 | pressure = float(self.read_pressure()) |
145 | altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0/5.255))) |
148 | def read_sealevel_pressure(self, altitude_m=0.0): |
149 | "" "Calculates the pressure at sealevel when given a known altitude in |
150 | meters. Returns a value in Pascals. "" " |
151 | pressure = float(self.read_pressure()) |
152 | p0 = pressure / pow(1.0 - altitude_m/44330.0, 5.255) |
主文件bmp180_example.py
04 | from BMP180 import BMP180 |
06 | # Initialise the BMP085 and use STANDARD mode ( default value) |
07 | # bmp = BMP085(0x77, debug=True) |
10 | # To specify a different operating mode, uncomment one of the following: |
11 | # bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode |
12 | # bmp = BMP085(0x77, 1) # STANDARD Mode |
13 | # bmp = BMP085(0x77, 2) # HIRES Mode |
14 | # bmp = BMP085(0x77, 3) # ULTRAHIRES Mode |
16 | temp = bmp.read_temperature() |
18 | # Read the current barometric pressure level |
19 | pressure = bmp.read_pressure() |
21 | # To calculate altitude based on an estimated mean sea level pressure |
22 | # (1013.25 hPa) call the function as follows, but this won't be very accurate |
23 | altitude = bmp.read_altitude() |
25 | # To specify a more accurate altitude, enter the correct mean sea level |
26 | # pressure level. For example, if the current pressure level is 1023.50 hPa |
27 | # enter 102350 since we include two decimal places in the integer value |
28 | # altitude = bmp.readAltitude(102350) |
30 | print "Temperature: %.2f C" % temp |
31 | print "Pressure: %.2f hPa" % (pressure / 100.0) |
32 | print "Altitude: %.2f\n" % altitude |