树莓派连接BMP085数字压力传感器

  • 内容
  • ....
  • 相关

我最近买了一块基于BMP085数字压力传感器的模块(GY-65),所以应该写一篇关于如何从树莓派中读取BMP085传感器数据的文章,树莓派读取BMP085的数据是通过SMbus总线来完成的。SMBus(System Management Bus)是I2C协议的一个子集。

GY-65-BMP085气压测量模块

GY65的价格参考

BMP085气压传感器

GY65与树莓派的连接可参考下图

GY65连接树莓派的接口定义

Python代码

下面是简单的测试代码,代码首先对BMP085气压传感器进行初始化,然后通过不断地循环来读取温度和气压数据。下面是具体的Python代码:

#!/usr/bin/python
import smbus
import time

bus = smbus.SMBus(0) # 如果树莓派版本是2.0,那么“ bus = smbus.SMBus(1) ”  
address = 0x77

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((0xffff - val) + 1)
    else:
        return val

def write_byte(adr, value):
    bus.write_byte_data(address, adr, value)

def twos_compliment(val):
    if (val >= 0x8000):
        return -((0xffff - val) + 1)
    else:
        return val

def get_word(array, index, twos):
    val = (array[index] << 8) + array[index+1]
    if twos:
        return twos_compliment(val)
    else:
        return val

def calculate():
    # 这段代码来源于 datasheet,并做了一些优化.    
    # 计算温度
    x1 = ((temp_raw - ac6) * ac5) / 32768
    x2 = (mc * 2048) / (x1 + md)
    b5 = x1 + x2
    t = (b5 + 8) / 16    
    # 计算压强
    b6 = b5 - 4000 
    x1 = (b2 * (b6 * b6 >> 12)) >> 11
    x2 = ac2 * b6 >> 11
    x3 = x1 + x2
    b3 = (((ac1 * 4 + x3) << oss) + 2) >> 2     
    x1 = (ac3 * b6) >> 13 
    x2 = (b1 * (b6 * b6 >> 12)) >> 16 
    x3 = ((x1 + x2) + 2) >> 2 
    b4 = ac4 * (x3 + 32768) >> 15 
    b7 = (pressure_raw - b3) * (50000 >> oss)
    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(t,p)
calibration = bus.read_i2c_block_data(address, 0xAA, 22)
oss = 3              # 超高分辨率
temp_wait_period = 0.004
pressure_wait_period = 0.0255 # 转换时间
# 传感器有一个出厂设置校准值需要读取
# 然后使用这些方法来获得温度和压强
ac1 = get_word(calibration, 0, True)
ac2 = get_word(calibration, 2, True)
ac3 = get_word(calibration, 4, True)
ac4 = get_word(calibration, 6, False)
ac5 = get_word(calibration, 8, False)
ac6 = get_word(calibration, 10, False)
b1 =  get_word(calibration, 12, True)
b2 =  get_word(calibration, 14, True)
mb =  get_word(calibration, 16, True)
mc =  get_word(calibration, 18, True)
md =  get_word(calibration, 20, True)

while True:
    # 原始温度值
    write_byte(0xF4, 0x2E)          # 告诉传感器测量温度
    time.sleep(temp_wait_period)    # 等待转换
    temp_raw = read_word_2c(0xF6)

    write_byte(0xF4, 0x34 + (oss << 6)) # 告诉传感器测量压强
    time.sleep(pressure_wait_period)    # 等待转换
    pressure_raw = ((read_byte(0xF6) << 16) \
                     + (read_byte(0xF7) << 8) \
                     + (read_byte(0xF8)) ) >> (8-oss)
    temperature, pressure = calculate()
    print time.time(), temperature / 10., pressure / 100.
    time.sleep(1)

要想从传感器中读取数据,首先必须读取出厂设置的校准值:

	ac1 = get_word(calibration, 0, True)
	ac2 = get_word(calibration, 2, True)
	ac3 = get_word(calibration, 4, True)
	ac4 = get_word(calibration, 6, False)
	ac5 = get_word(calibration, 8, False)
	ac6 = get_word(calibration, 10, False)
	b1 =  get_word(calibration, 12, True)
	b2 =  get_word(calibration, 14, True)
	mb =  get_word(calibration, 16, True)
	mc =  get_word(calibration, 18, True)
	md =  get_word(calibration, 20, True)

这对于每个设备来说会有差异,这些值用于计算实际的温度和压力。calculate() 函数只是对BMP085 datasheet中示例代码的直接引用,我也并不明白它的实际含义,但这段代码可以提供我们测试所需的值。

传感器测试

为了测试代码正常,将上面的代码保存到一个名为“read-pressure.py”的文件中,运行并将输出重新定向到文件,

sudo ./read-pressure.py > pressure-test.dat

然后,我慢慢地在家里走来走去,得到了一些数据,然后用gnuplot来呈现数据,

set terminal wxt persist size 800,800 background '#000000' 
  set style line 99 linecolor rgb "#ffffff" linetype 0 linewidth 2
  set key top right textcolor linestyle 99 
  set grid linestyle 99
  set border linestyle 99

  set yrange  [16.4:17.2]
  set y2range [1003.5:1005]
  set y2tics

  plot filename using 1:2 axes x1y1 title "True temp" w l ,\
       filename using 1:3 axes x1y2 title "True pressure" w l, \
       filename using 1:3 axes x1y2 title "Smoothed" smooth bezier

下面是生成数据图像的命令

gnuplot -e "filename='pressure-test.dat'" gnuplot-pressure.plg

当我爬上楼梯,然后又下来的时候,可以看到气压在下降。同时可以看到温度也随之上升,好奇怪的现象,也许只是我手上的热量导致了温度升高。

bmp085气压变化图gnuplot

BMP085海拔计算公式

计算海拔(地面高度),公式是从BMP085的datasheet中得到的。
bmp085海拔计算公式