树莓派连接BMP180气压传感器

作为最常见的传感器,本篇(来自于知乎某大神的文章)实现气压传感的交互:

1.先说明BMP180的特点

• 压力范围:300~1100hPa(海拔 9000 米~-500 米)

• 电源电压:1.8V~3.6V(VDDA), 1.62V~3.6V(VDDD)

• 尺寸:3.6mmx3.8x0.93mm

• 低功耗:5μA,在标准模式

• 高精度:低功耗模式下,分辨率为 0.06hPa(0.5 米)

• 高线性模式下,分辨率为 0.03hPa(0.25 米)

• 含温度输出

• I2C 接口

• 温度补偿

• MSL 1 反应时间:7.5ms

• 待机电流:0.1μA

注意了该传感器是I2C接口的,因此在后续步骤要稍加注意。

2. 接线

I2C 有两个总线:SCL 为时钟信号,和 SDA 为双向数据传输。 每个 I2C 器件采用独特的 7 位地址,这意味着你可以有超过 120 个独特的 I2C 器件共享总线, 并且可以同时控制这些器件一起工作。

树莓派连接BMP180气压传感器_第1张图片
图一 树莓派与BMP180接线图

将 BMP180 的 VCC 引脚用红色跳线连接树莓派的 3V3 ( 3.3 伏电源)。将 BMP180 的 SDA 引脚 接入树莓派的 SDA 引脚并将 BMP180 SCL 引脚接入树莓派的 SCL 引脚,该引脚提供一个规律的 时钟信号。SDA 传递数据信号。BMP180 的 GND 引脚通过黑色跳线连接树莓派的接地( GND) 引脚。 在上电前,一定多检查两次接线的准确性。

3. 环境和程序部分

配置文件/boot/config.txt:

dtparam=i2c_arm=on

重启树莓派,用如下命令查看传感器是否接上:

i2cdetect -y 1

如果接上了的话会显示下图:


树莓派连接BMP180气压传感器_第2张图片
图二 I2C接口检测结果

编写 BMP180.py:

#!/usr/bin/env python

import time

import smbus

# BMP085 default address.

BMP180_I2CADDR          = 0x77

# Operating Modes

BMP180_ULTRALOWPOWER    = 0

BMP180_STANDARD          = 1

BMP180_HIGHRES          = 2

BMP180_ULTRAHIGHRES      = 3

# BMP085 Registers

BMP180_CAL_AC1          = 0xAA  # R  Calibration data (16 bits)

BMP180_CAL_AC2          = 0xAC  # R  Calibration data (16 bits)

BMP180_CAL_AC3          = 0xAE  # R  Calibration data (16 bits)

BMP180_CAL_AC4          = 0xB0  # R  Calibration data (16 bits)

BMP180_CAL_AC5          = 0xB2  # R  Calibration data (16 bits)

BMP180_CAL_AC6          = 0xB4  # R  Calibration data (16 bits)

BMP180_CAL_B1            = 0xB6  # R  Calibration data (16 bits)

BMP180_CAL_B2            = 0xB8  # R  Calibration data (16 bits)

BMP180_CAL_MB            = 0xBA  # R  Calibration data (16 bits)

BMP180_CAL_MC            = 0xBC  # R  Calibration data (16 bits)

BMP180_CAL_MD            = 0xBE  # R  Calibration data (16 bits)

BMP180_CONTROL          = 0xF4

BMP180_TEMPDATA          = 0xF6

BMP180_PRESSUREDATA      = 0xF6

# Commands

BMP180_READTEMPCMD      = 0x2E

BMP180_READPRESSURECMD  = 0x34

