🌡️

Raspberry Pi で温度・湿度・CO2を監視する

2021/08/04に公開
1

コロナ禍によって巷にCO2センサーがあふれていますが、適切な空調設定や換気のために、室内の温度・湿度・CO2を測定してみたいと思います。

まず、Rapsberry Piに温度・湿度・CO2センサを接続し、空気の状態をモニタリングできるようにします。測定したデータは時系列データベースであるInfluxDBに保存し、システム監視等でよく使われるデータ可視化ツールGrafanaでデータの可視化を行います。これすべてをRaspberry Piの中で完結させます。

CO2センサーについて

CO2センサーには、測定方式によっていくつかの種類がありますが、一般的に入手しやすいセンサーはNDIR方式(非分散型赤外)が多いと思います。原理は正確で詳しい説明をされているサイトがたくさんあるのでそちらを参照してもらうとして、センサーの一部が不織布で覆われていて、測定中は赤く点滅するのが特徴です。他にも、水素濃度から等価的にCO2濃度を測定する eCO2 (qquivalent CO2) 方式などもあります。こちらは、CO2そのものをターゲットしているわけではないので、高い精度は出しにくいようです。

今回はCO2センサーとして SENSIRION の SCD-4x を使用します。温度・湿度・CO2センサーが搭載されており、NDIR方式とは別の、光音響センシング原理により小型化を実現させています。

https://www.sensirion.com/jp/environmental-sensors/carbon-dioxide-sensors/carbon-dioxide-sensor-scd4x/

Rasberry Piと簡単に接続でききるように、評価ボードの形になった SEK-SCD-41 を使用します。

https://www.digikey.jp/product-detail/ja/sensirion-ag/SEK-SCD41-SENSOR/1649-SEK-SCD41-SENSOR-ND/13684004

CO2の測定

I2C の有効化

SCD-41とRaspberry PiとはI2Cで通信するため、 raspi-config でI2Cを有効化します。

sudo raspi-config

メニューから 3 Interface Options - P5 I2C を選択し、I2Cを有効化します。設定後の再起動は必要ないようです。

ソフトウェアのインストール

SCD-41と通信するためのソフトウェアをインストールします。SENSIRION の Github でSINSIRIONの様々なセンサーのソフトウェアが公開されており、ドキュメントも非常に充実しています。SCD-4xのRaspberry Pi用のソフトウェアも公開されています。

https://github.com/Sensirion/raspberry-pi-i2c-scd4x

ただし、SINSIRIONが公開しているトライバはC言語で実装されているため、センサーから測定値を読みだした後の扱いやすさを考慮し、Pythonで実装されているAdafruitのドライバを使用します。

https://github.com/adafruit/Adafruit_CircuitPython_SCD4X

Pythonの仮想環境を作成し、ドライバをインストールします。

python3 -m venv .venv
. .venv/bin/activate
pip install adafruit-circuitpython-scd4x

接続

一度、Raspberry Piの電源を落とし、SENSIRIONのGithubを参考に、SEK-SCD-41のジャンパー線と、Raspberry Piのピンヘッダを接続します。

https://github.com/Sensirion/raspberry-pi-i2c-scd4x#connecting-the-sensor

SCD-41のデータシートを見ると、電圧は 2.4 - 5.5V となっているので、Raspberry PiのGPIOは3.3Vのもと5Vのもの、どちらでもよさそうです。

https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/9.5_CO2/Sensirion_CO2_Sensors_SCD4x_Datasheet.pdf

Raspberry Piの電源を投入し、I2Cのデバイスとして認識されているかを確認します。 0x62 として認識されているのが確認できます。

$ 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: -- -- 62 -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

動作確認

Adafuruitのサンプルコードをそのまま実行してみます。

https://github.com/adafruit/Adafruit_CircuitPython_SCD4X#usage-example

