部屋の不快指数を定期的に測定して、危険な値ならLINE通知を送るシステムをRaspberryPiで作ってみた


きっかけ

  • 今年も暑くなってきたけれど、クーラーってどれくらいの暑さで使うのがいいんだろう?
  • 不快指数を測定して「危ないからクーラー使え!」って通知が来たらきっと楽だよな……
  • 屋内でも熱中症の危険がある日本の夏、命を救うことが出来るシステム……かもしれない
  • ラズパイにセンサ接続して疎通だけならやってたし、作ってみるか

システム概要図

注意

  • 試行錯誤しながらのメモを元に書いた記事なので、手順に抜け漏れがあるかもしれません……

使った物

ラズパイ用OSの準備(Win10で作業)

OSをSDカードに書き出し

  • Raspberry Pi Imagerをダウンロードしてインストール
  • 起動してOSと書き出しするsdカードを指定して実行

OSを書き出したSDカードのルートに2ファイル生成

ssh

空ファイルでOK

wpa_supplicant.conf

wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
  ssid="SSID"
  psk="暗号化キー"
}

ラズパイ起動後設定(linux/raspberrypi作業)

teraterm等でWin10から接続しても良いですが、プログラミングは基本的にLinuxでやっていたので
Linux(Ubuntu)からsshでラズパイに接続して作業をする準備をしています。

sshアクセス(Linux)

linux
ssh [email protected]
# pass:raspberry

ラズパイ初期設定(raspberrypi)

raspberrypi
# sudoユーザ作成
sudo adduser kabu0404
sudo usermod -aG sudo kabu0404
su kabu0404

# 諸々更新
sudo apt update
sudo apt upgrade

# タイムゾーン/ロケール設定
sudo timedatectl set-timezone Asia/Tokyo
sudo localectl set-locale ja_JP.UTF-8
# 最終的にsudo raspi-configでいじったかも

公開鍵でのssh接続

linux
# 過去にssh-keygen -t rsaしてたので既存の公開鍵を送る
cd ~/.ssh
scp ./id_rsa.pub [email protected]:~/.ssh/
raspberrypi
cd ~
chmod 700 .ssh
cd ~/.ssh
cat id_rsa.pub >> authorized_keys
chmod 600 authorized_keys
rm -fv ~/.ssh/id_rsa.pub

BME280設定

BME280の接続

  • ブレッドボード経由で下表のように接続
BME280側 ピン番号
VDD 1(3.3V)
GND 9(GND)
CSB ---
SDI 3(I2C1_SDA1)
SDO 9(GND)
SCK 5(I2C1_SCL1)

※ スイッチサイエンス版の製品だとピンが一本多いので注意

BME280の疎通

raspberrypi
# spi/i2cを有効化&localeを直す
sudo raspi-config

sudo chmod 666 /dev/i2c-1

# 接続状態を確認
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 --  

# 76に接続されていることを確認

# レジスタ内容を確認
i2cdump -y 1 0x76

