Sunday, June 2, 2013

Reading Barometric Pressure with a Beaglebone Black & an Adafruit BMP085 Breakout Board

The Adafruit version of the BMP085 - BMP085 Barometric Pressure/Temperature/Altitude Sensor - is a barometer that connects to the Beaglebone Black via I2C.  The information on the Adafruit page says it is 5 volt ready, but it also works nicely with the 3.3 volt Beaglebone Black.

The example below shows how to read the barometric pressure (compensated for temperature and elevation above sea level). I've adapted this from the Adafruit library for the BMP085.


Connections


TMP085  Beaglebone Black
GND     P9 Pin 1
VIN     P9 Pin 3
SCL     P9 Pin 19
SDA     P9 Pin 20 


Python Code


import time
import smbus

bus = smbus.SMBus(1)
mode = 3
i2c_addr = 0x77

def read_word_signed(addr, reg):
msb = bus.read_byte_data(addr, reg)
if msb > 127: msb -= 256
lsb = bus.read_byte_data(addr, reg+1)
return (msb << 8) + lsb

def read_word_unsigned(addr, reg):
msb = bus.read_byte_data(addr, reg)
lsb = bus.read_byte_data(addr, reg+1)
return (msb << 8) + lsb

# Read factory programmed parameters
# These are used for calculations 
AC1 = read_word_signed(i2c_addr, 0xAA)
AC2 = read_word_signed(i2c_addr, 0xAC)
AC3 = read_word_signed(i2c_addr, 0xAE)
AC4 = read_word_unsigned(i2c_addr, 0xB0)
AC5 = read_word_unsigned(i2c_addr, 0xB2)
AC6 = read_word_unsigned(i2c_addr, 0xB4)
B1 = read_word_signed(i2c_addr, 0xB6)
B2 = read_word_signed(i2c_addr, 0xB8)
MB = read_word_signed(i2c_addr, 0xBA)
MC = read_word_signed(i2c_addr, 0xBC)
MD = read_word_signed(i2c_addr, 0xBE)

while True:
# read temperature cmd
bus.write_byte_data(i2c_addr, 0xF4, 0x2E) 
time.sleep(0.005)  # Wait 5ms
msb = bus.read_byte_data(i2c_addr, 0xF6)
lsb = bus.read_byte_data(i2c_addr, 0xF6+1)
raw_temp = (msb << 8) + lsb

X1 = ((raw_temp - AC6) * AC5) >> 15
X2 = (MC << 11) / (X1 + MD)
B5 = X1 + X2
# Read pressure cmd
bus.write_byte_data(i2c_addr, 0xF4, 0x34 + (1 << 6)) 
time.sleep(0.026)
msb = bus.read_byte_data(i2c_addr, 0xF6)
lsb = bus.read_byte_data(i2c_addr, 0xF6+1)
xlsb = bus.read_byte_data(i2c_addr, 0xF6+2)
raw_ps = ((msb << 16) + (lsb << 8) + xlsb) >> (8-mode)

B6 = B5 - 4000
X1 = (B2 * (B6 * B6) >> 12) >> 11
X2 = (AC2 * B6) >> 11
X3 = X1 + X2
B3 = (((AC1 * 4 + X3) << 3) + 2) / 4
X1 = (AC3 * B6) >> 13
X2 = (B1 * ((B6 * B6) >> 12)) >> 16
X3 = ((X1 + X2) + 2) >> 2
B4 = (AC4 * (X3 + 32768)) >> 15
B7 = (raw_ps - B3) * (50000 >> 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
# Pressure in Pascals
p = p + ((X1 + X2 + 3791) >> 4)
p = p * 0.000295333727 # Convert to inches Hg
# Adjust for elevation: Add 1200 Pa / 100 meters in elev.
# MPLS is 264m above sea level
# Converted to inches Hg this is 0.935
print p + 0.935 
time.sleep(10)


No comments:

Post a Comment