だれかの備忘録

主に自分用。

CO2(二酸化炭素)センサMH-Z19Bの測定周期等をオシロで確認

MH-Z19BはNDIR方式のCO2(二酸化炭素)センサで、赤外線がCO2に吸収される現象を利用してCO2濃度を測定するセンサモジュールです。
このMH-Z19Bを買ったのでRaspberry Piに繋いでCO2濃度を取れるようにしました。手順を簡単に触れつつ、この記事では主にオシロスコープを使って電気的なところを確認します。

やること

  • MH-Z19B 電源とUARTの端子電圧、波形の確認
  • CO2の測定周期、濃度値更新タイミングの確認

確認結果

  • MH-Z19BのVinは+5Vが必要、UARTは3.3Vの電圧レベルになる。
  • MH-Z19BのCO2測定周期は5秒、UARTで取得できる濃度値更新は測定の約1秒後。

準備

データシートの入手

データシートをダウンロードしておきます。
https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf
キーとなりそうな電気的仕様を抜粋します。

Working voltage 4.5~5.5V DC
Average current <60mA (@5V)
Peak current 150mA (@5V)
Interface level 3.3V(Compatible with 5V)
Output signal UART(TTL interface level 3.3V)

UART OUTPUT: Connect sensor Vin-GND-RXD-TXD with 5V-GND-TXD-RXD.

これらより、Vinには+5Vを入れればよく、UARTは3.3Vレベルだと分かります。Peak電流150mAは電源の安定性の点で注意が必要かもしれないので後で確認します。

接続

MH-Z19BをRaspberry Piに接続します。

RasPi側 MH-Z19B側
Pin4: +5V Vin
Pin6: GND GND
Pin8: TXD0 Rx
Pin10: RXD0 Tx
UARTでCO2濃度を取得

Pythonで10秒間隔でCO2濃度を取得するプログラムを書きます。

import serial
import time
from datetime import datetime

while True:
    ser = serial.Serial('/dev/ttyAMA0', timeout=1.0)
    ser.write(b"\xff\x01\x86\x00\x00\x00\x00\x00\x79")
    res = ser.read(9)
    ser.close()
    co2 = res[2]*0x100+res[3]

    print(datetime.now().strftime('%Y/%m/%d %H:%M:%S')+"\t"+str(co2))
    time.sleep(10)

実行結果:

2019/02/11 09:36:24     783
2019/02/11 09:36:34     782
2019/02/11 09:36:44     782
2019/02/11 09:36:54     783
2019/02/11 09:37:04     785

CO2濃度が取れています。単位は[ppm]です。

電圧レベル、波形の確認

ここからはオシロで電圧を確認します。オシロはPicoScope 3205Bを使いました。
なお測定を簡単にするためにUARTの待ち時間を0にして連続送受信するようにしました。

    time.sleep(0)
+5V (Vin)

f:id:positive_bedridden:20190211100820p:plain
+5V波形
+5V(Vin)はだいたい5.0Vです。Raspberry PiはUSBから+5Vを取っているのでそれと同じ電圧になります。

TXD0, RXD0 (Rx, Tx)

f:id:positive_bedridden:20190211103024p:plain
UART波形(青:TXD0, 赤:RXD0)
UARTの電圧レベルはTXD0, RXD0ともに3.3Vです。MH-Z19Bの電源(Vin)は5Vですが、UART Interfaceは3.3Vレベルになります。MH-Z19Bの内部で3.3Vを生成しているのでしょう。
ちなみに、Raspberry PiのRXD0やMH-Z19BのRxはオープンにしても3.3Vが出てきます。恐らくプルアップ抵抗を介してそれぞれの3.3Vに繋がっていると思います。

Raspberry Pi側からコマンドを送信した後、返信が返ってくるまでだいたい2~3msecでした。送信開始から受信完了まで約22msecです。

CO2濃度測定周期の確認

MH-Z19B内でCO2を測定している周期を確認します。データシートにも記載が無く、これが分からないとUARTでの取得周期も決めづらいので。

目視確認

センサの上にある窓から約5秒周期で薄いピンク色に点灯しているのが見えます。内部で赤外線が照射され、CO2濃度を測定しているものと思われます。

UART取得結果より推測

プログラムを

    time.sleep(1)

としてUARTでの取得を1秒周期に変更し、センサに息を吹きかけてCO2濃度の上昇を確認します。

2019/02/11 11:21:07     957
2019/02/11 11:21:08     957
2019/02/11 11:21:09     1001
2019/02/11 11:21:10     1001
2019/02/11 11:21:11     1001
2019/02/11 11:21:12     1001
2019/02/11 11:21:13     1001
2019/02/11 11:21:14     1104
2019/02/11 11:21:15     1104
2019/02/11 11:21:16     1104
2019/02/11 11:21:17     1104
2019/02/11 11:21:18     1104
2019/02/11 11:21:19     1241
2019/02/11 11:21:20     1241
2019/02/11 11:21:22     1241
2019/02/11 11:21:23     1241
2019/02/11 11:21:24     1241
2019/02/11 11:21:25     1401
2019/02/11 11:21:26     1401
2019/02/11 11:21:27     1401
2019/02/11 11:21:28     1401
2019/02/11 11:21:29     1401
2019/02/11 11:21:30     1568
2019/02/11 11:21:31     1568

こんな感じで5秒周期で値が更新されました。

オシロによる確認

せっかくなのでオシロでも確認します。Peak電流は150mAと記載があり、恐らく赤外線照射時にこれだけ電流が流れるのだと思います。電源から電流を引っ張ると僅かでも電圧降下が起きるはずなので、+5Vを拡大して確認します。

f:id:positive_bedridden:20190211114101p:plain
+5V拡大 (X: 2sec/div, Y: 40mV/div)
見やすくするため1kHzのLPFをかけています。約5秒周期で80mVぐらい電圧が落ちています。
時間軸も拡大して見てみると、
f:id:positive_bedridden:20190211114631p:plain
+5V拡大 (X:100msec/div, Y: 40mV/div)
電圧が落ちている幅は約400msecでした。5秒周期で400msec点灯してCO2を測定していると予測できます。

なお、電圧降下は電源自体の特性かもしれませんし、1mの長いUSBケーブルの抵抗成分のせいかもしれませんが、いずれにしても0.1V程度の変動なら問題は無さそうです。

CO2測定値がUART取得に反映されるまでの時間

CO2測定周期は分かったけど、じゃあ実際その値がUARTで取れるのはいつ?というのを確認します。
まず、CO2測定直前の受信内容です。

f:id:positive_bedridden:20190211120812p:plain
CO2測定直前のRXD0 (青:+5V, 赤:RXD0)
CO2濃度は3-4byte目なので、0x03F6=1014[ppm]です。この値が変化するのは次の図です。
f:id:positive_bedridden:20190211121107p:plain
RXD0のCO2濃度が変化したとき(青:+5V, 赤:RXD0)
CO2濃度は0x03FD=1021[ppm]に変化しました。CO2測定開始から約1.0秒後に更新されたことが分かります。

おわりに

今回はMH-Z19Bの電気的な部分の確認に主眼を置きましたが、測定の精度には触れていません。
CO2センサとして精度良く運用するには少なくともキャリブレーションが必要のようなので、その辺りはまた後日確認します。