みかんのゆるふわ技術ブログ

Raspberry PiやIoT関係のことを書き残していきます

Raspberry Piに22ドルの二酸化炭素(CO2)センサーをつなぐ

中国のお店が中国国外に売る通販モールAliExpressで、センサーをいくつか購入しました。 今回はその中の1つ、二酸化炭素(CO2)濃度が測れるセンサーをRaspberry Piにつないでみました。 なんと、黄金に輝く✨ゴージャスなセンサーです!

www.aliexpress.com

中国の河南省にあるWinsenというガスセンサーメーカーの製品MH-Z14Aです。

前回までメーカーもよく分からないノーブランドの安いセンサーモジュール(大手メーカーのセンサーを基板に載せただけのブレイクアウトボード)ばかり紹介してきましたが、今回はちゃんとしたメーカー品です。

Amazon.co.jpのマーケットプレイスでも手に入るみたいです。

AliExpressにはメーカー公式店もあり、そこでは2個セットで44ドル(記事執筆現在)となっています。

他のお店では1個だけのばら売りもされています。 私が見た時はこのセンサーがセール中のお店があり、値段はなんと$14.4でした!20ドル以下で売っている店はあまりなかったのでお買い得でした!(ちゃんと届くか心配でしたが、無事届きました)

趣味のDIYには高価💸とはいえ、1個から買える二酸化炭素センサーとしては、安いのではないでしょうか。

また、同メーカーからMH-Z19Bというセンサーも発売されており、同じくらいの値段で買えます (私は違いがよくわかっていませんが…)。 どちらも、UARTのコマンドインターフェースは共通のようですので、同じPythonプログラムが使えます。

二酸化炭素濃度とは?

二酸化炭素(CO2)はものを燃やしたり🔥、人間など動物の活動🏃‍♂️によりできる気体です。 逆に植物🪴は二酸化炭素と光を使って光合成をすることで、栄養を作って成長します。

人間の吐く息には4%くらいの二酸化炭素が含まれているようなので、人がいる室内だと屋外より二酸化炭素濃度が高くなります。 石油ストーブやコンロなど火をを使うと、さらに二酸化炭素が発生します。換気しないといけませんね。

逆にビニールハウスのような植物だけの密閉空間だと、大気中よりも二酸化炭素濃度が低くなり、 換気せず放っておくと光合成に影響が出て作物の出来に影響したりもするそうです。

空気中の二酸化炭素濃度

屋外の大気中の二酸化炭素濃度は変動あるものの、気象庁の観測によれば410ppmくらいのようです。

???「わしが小学生の頃は空気中の二酸化炭素の割合は0.03%くらいと習ったんじゃがのう…」

という方もいらっしゃるかもしれませんがそれは昔の話で、二酸化炭素の割合は猛烈に増加中で、すでに0.04% (400ppm)を突破しています。 温室効果ガスの中でも、気候変動への影響が大きいようです。

二酸化炭素濃度と換気の目安

二酸化炭素の濃度は快適性健康に影響を与えるそうです。 密閉された室内に人がいると二酸化炭素濃度が上昇するので、換気が必要です。

1000ppm以下なら十分換気されていて快適な環境です。 2000~5000ppmくらいになってくると、集中力の低下や眠気、頭痛などが起こることがあるようです。 10000ppmを越えるようだと、健康に影響を及ぼす事態になりかねません。

ちなみにppmとは100万分のいくらかという割合を示す単位です。10,000ppm=1%、100ppm=0.01%です。

このように健康に関わるものなので、 例えば学校🏫では平均で1500ppm以下を保つことなどが国の基準が定められています。

今であれば、新型コロナウィルス対策で換気が十分かを示す目安としても使えるかもしれませんね。

MH-Z14Aとは?

私にしては珍しくとても高価高級なセンサーを買ってしまったので、前置きが長くなりました。

AliExpressのお店で注文して待つこと約3週間、ついにセンサーが到着しました。

f:id:kimura_khs:20210204192719j:plain

こちらがMH-Z14Aです。ピンヘッダをはんだ付けした後の写真です。 金色に輝く✨センサー部分がかっこいいですね。

メーカー品だけあって、ちゃんと公式サイトやデーターシートもあります。

CO2測定性能

このセンサーはNDIR方式(非分散型赤外線分光法)という方法で測定するセンサーです。

私は詳しくないので説明できないのですが、Webで検索すると測定原理の解説記事が出てきます。 分子によって特定の波長の光を吸収する性質があるので、赤外線を使って吸収率を測定することでCO2濃度がわかる、という感じなのかな? 金メッキが施されているのは、長期的に安定して測定するためのようです。

このセンサーで0~5000ppmの二酸化炭素濃度を測定できるとのことです。 普通のご家庭ならこれだけ測れれば十分でしょう。この上限を越えるようなら直ちに換気!!

インターフェース

電源は5Vで、センサー値はUART、PWM、アナログ電圧の3通りの方法で読み出せます。 今回はRaspberry PiにつなぎやすいUARTを使用しました。

電源は5Vですが、UARTは3.3V(5Vトレラント)です。 電源に5Vを用意する必要はありますが、5V、3.3Vどちらのマイコンにもつなぎやすくなっています。

コネクタとスルーホールの2通りの接続方法が選べます。今回はスルーホールにピンヘッダをはんだ付けして使用しました。 スルーホールの左下4つのピンがUARTと電源になっています。

