2022 年度 OSS リテラシ 3 : Raspberry Pi でのセンサー利用

はじめに: 利用するセンサー

センサーの規格として最近よく利用されるのは I2C(アイ・スクエア・シー, アイ・アイ・シー, アイ・ツー・シー)である. I2C は低速な周辺機器をマイコンに接続するためのものであり, 組み込みシステムや携帯電話などで利用される.

  • 通信速度 : 0 ~ 100 kbps (標準モード)
  • 信号線 : SDA (データ), SCL (クロック)
  • 備考 : スレーブの識別にはアドレスを使う. 信号線にはプルアップ抵抗が必要.

演習では以下の I2C 規格のセンサーを利用する. これらのセンサー が全てラズパイの GPIO 2, 3 (ピン番号 3, 5) に接続されている. 各センサーにはアドレスが割り当てられており, 同じアドレスの機器を同時に接続することはできないことに注意せよ.

  • 気温・湿度センサー: Adafruit Si7021
    • 精度: -0.4 ~ +0.4 度 (温度), -3.0 ~ +3.0 % (湿度)
    • I2C アドレス: 0x40
  • 照度センサー: Adafruit TSL2561
    • ダイナミックレンジ: 0.1 ~ 40,000 Lux
    • I2C アドレス: 0x39 (0x29, 0x49)

センサーの接続方法

本演習ではセンサーを簡単に接続するために, ラズパイに専用基板を利用する. I2C 規格のセンサーは演習用基板の CON 1, CON 2, CON 3 のどれかに接続するすれば良い. これらのポートはラズパイの GPIO 2, GPIO 3 (ピン番号 3, 5) に並列に接続されている.

必要なライブラリのインストール

各センサーの python ライブラリが配布されているので, それをインストールする. pip コマンドは Python のパッケージ管理システムである. 近年は言語ごとにパッケージ管理システムを持ち, OS が用意している以外のライブラリをインストールことが容易になっている (例えば ruby なら gem).

TSL2561 用のライブラリのインストール

$ sudo pip3 install tsl2561

Si7021 用のライブラリのイストール

$ sudo pip3 install pi-si7021

実習用サンプルスクリプト

実習用サンプルスクリプトを GitHub から入手する.

$ cd

$ git clone https://github.com/sugiymki/iotex-sensor.git

I2C 規格のセンサーの利用

"メニュー" => "設定" => "Raspberry Pi の設定" を選択し, "インターフェイス" タブより I2C を有効にする

I2C で接続された周辺機器には固有のアドレスが付与される. 接続した I2C 機器に振られたアドレスを確認するためには, i2cdetect コマンドを使う. 機器ごとにアドレスが決まっているので, アドレスが表示されるか確認をする. 以下の例では, 0x39 が TSL2561, 0x40 が Si7021 である. 自分の接続したセンサーのアドレスが表示されていることを確認すること.

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

TSL2561

tsl2561 を用いると照度を Lux 単位で測ることができる.

$ ./iotex-sensor/bin/tsl2561
262
練習) センサーの前に手をかざしたり, センサーを蛍光灯に向けると照度が変化することを確認せよ.

Si7021

Si7021 を使うためには, まず pigpiod を起動する必要がある (1 回行えば良い).

$ sudo pigpiod

その後, 実行する.

$ ./iotex-sensor/bin/si7021
Temperature: 23.54 °C
Relative humidity: 63.0 %

オプション -t, -r をつけると温度と相対湿度の値だけを出力する.

$ ./iotex-sensor/bin/si7021 -t
23.54

$ ./iotex-sensor/bin/si7021 -r
63.0

センサーで取得したデータの送信と可視化

取得したデータをセンサーに送るためのプログラムを作成する. ここではセンサーからデータを取得して送信するだけの簡単なシェルスクリプトを作成してみよう.

curl コマンド

シェルスクリプトは実行すべき一連の Unix コマンドをまとめたものである. ループなどの制御構文も使える. 今回作成するシェルスクリプトの中核を成すのが curl コマンドである. curl コマンドは手軽に HTTP リクエストを投げることができるので大変重宝するコマンドである. HTTPS で Basic 認証がかかっているときは -u オプションで Basic 認証用のユーザ名とパスワードを指定する. なお, URL は IP 直打ちではなく, iot-XX.epi.it.matsue-ct.jp (XX は数字) という SSL 証明書を取る時に用いたホスト名にすること.

今回は curl コマンドを用いてサーバ側で動いている monitoring.php (受け取っ たデータをデータベースに格納するための PHP スクリプト) に対してHTTP GET メソッドでデータを送る. PHP のセットアップ: データ ベースへの入力でブラウザに入力した URL を, curl コマンドの引数に与える形になる. hostname= や time= の後に ホスト名や時刻を適当に入れてみよ. なお, https 以下の文字列はダブルクォーテーションで囲むこと. ユーザ名・パスワードはセキュリティ対策(HTTPS)で設定したものを入れること.

