ラズパイZeroとDHT11で温度湿度ロガーを作る

## きっかけ

前回までとは基本的に全く違うアレなのですが、世を忍ぶ仮の本職の職場、仕事自体は問題無いのですが、住環境的な意味ではかなりよろしくない<sub>(穏当な表現)</sub>。

具体的に言うとこの夏、就業時間の8時間の間に、室温が25℃から30℃の間を何度も行き来し、湿度は50%以下から80%近くまでを行き来する、地獄のような環境。少し前まで汗だくだったかと思えば1時間後には凍えるような状態になり、からっとした湿度だったのがあっという間にじめじめになる、そんな職場です。

職務自体、ふつーのデスクワーク<sub>(個人の感想)</sub>で外気とは基本切り離されてるし、エアコンの設定だって、それほど極端なアレコレは無い、ハズなのです。職場の環境調査でまれにやってくる業者の人は3分くらいで(多分CO2測って)帰って行くので、過酷さがイマイチ管理部門の人に伝わらない。

**ならば気温と湿度を計測して、データをたたきつけるしか無い。**

そういう理由から、温度と湿度を<sub>それなりの</sub>長時間計測するロガーを作成することにしました。

## 要求仕様と用意したもの

　極めて雑な要求仕様は以下の通り。

- 設置時点から24時間以上、温度と湿度を計測する。
- USB電源が使える環境だが、最悪、モバイルバッテリーでなんとか出来るようにする
- 持ち運びとか設置で邪魔にならないこと。
- 結果を表示したりするのは考えない。後から加工すれば良いし。
- 精度は参考になる程度の値が出てれば良い(チェックしようが無いし)
- 安価であること。簡単に作れること。
- 職場内のLAN等に接続できないので、データは内部に貯めて後から取り出す。
- キーボードやマウス、ディスプレイも接続できないので、電源投入で(コマンド入力無しで)開始する事。<br>終了は……**ぶちっ**と……(雑)

　以上を(まあそれなりに)満たすモノとして、

- Raspberry Pi Zero WH(秋月でケースセット2700円くらい)
- 温度湿度センサDHT11(モジュールタイプで700円くらい)
- ソフトはPython。SQLiteでデータ保存。
- SDカード(Micro SD(HC|XC))は、OSとデータが載れば良い。極端に高速である必要も無い。

