chakokuのブログ(rev4)

テック・コミック・ごくまれにチャリ

CO2センサ(MH-Z19C)を接続してみた

先日入手した、CO2 Sensor Module(MH-Z19C)をシリアル接続して値を取ってみた。普通にデータを取得すると以下のような値で、これは高すぎると思われる。

sensing CO2
['0xff', '0x86', '0x7', '0x89', '0x46', '0x0', '0x0', '0x0', '0xa4']
value:1929 (0789H)

単純に、上位8bit+下位8bitで演算した結果がCO2濃度(PPM)らしいのですが、、CO2濃度が1929ppmってこれが本当なら危険なぐらいにCO2濃度が高い。キャリブレーションをやり直すか、なんかその辺がおかしいのではと思える。コマンドでもキャリブレーション(Zero Point On/Off?)を指定できるらしいので、、コマンド経由で指示するか。。
マニュアルでは「デフォルトでAuto-CalibrationがONに設定されていて、24H周期でキャリブレーションがなされる」と読み取ったのだが、、手っ取り早くPin1(HD; zero point calibration)を一定時間Lに固定してCalibrationを実行させた。現在は404ppmとなっている。

sensing CO2
['0xff', '0x86', '0x1', '0x94', '0x47', '0x0', '0x0', '0x0', '0x9e']
value:404 (0194H)

電源投入後に、HDピンをLに落とす機能を作るべきかどうするか、、マニュアルでは24時間周期でZero Point Calibrationが実行されると書かれているので、それを信じて今は実装しない。今回作成したCO2Sensor(MH-Z19C)用のライブラリは以下*1

from machine import UART
from machine import Pin
import utime

uart0 = None
READ_CO2 = bytes((0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79))
SENSOR_TX_PIN = 16
SENSOR_RX_PIN = 17

def setup_CO2_sensor():
    global uart0
    uart0 = UART(0, baudrate=9600, tx=Pin(SENSOR_TX_PIN), rx=Pin(SENSOR_RX_PIN))

def get_co2_sensing():
    value = 0
    uart0.write(READ_CO2)  
    data = uart0.read()         
    if data and len(data) == 9:
          value = data[2] << 8 
          value += data[3]
    return value

def get_check_sum(packet):
    checksum = 0
    for data in packet[1:]:  # to skip Start Byte(0xff), use [1:]
        checksum += data
    checksum &= 0xff
    if checksum  == 0:
        return 0
    else:
        return 0x100 - checksum

#
# set calibration for Zero Point On/Off
#
def set_calibration(cb_zp_on=True):
    calib_zp = bytearray((0xff,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x00))
    if cb_zp_on:
       calib_zp[3] = 0xa0
    else:
       calib_zp[3] = 0x00
    calib_zp[-1] = get_check_sum(calib_zp[-1:])
    uart0.write(calib_zp)

def co2_monitoring():
    while True:
        print("sensing CO2")
        value = get_co2_sensing()
        print(f"value:{value:d} ({value:04x}H)")
        utime.sleep(3)

先日AppSheetで作成した部屋の空気質の見える化アプリにCO2を加えた。夏なので窓開けっぱなしのせいか、ずっと400ppmを維持している。

■関連URL
MH-Z19Cの仕様書
https://www.winsen-sensor.com/d/files/mh-z19c-pins%26terminal-type-co2-manual(ver1_2).pdf
ちなみに、、checksumの実装例がC言語で掲載されているが、これは間違っていると思う(最後にchecksum += 1が必要では?)

*1:先人のGithubのドライバを見ていると、温度計測等の隠しオプションもあるらしい