$ curl -u user:password "https://iot-XX.epi.it.matsue-ct.jp/~hogehoge/php/monitoring.php?hostname=test&time=20221025000000"

 ...

サーバからの戻り値としてサーバ側で実行された SQL 文がターミナル上に表示される. SQL 文から判断できるように, ラズパイから送られたデータはサーバ上のデータベースに格納される. メッセージをよく見て, エラーが出ていないことを確認すること.

シェルスクリプトの実行

以下はシェルスクリプト (sensor.sh) の例であるが, データの取得と送信を無限ループしている. サーバに送るデータ群にホスト名とデータ取得時刻を含めることは必須である (これらがテーブルの主キーなので). シェルスクリプト内で, hostname コマンドでホスト名を取得し, date コマンドで現在時刻を取得している. また, センサー Si7021 で得た温度 ($temp に保管) を curl コマンドの引数で使っている.

$ cp ./iotex-sensor/bin/sensor.sh .

$ vi sensor.sh

  ### サンプルファイルは si7021 のデータを送るスクリプトになっている.###
  ### 送信先サーバ・ファイルのパスなどは,自分の環境に合わせること.  ###

 #/bin/bash

 # 送信先サーバ
 url=iot-50.epi.it.matsue-ct.jp/~hogehoge/php/monitoring.php

 # 計測用コマンド
 bin=$HOME/iotex-sensor/bin/si7021

 # ホスト名
 hostname=`hostname`

 # sensor.sh が他に起動していないか確認
 pid=`pgrep sensor.sh -fc`
 echo $pid
 if [ $pid = "2" ]; then
    pkill -fo sensor.sh
 fi

 # pigpiod が起動しているかの確認
 pid=`pgrep pigpiod -fc`
 echo $pid
 if [ $pid = "0" ]; then
    sudo pigpiod
 fi

 # 計測とデータ送信
 while :
 do
   sec=`date +"%S"`
   if [ $sec = "00" ] ; then
     time=`date +%Y%m%d%H%M%S`
     temp=`$bin -t`
     echo $time $temp $humi
     curl -u herohero:hogehero "https://$url?hostname=$hostname&time=$time&temp=$temp"
   fi
   sleep 1
 done

上記スクリプト sensor.sh を実行してみよ. サーバからの戻り値としてサーバ側で実行された SQL 文がターミナル上に表示されるので, エラーが出ていないか確認すること. SQL 文から判断できるように, ラズパイから送られたデータはサーバ上のデータベースに格納される.

$ bash sensor.sh

 .....

環境情報データの受け取りの確認 (サーバ (VM) での作業)

以下ではサーバ (VM) とラズパイを区別するために, サーバ上で実行するコマンドについては, プロンプトの前に VM の文字列を付す.

例)
  $ ls      (ラズパイで実行するコマンド)
  # ls      (ラズパイで実行するコマンド)
  VM$ ls    (サーバ (VM) で実行するコマンド)
  VM# ls    (サーバ (VM) で実行するコマンド)

まず Web サーバのログを確認し, ラズパイからのアクセスがあることを確認する. tail -f コマンドを使うことで, ファイルに新たなログが追加されるたびに標準出力が更新される. 数分間見ていれば 1 分間隔でログが増えていくことがわかる. tail -f コマンドを終了させるときは Ctrl-C (コントールキーを押しながら c キーを押す) とする.

VM$ sudo -s

VM# tail -f /var/log/apache2/access.log

  ...(略)...
  10.52.2.36 - - [18/Dec/2018:20:15:01 +0900] "GET /~hogehoge/php/monitoring.php?hostname=j52&time=2018/12/18T20:15:00&experiment_id=mon&essid=&temp=22.353333333333335&humi=35.318565163500004&dp=6.267685202446666 HTTP/1.1" 200 579 "-" "curl/7.52.1"
  10.52.2.36 - - [18/Dec/2018:20:16:00 +0900] "GET /~hogehoge/php/monitoring.php?hostname=j52&time=2018/12/18T20:16:00&experiment_id=mon&essid=&temp=22.17&humi=35.73597459725&dp=6.276913743041666 HTTP/1.1" 200 579 "-" "curl/7.52.1"
  10.52.2.36 - - [18/Dec/2018:20:17:00 +0900] "GET /~hogehoge/php/monitoring.php?hostname=j52&time=2018/12/18T20:17:00&experiment_id=mon&essid=&temp=22.2&humi=35.727903358750005&dp=6.300135280706667 HTTP/1.1" 200 579 "-" "curl/7.52.1"
  10.52.2.36 - - [18/Dec/2018:20:18:00 +0900] "GET /~hogehoge/php/monitoring.php?hostname=j52&time=2018/12/18T20:18:00&experiment_id=mon&essid=&temp=22.25166666666667&humi=35.738378330833335&dp=6.350015274005 HTTP/1.1" 200 579 "-" "curl/7.52.1"

