Hobby Science&Experiment

愛と工作の日々

趣味でやっている工作や勉強したことのメモ書きです。

Raspberry Pi3+でCO2濃度測定+CSVデータ取得とプロット(Python3)

自宅スマート化の一環として、CO2濃度のモニタリングには以前から興味がありました。新型コロナの影響で在宅勤務が増えたため、業務効率向上につながればと思い挑戦してみることにしました。。

f:id:tara-chang:20200501205246p:plain
安価なCO2センサーMH-Z19B
しかしいざ取り掛かろうとすると、先人達の情報は豊富に存在するのですが、人によって方法が異なるため結構迷子になりました。備忘録として最終的に私が成功した方法を記録しておくことにしました。

この記事でやること

・Raspberry Pi3のUARTを有効にする。
・Raspberry Pi3とCO2センサー(MH-Z19B)を配線する。
・MH-Z19Bのモジュールインポートとpythonコード作成。
・一定時間ごとにCO2濃度を取得し、データをプロット及びCSV出力する。

準備

・Raspberry Pi3+
・配線用ジャンパーケーブル、ブレッドボード等適宜
・CO2センサー(MH-Z19B)
Aliexpressで送料込みで15$程。注文から2週間ほどで無事届きました!
ja.aliexpress.com
f:id:tara-chang:20200423224309p:plain
 

配線

センサーモジュールにはピンがないため、このままではラズパイに繋ぐことが出来ません。ジャンパーケーブルをぶっ刺して半田付けも考えましたが、今回は購入時についてきたケーブルを有効活用することにしました。ケーブルの先の被膜を剥き、ピン(抵抗の足)を半田付けしました。これでブレッドボードに接続できます。茶色と白の線は使わないため切ってしまいました。ケーブルとモジュール端子の対応は以下の通りです。
赤線:Vin
黒線:GND
青線:RX
黄線:TX

次にラズパイに接続します。RXはReceiver、TxはTransimitter(送信機)だそうですから、これらはクロスにして繋ぐことになります。

センサー側 ラズパイ側
GND
GND
VCC
5VO
RX
TXD0(14pin)
TX
RXD0(15pin)

※pinはGPIO番号です。

f:id:tara-chang:20200423222017p:plain
mh-z19b

こちらの回路図を参考にしました。ちなみにpythonライブラリもこの方が開発してくださったものを有難く使わせて頂きますm(__)m

環境設定

※予めpip3はインストールしてあります。後半のプロットにはpandas、numpy、matplotlibも使用してますが、とりあえずCO2濃度取るだけでしたら必要ありません。
まずラズパイでLXTerminalを起動。次のように入力しvi エディタでconfig.txtを開きます。実際の操作はTera Termを通して行っています。

$ sudo vi /boot/config.txt

viエディタの操作は独特で所見では面食らいます(^^;)
起動時はテキストの入力ができないようになっています(コマンドモード)。
最終行の最後尾にカーソルを合わせ、oをタイプすると新しい行が作成されます。
入力モードに変わり追記ができるようになっているので、enabek_uart=1と入力します。
f:id:tara-chang:20200423194818p:plain
ESCキーで入力モードを抜け、:wq!を入力してエンターすると、変更が保存されエディタが閉じます。保存せず閉じる場合は、:q!を入力します。
OSを再起動することでUARTが有効になりました。UARTとはUniversal Asynchronous Receiver Transmitterの略でシリアル通信装置の一種…だそうです。

$ sudo reboot

ライブラリをインストールします。

$ sudo pip3 install mh-z19

結果

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting mh-z19
Downloading https://www.piwheels.org/simple/mh-z19/mh_z19-0.4.1-py3-none-any.whl (7.2 kB)
Collecting argparse
Downloading argparse-1.4.0-py2.py3-none-any.whl (23 kB)
Collecting getrpimodel
Downloading https://www.piwheels.org/simple/getrpimodel/getrpimodel-0.1.15-py3-none-any.whl (2.9 kB)
Requirement already satisfied: requests in /usr/lib/python3/dist-packages (from mh-z19) (2.12.4)
Requirement already satisfied: pyserial in /usr/lib/python3/dist-packages (from mh-z19) (3.2.1)
Installing collected packages: argparse, getrpimodel, mh-z19
Successfully installed argparse-1.4.0 getrpimodel-0.1.15 mh-z19-0.4.1

