正規のオンライン小売業者:

AMAZON
AMAZON
amzuk

紹介

この記事では、Raspberry Piを使用してBMP180デジタル圧力センサからデータを読み取る方法を紹介します。

ソフトウェアの準備
1 * Raspberry Pi
1 * BMP180デジタル圧力センサ
1 * ブレッドボード
数本のジャンパーワイヤー

ソフトウェアの準備
注:このレッスンでは、パソコンのPuTTyを介してRaspberry Piをリモート制御します。Raspberry Piの設定方法については、lesson 1: getting started with raspberry piをご覧ください。

実験原理

BMP180デジタル圧力センサは、圧力、温度、高度を検出できます。Raspberry Piを使用して、II2インターフェースを介してBMP180センサからこれらのデータを入力し、値を端末ウィンドウに表示します。

回路図

注:Raspberry PiのGPIOについて詳しく学ぶには、lesson 2: Introduction Of Raspberry Pi GPIOを参照してください。

ハードウェアセットアップ
回路を組み立てるには、以下の接続図に従って接続してください。

ソフトウェア

I2Cインターフェースを使用するには、まずI2Cを有効にする必要があります。次のコマンドを入力してください。

sudo  nano  /boot/config.txt

/boot/config.txtファイルを開き、「dtparam = i2c_arm」というコード行を見つけ、その行の前に#記号があるかどうかを確認し、その#を取り除いてコメントを解除します。そして、行の最後が「on」になっていることを確認してください。最終的に、コードは以下のようになります。


Ctrl+Xを押して、修正したファイルを保存するには “Y”とタイプします。Piを再起動してください。
C言語ユーザーとPython言語ユーザーのために、2種類のコードを提供します。

C言語ユーザーの場合は、次の手順に従ってください。


wiringpiのインストールが必要です。wiringPiをインストールしていない場合は、lesson 3: installation wiringpiを読んでください。

Step 1) コードをダウンロードして解凍します。

cd ~
wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_18/bmp180-c.tar.gz
sudo   tar  zxvf   bmp180-c.tar.gz

Step 2) パスを変更します。

cd   bmp180-c

Step 3) コードをコンパイルします。

sudo gcc -Wall -o bmp180 bmp180test.c -lwiringPi -lm

Step 4) プログラムを実行します。

sudo  ./bmp180
Program result
プログラムが実行されると、ターミナルにはBMP180センサーが検出した圧力、温度、高度が表示されます。

bmp180.h and bmp180test.c Code

#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
#include < wiringPi.h>
#include < wiringPiI2C.h>
#include < stdio.h>
#include < math.h>
#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;

Pythonユーザーの場合は


Pythonについて詳しくは、Raspberry Pi Starter Kit lesson 4にアクセスしてください。

1) IICと通信するためのpythonツールソフトウェア(smbus)をインストールしてください。

cd  ~

sudo apt-get install python-smbus

2) コードをダウンロードして解凍します。

cd  ~

wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_18/bmp180-python.tar.gz

sudo  tar zxvf  bmp180-python.tar.gz

3) パスを変更します。

cd  bmp180-python

4) プログラムを実行します。

sudo  python  ./BMP180test.py

5)プログラムの結果

プログラムが実行されると、ターミナルにはBMP180センサーが検出した圧力、温度、高度が表示されます。

BMP180.py, BMP180.pyc and BMP180test.py code

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
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)