Raspberry Pi : Barometric Pressure Sensor or Security System?

A couple months ago I was chatting with a coworker (Chad Wells who blogs here) about Raspberry Pi. He speculated that, given a sufficiently sensitive barometric pressure sensor, you should be able to detect the change in air pressure in a house that results from opening a door.

Intrigued, I bought a barometric sensor (this one here which has since been replaced with the more modern one here), and last night, finally got around to wiring it up!

Wiring

The BPM085 sensor uses the I2C protocol for communicating with the Raspberry Pi. I2C is a protocol for attaching sensors / other devices to an embedded system on a bus. You can chain multiple sensors / other devices together and refer them by their bus number.

The BPM085 requires 3.3v, ground, and the two I2C pins (marked SDA and SCL). 

I am using a Raspberry Pi B+ in this blog. The I2C wiring is different for each version of Raspberrry Pi (including the 256 MB and 512 MB B variants), so you should consult the appropriate pin layout diagrams for your model of Pi. (I used this one for the B+.)

Here are pictures of my breadboard and Raspberry Pi wiring.

Breadboard

Raspberry Pi

Raspberry Pi closeup

(Note: I have started using the C4 Labs Black Ice cases for my all my Raspberry Pi needs. Hands down the best cases for a Raspberry Pi in existence, bar none. Perfect fit, sturdy construction, beautiful aesthetics... Comes in black, or wood grain, or some other colors. It is the only case you will ever need ever again, I promise!)

The wiring is the simple part! Once that is down you need to enable support for I2C in the Raspberry Pi kernel.

Kernal Support

You must enable Kernal Support for I2C in order to use your newly wired sensor.

You can attempt to do this from the Raspberry Pi Config tool.

sudo raspi-config  

Then Advanced Options -> I2C and follow the prompts. Reboot your Raspberry Pi, and then run this command to see if I2C is configured properly:

sudo i2cdetect -y 1  

(Note: If you are running a Raspberry Pi B 256 Model, use 0 instead of 1).

You should get no error messages and see a grid printed out to the console presenting the attached devices.

However, I found when I did this, even on a Raspberry Pi B+ with fully updated firmware, that I2C was not correctly enabled. (Dagger!)

I had to go through the following manual steps to setup and verify that I2C support was enabled correctly in the kernel.

To start, edit your modules file:

sudo nano /etc/modules  

At the bottom of this file, add the following lines if they are not already present:

i2c-bcm2708  
i2c-dev  

Then, if there is a /etc/modprobe.d/raspi-blacklist.conf file, edit it:

sudo nano /etc/modprobe.d/raspi-blacklist.conf  

And verify that, if the following lines are present, they are commented out:

#blacklist spi-bcm2708
#blacklist i2c-bcm2708

Then, edit your boot config:

sudo nano /boot/config.txt  

At the bottom of this file, add the following lines if they are not already present:

dtparam=i2c1=on  
dtparam=i2c_arm=on  

Now, reboot your Pi:

sudo reboot  

Now run the test command to test if I2C is configured properly:

sudo i2cdetect -y 1  

(Note: Again, if you are running a Raspberry Pi B 256 Model, use 0 instead of 1).

Software

AdaFruit maintains a drivers and sample code for many sensors in the Arduino, Raspberry Pi, Beagle Bone, etc. community. I used their Python BPM085 driver as a starting point for my "door opened" detector.

Installation is simple:

sudo apt-get install git build-essential python-dev python-smbus  
git clone https://github.com/adafruit/Adafruit_Python_BMP.git  
cd Adafruit_Python_BMP  
sudo python setup.py install  

After the setup is complete, you can test that the driver is working by running their example program:

cd examples  
sudo python simpletest.py  

Door Detector

So, the basic idea behind my "door opened" script was to first establish a "baseline" pressure in the house by sampling the pressure repeatedly to form an average pressure. Once the baseline was established, the house's pressure could be sampled many times a second to try to detect a spike in pressure corresponding to a door opening (or a window breaking.)

Note: You can download the entire script here.

We'll take the script line by line:

#!/usr/bin/python

import sys  
import time  
import Adafruit_BMP.BMP085 as BMP085

# Parameters are:
#   busnum (i2c bus number, defaults to 1)
#   mode (BMP085_ULTRALOWPOWER, BMP085_STANDARD, BMP085_HIGHRES, or BMP085_ULTRAHIGHRES, defaults to BMP085_STANDARD). See the data sheet.
#
#sensor = BMP085.BMP085()
sensor = BMP085.BMP085(mode=BMP085.BMP085_ULTRAHIGHRES)  

Here I am doing all the necessary imports and configuring the AdaFruit driver. (The datasheet can be found here.) I opted for Ultra High Res since power is not a concern (my Raspberry Pi is plugged in) and I wanted to most accurate and sensitive reading I could get.

try:  
  sys.stdout.write('Establishing a baseline.')
  sys.stdout.flush()
  baseline_points=[];
  for x in range(0, 100):
    time.sleep(.1)
    baseline_points.append(sensor.read_pressure())
    if x % 10 == 0:
      sys.stdout.write('.')
      sys.stdout.flush()

  tolerance=8

Originally I just sampled the pressure at the start of the program and used that average for the rest of the run, but then I realized that environmental factors (AC, outside temperature, time of day, etc.) might have subtle effects on the air pressure in the house. 

So I changed the program to use a rolling average. I created a fixed size queue of the last 100 pressure readings and used those to compute the baseline average. So if the air pressure in the house does change gradually, the program will adapt.

  while 1:
    time.sleep(.1)
    reading = sensor.read_pressure()

    baseline_points.pop(0);
    baseline_points.append(reading);

    baseline = 0;
    for x in baseline_points:
      baseline += x
    baseline /= len(baseline_points)
    print('Baseline: %s' % baseline)

    if abs(reading - baseline) > tolerance:
      print reading
except KeyboardInterrupt:  
  print "\nStopped."

Here, I now loop and every 1/10 second, take a pressure reading, update and calculate the rolling average, and then test to see if the pressure reading is sufficiently different from the baseline to report an alert.

Results

And so, with all that work, the question is, did it work? 

Yes and no.

This setup could detect local changes in pressure (a puff of air, the door opening if it was really close, the AC coming on, etc.)

However, noise was a big problem. The sensor would occasionally read too high (or too low) and trigger a false alarm making it hard to distinguish noise from real events.

I found a tolerance of 8 to work well. 10 cuts down on the noise, but makes the actual events (door opening) harder to detect. (So instead of a "door opened" sensor, it becomes more of a "door breached" sensor...)

Still, a very fun and interesting experiment! With more sensitive equipment (and maybe other sensors...) it could get better results!

Thanks for reading!

Questions? Comments? Email me at: [email protected]