Notes About Working with Various Arduino & Netduino Microcontroller Boards

Thursday, May 28, 2015

Python Script for an Arduino Galileo to Read Barometric Pressure from an Adafruit BMP085 via I2C

This example shows how to read barometric pressure from an Adafruit BMP085 via I2C using a Python script on an Arduino Galileo (Gen. 1 running Clanton).

I want to rewrite this code in C, but using this Python script that I had on hand for another board helped me work through how to set the multiplexing for the Galileo's pins to get I2C working.  For information on the Galileo's GPIO pins and how to access them from outside of an Arduino sketch, see Sergey Kiselev's blog post.  I also found this post (and answer by rgb)  in an Intel discussion forum very helpful in getting this right.

Prerequisites 


The python-smbus package provides access to the I2C bus, so be sure that it is installed using opkg  before running this script.  You may also want to the i2c-tools package that provides the i2cdetect utility.  I installed these after configuring opkg as described in AlexT's Galileo and Edison Pages, so that configuration of opkg may be a requirement, too.

Connections

Galileo   BMP085
VIN       3.3V
GND       GND
SCL       SCL (or A5)
SDA       SDA (or A4)

Code 


Here is the Python code.  When copying from the code to this block, the tabs have been converted to a single space indentation.  This makes it a bit harder to see the indentation but won't offend the Python interpreter if the code is copied and pasted.

import time
import smbus

# Galileo i2c is on bus 0
bus = smbus.SMBus(0)
mode = 3
i2c_addr = 0x77 #Addr for bmp085

#=================================================================
# Fix port mux. Export gpio29 for access via sysfs.
# sysfsgpio29 controls the multiplexing of pins A4/A5 (and SCL/SDA pins)
with open("/sys/class/gpio/export","w") as fh:
 fh.write("29")
# Set gpio29 for output
with open("/sys/class/gpio/gpio29/direction","w") as fh:
 fh.write("out")
# Set value to 0 for i2c via the Quark chip
with open("/sys/class/gpio/gpio29/value","w") as fh:
 fh.write("0")
#=================================================================

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