class BMP180(object):

    def __init__(self, address=BMP180_I2CADDR, mode=BMP180_STANDARD):

        self._mode = mode

        self._address = address

        self._bus = smbus.SMBus(1)

        # Load calibration values.

        self._load_calibration()

    def _read_byte(self,cmd):

        return self._bus.read_byte_data(self._address,cmd)

    def _read_u16(self,cmd):

        MSB = self._bus.read_byte_data(self._address,cmd)

        LSB = self._bus.read_byte_data(self._address,cmd+1)

        return (MSB << 8) + LSB

    def _read_s16(self,cmd):

        result = self._read_u16(cmd)

        if result > 32767:result -= 65536

        return result

    def _write_byte(self,cmd,val):

        self._bus.write_byte_data(self._address,cmd,val)

    def _load_calibration(self):

        "load calibration"

        self.cal_AC1 = self._read_s16(BMP180_CAL_AC1)  # INT16

        self.cal_AC2 = self._read_s16(BMP180_CAL_AC2)  # INT16

        self.cal_AC3 = self._read_s16(BMP180_CAL_AC3)  # INT16

        self.cal_AC4 = self._read_u16(BMP180_CAL_AC4)  # UINT16

        self.cal_AC5 = self._read_u16(BMP180_CAL_AC5)  # UINT16

        self.cal_AC6 = self._read_u16(BMP180_CAL_AC6)  # UINT16

        self.cal_B1  = self._read_s16(BMP180_CAL_B1)    # INT16

        self.cal_B2  = self._read_s16(BMP180_CAL_B2)    # INT16

        self.cal_MB  = self._read_s16(BMP180_CAL_MB)    # INT16

        self.cal_MC  = self._read_s16(BMP180_CAL_MC)    # INT16

        self.cal_MD  = self._read_s16(BMP180_CAL_MD)    # INT16

    def read_raw_temp(self):

        """Reads the raw (uncompensated) temperature from the sensor."""

        self._write_byte(BMP180_CONTROL, BMP180_READTEMPCMD)

        time.sleep(0.005)  # Wait 5ms

        MSB = self._read_byte(BMP180_TEMPDATA)

        LSB = self._read_byte(BMP180_TEMPDATA+1)

        raw = (MSB << 8) + LSB

        return raw

    def read_raw_pressure(self):

        """Reads the raw (uncompensated) pressure level from the sensor."""

        self._write_byte(BMP180_CONTROL, BMP180_READPRESSURECMD + (self._mode << 6))

        if self._mode == BMP180_ULTRALOWPOWER:

            time.sleep(0.005)

        elif self._mode == BMP180_HIGHRES:

            time.sleep(0.014)

        elif self._mode == BMP180_ULTRAHIGHRES:

            time.sleep(0.026)

        else:

            time.sleep(0.008)

        MSB = self._read_byte(BMP180_PRESSUREDATA)

        LSB = self._read_byte(BMP180_PRESSUREDATA+1)

        XLSB = self._read_byte(BMP180_PRESSUREDATA+2)

        raw = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - self._mode)

        return raw

    def read_temperature(self):

        """Gets the compensated temperature in degrees celsius."""

        UT = self.read_raw_temp()

        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

        return temp

    def read_pressure(self):

        """Gets the compensated pressure in Pascals."""

        UT = self.read_raw_temp()

        UP = self.read_raw_pressure()

        X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15

        X2 = (self.cal_MC << 11) / (X1 + self.cal_MD)

        B5 = X1 + X2

        # 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

        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 B7 < 0x80000000:

            p = (B7 * 2) / B4

        else:

            p = (B7 / B4) * 2

        X1 = (p >> 8) * (p >> 8)

        X1 = (X1 * 3038) >> 16

        X2 = (-7357 * p) >> 16

        p = p + ((X1 + X2 + 3791) >> 4)

        return p

    def read_altitude(self, sealevel_pa=101325.0):

        """Calculates the altitude in meters."""

        # Calculation taken straight from section 3.6 of the datasheet.

        pressure = float(self.read_pressure())

        altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0/5.255)))

        return altitude

    def read_sealevel_pressure(self, altitude_m=0.0):

        """Calculates the pressure at sealevel when given a known altitude in

        meters. Returns a value in Pascals."""

        pressure = float(self.read_pressure())

        p0 = pressure / pow(1.0 - altitude_m/44330.0, 5.255)

        return p0

然后编写调用函数bmp180_example.py:

#!/usr/bin/python

import time

from BMP180 import BMP180

# Initialise the BMP085 and use STANDARD mode (default value)

# bmp = BMP085(0x77, debug=True)

bmp = BMP180()

# To specify a different operating mode, uncomment one of the following:

# bmp = BMP085(0x77, 0)  # ULTRALOWPOWER Mode

# bmp = BMP085(0x77, 1)  # STANDARD Mode

# bmp = BMP085(0x77, 2)  # HIRES Mode

# bmp = BMP085(0x77, 3)  # ULTRAHIRES Mode

while True:

    temp = bmp.read_temperature()

# Read the current barometric pressure level

    pressure = bmp.read_pressure()

# To calculate altitude based on an estimated mean sea level pressure

# (1013.25 hPa) call the function as follows, but this won't be very accurate

    altitude = bmp.read_altitude()

# To specify a more accurate altitude, enter the correct mean sea level

# pressure level.  For example, if the current pressure level is 1023.50 hPa

# enter 102350 since we include two decimal places in the integer value

# altitude = bmp.readAltitude(102350)

    print "Temperature: %.2f C" % temp

    print "Pressure:    %.2f hPa" % (pressure / 100.0)

    #print "Altitude:    %.2f\n" % altitude

    time.sleep(1)

执行./bmp180_example.py就可以在终端看到实时的温度/气压输出。

你可能感兴趣的:(树莓派连接BMP180气压传感器)