8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ラズパイ+BME280でIoT環境センサー構築(その3)

Last updated at Posted at 2018-08-03

##概要
Raspberry PiでスイッチサイエンスのBME280モジュールを使用して、温湿度と気圧を測定し、WEBブラウザで確認できるようにする。どうせならグラフ化して表示したい。今回は、PHPのページ作成について記載します。なお、内容については私自身がよく分かっておりません。ヘルプとにらめっこしてとりあえず動いたという程度の内容です。

試行錯誤したけど全部忘れたので、結論だけ書きます。
サンプルコードは、スクリプトを実行して結果を返すだけですが、PHPで表示するために関数化した(のかな?)
そのまま返すのではなく変数に格納して、別スクリプトから読みだしている。
(用語がよくわからない^^;)

##WEBページの構造
/var/www/html/ にphpを配置。ここからスクリプトを実行する。
スクリプトは/home/pi/bme280/に配置、内容は以下。

ファイル名 内容
bme280.py CSVファイルを作成
bme280_custom.py 温度、湿度、気圧を返す
bme280_temp.py 温度を返す
bme280_humid.py 湿度を返す
bme280_pres.py 気圧を返す

一覧表とグラフの両方を見るためにこのようにしました。もっとうまいやり方があるとは思いますが。

/home/pi/bme280/data/ に観測値をcsvファイルとして保存する。csvファイルは日付単位で作成する。

##スクリプトの作成
###1.サンプルコードを修正する
bme280_sample.pyをbme280_custom.py にリネームして以下のように修正しました。
先頭部分は

bme280_custom.py
先頭部分
()
from smbus2 import SMBus
import time

bus_number  = 1
i2c_address = 0x76

bus = SMBus(bus_number)

(修正後)
import smbus
import time
 
bus_number  = 1
i2c_address = 0x76
 
bus = smbus.SMBus(bus_number)

~~中略~~

def readData():
    data = []
    for i in range (0xF7, 0xF7+8):
        data.append(bus.read_byte_data(i2c_address,i))
    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
    hum_raw  = (data[6] << 8)  |  data[7]
     
    #compensate_T(temp_raw)
    #compensate_P(pres_raw)
    #compensate_H(hum_raw)
    t = compensate_T(temp_raw)
    p = compensate_P(pres_raw)
    h = compensate_H(hum_raw)
    return p + "," + t + "," + h

def compensate_P(adc_P):
     :
    #print "pressure : %7.2f hPa" % (pressure/100)
    return "%7.2f" % (pressure/100)

def compensate_T(adc_T):
     :
    #print "temp : %-6.2f ℃" % (temperature) 
    return "%.2f" % (temperature) 

def compensate_H(adc_H):
     :
    #print "hum : %6.2f %" % (var_h)
    return "%.2f" % (var_h)

###2.温度のみ返すスクリプトを作成
基本的にはcustomファイルから温度の部分のみを取り出したものです。
ちゃんと作るべきなんだろうけど、tだけ返せばいいわけで、bme280_custom.pyをコピー&リネームして、下記1行のみ変更。

bme280_temp.py
()
def readData():
     :
    return p + "," + t + "," + h
(修正)
def readData():
     :
    return t

###3.湿度のみ返すスクリプトを作成
温度と同じです。
bme280_custom.pyをコピー&リネームして、下記1行のみ変更。

bme280_humid.py
()
def readData():
     :
    return p + "," + t + "," + h
(修正)
def readData():
     :
    return h

###4.気圧のみ返すスクリプトを作成
温度と同じです。
bme280_custom.pyをコピー&リネームして、下記1行のみ変更。

bme280_pres.py
()
def readData():
     :
    return p + "," + t + "," + h
(修正)
def readData():
     :
    return p

###5.CSVファイルに保存するスクリプトを作成
読みだした値をCSVファイルとして保存します。WEBに表示する際に、日付ごとに分けたいので、手っ取り早く日付単位でファイルを作成します。

bme280.py
#coding: utf-8
 
import bme280_custom
import bme280_temp
import bme280_pres
import bme280_humid
import datetime
import os
 
dir_path = '/home/pi/bme280/data'
 
now = datetime.datetime.now()
filename = now.strftime('%Y%m%d')
label = now.strftime('%H:%M')
date = now.strftime('%Y/%m/%d %H:%M')
csv = bme280_custom.readData()
csv_t = bme280_temp.readData()
csv_p = bme280_pres.readData()
csv_h = bme280_humid.readData()

if not os.path.exists('/home/pi/bme280/data'):
    os.makedirs('/home/pi/bme280/data')
f = open('/home/pi/bme280/data/'+filename+'.csv','a')
f.write("'"+date+"',"+csv+"\n")
f.close()
f = open('/home/pi/bme280/data/'+filename+'_t.csv','a')
f.write("'"+date+"',"+csv_t+"\n")
f.close()
f = open('/home/pi/bme280/data/'+filename+'_p.csv','a')
f.write("'"+date+"',"+csv_p+"\n")
f.close()
f = open('/home/pi/bme280/data/'+filename+'_h.csv','a')
f.write("'"+date+"',"+csv_h+"\n")
f.close()

##WEBページの作成
###1.表形式で表示する
記録した温度、湿度、気圧を表形式でまとめて表示する。表の作成はGoogleChartを使用する。

