概述
在这一课中我们将学习如何用Raspberry Pi读取BMP180数字气压传感器。
所需器件
1 * Raspberry Pi
1 * Breadboard
1 * BMP180
Several jumper wires
工作原理
BMP180能够检测气压和温度,BMP180通过IIC接口输出数据,我们用Pi的IIC去读取BMP180测量到的气压值和温度值并输出在屏幕上。
原理图如下

实物连线图
没画
软件
在进行下面的步骤之前先打开Pi的IIC接口,具体操作请看lesson13,如果已经打开请跳过此步。
For C Language users, please follow the next step:
1) 在/home/pi目录下新建一个.h头文件,名字随意(你开心就好)
cd ~
sudo nano bmp180.h
先向头文件中添加一下代码
#ifndef _BMP180_ #define _BMP180_ //i2c address #define BMP180_Address 0x77 //Operating Modes #define BMP180_ULTRALOWPOWER 0 #define BMP180_STANDARD 1 #define BMP180_HIGHRES 2 #define BMP180_ULTRAHIGHRES 3 //BMP185 Registers #define BMP180_CAL_AC1 0xAA //Calibration data (16 bits) #define BMP180_CAL_AC2 0xAC //Calibration data (16 bits) #define BMP180_CAL_AC3 0xAE //Calibration data (16 bits) #define BMP180_CAL_AC4 0xB0 //Calibration data (16 bits) #define BMP180_CAL_AC5 0xB2 //Calibration data (16 bits) #define BMP180_CAL_AC6 0xB4 //Calibration data (16 bits) #define BMP180_CAL_B1 0xB6 //Calibration data (16 bits) #define BMP180_CAL_B2 0xB8 //Calibration data (16 bits) #define BMP180_CAL_MB 0xBA //Calibration data (16 bits) #define BMP180_CAL_MC 0xBC //Calibration data (16 bits) #define BMP180_CAL_MD 0xBE //Calibration data (16 bits) #define BMP180_CONTROL 0xF4 #define BMP180_TEMPDATA 0xF6 #define BMP180_PRESSUREDATA 0xF6 //Commands #define BMP180_READTEMPCMD 0x2E #define BMP180_READPRESSURECMD 0x34 #endif
在键盘上输入Ctrl+X,在输入Y保存退出。
1) 在/home/pi目录下新建一个.c源文件,名字随意(你开心就好)
cd ~
sudo nano bmp180test.c
向新建的源文件中添加一下代码
#include
#include
#include
#include
#include "bmp180.h"
#define OSS BMP180_STANDARD
short AC1,AC2,AC3,B1,B2,MB,MC,MD;
unsigned short AC4,AC5,AC6;
int fd;
char I2C_readByte(int reg)
{
return (char)wiringPiI2CReadReg8(fd,reg);
}
unsigned short I2C_readU16(int reg)
{
int MSB,LSB;
MSB = I2C_readByte(reg);
LSB = I2C_readByte(reg + 1);
int value = (MSB << 8) +LSB; return (unsigned short)value; } short I2C_readS16(int reg) { int result; result = I2C_readU16(reg); if (result > 32767)result -= 65536;
return (short)result;
}
void I2C_writeByte(int reg,int val)
{
wiringPiI2CWriteReg8(fd,reg,val);
}
void load_calibration()
{
AC1 = I2C_readS16(BMP180_CAL_AC1);
AC2 = I2C_readS16(BMP180_CAL_AC2);
AC3 = I2C_readS16(BMP180_CAL_AC3);
AC4 = I2C_readU16(BMP180_CAL_AC4);
AC5 = I2C_readU16(BMP180_CAL_AC5);
AC6 = I2C_readU16(BMP180_CAL_AC6);
B1 = I2C_readS16(BMP180_CAL_B1);
B2 = I2C_readS16(BMP180_CAL_B2);
MB = I2C_readS16(BMP180_CAL_MB);
MC = I2C_readS16(BMP180_CAL_MC);
MD = I2C_readS16(BMP180_CAL_MD);
}
int read_raw_temp()
{
int raw;
I2C_writeByte(BMP180_CONTROL,BMP180_READTEMPCMD);
delay(5); //5ms;
raw = I2C_readByte(BMP180_TEMPDATA) << 8;
raw += I2C_readByte(BMP180_TEMPDATA+1);
return raw;
}
int read_raw_pressure()
{
int MSB,LSB,XLSB,raw;
I2C_writeByte(BMP180_CONTROL,BMP180_READPRESSURECMD +(OSS << 6));
switch(OSS)
{
case BMP180_ULTRALOWPOWER:
delay(5);break;
case BMP180_HIGHRES:
delay(14);break;
case BMP180_ULTRAHIGHRES:
delay(26);break;
default :
delay(8);
}
MSB = I2C_readByte(BMP180_PRESSUREDATA);
LSB = I2C_readByte(BMP180_PRESSUREDATA + 1);
XLSB = I2C_readByte(BMP180_PRESSUREDATA + 2);
raw = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - OSS);
return raw;
}
float read_temperature()
{
float T;
int UT,X1,X2,B5;
UT = read_raw_temp();
X1 = ((UT - AC6)*AC5) >> 15;
X2 = (MC << 11) / (X1 + MD); B5 = X1 + X2; T = ((B5 + 8) >> 4) /10.0;
return T;
}
int read_pressure()
{
int P;
int UT,UP,X1,X2,X3,B3,B5,B6;
unsigned int B4;
int B7;
UT = read_raw_temp();
UP = read_raw_pressure();
X1 = ((UT - AC6)*AC5) >> 15;
X2 = (MC << 11) / (X1 + MD); B5 = X1 + X2; //Pressure Calculations B6 = B5 - 4000; X1 = (B2 * (B6 * B6) >> 12) >> 11;
X2 = (AC2 * B6) >> 11;
X3 = X1 + X2;
B3 = (((AC1 * 4 + X3) << OSS) + 2) / 4; X1 = (AC3 * B6) >> 13;
X2 = (B1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = (AC4 * (X3 + 32768)) >> 15;
B7 = (UP - B3) * (50000 >> OSS);
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;
P = P + ((X1 + X2 + 3791) >> 4);
return P;
}
float read_altitude()
{
float pressure,altitude;
float sealevel_pa = 101325.0;
pressure = (float)read_pressure();
altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa,(1.0/5.255)));
return altitude;
}
float read_sealevel_pressure()
{
float altitude_m = 0.0;
float pressure,p0;
pressure =(float)read_pressure();
p0 = pressure / pow(1.0 - altitude_m/44330.0,5.255);
return p0;
}
int main(int argc,char **argv)
{
printf("BMP180 Test Program ...\n");
if(wiringPiSetup() < 0) return 1;
fd = wiringPiI2CSetup(BMP180_Address);
load_calibration();
while(1)
{
printf("\nTemperature : %.2f C\n",read_temperature());
printf("Pressure : %.2f Pa\n",read_pressure()/100.0);
printf("Altitude : %.2f h\n",read_altitude());
delay(1000);
}
return 0;
}
在键盘上输入Ctrl+X,在输入Y保存退出。
完整的程序源码可以通过下面命令获取
wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_18\c
2) 编译
sudo gcc -Wall -o bmp180 bmp180test.c -lwiringPi -lm
3) 运行程序
sudo ./bmp180
4) 最终结果
运行上面的程序,屏幕上会输出BMP180测量到的温度值,气压值以及海拔高度。
for python users
1)我们需要安装一个工具软件(smbus)与IIC通讯
sudo apt-get install python-smbus
2) 在/home/pi下新建一个.py脚本文件,文件名随意(你爱咋咋地)
cd ~
sudo nano BMP180.py
先新建的脚本文件中添加以下代码
import time
import smbus
# BMP085 default address.
BMP180_I2CADDR = 0x77
# Operating Modes
BMP180_ULTRALOWPOWER = 0
BMP180_STANDARD = 1
BMP180_HIGHRES = 2
BMP180_ULTRAHIGHRES = 3
# BMP085 Registers
BMP180_CAL_AC1 = 0xAA # R Calibration data (16 bits)
BMP180_CAL_AC2 = 0xAC # R Calibration data (16 bits)
BMP180_CAL_AC3 = 0xAE # R Calibration data (16 bits)
BMP180_CAL_AC4 = 0xB0 # R Calibration data (16 bits)
BMP180_CAL_AC5 = 0xB2 # R Calibration data (16 bits)
BMP180_CAL_AC6 = 0xB4 # R Calibration data (16 bits)
BMP180_CAL_B1 = 0xB6 # R Calibration data (16 bits)
BMP180_CAL_B2 = 0xB8 # R Calibration data (16 bits)
BMP180_CAL_MB = 0xBA # R Calibration data (16 bits)
BMP180_CAL_MC = 0xBC # R Calibration data (16 bits)
BMP180_CAL_MD = 0xBE # R Calibration data (16 bits)
BMP180_CONTROL = 0xF4
BMP180_TEMPDATA = 0xF6
BMP180_PRESSUREDATA = 0xF6
# Commands
BMP180_READTEMPCMD = 0x2E
BMP180_READPRESSURECMD = 0x34
class BMP180(object):
def __init__(self, address=BMP180_I2CADDR, mode=BMP180_STANDARD):
self._mode = mode
self._address = address
self._bus = smbus.SMBus(1)
# Load calibration values.
self._load_calibration()
def _read_byte(self,cmd):
return self._bus.read_byte_data(self._address,cmd)
def _read_u16(self,cmd):
MSB = self._bus.read_byte_data(self._address,cmd)
LSB = self._bus.read_byte_data(self._address,cmd+1)
return (MSB << 8) + LSB def _read_s16(self,cmd): result = self._read_u16(cmd) if result > 32767:result -= 65536
return result
def _write_byte(self,cmd,val):
self._bus.write_byte_data(self._address,cmd,val)
def _load_calibration(self):
"load calibration"
self.cal_AC1 = self._read_s16(BMP180_CAL_AC1) # INT16
self.cal_AC2 = self._read_s16(BMP180_CAL_AC2) # INT16
self.cal_AC3 = self._read_s16(BMP180_CAL_AC3) # INT16
self.cal_AC4 = self._read_u16(BMP180_CAL_AC4) # UINT16
self.cal_AC5 = self._read_u16(BMP180_CAL_AC5) # UINT16
self.cal_AC6 = self._read_u16(BMP180_CAL_AC6) # UINT16
self.cal_B1 = self._read_s16(BMP180_CAL_B1) # INT16
self.cal_B2 = self._read_s16(BMP180_CAL_B2) # INT16
self.cal_MB = self._read_s16(BMP180_CAL_MB) # INT16
self.cal_MC = self._read_s16(BMP180_CAL_MC) # INT16
self.cal_MD = self._read_s16(BMP180_CAL_MD) # INT16
def read_raw_temp(self):
"""Reads the raw (uncompensated) temperature from the sensor."""
self._write_byte(BMP180_CONTROL, BMP180_READTEMPCMD)
time.sleep(0.005) # Wait 5ms
MSB = self._read_byte(BMP180_TEMPDATA)
LSB = self._read_byte(BMP180_TEMPDATA+1)
raw = (MSB << 8) + LSB
return raw
def read_raw_pressure(self):
"""Reads the raw (uncompensated) pressure level from the sensor."""
self._write_byte(BMP180_CONTROL, BMP180_READPRESSURECMD + (self._mode << 6))
if self._mode == BMP180_ULTRALOWPOWER:
time.sleep(0.005)
elif self._mode == BMP180_HIGHRES:
time.sleep(0.014)
elif self._mode == BMP180_ULTRAHIGHRES:
time.sleep(0.026)
else:
time.sleep(0.008)
MSB = self._read_byte(BMP180_PRESSUREDATA)
LSB = self._read_byte(BMP180_PRESSUREDATA+1)
XLSB = self._read_byte(BMP180_PRESSUREDATA+2)
raw = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - self._mode)
return raw
def read_temperature(self):
"""Gets the compensated temperature in degrees celsius."""
UT = self.read_raw_temp()
X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
X2 = (self.cal_MC << 11) / (X1 + self.cal_MD) B5 = X1 + X2 temp = ((B5 + 8) >> 4) / 10.0
return temp
def read_pressure(self):
"""Gets the compensated pressure in Pascals."""
UT = self.read_raw_temp()
UP = self.read_raw_pressure()
X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
X2 = (self.cal_MC << 11) / (X1 + self.cal_MD) B5 = X1 + X2 # Pressure Calculations B6 = B5 - 4000 X1 = (self.cal_B2 * (B6 * B6) >> 12) >> 11
X2 = (self.cal_AC2 * B6) >> 11
X3 = X1 + X2
B3 = (((self.cal_AC1 * 4 + X3) << self._mode) + 2) / 4 X1 = (self.cal_AC3 * B6) >> 13
X2 = (self.cal_B1 * ((B6 * B6) >> 12)) >> 16
X3 = ((X1 + X2) + 2) >> 2
B4 = (self.cal_AC4 * (X3 + 32768)) >> 15
B7 = (UP - B3) * (50000 >> self._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
p = p + ((X1 + X2 + 3791) >> 4)
return p
def read_altitude(self, sealevel_pa=101325.0):
"""Calculates the altitude in meters."""
# Calculation taken straight from section 3.6 of the datasheet.
pressure = float(self.read_pressure())
altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0/5.255)))
return altitude
def read_sealevel_pressure(self, altitude_m=0.0):
"""Calculates the pressure at sealevel when given a known altitude in
meters. Returns a value in Pascals."""
pressure = float(self.read_pressure())
p0 = pressure / pow(1.0 - altitude_m/44330.0, 5.255)
return p0
按键盘上Ctrl+X,再按Y保存退出。
在/home/pi下再新建一个.py脚本文件,文件名随意(你爱咋咋地)
cd ~
sudo nano BMP180test.py
向这个脚本文件中添加以下代码
import time
from BMP180 import BMP180
# Initialise the BMP085 and use STANDARD mode (default value)
# bmp = BMP085(0x77, debug=True)
bmp = BMP180()
# To specify a different operating mode, uncomment one of the following:
# bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode
# bmp = BMP085(0x77, 1) # STANDARD Mode
# bmp = BMP085(0x77, 2) # HIRES Mode
# bmp = BMP085(0x77, 3) # ULTRAHIRES Mode
while True:
temp = bmp.read_temperature()
# Read the current barometric pressure level
pressure = bmp.read_pressure()
# To calculate altitude based on an estimated mean sea level pressure
# (1013.25 hPa) call the function as follows, but this won't be very accurate
altitude = bmp.read_altitude()
# To specify a more accurate altitude, enter the correct mean sea level
# pressure level. For example, if the current pressure level is 1023.50 hPa
# enter 102350 since we include two decimal places in the integer value
# altitude = bmp.readAltitude(102350)
print "Temperature: %.2f C" % temp
print "Pressure: %.2f hPa" % (pressure / 100.0)
print "Altitude: %.2f\n" % altitude
time.sleep(2)
按键盘上Ctrl+X,再按Y保存退出。
完整代码可以下面命令获取到
wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_18/python
3) 运行你的脚本程序
sudo python BMP180test.py
4) 最终结果
运行上面Python脚本程序,屏幕上会输出BMP180测量到的温度值、气压值以及海拔高度。
DownLoad Url osoyoo.com