Raspberry Pi – BME280で温度、湿度、気圧を測定する。その2

2019年4月17日

その1では、販売終了されたセンサーを使用したので、今売っているセンサーを購入し実験してみました。

使用した機器

・Raspberry Pi 2
・秋月電子:BME280使用 温湿度・気圧センサモジュールキット

Pi で i2c を使えるようにする

# sudo raspi-config

配線

動作確認

このセンサーのアドレスは、0x76.

# sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

プログラムを実行して、変換値を得る。

PHPをインストールする。

sudo apt-get install php7.0 php7.0-php

以下のプログラムを実行して変換値を得る
: php BME280.php

<?php
 
// ---------------------------------------------------------------------------
//	2019/4/13 SABA
//
// 温度、湿度、大気圧センサをBME1280使用したBME1280使用した PHPプログラム
//
// ---------------------------------------------------------------------------
 
 
 
// ---------------------------------------------------------------------------
// hexdecは unsignd なので、signed 変換する関数群。
// 2の補数です。
// ---------------------------------------------------------------------------
 
// ---------------------------------------------------------------------------
// 8bit unsignd を signed にする、
// ---------------------------------------------------------------------------
function signed8hexdec($hex)
{
	$hex = str_replace('0x', '', $hex);
	$dec = hexdec($hex);
	if( $dec & 0x80 ) {
		$dec = (~($dec -1) & 0xFF) * -1;
	}
	return $dec;
}
 
// ---------------------------------------------------------------------------
// 12bit unsignd を signed にする、
// ---------------------------------------------------------------------------
function signed12hexdec($hex)
{
	$hex = str_replace('0x', '', $hex);
	$dec = hexdec($hex);
	if( $dec & 0x800 ) {
		$dec = (~($dec -1) & 0xFFF) * -1;
	}
	return $dec;
}
 
// ---------------------------------------------------------------------------
// 16bit unsignd を signed にする、
// ---------------------------------------------------------------------------
function signed16hexdec($hex)
{
	$hex = str_replace('0x', '', $hex);
	$dec = hexdec($hex);
	if( $dec & 0x8000 ) {
		$dec = (~($dec -1) & 0xFFFF) * -1;
	}
	return $dec;
}
 
// ---------------------------------------------------------------------------
function WriteRegister($Address, $Register, $Data)
{
	$str1 = 'i2cset -y 1 ' . $Address . ' ' . $Register . ' ' . $Data . ' b';
	exec($str1);
}
 
// ---------------------------------------------------------------------------
function ReadRegister($Address, $Register)
{
	$str1 = 'i2cget -y 1 ' . $Address . ' ' . $Register . ' b';
	$str1 = exec($str1);
	return $str1;
}
 
