この記事は高知工科大Advent Calendar 2018の第9日目の記事です。
概要
こんにちは。情報学群3年のsttnです。遅刻してしまい深く反省しております。(>_<)
今回は温湿度センサを使ってお部屋の不快指数を算出して、LEDでそれに応じた色を光らせてみたよ!という話をしようと思います。
はじまり
7月某日
ちょっとした機会があって大阪は日本橋に立ち寄ることがありました。
今年の7月は(例年通り)気温も湿度も高く、大学に登校するのが億劫になるくらいムシムシとした暑さの毎日でした。
そんな気温や湿度を体感するうちに、温湿度センサを使って不快指数を算出したら面白いんじゃないか?と思いつき、温湿度センサを欲するようになってきました。
買いました。
今回使用する温湿度センサ「Grove-Temperature&Humidity Sensor TH02」(1728円)を衝動買いしました。(http://eleshop.jp/shop/g/gI3A314/)
お会計・・・1728円。
値段。
値段が高い。
おそらく熱で頭がやられていたのでしょう。
秋月電子でAM2302(950円)を買ったほうがお財布的にも賢かったんじゃないかとも思います。
……
でも買ってしまったものは仕方ないです!
これは仕方ない!
温度と湿度測る!
というわけで、7月末頃に温度と湿度の測定と不快指数の計算まで行いました。
今回は夏に行ったことの見直し&LEDでの可視化を行います!
やること
以下の三点を主に行います。
- 温度と湿度を測る
- 不快指数を算出する。
- LEDを用いて可視化する。
…どこかで見たことがある内容ですね。多分気のせいだと思います。
#構成
- RaspberryPi zero WH
- Grove-Temperature&Humidity Sensor TH02(温湿度センサ)
- フルカラーLED
- 抵抗(1kΩ×6個)
- 2N7000(Nch FET×3)
- ユニバーサル基板やジャンパ線とかそのほか必要なもの
ラズパイのGPIOを使ってセンシングとLチカをします。
#TH02を動かす
部屋の気温と湿度を測定し、不快指数の算出を行います。
温度・湿度の算出
TH02の値を読み取って、気温と湿度を測ります。
上のような状態でセンサとラズパイを接続します。ジャンパ線で繋げるだけです。
TH02側ピン | Raspberry PI側ピン |
---|---|
VCC | 3V3 |
GND | GND |
SDA | 2 |
SCL | 3 |
接続はこんな感じです。
プルアップ回路も基板の中に入ってるので接続がとても楽でした。(気になって後輩を巻き込んでめちゃくちゃ確認した。)
今回のセンサはI2C接続なので必要なアドレスの確認を行い、まとめます。
contents | address |
---|---|
Address | 0x40 |
reg_config | 0x03 |
data_h | 0x01 |
data_l | 0x02 |
select_hum | 0x01 |
select_temp | 0x11 |
使用するアドレスは上記の通りです。
次にソースコードを実装していきます。
TH02クラスを作成し、温度を読む関数と湿度を読む関数を実装します。
import sys
import smbus2
class TH02:
#定数宣言
address = 0x40
reg_conf = 0x03
data_h = 0x01
data_l = 0x02
select_hum = 0x01
select_temp = 0x11
def __init__(self):
self.channel = 1
self.bus = smbus2.SMBus(self.channel)
def readTemp(self):
self.bus.write_i2c_block_data(self.address, self.reg_conf, [self.select_temp])
self.bus.write_i2c_block_data(self.address, self.data_h, [])
block1 = self.bus.read_i2c_block_data(self.address,0,3)
data = (block1[1] << 8 | block1[2])
data = data >> 2
data = (data/32.0) - 50.0
return data
def readHum(self):
self.bus.write_i2c_block_data(self.address, self.reg_conf, [self.select_hum])
self.bus.write_i2c_block_data(self.address, self.data_h, [])
block2 = self.bus.read_i2c_block_data(self.address,0,3)
data = (block2[1] << 8 | block2[2])
data = data >> 4
data = data / 16.0 - 24.0
return data
TH02クラスをdiscomfortIndex.pyの中にインポートしてメインの動作を行います。
while True:
time.sleep(0.1)
temp = th02.readTemp()
time.sleep(0.1)
temp = th02.readTemp()
time.sleep(0.1)
hum = th02.readHum()
time.sleep(0.1)
hum = th02.readHum()
print('tempureture: %.2f , humidity: %.2f' % (temp, hum))
実行するときの注意点ですが、上記のソースコードのように関数を2回呼び出さないと正常な値が読めないという不具合がありました。原因はちゃんと究明してないので何とも言えないですが……メモリの関係ですかね…?(私が情弱なだけというのもありそう…?:thinking-face:)
不快指数の算出
取得した温度と湿度を利用して不快指数を算出します。
outputDI関数をTH02クラスに実装して計算を行いました。
def outputDI(self, temp, hum):
di = 0.81 * temp + 0.01 * hum * (0.99 * temp - 14.3) + 46.3
return di
メイン関数で呼び出して、不快指数の算出を行います。
di = th02.outputDI(temp, hum)
print('不快指数: %.2f \n' % di)
ここまで実装した結果、画像のように温度と湿度、不快指数の表示ができました。
エアコンの影響で乾燥してますが、正常にロギングできているようです。
ちなみに関数を二回呼び出ししなかった場合の結果です。人類が生存するのに非常に厳しい環境が出来上がっていますね。
#フルカラーLEDを光らせる
フルカラーLEDで複数の色が光るようにします。
回路作成
Qiitaなのであまり踏み込まない程度に話します。
回路を組むうえで話しておきたいこと
製作直後に気づいたんですが、自分が持っていたフルカラーLEDがアノードコモンだったんですよね。入力側の足が1本で出力側が3本のタイプです。
これをGNDにつなげる側をGPIOにすると制御側が危ないんじゃないか?という懸念が浮かびました。
実際にそのままつけると、ほんのり回路が繋がってLEDがじわっと光るんですよ。
こわい。
なのでFETをかませてGPIOで信号の制御を行う構造にしました。おかげで何もしてない状態でLEDがじわっと光る現象は解決しました。
この方法が正しかったのか本当に分からないので分かる人誰か教えて欲しいです。
回路図
FETのせいで複雑な回路に見えるますね。(情報学徒並感)
プログラム
センサと同様、LEDクラスを作成して各色を光らせる関数を実装します。
環境準備
今回は「pigpio」というライブラリを用いてGPIOを制御しました。
こちらのRaspberry PiのGPIO制御の決定版 pigpioを試すを参考にしました。
RaspberryPiにpigpioをインストール。
$ sudo apt-get update
$ sudo apt-get install pigpio
pigpioは使用する前にpigpiodというデーモンを立ち上げる必要があるらしいです。立ち上げるのを忘れそうなので/etc/rc.local
に書いておきます。
$ sudo vim /etc/rc.local
----
~
~
pigpiod
exit 0
これで実行の準備はできました。
しかし、この時点ではpythonのライブラリがまだ入っていなかったので、ライブラリのインストールをします。入ってることもあるかもしれないですが、忘れがちなので念のため確認したほうがいいと思います。
pip install pigpio
これで環境の準備が整いました。
ソースコード
import pigpio
import time
class LED:
GPIO_R = 5
GPIO_G = 26
GPIO_B = 13
def __init__(self):
self.pi = pigpio.pi()
self.pi.set_mode(self.GPIO_R, pigpio.OUTPUT)
self.pi.set_mode(self.GPIO_G, pigpio.OUTPUT)
self.pi.set_mode(self.GPIO_B, pigpio.OUTPUT)
def red(self):
self.pi.write(self.GPIO_R, 1)
self.pi.write(self.GPIO_G, 0)
self.pi.write(self.GPIO_B, 0)
def blue(self):
~
def green(self):
~
def magenta(self):
~
def cyan(self):
~
def yellow(self):
~
def white(self):
~
def clear(self):
self.pi.write(self.GPIO_R, 0)
self.pi.write(self.GPIO_G, 0)
self.pi.write(self.GPIO_B, 0)
7色の色とLEDの消灯させることができます。
self.pi = pigpio.pi()
で初期化、
set_mode(pin,I/O)
でピンの設定、
write(pin, T/F)
で出力の制御を行っています。
動作確認
不快指数をLEDで示す
不快指数を可視化するにあたって、どの色でどの状態を示すのか定義します。
こちらのブログを参考にして不快指数の値と色を関連付けました。
色 | 不快指数 |
---|---|
青色 | ~64 |
水色 | 65~69 |
緑色 | 70~74 |
黄色 | 75~79 |
赤紫色 | 80~84 |
赤色 | 85~100 |
白色 | その他(異常状態) |
この表に従って、discomfortIndex.pyに以下のソースコードを追加します。
if di < 65:
led.blue()
elif di < 70:
led.cyan()
elif di < 75:
led.green()
elif di < 80:
led.yellow()
elif di < 85:
led.magenta()
elif di < 100:
led.red()
else:
led.white()
ひとまずこれで完成です。
作ってみて
TH02について
かなり値段が高いので手は出しづらい印象を受けました。
精度は確かに高いと感じましたが、実際に使ってみると変化に弱い部分があるらしく(仕様?)、飛翔体のロガーなど変化が激しい場所で使用するのにはナンセンスだと思いました。
ソースコードを見ると分かりますが、ちょっと余分な内容を書かないと動かなかったりするので使い勝手も凄く良いというわけではなかったです。
定点観測用としてはまずまずの性能を持ったセンサなんじゃないかなーと思います。
温度と湿度(特に湿度)をロギングしたいのであれば、AM2302やBME280を選んだほうがいいんじゃないかなーと個人的には思います。
あくまで参考までに。
pigpioについて
今回初めて使用したのですが、個人的には使いやすいと感じました。
最初に設定する際に少し準備が必要ですが、それが済めばけっこう色んなこと~~[要出典]~~ができるかと思います。
I2Cの制御も可能らしいので(参考記事)、近いうちに試してみたいです。
ライブラリの詳細な情報についてはこの方の記事で沢山紹介してくれているので、興味のある方は確認してみてください。
ちなみにpigpioで使用できる関数はこちらでまとめられています。
ソースコード
ソースコードはGithubに全て上げています。(修正したい部分もあるのであしからず…)
https://github.com/sattonx/DiscomfortIndexSystem
まとめ
- TH02はコスパ悪い(個人的見解)
- フルカラーLEDは「カソードコモン」と書かれたものを選ぼう
- pigpioけっこう良さそう
- らずぱいはいいぞ!