Tuesday, December 9, 2014

MPL3115A2 sensor with Raspberry Pi

Here is a short write up on using the MPL3115A2 with the Raspberry Pi.

The MPL3115A2 is a precision pressure and temperature sensor. I bought mine from SparkFun.
MPL3115A2:  https://www.sparkfun.com/products/11084

Installing I2C for Pi

Getting started you'll have to install the I2C packages for Raspberry Pi, and enable them.
From a Raspberry Pi terminal use the following commands:
sudo apt-get install python-smbus
sudo apt-get install i2c-tools

Enable the modules by adding them to /etc/modules
sudo nano /etc/modules
and add the following two lines:
i2c-bcm2708
i2c-dev

Remove the modules from the blacklist by commenting them out "add # to the front"
sudo nano /etc/modprobe.d/raspi-blacklist.conf
Make sure the spi and i2c lines are commented out:
#blacklist spi-bcm2708
#blacklist i2c-bcm2708

Lastly, the MPL3115A2 requires a proper repeated start command in it's I2C communication. Raspberry Pi doesn't do this out of the box, but there is a kernel module that can be enabled to make it perform repeated start correctly. Run the following commands to enable repeated start on the Pi:
sudo su -
echo -n 1 > /sys/module/i2c_bcm2708/parameters/combined
exit
More details about the repeated start problem can be found here:
http://www.raspberrypi.org/forums/viewtopic.php?f=44&t=15840&start=25

Connecting the Sensor

Next solder some headers to the breakout and connect it to the Raspberry Pi. You'll want to use the following Raspberry Pi GPIO pinout:
pinsensor
1VCC
3SDA
5SCL
6Ground


Python I2C Code

Finally, we need to write some code to read data from the sensor. The following is an example Python program to use smbus to read data from the sensor.

MPL3115A2.py
from smbus import SMBus
import time

# Special Chars
deg = u'\N{DEGREE SIGN}'

# I2C Constants
ADDR = 0x60
CTRL_REG1 = 0x26
PT_DATA_CFG = 0x13
bus = SMBus(1)

who_am_i = bus.read_byte_data(ADDR, 0x0C)
print hex(who_am_i)
if who_am_i != 0xc4:
    print "Device not active."
    exit(1)

# Set oversample rate to 128
setting = bus.read_byte_data(ADDR, CTRL_REG1)
newSetting = setting | 0x38
bus.write_byte_data(ADDR, CTRL_REG1, newSetting)

# Enable event flags
bus.write_byte_data(ADDR, PT_DATA_CFG, 0x07)

# Toggel One Shot
setting = bus.read_byte_data(ADDR, CTRL_REG1)
if (setting & 0x02) == 0:
    bus.write_byte_data(ADDR, CTRL_REG1, (setting | 0x02))

# Read sensor data
print "Waiting for data..."
status = bus.read_byte_data(ADDR,0x00)
while (status & 0x08) == 0:
    #print bin(status)
    status = bus.read_byte_data(ADDR,0x00)
    time.sleep(0.5)

print "Reading sensor data..."
p_data = bus.read_i2c_block_data(ADDR,0x01,3)
t_data = bus.read_i2c_block_data(ADDR,0x04,2)
status = bus.read_byte_data(ADDR,0x00)
print "status: "+bin(status)

p_msb = p_data[0]
p_csb = p_data[1]
p_lsb = p_data[2]
t_msb = t_data[0]
t_lsb = t_data[1]

pressure = (p_msb << 10) | (p_csb << 2) | (p_lsb >> 6)
p_decimal = ((p_lsb & 0x30) >> 4)/4.0

celsius = t_msb + (t_lsb >> 4)/16.0
fahrenheit = (celsius * 9)/5 + 32

print "Pressure and Temperature at "+time.strftime('%m/%d/%Y %H:%M:%S%z')
print str(pressure+p_decimal)+" Pa"
print str(celsius)+deg+"C"
print str(fahrenheit)+deg+"F"

Sample Output:
pi@raspberrypi ~ $ sudo python MPL3115A2.py
0xc4
Waiting for data...
Reading sensor data...
status: 0b0
Pressure and Temperature at 12/10/2014 04:51:56+0000
99838.75 Pa
20.375°C
68.675°F

More Resources

MPL3115A2 Datasheet:
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Pressure/MPL3115A2.pdf

Arduino code for reference:
https://github.com/sparkfun/MPL3115A2_Breakout/blob/master/firmware/MPL3115A2/MPL3115A2.ino