MH-Z14A CO2からのデータ取得

MH-Z14Aが手元にあり、データを取得してみようと思います。

こちらの製品は中国のWinsenという会社のもののようです。

MH-Z14A NDIR CO2 SENSOR FOR CARBON DIOXIDE DETECTION--Winsen
Winsen Electronics manufactures infrared CO2 gas sensor modu...

データの取得はアナログ、PWMもありますが、UARTで取得しようと思います。ただMH-Z14Aのデータシートにはデータ取得の手順がありません。そこでWEBで調べてみると、@watiko様が既に同様の件で記載いただいていました。

Raspberry Pi 3 Model B+ で二酸化炭素濃度を測る(MH-Z14A) -AWS IoT もあるよ- - Qiita
想定読者センサー類の接続・制御などはやったことがないクラウドサービスを触ったことがあるAWS のマネージドコンソールで設...

先の製品ページにあるMH-Z14(Aがない機種)のデータシートを参照したそうで、Pythonのコードも記載あります。

今回、MH-Z14AにUART-USB変換ケーブル(PL2303HX搭載)を接続し、Windows環境でPythonによる取得としてみます。なおUART-USB変換ケーブルのロジック電圧は3.3Vのものを使用します。

まずUART-USB変換ケーブルをWindows10マシンに接続すると、ドライバを自動でインストールしてくれCOMとして認識してくれました。ただ、このCOMがオープンできない!

あれ?っと思い、調べてみるとドライバを新たにインストールするようです。

【Windows10】PL2303HX搭載のシリアル-USB変換ケーブルを動かす
以前の記事で、ラズベリーパイのUart通信用に、PL2303HX搭載のシリアルーUSB変換ケーブルを使った。 とても安価...

ダウンロードしたドライバはこちら。難なくインストールすることができ、Windowsの再起動を求められたので実施すると、次は問題なくCOMがオープンできるようになりました。

ここまでくれば、 @watiko様のコードをほとんど、そのまま適用させていただきます。

!/usr/bin/env python3

import serial
import time
import datetime
import json
import argparse
import sys

class MHZ14A():
    PACKET = [0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]
    ZERO = [0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78]
    
    def __init__(self, ser):
        self.serial = serial.Serial(ser, 9600, timeout=1)
        time.sleep(2) 

    def zero(self):
        self.serial.write(bytearray(MHZ14A.ZERO)) 

    def get(self):
        self.serial.write(bytearray(MHZ14A.PACKET))
        res = self.serial.read(size=9)
        res = bytearray(res)
        checksum = 0xff & (~(res[1] + res[2] + res[3] + res[4] + res[5] + res[6] + res[7]) + 1)
        if res[8] == checksum:
            return {
                "ppm": (res[2] << 8) | res[3],
                "dt": datetime.datetime.today().isoformat(),
                "ts": datetime.datetime.today().timestamp(),
            }
        else:
            raise Exception("checksum: " + hex(checksum)) 

    def close(self):
        self.serial.close()
 
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--mode")
    args = parser.parse_args()
    mode = args.mode or "co2"
    co2 = MHZ14A("COM3") 
     while True:
        if mode == "zero":
            co2.zero()
        else:
            try:
                print(json.dumps(co2.get()))
            except:
                pass
        time.sleep(1)
    co2.close()

if name == 'main':
    main()

実行させると1秒おきにデータが表示されます。

{"ppm": 936, "dt": "2020-01-18T07:57:37.515812", "ts": 1579301857.515812}
{"ppm": 935, "dt": "2020-01-18T07:57:38.540146", "ts": 1579301858.540146}
{"ppm": 935, "dt": "2020-01-18T07:57:39.563508", "ts": 1579301859.563508}

ん~、MH-Z14AをESPに接続し、コードを変更すればWi-FiやBLEでの通信が簡易に行え、小型・軽量の二酸化炭素モニタリングができそうです。