RaspberryPi
NDIR方式によるCO2センサー

 様々なガスは、それぞれ特有の赤外線吸収波長を持っています。その特性を利用したガス計測の方法にNDIR方式(Non Dispersive InfraRed)があります。赤外光源より照射された赤外線は広域の波長を含んでいますが、ガスによる吸収で、そのガス特有の波長の赤外線は、ガス濃度に応じた割合で減衰します。このガスの吸収波長と吸収の影響を受けない参照波長でのセンサーからの信号を比較することにより、ppmレベルでの高精度な分析・検知ができるといいます。
 NDIR方式のCO2センサーは様々なものが市販されていますが、いずれも高価です。安価な中国製のMH-Z19が入手できたので、トライしてみました。banggood.comやebay.comのサイトで3000円程度で、入手可能です。

 絶対値の精度はキャリブレーションはしましたが、自信がありません。絶対値よりも、変化に注目していただきたい。 計測してみると、一日の変化が大きく、日中に低下し、夜間に増加するのがみられます。木々の炭酸同化作用によるものと思われます。

 (2017/05/10公開、2017/06/03更新) 
MH-Z19センサー
 MH-Z19センサーは、サイズ26.5X19.5X8.5mm 20gの小型で、2つの繊維質のフィルタ窓があり、そこから空気が出入りするようです。金色ですが、プラスチック製です。
 インターフェースはUARTとPWMがあり、今回はUART(Universal Asynchronous Receiver/Transmitter)を用います。

型番 :MH-Z19 NDIR CO2 Module
販売サイト:banggood.com あるいはebay.com 
メーカ: Zhengzhou Winsen Electronics Technology Co., Ltd

規格表:こちら

 規格表の一部を貼り付けておきます。測定範囲は0〜2000ppmで、誤差50ppm、温度補正がされていると書いてあります。




RaspberryPiとの接続
RaspberryPiには、USBがつかえますので、そこにCO2センサーをつなぐ手がありますが、ここではRaspberryPiのGPIOに直接つなぎます。次の通り4本の線でつなぎます。

 MH-Z19  RaspberryPi GPIO
 2  RXD  8  TXD
 3  TXD  10 RXD
 6  Vin  4  5V
 7  GND  6  GND

 

 


UARTの準備
RaspberryPiでUARTを使う準備をします。


RaspberryPi モデルB (OSはRASPBIAN WHEEZY)の場合

ステップ1  /boot/cmdline.txtを次のように編集
$ sudo nano /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
のように編集。すなわちconsole=ttyAMA0,115200 という部分を外し、ttyAMA0をコンソールとして使用しないようにします。

ステップ2 /etc/inittabの最後の行をコメントアウト
$ sudo nano /etc/inittab
#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

ステップ3 リブートして/devディレクトリのなかに、ttyAMA0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

ステップ4 つぎにPythonからUARTを使えるようにするために、シリアルポート操作ライブラリpython-serialをインストール
$ sudo apt-get install python-serial


RaspberryPi モデルB3(OSはRaspbian Jessie)の場合(こちらを参考)

ステップ1  /boot/cmdline.txtを次のように編集
$ sudo nano /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
のように編集。すなわちconsole=serial0,115200という部分を外します。

ステップ2 /dev/ttyS0 をGPIOから使えるようにつぎの2つを実行します。
$ sudo systemctl stop serial-getty@ttyS0.service
$ sudo systemctl disable serial-getty@ttyS0.service

ステップ3 config.txtを次のように編集
$ sudo nano /boot/config.txt
config.txtの最後に
enable_uart=1
を追加

ステップ4 リブートして/devディレクトリのなかに、ttyS0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

ステップ5 つぎにPythonからUARTを使えるようにするために、シリアルポート操作ライブラリpython-serialをインストール
$ sudo apt-get install python-serial



Raspberry PiのCO2センサソフトの作成

 

Raspberry Piで動かす、CO2センサーのよみとりプログラムをPythonで作ります。

コメント番号
(1)  UARTを読めるようにserialをinclude

(2)  ttyS0 にUARTの設定 (RaspberryPiモデルBの場合は'/dev/ttyAMA0'とすること)
Baud rate = 9600
Data bit = 8 bit
Non Parity
Stop bit = 1bit

(3) センサーにコマンドを送る
 Byte0は常に0xFF
 Byte1はセンサー番号デフォルトは0x01
 Byte2はコマンド 0x86は濃度測定コマンド 0x87はゼロ点キャリブレーションコマンド(使い方不明のため未使用)
 Byte8はチェックバイト


(4) 9バイトのreturn valueを読んでresultに代入
Byte2とByte3に計測された濃度(ppm)が返される


(5) チェックサムは
checksum = (invert (byte 1 +... + 7)) + 1
と計算。チェックバイトがこの計算と合わないことがあります。そのデータは棄却します。(特に始めて動作させた時)

(6) チェックサムが正しければ濃度を10進数に変換し返す

(7) 出力データは時刻、濃度

(8) 10秒に1回 ファイル出力
CO2.txtというCSV形式のファイルができる。たとえば
2017/02/23 14:51:19,437

 CO2センサー読み取りプログラム  CO2sensor.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 2017/06/03 (C) Hiroshi Ishikawa.
                  
import serial #(1)
import time
import datetime
   
s = None
filename = 'CO2data/' +  'CO2data.txt'

def setup():#(2)UARTの設定 RaspberryPiモデルBの場合は'/dev/ttyAMA0'とすること
	global s
	s = serial.Serial('/dev/ttyS0',baudrate=9600,bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,timeout=1.0)
	
def readdata():
	#(3) 9バイトからなるコマンドを送る
	b = bytearray([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])
	s.write(b)
	time.sleep(10)
	#(4)return valueをよむ
	result = s.read(9)
	#(5)チェックサムを計算
	checksum = (0xFF - ((ord(result[1])+ord(result[2])+ord(result[3])+ord(result[4])+ord(result[5])+ord(result[6])+ord(result[7]))% 256))+ 0x01
	if checksum == ord(result[8]):
		#(6)チェックサムが正しければ濃度を10進数に変換し返す
		return(ord(result[2])*256+ord(result[3]))

if __name__ == '__main__':
	setup()
	while True:
		now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
		#(7)出力データ
		data = now + "," + str(readdata()) + "\n"
		#(8)ファイル出力
		file_data = open(filename , "a" )
		file_data.write(data)
		print (data)
		file_data.close()


起動は
$ sudo python ./CO2sensor.py とします。
ファイル CO2data.txtを、親機のパソコンからよんで、適宜グラフ化します。

5分ごとに移動平均した結果をこちらに示します。