買ったセンサーは[これ](http://akizukidenshi.com/catalog/g/gM-07040/)。センサー単体でもっと安いのもありますが、抵抗を別に用意するとか、ブレッドボード上に配置とか、率直にめどいのでワイヤまでついてるこちらに決定。

なお、付属品のワイヤの配線そのままではラズパイに接続出来ないので、コネクタとピンを買ってきて差し替える必要があります。ワイヤーストリッパーとかしめ工具があれば、さほど時間掛からずに配線準備完了。

ラズパイは、ご家庭で余っている普通のラズパイならだいたいなんとでもなるハズです。DHT11はGPIOが1本、5Vが1本、GNDが1本あいていれば、他のピンに何か刺さっていて文句言われるようなことは無いはずです。
今回は持ち運びと設置の都合上、ラズパイZero WHを採用。運用準備と実行結果の取得などを考えると、無線LANモデル、センサーとの接続を考えるとピン付きモデルのWHなのはだいたい自明。

あとは、センサーがぶらぶらしないよう、適当に固定して完了。

![s_DSC_0620.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139416/58e498c0-5ce4-c7bb-1c77-d4cb31101070.jpeg)

極めて雑な工作結果。なお、SDカードはラズパイ純正ケースに納める前に(イメージ焼いた上で)挿しておかないと詰む。

## ラズパイ側の構築

ラズパイ側の設定はいろんなところで解説されてるので省略。

自宅での設定時は無線LAN＆SSH接続なので、イメージを焼いたのち、bootドライブに所定のファイルを置きます。
参考にしたのは[こちら](https://qiita.com/mascii/items/a43d71572e1919e56398)。注意点としては、5GHz帯は使えないので2.4GHz帯のSSIDを指定する点(気が付くまでに3度やりなおした)。

特に大きな理由があるわけではないものの、動作させるPythonのバージョンは3.7(Raspibianインストール時に入っていた最新)で。

DHT11とのやり取りは、[便利なライブラリ作っている方](https://github.com/szazo/DHT11_Python)と[それを使った事例を紹介されている方](https://qiita.com/mininobu/items/1ba0223af84be153b850)がいたので、盛大に乗っかることに。

上の写真の配線例の場合、サンプルからピン番号を変更する必要もなく、実行して取れることを確認。

## 一定間隔実行とログ取得

最初はサンプルコードを拡張してループ処理の中で取得すればいいかなー、と考えていたのですが。

**なんか取得間隔が変。**

サンプルプログラムではtime.sleep()で6秒ごとに実行、となってる割に、一定間隔での温度の表示が行われていない様子。

調べてみると、read()処理後にis_varlid()関数を実施して、適切に取得できたかチェックしているようなのですが、この関数で失敗と返る場合が結構あるようです(自分の環境だけでしょうか？)

動作チェックの範囲では、**連続40回失敗**という例もあり、サンプルならばともかくこのままやるのはちょっとまずい。取得時間がどんどんずれます。

　そんなわけで、一定間隔実行に重きを置いてサンプルを改変した結果がこんな。

```Python3:一定間隔処理サンプル.py
import RPi.GPIO as GPIO
import dht11
import time
import datetime
import signal

# read data using pin 14
instance = dht11.DHT11(pin=14)

def read_signal(arg1, args2):

    result = instance.read()
    while not result.is_valid():
        time.sleep(0.5)
        result = instance.read()
    print("Last valid input: " + str(datetime.datetime.now()))
    print("Temperature: %-3.1f C" % result.temperature)
    print("Humidity: %-3.1f %%" % result.humidity)

if __name__ == '__main__':

    # initialize GPIO
    GPIO.setwarnings(True)
    GPIO.setmode(GPIO.BCM)

    try:
        signal.signal(signal.SIGALRM, read_signal)
        signal.setitimer(signal.ITIMER_REAL, 1, 30)
        while True:
            time.sleep(5)

    except KeyboardInterrupt:
        print("Cleanup")
        GPIO.cleanup()
```

signalで一定間隔毎に処理を走らせるようにし、result.is_valid()失敗時は少しの間で再実行するように変更。気温の取得程度で取得間隔を厳密にそろえる理由はないので、だいたいの間隔がそろえば(取得の起点時刻が一定間隔ならば)問題なしとする。30秒ごとに取得するとして、エラーが60回連続発生(=次のシグナル発生時まで遅延)することはない、とおもう。たぶん。

あとはsqliteで取得時刻、温度、湿度を書き込むようにすれば出来上がり。

## 自動実行の処理

起動時自動実行は[こちらの方の解説が大変わかりやすかったです](https://qiita.com/molchiro/items/ee32a11b81fa1dc2fd8d)。

systemdを利用してサービス登録し、おおむね完了。注意点としては、スクリプト内で指定するファイルのパスは、絶対パスで指定する点。一件動いているように見えて、データの書込み先が行方不明になります(なりました)。

## 実行結果

実際に職場で計測する前に、自宅の一室で24時間ほど動かしてみた結果がこちら。30秒ごとに取得したモノを1分単位で平均を取ってご家庭によくあるPowerBI Desktopで適当にグラフ化。

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139416/f59695ad-9f94-25b9-c086-7553fd6bf6ba.jpeg)
<sub>(本来なら気温と湿度の2軸グラフにするべきなんでしょうが、線が重なって見づらいのでこれでいいや。)<sub>

室温は割と安定して取れていますが、湿度はたまに大きくぶれるようです。帰宅後にエアコンを入れたのがモロわかりですね。在室時は湿度のブレがかなり大きいですが、人間やエアコンが比較的近いところにある影響でしょうか。

まあ、これくらいの情報が取れれば、おおむね問題無いでしょう。実運用でも最低限の<sub>(素人的な意味で)</sub>説得力があるデータになる、んじゃないかな？

## Q&A

Q:写真のセンサーの位置だと、本体の熱の影響が出るのでは？

A:ほんのりケースから熱が伝わってくるので、影響がないとは言い切れません。一応、設置場所は微風が流れるようにしました。<br>持ち運びの都合で本体上に固定してますが、テープで貼ってあるだけなので付け替えは楽です。

Q:センサーからの読み込み失敗が多発しているのは、本体からのノイズが影響しているのでは？

A:失敗時のエラーコードを見る限り、CRCエラーではなく、MISSING DATAエラーの方が多発していました。<br>データの取得でミスってるので、取得タイミングの問題かなー、などと思っているのですが、ビットの話はよくわからんので連打実行で対処してます。<br>なお、ワイヤをギリギリまで本体から伸ばしてみたりしましたが、あんまり変わりませんでした。

Q:工作雑過ぎない？

A:**ですよね。**

Q:プログラム適当過ぎない？

A:**ですよね。**

## なお

この件を書いてまとめている最中に、ビルの大家がダイ○ンの人を連れて居室調査に来ました。どうやら、空調リフレッシュ工事を行う模様。

**それをもっと早くやってくれと(略**

以上。

## 9月12日追記

なんどかよく分からない失敗(ログが取られていない、時間が合っていないなど……理由が今もって不明)をへて、ひとまず在室時間中分の職場でのログを得ることが出来ました。

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139416/89f9203f-d352-6d80-60e1-219b6546a1be.jpeg)

比較的外気温が低め安定の日だったこともあってか、温度については思った以上に安定しているように見えます(設置場所の場合)。

対して湿度はかなり激しい変動状態です。1時間単位で高値と低値を繰り返すあたり、何かの制御は働いているが、とてつもなく雑な制御のように思えます。

これとは別に飾っていたタニタの温湿度計では、温度は25～30℃、湿度は45～70%を記録しており、調整や設置の影響が大きいことを思わせます。

**どっちにしてもこの環境は大変厳しいので、さっさとどうにかして欲しいものです。**

こんどこそ以上。