次に, mysql コンソールを立ち上げ, テーブル monitoring と monitoring_hosts にデータが登録されていることを確認すること.

仮想サーバ上で MySQL に接続して, ラズパイから送られてきたデータがデータベースに登録されているか確認する.

VM$ sudo -s

VM# mysql -u root -p

  Enter password:    (エンター打鍵)

  ...(略)...

  MariaDB [(none)]> use iotex

    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A

    Database changed

観測値を入れるテーブル monitoring を確認!

MariaDB [iotex]> select * from monitoring where time > '2021-12-07';

  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+---------+---------+
  | hostname | time                | temp  | temp2 | temp3 | humi  | humi2 | humi3 | dp   | dp2  | dp3  | bmptemp | dietemp | lux  | objtemp | pres | winddir | windvel |
  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+---------+---------+
  | hogehoge | 2021-12-07 16:11:00 | 23.66 |  NULL |  NULL | 54.92 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  | hogehoge | 2021-12-07 16:12:00 | 23.67 |  NULL |  NULL |  54.9 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  | hogehoge | 2021-12-07 16:13:00 | 23.64 |  NULL |  NULL | 54.92 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+--------+--------+------+------+---------+---------+

しばらく時間を空けてから再び同じ SQL を実行すると, データ数が増えていること, データ間隔が 1 分おきであることが確認できる.

MariaDB [iotex]> select * from monitoring where time > '2021-12-07';

  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+---------+---------+
  | hostname | time                | temp  | temp2 | temp3 | humi  | humi2 | humi3 | dp   | dp2  | dp3  | bmptemp | dietemp | lux  | objtemp | pres | winddir | windvel |
  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+---------+---------+
  | hogehoge | 2021-12-07 16:11:00 | 23.66 |  NULL |  NULL | 54.92 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  | hogehoge | 2021-12-07 16:12:00 | 23.67 |  NULL |  NULL |  54.9 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  | hogehoge | 2021-12-07 16:13:00 | 23.64 |  NULL |  NULL | 54.92 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  | hogehoge | 2021-12-07 16:15:00 | 23.61 |  NULL |  NULL | 55.03 |  NULL |  NULL | NULL | NULL | NULL |    NULL |    NULL | NULL |    NULL | NULL |   NULL |   NULL | NULL | NULL |    NULL |    NULL |
  +----------+---------------------+-------+-------+-------+-------+-------+-------+------+------+------+---------+---------+------+---------+------+--------+--------+------+------+---------+---------+

また, 送信元となるラズパイのホスト名と IP が monitoring_hosts に保管されていることが確認できる.

MariaDB [iotex]> select * from monitoring_hosts where time > '2021-12-07';

  +-------------+------------+---------------------+
  | hostname    | ip         | time                |
  +-------------+------------+---------------------+
  | hogehoge    | 10.52.2.66 | 2021-12-07 16:16:00 |
  +-------------+------------+---------------------+

可視化

MySQL に保管されたデータからグラフを作るのには grafana を用いる. 環境データの可視化のためのサーバ設定(grafana) の課題を終えていれば, 送られたデータを表示するためのダッシュボードができているはずである (http://iot-XX.epi.it.matsue-ct.jp:3000/ へアクセスせよ. XX は自分の番号にすること). ダッシュボードに送信したデータが全て表示されているか確認すること. (-> 本日の課題)

課題

  • ラズパイのデータ送信スクリプト (sensor.sh) を改良し, 自分の使っている全てのセンサーのデータをサーバに送れるようにすること. すなわち, 温湿度計 Si7021 で計測した「温度」・「湿度」と照度計 TSL2561 で計測した「照度」をサーバに送信せよ.
    • 温湿度計 Si7021 のデータをテーブル monitoring のカラム humi に入力すること.
    • 照度計 TSL2561 のデータをテーブル monitoring のカラム lux に入力すること.
    • 改良したスクリプトを wbt に提出しなさい.
  • 上記を行った後に, grafana で新たなダッシュボードを作成し, ラズパイから送信されたデータを全て表示すること. grafana のダッシュボードののスナップショットを wbt より提出せよ.
    • スナップショットには必ず URL を含め,自分の grafana の画面であることを明示すること.