bme280.php
<?php
$today  = date("Ymd");
$csv_dir  = '/home/pi/bme280/data/';
$csv_file = $today.'.csv';
$grapgh   = '';
if (($handle = fopen($csv_dir.$csv_file, "r")) !== false) {
    while (($line = fgets($handle)) !== false) {
    $grapgh .= '['.rtrim($line).'],'.PHP_EOL;
    }
    fclose($handle);
}else{
    echo 'no data';
}
?>
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
    google.load("visualization", "1", {packages:["table"]});
    google.setOnLoadCallback(drawTable);
 
    function drawTable() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Time');
    data.addColumn('number', 'Pressure[hPa]');
    data.addColumn('number', 'Temperature[℃]');
    data.addColumn('number', 'Humidity[%]');
    data.addRows([
 
<?php echo $grapgh; ?>
 
    ]);
 
      var table = new google.visualization.Table(document.getElementById('table_div'));
      table.draw(data, {showRowNumber: true});
    }
</script>
</head>
<body>
 
<div id="table_div"></div>
 
</body>
</html>

###2.グラフで表示する
記録した温度、湿度、気圧をそれぞれをグラフにして表示する。Y軸を複数にして重ねることもできるが、温度と湿度と気圧だと2桁と4桁なので単純に重ねると気圧しか見えなくなり、難しいので3つに分けた。グラフの作成はGoogleChartを使用する。

bme280-2.php
<?php
$today  = date("Ymd");
$csv_dir  = '/home/pi/bme280/data/';
$temp_file = $today.'_t.csv';
$grapgh_t   = '';
$pres_file = $today.'_p.csv';
$grapgh_p   = '';
$hum_file = $today.'_h.csv';
$grapgh_h   = '';
if (($handle = fopen($csv_dir.$temp_file, "r")) !== false) {
    while (($line = fgets($handle)) !== false) {
    $grapgh_t .= '['.rtrim($line).'],'.PHP_EOL;
    }
    fclose($handle);
}else{
    echo 'no data';
}
if (($handle = fopen($csv_dir.$pres_file, "r")) !== false) {
    while (($line = fgets($handle)) !== false) {
    $grapgh_p .= '['.rtrim($line).'],'.PHP_EOL;
    }
    fclose($handle);
}else{
    echo 'no data';
}
if (($handle = fopen($csv_dir.$hum_file, "r")) !== false) {
    while (($line = fgets($handle)) !== false) {
    $grapgh_h .= '['.rtrim($line).'],'.PHP_EOL;
    }
    fclose($handle);
}else{
    echo 'no data';
}
?>
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
    google.charts.load('current', {packages:['corechart', 'line']});
    google.charts.setOnLoadCallback(drawChart);
 
    function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Time');
        data.addColumn('number', 'Temperature[℃]');
        data.addRows([
            <?php echo $grapgh_t; ?>
        ]);

	var options = {
	    title: 'Temprature by BME280(raspberry pi3)'
  	};

        var chart = new google.visualization.LineChart(document.getElementById('chart1'));
        chart.draw(data,options);
    }

    google.charts.load('current', {packages:['corechart', 'line']});
    google.charts.setOnLoadCallback(drawChart2);

    function drawChart2() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Time');
        data.addColumn('number', 'Pressure[hPa]');
        data.addRows([
            <?php echo $grapgh_p; ?>
        ]);

	var options = {
	    title: 'Pressure by BME280(raspberry pi3)'
  	};

        var chart = new google.visualization.LineChart(document.getElementById('chart2'));
        chart.draw(data,options);
    }

    google.charts.load('current', {packages:['corechart', 'line']});
    google.charts.setOnLoadCallback(drawChart3);

    function drawChart3() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Time');
        data.addColumn('number', 'Humid[%]');
        data.addRows([
            <?php echo $grapgh_h; ?>
        ]);

	var options = {
	    title: 'Humid by BME280(raspberry pi3)'
  	};

        var chart = new google.visualization.LineChart(document.getElementById('chart3'));
        chart.draw(data,options);
    }
</script>
</head>
<body>
 
<div id="chart1"></div>
<div id="chart2"></div>
<div id="chart3"></div>

</body>
</html>

##WEBの設定と自動実行
###1.ファイルの配置
作成したPHPファイルを/var/www/html/に置きます。
作成したスクリプトファイルを/home/pi/bme280/に置きます。
bme280.pyのパーミッションを755に変更する。

sudo chmod 755 bme280.py

###2.自動実行の設定
cronを起動する。

sudo /etc/init.d/cron start
[ ok ] Starting periodic command scheduler: cron.

sudo apt install -y chkconfig
sudo chkconfig cron
cron on

スクリプトを登録する。bme280.pyを実行すると、ほかの4つはこの中で呼ばれるのでbme280.pyのみ登録すればよい。10分ごとにスクリプトを実行する。
初めて登録する場合、エディタの選択肢が出るので好きなものを指定する。

crontab -e

最下行に以下を追加。
*/10 * * * * python /home/pi/bme280/bme280.py

###3.動作確認
ブラウザで、ラズパイのIPアドレスを表示。
(例)
http://192.168.0.36/bme280.php
キャプチャ20.JPG
http://192.168.0.36/bme280-2.php
クリップボード.jpg
グラフはマウスをあてると吹き出しが出る。Google Chartは高性能だった。

##参考

8
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?