無事インストールできたようです。

CO2濃度測定

次のコマンドでCO2値を取得できます。

$ sudo python3 -m mh_z19

{'co2': 477}のような値が出れば成功です。Pythonファイルの中で使用する際は、例えば以下コードでCO2値を取り出せます。

#CO2.py
import mh_z19
co2 = mh_z19.read_all()["co2"]
print(co2)

最初のほうはnullが出てたのですが、10回ほど入力すると値が出始めました…汗。
結線直後は実際より明らかに低い値(410ppm)が出ますが、段々安定してきます。暖機に時間がかかるんでしょうか。CO2センサーの仕組みも調べたら追記します。

ログデータ取得・プロット

10秒ごとに経時変化を連続取得してcsvファイルに出力してみます。ブラウザからモニタリングも出来るみたいですが、少し難しそうだったので今回はpythonで書いてみました。備忘録なので一応コードを載せておきます。

import pandas as pd
from datetime import datetime
import mh_z19
import time

df = pd.DataFrame({'date': [], 'co2': []})#データフレーム作成
while True:
    co2 = mh_z19.read_all()["co2"]
    date=datetime.now()#日時取得
    print(date, " CO2=", co2)

    dfx = pd.DataFrame({'date': [date], 'co2':[co2]})#追記行の作成 
    df=df.append(dfx)#df最後尾に追加
    df.to_csv('./co2.csv')#csvに出力
    time.sleep(10) #10秒待機 

 一日在宅で過ごした後、プロットしてみました。なんか測れてそうな感じです!
f:id:tara-chang:20200422225427p:plain
 プロットのコードも置いておきます。

#co2log.py
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime as dt
df = pd.read_csv('./co2.csv')
x = pd.to_datetime(df['date'])
y = df["co2"]

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

ax.plot(x,y, color="black", lw=2)
daysFmt = mdates.DateFormatter('%H:%M')
ax.xaxis.set_major_formatter(daysFmt)
ax.set_xlim([dt(2020,4,21,9,0),dt(2020,4,21,19,0)])

ax.text(dt(2020,4,21,19,1), 400, "400ppm", size = 15, color = "green")
ax.axvline(dt(2020,4,21,11,25), ls = "--", color = "blue", lw=1)#換気(1回目)
ax.axvline(dt(2020,4,21,16,11), ls = "--", color = "blue", lw=1)#換気(2回目)
ax.axhline(400, ls = "--", color = "green", lw=1)
ax.set_ylabel("CO2 conc. [ppm]")#, fontsize=12)
fig.savefig("co2_plot.png")

青線は窓を開けて換気した時間、赤線は窓を閉めた時間です。換気によってCO2濃度が低下し、大気のCO2濃度に近い400ppmで一定となっていることがわかりました。校正にも問題なさそうです。前日は換気をしなかったので初期値が高めになっています。11時ごろに謎のピークがありますが、呼気が掛かってしまったのかもしれません。

f:id:tara-chang:20200422231905p:plain
換気時間とセンサーの反応にはラグがありますが、CO2濃度は10分もあれば大気レベルまで落ちるようですね。窓を一つしか開けていなくても十分空気が入れ替わることもわかりました。

今後の計画

・CO2濃度が一定を超えるとアレクサもしくはスマートフォンからからアラートを出す。
スマホタブレットのホーム画面上にCO2濃度、湿度等を表示するウィジェット
・スイッチボットで換気扇をオンにし自動で換気を行う。
・CO2濃度と生体情報の相関とか取ってみたい。
・I2C LCDに取得値を表示。➡こちら