// ---------------------------------------------------------------------------
// ADCの補正
function BME280_GetCompensation(&$CompTemp, &$CompPress, &$CompHum)
{
	// -----------------------------------------------------------------------
	// 温度補正
	$str1 = ReadRegister(0x76, 0x88);
	$str2 = ReadRegister(0x76, 0x89);
	$str3 = str_replace('0x', '', $str2 . $str1);	// unsigned short
	$CompTemp[0] = hexdec($str3);
	
	$str1 = ReadRegister(0x76, 0x8A);
	$str2 = ReadRegister(0x76, 0x8B);
	$CompTemp[1] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x8C);
	$str2 = ReadRegister(0x76, 0x8D);
	$CompTemp[2] = signed16hexdec($str2 . $str1);
	
	// -----------------------------------------------------------------------
	// 気圧補正
	$str1 = ReadRegister(0x76, 0x8E);				// unsigned short
	$str2 = ReadRegister(0x76, 0x8F);
	$str3 = str_replace('0x', '', $str2 . $str1);
	$CompPress[0] = hexdec($str3);
	
	$str1 = ReadRegister(0x76, 0x90);
	$str2 = ReadRegister(0x76, 0x91);
	$CompPress[1] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x92);
	$str2 = ReadRegister(0x76, 0x93);
	$CompPress[2] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x94);
	$str2 = ReadRegister(0x76, 0x95);
	$CompPress[3] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x96);
	$str2 = ReadRegister(0x76, 0x97);
	$CompPress[4] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x98);
	$str2 = ReadRegister(0x76, 0x99);
	$CompPress[5] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x9A);
	$str2 = ReadRegister(0x76, 0x9B);
	$CompPress[6] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x9C);
	$str2 = ReadRegister(0x76, 0x9D);
	$CompPress[7] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0x9E);
	$str2 = ReadRegister(0x76, 0x9F);
	$CompPress[8] = signed16hexdec($str2 . $str1);
	
	// -----------------------------------------------------------------------
	// 湿度補正
	$str1 = ReadRegister(0x76, 0xA1);				// unsigned char
	$str3 = str_replace('0x', '', $str1);
	$CompHum[0] = hexdec($str3);
	
	$str1 = ReadRegister(0x76, 0xE1);
	$str2 = ReadRegister(0x76, 0xE2);
	$CompHum[1] = signed16hexdec($str2 . $str1);
	
	$str1 = ReadRegister(0x76, 0xE3);				// unsigned char
	$str3 = str_replace('0x', '', $str1);
	$CompHum[2] = hexdec($str3);
	
	$e5 = ReadRegister(0x76, 0xE5);
	
	$str1 = ReadRegister(0x76, 0xE4);
	$str3 = $str1 . substr($e5, 3, 1);
	$CompHum[3] = signed12hexdec($str3);
	
	$str1 = ReadRegister(0x76, 0xE6);
	$str3 = substr($e5, 2, 1) . $str1;
	$CompHum[4] = signed12hexdec($str3);
	
	$str1 = ReadRegister(0x76, 0xE7);				// char
	$str3 = str_replace('0x', '', $str1);
	$CompHum[5] = signed8hexdec($str3);
}
// ---------------------------------------------------------------------------
// 温度のA/D 変換
function BME280_GetAdcTemp()
{
	$str3 = ReadRegister(0x76, 0xFA);
	$str2 = ReadRegister(0x76, 0xFB);
	$str1 = ReadRegister(0x76, 0xFC);
	$str1 = substr($str1, 2, 1);
	$str4 = str_replace('0x', '', $str3 . $str2 . $str1);
	$num1 = hexdec($str4);
	return $num1;
}
 
// ---------------------------------------------------------------------------
// 大気圧のA/D 変換
function BME280_GetAdcPress()
{
	$str3 = ReadRegister(0x76, 0xF7);
	$str2 = ReadRegister(0x76, 0xF8);
	$str1 = ReadRegister(0x76, 0xF9);
	$str1 = substr($str1, 2, 1);
	$str4 = str_replace('0x', '', $str3 . $str2 . $str1);
	$num1 = hexdec($str4);
	return $num1;
}
 
// ---------------------------------------------------------------------------
// 湿度の A/D 変換
function BME280_GetAdcHum()
{
	$str2 = ReadRegister(0x76, 0xFD);
	$str1 = ReadRegister(0x76, 0xFE);
	$str4 = str_replace('0x', '', $str2 . $str1);
	$num1 = hexdec($str4);
	return $num1;
}
 
// ---------------------------------------------------------------------------
function BME280_GetT_Fine($AdcTemp, $CompTemp)
{
	$var1 = (((($AdcTemp / pow(2, 3)) - ($CompTemp[0]* pow(2, 1)))) * $CompTemp[1]) / pow(2, 11);
	$var2 = ($AdcTemp / pow(2, 4)) - $CompTemp[0];
	$var2 = ((($var2 * $var2) / pow(2, 12)) * $CompTemp[2]) / pow(2, 14);
	$t = $var1 + $var2;
	return $t;
}
 
// ---------------------------------------------------------------------------
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
// t_fine carries fine temperature as global value
function BME280_GetTemp($t_fine)
{
	return ($t_fine * 5.0 + 128.0) / pow(2, 8);
}
 