No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 8a 70 89 8e 83 0f fc 06 34 6e 56 66 32 00 8a 8e    ?p??????4nVf2.??
90: 17 d6 d0 0b 5e 1d f0 ff f9 ff ac 26 0a d8 bd 10    ????^??.?.?&????
a0: 00 4b 40 00 00 00 00 00 00 00 00 00 33 00 00 c0    [email protected]..?
b0: 00 54 00 00 00 00 60 02 00 01 ff ff 1f 60 03 00    .T....`?.?..?`?.
c0: 00 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    `...............
e0: 00 67 01 00 14 05 00 1e 57 41 ff ff ff ff ff ff    .g?.??.?WA......
f0: ff 00 00 00 00 00 00 80 00 00 80 00 00 80 00 80    .......?..?..?.?

# レジスタ設定
# 動作設定系レジスタの値確認
echo -n '0xF5:' ; i2cget -y 1 0x76 0xF5 ; \
echo -n '0xF4:' ; i2cget -y 1 0x76 0xF4 ; \
echo -n '0xF2:' ; i2cget -y 1 0x76 0xF2

# 動作設定系レジスタの値設定
# i2cset -y 1 0x76 [内部アドレス] [値]
i2cset -y 1 0x76 0xF5 0xA0 ; \
i2cset -y 1 0x76 0xF4 0x27 ; \
i2cset -y 1 0x76 0xF2 0x01
# 設定値は特殊なことをしたくなければ上記の設定でOKなはず

# 温度・湿度・気圧の値取得
i2cdump -r 0xF7-0xFE -y 1 0x76

No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
f0:                      54 0b 00 84 00 00 74 62              T?.?..tb 

# こんな感じで値が取得できていればOKのはず
# 他のレジスタの値を利用して上手いことやるときれいにデータが出力できるらしい

Pythonでの測定値取得準備

キットは秋月電子の製品ですが、センサー自体は同じなのでSWITCHSCIENCEのサンプルコードを活用しています

raspberrypi
mkdir i2ctest
cd i2ctest/
wget https://github.com/SWITCHSCIENCE/samplecodes/archive/master.zip
unzip master.zip
# 展開後必要となるのは
# i2ctest/BME280/Python27/bme280_sample.pyのみなので
# 任意のDir配下にtouchしたファイルにコード内容をコピペで十分

cd BME280/Python27/
sudo python bme280_sample.py
temp : 28.37  ℃
pressure : 1003.83 hPa
hum :  51.99 %

LINE通知用のトークン取得

LINE通知用の追加コーディング

気温・湿度用関数をコンソール出力から値返却に変更

bme280_sample.py
# 気温用関数
def compensate_T(adc_T):
    # 中略
    # print "temp : %-6.2f ℃" % (temperature) 
    return temperature

# 湿度用関数
def compensate_H(adc_H):
    # 中略
    # print "hum : %6.2f %" % (var_h)
    return var_h

データ取得関数でLINE通知用関数を呼び出し

bme280_sample.py
def readData():
    # 中略
    temp = compensate_T(temp_raw)
    # 気圧は使用しない
    # compensate_P(pres_raw)
    hum  = compensate_H(hum_raw)

    # 不快指数を計算し80超なら通知を送る
    discomfortIndex = 0.81 * temp + 0.01 * hum * ( 0.99 * temp - 14.3 ) + 46.3
    if discomfortIndex > 80:
        sendNotice(temp, hum, discomfortIndex)

LINE通知送信用関数を追加

bme280_sample.py
def sendNotice(temp, hum, discomfortIndex):
    url = 'https://notify-api.line.me/api/notify'
    token = #通知用のトークンを設定
    headers = {'Authorization' : 'Bearer ' + token}
    now = datetime.datetime.now()
    message = \
        '\r\n日付: ' + now.strftime('%Y/%m/%d') + \
        '\r\n時刻: ' + now.strftime('%H:%M:%S') + \
        '\r\n指数: %5.2f' % (discomfortIndex) + \
        '\r\n気温: %5.2f ℃' % (temp) + \
        '\r\n湿度: %5.2f %' % (hum)
    payload = {'message' : message}
    r = requests.post(url, headers=headers, params=payload)

定期実行の設定

RaspberryPi3で初めてcrontabを使う前に を参考にcronで定期実行を設定

lineNoticeCron
# 5分間隔で実行する例
*/5 * * * * kabu0404 sudo python /home/kabu0404/i2ctest/BME280/Python27/bme280_sample.py

実行結果

作ってみた感想

LINE Nortify

  • トークン取得したらリクエスト送るだけでOKだったので楽
  • グループのトークルームにも通知を送信可能らしいので結構使えるかも。時間があるときに公式のドキュメント読んでみます

シリアル通信

  • I2C? SPI? 何だそれ? ってレベルだったので苦労しました。今もよくわからんです。
  • ラズパイで何かしようとすると事実上必須みたいな部分でもあるので、もうちょっと勉強したほうが良さそう

レジスタ仕様

  • 読み飛ばせた部分だけれども、読み方で少し詰まった。
  • 今の理解は下記、間違ってたらご指摘ください
    • hoge<n:m>fuga[n:m]は、nbit目〜mbit目の値を使うって意味
    • hoge<0>fuga[0]は、使用する値が1桁だけだと0:0って書くのは冗長なので省略

Python

  • 単純に勉強が足りない

このシステムの使いみちって?

  • クーラー嫌いの家族の家に置いて、グループラインに「暑いのにクーラーつけてないかも!」って通知する
  • 窓の外に置いて「もうクーラー消しても良い程度に涼しくなったよ」って通知する

その他

  • IFTTTとかスマート家電(持ってないけど)を組み合わせると面白そう
  • 接続まではしてあるGPSと組み合わせてなんか面白いこと出来ないもんかな

参考にさせていただいた記事・サイト