Barometric pressure sensor, Raspberry, Python and things in the works

After a few weeks of waiting, I’ve finally received two breakout boards with BMP085 barometric pressure sensors.

These little chips can run from as low as 1.8V to 3.6V, and measure atmospheric pressure within a 300-1100hPa range, as well as temperature within -40 – 85C range.
They provide a standard I2C interface, so connecting them to Raspberry Pi, Arduino, MSP430 Launchpad etc. is quite easy.
You can get these sensors from Sparkfun, Adafruit (~$20) or (like I did) from Dealextreme (~$8).

I’m planning to use them with MSP430 Launchpad to create a wireless environment monitor (together with an air humidity sensor).
On the photo above, you can also see a RFM23B transceiver (on the right, connected to R-Pi’s SPI port) – I’m in a process of writing a C library for it, compatible with both Linux and MSP430.
Raspberry will become a wireless data acquisition server 😉

Here’s a little quick’n’dirty Python script which reads, processes and displays current temperature and air pressure read from BMP085.
The temperature and pressure calculation code is based on the BMP085 Datasheet
Note, that because it talks with the hardware, it has to be executed as root…

#!/usr/bin/python

from smbus import SMBus
from time import sleep
from ctypes import c_short

addr = 0x77
oversampling = 3        # 0..3

bus = SMBus(0);         # 0 for R-Pi Rev. 1, 1 for Rev. 2

# return two bytes from data as a signed 16-bit value
def get_short(data, index):
        return c_short((data[index] << 8) + data[index + 1]).value

# return two bytes from data as an unsigned 16-bit value
def get_ushort(data, index):
        return (data[index] << 8) + data[index + 1]

(chip_id, version) = bus.read_i2c_block_data(addr, 0xD0, 2)
print "Chip Id:", chip_id, "Version:", version

print
print "Reading calibration data..."
# Read whole calibration EEPROM data
cal = bus.read_i2c_block_data(addr, 0xAA, 22)

# Convert byte data to word values
ac1 = get_short(cal, 0)
ac2 = get_short(cal, 2)
ac3 = get_short(cal, 4)
ac4 = get_ushort(cal, 6)
ac5 = get_ushort(cal, 8)
ac6 = get_ushort(cal, 10)
b1 = get_short(cal, 12)
b2 = get_short(cal, 14)
mb = get_short(cal, 16)
mc = get_short(cal, 18)
md = get_short(cal, 20)

print "Starting temperature conversion..."
bus.write_byte_data(addr, 0xF4, 0x2E)
sleep(0.005)
(msb, lsb) = bus.read_i2c_block_data(addr, 0xF6, 2)
ut = (msb << 8) + lsb

print "Starting pressure conversion..."
bus.write_byte_data(addr, 0xF4, 0x34 + (oversampling << 6))
sleep(0.04)
(msb, lsb, xsb) = bus.read_i2c_block_data(addr, 0xF6, 3)
up = ((msb << 16) + (lsb << 8) + xsb) >> (8 - oversampling)

print "Calculating temperature..."
x1 = ((ut - ac6) * ac5) >> 15
x2 = (mc << 11) / (x1 + md) b5 = x1 + x2 t = (b5 + 8) >> 4

print "Calculating pressure..."
b6 = b5 - 4000
b62 = b6 * b6 >> 12
x1 = (b2 * b62) >> 11
x2 = ac2 * b6 >> 11
x3 = x1 + x2
b3 = (((ac1 * 4 + x3) << oversampling) + 2) >> 2

x1 = ac3 * b6 >> 13
x2 = (b1 * b62) >> 16
x3 = ((x1 + x2) + 2) >> 2
b4 = (ac4 * (x3 + 32768)) >> 15
b7 = (up - b3) * (50000 >> oversampling)

p = (b7 * 2) / b4
#p = (b7 / b4) * 2

x1 = (p >> 8) * (p >> 8)
x1 = (x1 * 3038) >> 16
x2 = (-7357 * p) >> 16
p = p + ((x1 + x2 + 3791) >> 4)

print
print "Temperature:", t/10.0, "C"
print "Pressure:", p / 100.0, "hPa"

Script’s sample output:

root@raspi:~/bmp085# ./bmp_test.py
Chip Id: 85 Version: 2

Reading calibration data...
Starting temperature conversion...
Starting pressure conversion...
Calculating temperature...
Calculating pressure...

Temperature: 23.4 C
Pressure: 979.64 hPa

1 thought on “Barometric pressure sensor, Raspberry, Python and things in the works

  1. Petr

    Hi, thanks for great piece of python code! I use it to read barometric pressure from the sensor connected to my RasPi.
    But sometimes it returns bad value. I execute this code every 15 minutes and this is what I get:
    2013-07-24 05:15:02 0962.3
    2013-07-24 05:30:02 0962.1
    2013-07-24 05:45:02 1050.5
    2013-07-24 06:00:02 0962.2
    2013-07-24 06:15:02 0962.2
    I tried to change power from 3.3V to 5V and back with no change.
    One more hint – when I used Adafruits code, the error occurred much more often, but values were lower – for example 560 or 760.
    I would appreciate any help. Thanks, best regards, PetrN

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.