// ---------------------------------------------------------------------------
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
function BME280_GetPress($AdcPress, $CompPress, $t_fine)
{
	$var1 = $t_fine - 128000.0;
	$var2 = $var1 * $var1 * $CompPress[5];
	$var2 = $var2 + (($var1 * $CompPress[4]) * pow(2, 17));
	$var2 = $var2 + ($CompPress[3] * pow(2, 35));
	$var1 = (($var1 * $var1 * $CompPress[2]) / pow(2, 8)) + (($var1 * $CompPress[1]) * pow(2, 12));
	$var1 = ((1 * pow(2, 47)) + $var1) * ($CompPress[0] / pow(2, 33));
	if ($var1 == 0)
	{
		return 0; // avoid exception caused by division by zero
	}
	$p = 1048576.0 - $AdcPress;
	$p = ((($p * pow(2, 31)) - $var2) * 3125.0) / $var1;
	$var1 = $CompPress[8] * ($p / pow(2, 13)) * ($p / pow(2, 13)) / pow(2, 25);
	$var2 = ($CompPress[7] * $p) / pow(2, 19);
	$p = (($p + $var1 + $var2) / pow(2, 8)) + ($CompPress[6] * pow(2, 4));
	$str3 = dechex($p);
	$p = hexdec('00' . $str3);
	return $p;
}
 
// ---------------------------------------------------------------------------
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
// Output value of “47445” represents 47445/1024 = 46.333 %RH
function BME280_GetHum($AdcHum, $CompHum, $t_fine)
{
	$num1 = $t_fine - 76800.0;
	$num1 = ((((($AdcHum * pow(2, 14)) - ($CompHum[3] * pow(2, 20)) - ($CompHum[4] * $num1)) +
			16384) / pow(2, 15)) * ((((((($num1 * $CompHum[5]) / pow(2, 10)) * ((($num1 *
			$CompHum[2]) / pow(2, 11)) + 32768)) / pow(2,10)) + 2097152) *
			$CompHum[1] + 8192) / pow(2, 14)));
	$num1 = $num1 / pow(2, 12);
	return $num1;
}
 
// ---------------------------------------------------------------------------
$CompTemp = [0,0,0];
$CompPress = [0,0,0,0,0,0,0,0,0];
$CompHum  = [0,0,0,0,0,0];
 
// ---------------------------------------------------------------------------
// センサーの初期化
$osrs_t = 1;            		// Temperature oversampling x 1
$osrs_p = 1;            		// Presssure oversampling x 1
$osrs_h = 1;            		// Humidity oversampling x 1
$mode   = 3;            		// Normal mode
$t_sb   = 7;            		// Tstandby 20ms
$filter = 0;            		// Filter off
$spi3w_en = 0;          		// SPI Disable
 
$F2 = '0x' . dechex($osrs_h);
$F4 = '0x' . dechex($osrs_t << 5 | $osrs_p << 2 | $mode);
$F5 = '0x' . dechex($t_sb << 5 | $filter << 2 | $spi3w_en);
 
WriteRegister(0x76, 0xF2, $F2);
WriteRegister(0x76, 0xF4, $F4);
WriteRegister(0x76, 0xF5, $F5);
 
// ---------------------------------------------------------------------------
// 補正データ読み込み
BME280_GetCompensation($CompTemp, $CompPress, $CompHum);
 
// ---------------------------------------------------------------------------
function BME280_main(){}	// エディタに関数リストを表示するためだけにある。
 
while(1) {
	// A/D 変換
	$AdcTemp = BME280_GetAdcTemp();
	$AdcHum = BME280_GetAdcHum();
	$AdcPress = BME280_GetAdcPress();
	
	// 補正
	$t_fine = BME280_GetT_Fine($AdcTemp, $CompTemp);
	$Temp = BME280_GetTemp($t_fine);
	$Hum = BME280_GetHum($AdcHum, $CompHum, $t_fine);
	$Press = BME280_GetPress($AdcPress, $CompPress, $t_fine);
	
	echo sprintf("%6.1f C\n", $Temp / 100.0);
	echo sprintf("%6.1f %%RH\n", $Hum / 1024.0);
	echo sprintf("%6.1f hPa\n", $Press / 256.0 / 100.0);
	
	sleep(2);
}
 
?>

ちゃんと表示できました。

pi@raspberrypi:~/ $ php FW043_BME280.php
  22.5 C
  34.7 %RH
 996.8 hPa
  22.5 C
  34.6 %RH
 996.8 hPa