$ python scd4x-example.py
Serial number: ['0x81', '0xba', '0x1f', '0x7', '0x3b', '0xe3']
Waiting for first measurement....
CO2: 991 ppm
Temperature: 31.5 *C
Humidity: 54.4 %

CO2: 969 ppm
Temperature: 31.2 *C
Humidity: 55.1 %

CO2: 974 ppm
Temperature: 30.9 *C
Humidity: 55.7 %

無事、測定値の取得を行うことができました。それっぽい値が取れています。明らかにCO2濃度がおかしい場合は、自動補正が効くのを待つか、強制的に補正を行う必要があります。詳細はデータシートに記載されていますが、今回は省略します。

次は、データの保存と蓄積を行います。

データの保存

InfluxDB のインストール

InfluxDB をインストールし、自動起動の設定を行います。InfluxDBは2.0がリリースされていますが、ARM系は64bit OSしかバイナリが用意されていないようなので、aptコマンドでインストールできる1.x系をインストールします。

sudo apt install influxdb
sudo systemctl start influxdb
sudo systemctl enable influxdb

1.6.4 がインストールされました。(随分と古いような…。)

$ dpkg -l | grep influxdb
ii  influxdb                               1.6.4-1+deb10u1                         armhf        Scalable datastore for metrics, events, and real-time analytics

Python クライアントのインストール

InfluxDB にデータを書き込むために Python クライアントをインストールします。2.0系統はクライアントが異なるので注意してください。

https://github.com/influxdata/influxdb-python

pip install influxdb

最初にデータベースとユーザー、リテンションポリシーを作成します。InfluxDBではリテンションポリシーを設定できるため、バッチ処理で古いデータを削除する必要はありません。また、今回は使用しませんが、continuous queriesといって、クエリをを定期実行する機能もあるので、生データは3か月保存するけど、1時間毎に最大・最小・平均を求め、ダウンサンプリングしたデータは1年間保存する、なんて使い方もできます。

データの書き込み

先ほどのSCD-4x用のサンプルを改修し、測定データをInfluxDBに書き込むようにします。変化が分かり易いように1秒間隔でデータを書き込んでいますが、実際に運用する場合は、microSDの耐久性を考慮し、もう少し長い間隔にした方がよいでしょう。(ドライブレコーダーなどと比較すれば、1秒間隔でもかわいいものですが。)

InfluxDBでは、RDBMSにおけるテーブルに相当するものをmeasurementと呼び、カラムに相当するものをfield呼びます。このfieldに測定値である温度・湿度・CO2を保存していきます。またレコードには tag をつけることができ、この tag を使ってフィルタリングやグルーピングを行うことができます。

スクリプトを実行します。

scd4x-influxdb-write.py
$ python scd4x-influxdb-write.py
Serial number: ['0x81', '0xba', '0x1f', '0x7', '0x3b', '0xe3']
Waiting for first measurement....
[{'measurement': 'air_condition', 'tags': {'host': 'raspberry-pi-01'}, 'time': '2021-07-30T13:02:56.959541+00:00', 'fields': {'tempareture': 29.8, 'humidity': 46.3, 'co2': 1661}}]
[{'measurement': 'air_condition', 'tags': {'host': 'raspberry-pi-01'}, 'time': '2021-07-30T13:03:01.744396+00:00', 'fields': {'tempareture': 29.5, 'humidity': 47.0, 'co2': 1635}}]
[{'measurement': 'air_condition', 'tags': {'host': 'raspberry-pi-01'}, 'time': '2021-07-30T13:03:06.531361+00:00', 'fields': {'tempareture': 29.1, 'humidity': 47.7, 'co2': 1636}}]
[{'measurement': 'air_condition', 'tags': {'host': 'raspberry-pi-01'}, 'time': '2021-07-30T13:03:11.317588+00:00', 'fields': {'tempareture': 28.8, 'humidity': 48.4, 'co2': 1629}}]

データが書き込めているかを確認してみます。直近、1分間の温度・湿度・CO2を取得します。

