树莓派连接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接线图

将 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

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


图二 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就可以在终端看到实时的温度/气压输出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容