製品レビュー|電子機器7:CO2センサ(MH-Z19C)
1.概要
購入した製品の使い方および感想用記事です。
今回は「CO2センサーモジュール MH-Z19C(2,480円/個(税込))」をレビューしました。
1-1.基本仕様
MH-Z19CはNDIR(非分散型赤外)方式の二酸化炭素のセンサであり、モジュールとして一体化しています。
https://akizukidenshi.com/goodsaffix/MH-Z19C_20210518.pdf
1-1-1.仕様の概要
基本の概要は下記参照。
電源電圧:4.5~5.5V (MAX:5.0V)
CO2濃度:400~5000ppm
分解能:1ppm
精度:±50ppm+読み取り値の5%
インターフェイス:UART・PWM
周辺環境:
温度:-10~50℃
湿度:0~95% RH(凝集水は無きこと)
予熱時間:1min
反応速度:$${T_{90}}$$<120sec=2min
1-1-2.ピン配置
ピンの配置は下図の通り
1-2.詳細仕様
センサの出力値は「PWM」か「UART」で選択することが出来ます。
1-2-1.出力値1:PWM信号
PWM信号でのCO2濃度計算は下記の通りです。
$$
CO_2濃度[ppm]=2000\times \frac{TH-2ms}{T-4ms}
$$
TH:サイクル中のHigh level 出力時間▶PWMでのパルス幅
T:サイクル中の出力時間(1004ms±5%)▶PWMでの周期
参考としてPWMの詳細は下記記事に記載しています。
1-2-2.出力値2:UART
シリアル通信のUARTを使用する場合、仕様は下記の通りです。
【ハードウェア接続】
モジュールのVin-GND-RXD-TXDをマイコンの5V-GND-TXD-RXDに接続
※RS232 levelでなく、TTL levelを使うことと記載があるが、よくわからないので追って追記
【ソフトウェア設定】
UARTに関連する設定値は下記の鳥
シリアルポートバウンドレート:9600
データビット:8byte
ストップbit:1byte
パリティービット:Null
【0x79 Turn on/off self-calibration function】
【Checksum calculation method】
1-2-3.ゼロ点校正(400ppm)
本モジュールはゼロ点校正として「:hand-operated method」と「self-calibration」の2手法があり、両方とも400ppmで校正を行う。
校正時の条件は「センサーが20min以上400ppmの大気条件下にあること」である。
※大気条件=400ppmと仮定しているため、正確な校正とは言えないことに注意
2.製品原理
製品の動作原理に関する部分を説明します。
2-1.赤外線とは
赤外線とはおおよそ波長780nmから1mm程度までの波長範囲の電磁波である。可視光の波長が約400~800nmのため、肉眼では確認できません。
波長によって近赤外線(2.5 μm以下)、赤外線(2.5 μm-25 μm)、遠赤外線(25 μm以上)と区別されます。
2-2.NDIRとは
NDIRとはNon-Dispersive InfraRed(非分散型赤外線吸収法)の略であり、測定の対象となるガスが特定の波長域の赤外線を吸収し、その吸収の度合いがガス濃度に応じているという原理を利用したものです。
NDIRの特徴としては、赤外光を波長ごとに分散しない(光をプリズム等に通して波長に応じた光に分ける(= 分光)ことをしない)でそのまま全体を照射する技術となります。
光源から放出された赤外線は、測定対象のガスを通過したのち赤外線センサにて計測されます。 ガスにより赤外線が吸収されると、赤外線センサが受光する赤外線の光量に変化が生じます。
赤外線センサは、測定に不要な波長の赤外線を取り除く光学フィルタが備えられており、特定の波長域の赤外線のみを測定することによって対象となるガス以外の干渉を最小限に抑えます。
CO2分子の場合、波長4.26μmの赤外線を選択的に吸収する性質を持っており、赤外線エネルギーの吸収量に対する変化の関係は、CO2のガス濃度と測定セルの長さによって決まります。これをランベルト・ベールの法則といい、センサ出力と濃度は指数関数的な関係となります。
NDIR方式を用いてガス濃度計測をするための重要な項目の一つに光源の選定があり、十分な光量が得られる光源選定が必要です。そのため、多くのNDIR方式CO2センサーには”十分な光量が得られ”、”CO2センサーに必要とされる波長:3µm~5µmで比較的大きな放射出力”をもつ、タングステン・フィラメントを用いた白熱電球が使用されています。
白熱電球以外の光源としてはLEDがあり、小型化・低消費電力化が可能ですが、放射出力がやや小さく、出力される波長域も限定的です。二波長方式のNDIRセンサーを構築するためには、2つのLED光源が必要となります。
NDIRの装置構成は下図の通り。
2-3.ランベルト・ベールの法則
ある媒質の濃度とこの媒質によって光が吸収される割合との間に一定の関係(ランベルト・ベールの法則)があり、光が均一な媒質を透過するとき透過光の強度の減少量$${\frac{I_0}{I}}$$は光の強度と媒質の厚さ(光路長:$${l}$$)に比例します(ランベルトの法則)。また、この媒質が溶液の場合、媒質の厚さ($${l}$$)が等しければ、吸収される光の量は溶液の濃度($${c}$$)に比例します(ベールの法則)。 これらは次式で表されます。
$$
\begin{aligned}
A & =log(\frac{1}{透過率})
\\&= log\frac{I_0}{I}
\\&=\epsilon\cdot c \cdot l
\\&= 分子吸光係数[M^{-1}cm^{-1}]\times 溶液濃度[M/L]\times 光路長[cm]
\end{aligned}
$$
2-4.ガスの吸収波長(吸光帯)
水(湿度)があってもCO2濃度が計測可能な理由としてはH2OとCO2の吸光帯が重なっていないからだと思います。
上記以外は適切な参考文献が見当たらなかったので、参考レベルとして資料載せておきます。
3.部材購入
3-1.購入品
部品は本体のみ購入しました。
3-2.準備必須品
その他必需品は下記の通りです。
マイコン/シングルボード(Raspberry Pi/Pico)
ブレッドボード
ジャンピングワイヤー
4.環境構築
4-1.マイコン準備
センサを制御するためのシングルボードやマイコンの準備を行います。
Raspberry PiやPicoの準備は下記記事参照のこと
Raspberry PiにGPIOを制御するためのライブラリが無い場合は”RPi.GPIO”を事前にインストールしておきます。
Picoの場合はMicropythonを使用できるようにしておきます。
[Terminal]
pip install rpi.gpio
4-2.ライブラリ
Raspberry Pi Picoは組み込み関数と標準ライブラリで対応できるため、追加の環境構築は不要です。
Raspberry Piの場合はそのままだとシリアル通信(UART)の実装が手間ですが、PyPIにライブラリが公開されているためこちらを利用します。
[Terminal]
pip3 install mh_z19
5.使用前の準備
5-1.はんだ付け
本製品の既にピンがつけられているため、はんだ付けは不要です。
5-2.部品の組付け
部品の組付けはジャンパー線を使用して下記の通り繋ぎました。
※UART通信はマイコンのTX▶センサーのRxに繋ぐのに注意
【Raspberry Pi】
MH-Z19C|Vin▶ラズパイ|4pin(5V)
MH-Z19C|GND▶ラズパイ|6pin(GND)
MH-Z19C|Tx▶ラズパイ|GPIO15(RXD)
MH-Z19C|Rx▶ラズパイ|GPIO14((TXD))
【Raspberry Pi Pico】
MH-Z19C|Vin▶Pico|40pin(5V)
MH-Z19C|GND▶Pico|38pin(GND)
MH-Z19C|Tx▶Pico|GP17(UART0 RX)
MH-Z19C|Rx▶Pico|GP16(UART0 TX)
6.MicroPythonスクリプト(Pico)
6-1.任意:デバイス接続の確認
UART通信のためデフォルトで確認コマンドはありません。配線完了時に本体が点灯しているかだけ確認しておきます。
[Terminal]
-
6-2.コードの設計思想
設計思想は下記の通りです。
UARTでのCO2濃度読み取りは"Sending command"の値を使用
8byte値:”\xff\x01\x86\x00\x00\x00\x00\x00\x79”
uart.read()による戻り値は9byteであり、CO2データはByte2とByte3
Byte2がHIGH値であり、Byte3がLOW値
$${CO_2濃度=256\times HIGH+LOW}$$
戻り値が正しいことを確認するためにif文追加
データ数は最低でも4byte以上(Byte0~Byte3)
Byte0は0xFFであり、Byte1は0x86
ゼロ点校正は”0x79 On/Off Self-calibration for Zero Point”の値を使用
送るコマンドは9Byteであり、Byte3は選択、Byte8はChecksum
Byte3=0xA0:自動校正がON
Byte3=0x00:自動校正をOFF
【CO2濃度読み取り】
【戻り値】
【ゼロ点校正】
6-3.スクリプト実行
スクリプトを作成し、実行しました。なお実行と同時にセンサーに息を吹きかけてCO2濃度の変化を確認しました。
Gif(画像)はprint文をコメントアウトし、フレームも削減しています。
[IN]
from machine import Pin, UART
import time
#設定条件
CH_UART = 0 #PicoのUART0を使用
No_PIN_TX = 16 #TXのGPIO番号
No_PIN_RX = 17 #RXのGPIO番号
uart = UART(CH_UART, baudrate=9600,
tx=Pin(No_PIN_TX), rx=Pin(No_PIN_RX))
def auto_calibration(flag=False):
if flag:
uart.write(b"\xff\x01\x79\xa0\x00\x00\x00\x00\xe6")
print('Auto Calibration is Done')
else:
uart.write(b"\xff\x01\x79\x00\x00\x00\x00\x00\x86")
#自動校正
auto_calibration(False) #自動校正の設定
time.sleep(1)
#CO2濃度の取得
while True:
#計測値の取得
uart.write(b"\xff\x01\x86\x00\x00\x00\x00\x00\x79") #CO2濃度の取得
data = uart.read(9) #9バイト読み込み
print(data) #中身確認用
#計測値の表示
if len(data) >=4 and data[0] == 0xff and data[1] == 0x86: #確認:データ数4以上、先頭2バイトが0xff,0x86
co2 = data[2] * 256 + data[3]
print(f'CO2: {co2} ppm')
else:
print('No Data')
time.sleep(1)
[OUT]
b'\xffy\x01\x00\x00\x00\x00\x00\x86'
No Data
b'\xff\x86\x02\x96A\x00\x00\x00\xa1'
CO2: 662 ppm
b'\xff\x86\x02\x95A\x00\x00\x00\xa2'
CO2: 661 ppm
センサの検出速度は所定濃度の90%に達するまで120secかかるため、非常にゆっくり検出されることが確認できました。
【おまけ:自動校正ON】
濃度が安定してからゼロ点校正を実行してみました。実行後に濃度が400ppmになったわけではないので、どこかのタイミングで勝手に校正されるものだと思われます。
7.Pythonスクリプト(Raspberry Pi)
参考までにRaspberry Piでも実行しました。配線は5章参照のこと。
7-1.スクリプト実行
ライブラリをpip install後にターミナルから下記コマンドを実行するとCO2濃度を出力できます。
[Terminal]
sudo python3 -m mh_z19
7-2.Jupyterで実行
Jupyterで実行確認しました。結果としてConda環境の有無にかかわらずエラーが発生しました。おそらくJupyter上からだとシリアルポートへのアクセス権限がないためと思います。
対応としては権限設定すればいけると思いますが、本記事では対応せずCLOSEとします。
[IN]
import mh_z19
def read():
out = mh_z19.read()
return str(out)[8:-1]
co2=read()
print(f'CO2濃度:{co2}ppm')
[OUT]
CO2濃度:ppm
Traceback (most recent call last):
File "/home/kiyo/miniforge3/lib/python3.10/site-packages/serial/serialposix.py", line 322, in open
self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
PermissionError: [Errno 13] Permission denied: '/dev/serial0'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/kiyo/miniforge3/lib/python3.10/site-packages/mh_z19/__init__.py", line 67, in read_concentration
ser = connect_serial()
File "/home/kiyo/miniforge3/lib/python3.10/site-packages/mh_z19/__init__.py", line 58, in connect_serial
return serial.Serial(serial_dev,
File "/home/kiyo/miniforge3/lib/python3.10/site-packages/serial/serialutil.py", line 244, in __init__
self.open()
File "/home/kiyo/miniforge3/lib/python3.10/site-packages/serial/serialposix.py", line 325, in open
raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 13] could not open port /dev/serial0: [Errno 13] Permission denied: '/dev/serial0'
8.所感
簡単な所感は下記の通り
思った以上に感度(検出速度)が遅い(2min)。観測用くらいならこれでもいいかもしれないけど。
室内用とのことであり、大気中のCO2計測には下限値が低すぎる。
そもそも校正ガスを使用していない校正(大気濃度=400ppm)を、校正とよんでいいのか??
ライブラリを用意してくれている人には感謝
参考資料
別添1 Python関係
別添2 技術関係
あとがき
この手のセンサ類の校正ってどうしているんだろうか??