Raspberry Piにつないでみよう

f:id:kimura_khs:20200922113215p:plain
画像出典: raspberrypi.org

Raspberry Piのピンヘッダは上図のように機能が割り当てられています。このモジュールはUARTで通信するので、次のピンに接続します。

RasPiピン番号 RasPi 機能 MH-Z14A 説明
4 5V power V+ 電源(5V)
6 Ground V- グランド (0V基準電圧)
8 GPIO 14 (TX) R UART (RasPi→MH-Z14B)
10 GPIO 15 (RX) T UART (MH-Z14B→RasPi)

UARTは2つの機器を1対1でつなぐ通信方式で、A→B、B→Aの片方向ごとに1本ずつ線があり、2本の線で通信します。 一方の機器の送信端子(TX)をもう一方の受信端子(RX)につなぎます。なので、このような接続になります。

これらをジャンプワイヤーでRaspberry Pi Zero WHに接続すると、次のようになりました。

f:id:kimura_khs:20210207143858j:plain

Raspberry Pi Zero WHの場合、1番ピンはSDカードスロットの横にあたります。

PythonからMH-Z14Aにアクセス

UARTの有効化

Raspberry Pi OSのインストール直後はUARTが無効になっています。 有効化するには、raspi-configのメニューから設定できます。

$ sudo raspi-config

で設定画面を起動し、"5 Interfacing Options" → "P6 UART"選択してください。

f:id:kimura_khs:20210207135704p:plain:w400

"Would you like a login shell to be accessible over serial?"と聞かれます。UARTをログインシェルとしても利用できるのですが、今回はセンサーを接続したいのでNoを選びます。

f:id:kimura_khs:20210207135825p:plain:w400

"Would you like the serial port hardware to be enabled?"と聞かれます。ここでYesを選びます。

以上でUARTの有効化ができました。Linux上からUARTへは/dev/ttyS0というデバイスファイルとしてアクセスできます。

動かしてみよう

Raspberry Pi OSからMH-Z14Aにアクセスできる準備が整いました。 Pythonからアクセスしてみましょう。

Pythonライブラリのインストール

PythonからUART通信をするには、pySerialというライブラリの利用が便利です。

pythonhosted.org

次のようにして簡単にpySerialをインストールできます。

$ sudo apt install python3-pip
$ pip3 install pyserial

これで準備が完了です。

MH-Z14Aのセンサ値読み取り方法

MH-Z14AはUARTでどのようにセンサー値を出してくるのでしょうか?データシートを見てみましょう。

f:id:kimura_khs:20210207140101p:plain:w400
出典: MH-Z14Aデータシート

9600bpsで通信し、5つのコマンドを使って設定や二酸化炭素濃度読み取りを行うようです。 二酸化炭素濃度読み取りコマンドは、0x86ですね。

このセンサーはキャリブレーションにも対応しています。屋外の二酸化炭素濃度は概ね400ppm程度なので、 このセンサーを屋外に放置してキャリブレーションコマンドを実行することで、その濃度を400ppmとして記憶し、補正を行います。

時々これを実行することで、長期的に安定して正確な値が測定できると思います。 まあ、ご家庭のDIYならそこまで精度はいらないので、キャリブレーションは行わずに使います。

f:id:kimura_khs:20210207140130p:plain
出典: MH-Z14Aデータシート

二酸化炭素読み取りコマンドの詳細がこちらの表です。9バイトのコマンドを送ると、9バイトの応答がセンサから帰ってくるようです。 コマンドは常に固定でいいみたいですね。応答の2バイト、3バイト目(※0バイト始まり)が二酸化炭素濃度です。

これを踏まえて、Pythonプログラムを作ってみましょう。

動かしてみよう

簡単ではありますが、次のようなプログラムを作ってみました。

import serial
import time

s = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=0.1)

def read_co2():
    # Send command to MH-Z14A
    s.write(bytes([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))
    # Read response
    data = s.read(9)

    # Is response length correct?
    if len(data) != 9:
        print("Response length is not correct.")
        s.reset_input_buffer()
        return None

    # Is this a valid command response?
    if data[0] != 0xFF or data[1] != 0x86:
        print("Not a valid response")
        s.reset_input_buffer()
        return None

    # Checksum
    checksum = 0xFF - (sum(data[1:7]) & 0xFF) + 1
    if checksum != data[8]:
        print("Checksum error!")
        s.reset_input_buffer()
        return None

    # Return CO2 level [ppm]
    return data[2] * 256 + data[3]

while True:
    co2 = read_co2()
    print(co2, "ppm")
    time.sleep(1)

s = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=0.1)でUARTポートを開き、s.write(bytes([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))で二酸化炭素読み取りコマンドを送信、data = s.read(9)で応答の9バイトを受信します。あとは応答がちゃんと受信できたかを確認し、最後に2バイト目と3バイト目から二酸化炭素濃度を計算して表示します。

コマンドが単純ですし、pyserialを使えばドライバも簡単に書けますね。

このプログラムをread_co2.pyなどのファイルに保存して、実行してみましょう。

$ python3 read_co2.py
753 ppm
...

このように二酸化炭素濃度が読み取れました!1000ppmを下回っているので、換気は十分のようですね。 試しに窓を開けてみると、400ppm台に下がりました。

二酸化炭素濃度が一定値を超えるとアラームを出したり、いろいろ遊べそうですね☺️ 皆さまもいろんなDIYを試してみてください!