scd4x-influxdb-select.py
$ python scd4x-influxdb-select.py
ResultSet({'('air_condition', None)': [
     {'time': '2021-07-30T13:02:56.959541Z', 'tempareture': 29.8, 'humidity': 46.3, 'co2': 1661},
     {'time': '2021-07-30T13:03:01.744396Z', 'tempareture': 29.5, 'humidity': 47.0, 'co2': 1635},
     {'time': '2021-07-30T13:03:06.531361Z', 'tempareture': 29.1, 'humidity': 47.7, 'co2': 1636},
     {'time': '2021-07-30T13:03:11.317588Z', 'tempareture': 28.8, 'humidity': 48.4, 'co2': 1629}]})

データの可視化

InfluxDBに保存したデータを可視化するためにGrafanaをインストールします。

https://grafana.com/docs/grafana/latest/installation/debian/

curl -sL https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list
sudo apt update
sudo apt install grafana

インストールが完了したら、Grafanaを起動し、自動起動を有効にします。

sudo systemctl start grafana-server
sudo systemctl enable grafana-server

Webブラウザで http://raspberrypi:3000/login にアクセスします。 admin / admin でログインします。初回ログインでは、パスワードの変更を要求されます。

Grafana Login

サイドメニューから Configuration - Data sources を選択します。
Data

Add data source を選択します。
Add data source

データソースとして最低限必要な設定項目は、Name, URL, Database, User, Password になります。
Data source settings

サイドメニューから Create を選択し、ダッシュボードを追加します。
Create dashboard

Add an empty panel を選択します。
Add an empty panel

パネルの編集画面で Data source に先ほど作成したデータソースを設定し、Query を設定していきます。パネルの種類は右上で選択できます。
Panel Settings

FROM に、InfluxDB をセットアップした時の Retension policyMeasurement を設定します。Tag など、条件を追加する場合は WHERE に追加していきます。

SELECT で表示したい Field (温度・湿度・CO2)を選択します。mean() を設定すると、次に設定する GROUP BY と合わせて、単位時間当たりの平均値が取得できます。

GROUP BYtime($__interval) を設定することにより、表示する時間(直近の何時間か?)に合わせて適切にグループ化してくれま。 fill で欠損値のの補完方法指定します。 fill(null) で、グラフが線にならずに点の集合になってしまう場合には、nonelinear などを選びましょう。

色々設定するとこんな感じになります。
Dashboard

エアコンをつけていると、室温は設定温度のあたりでジグザクするようなグラフになるようです。

CO2は、外気が 400 ~ 500 ppm くらい、屋内でも 1,000 ppm 以下が推奨され、15,000 ppm を超えるようであれば換気が必要になります。
6畳程度の部屋では、一人でも閉め切っていると 15,000 ppm を超えることがあるようです。眠気や集中力の低下にもつながるので、こまめな換気を心がけましょう。

まとめ

Raspberry Pi と環境センサーを使って、室内の空気の状態を可視化することができました。大抵の温湿度センサーやCO2センサーは、I2CやUARTのインタフェースを持っているため、Raspberry Piからでも簡単に測定値を読みだすことができます。ネット上にはLEDを点灯させる(Lチカ)のたくさんありますので、それと組み合わせて、換気を促すような仕組みを実現できると思います。

Discussion

e4expe4exp

大変参考になりました.ありがとうございます.

Grafanaのインストール部分でリポジトリ情報を/etc/apt/sources.listに上書きするとその後のインストールに不具合がでるので,追記するか,またはsources.list.d以下に追加が良いのではと思いました.
https://grafana.com/docs/grafana/latest/installation/debian/#:~:text=oss/deb stable main" |-,sudo tee -a /etc/apt/sources.list.d/grafana.list,-Bash

また,Rapsberry Pi の環境によっては通常のgrafanaが動作せず,grafana-rpiなら動作することがあるようでした
sudo apt install grafana-rpi
https://github.com/grafana/grafana/issues/13008#issuecomment-1011991510